## **- A SHELL REFERENCE** 

A-Shell Documentation Series 

Copyright 2026 Jack McGregor. All rights reserved. This edition was produced on 30 June 2026. 

A-Shell Reference 

Page 2 

## **- ABOUT A SHELL** 

A-Shell is a general purpose development and operating environment that provides a common framework for Windows and Linux. A user running A-Shell under Windows, in other words, would see and interact with the system in exactly the same way as she would if running A-Shell under Linux. 

A-Shell was introduced in 1990 as a virtualization of the Alpha Micro Operating System (AMOS), offering business applications an escape from proprietary Alpha Micro hardware to the much wider range of Unix platforms. With Windows support beginning in 1993, A-Shell became a truly portable option that freed users, dealers and programmers from underlying hardware concerns. 

Key aspects of A-Shell include: 

- Provides a shell—or command prompt—with its own virtual disk directory structure, a rich set of shell commands, 

- command line editing and recall, a scripting capability, an editor, and a robust programming language called A-Shell Basic ("ASB"). 

- Includes an extensive toolbox containing hundreds of standard library routines to speed and simplify application 

- development. It also provides a generic C-compatible interface for calling Windows (DLL) or Linux (so) dynamic libraries. 

- Supports both plain text and graphical user interfaces, including GUI in the Unix environment without the overhead 

- normally required. 

- Operates in multiple modes: client-only (standalone PC or peer-to-peer network), server-only (web services, back-ends), 

- and client-server (smart terminal connections over SSH). 

- Scales smoothly from single PCs to systems of 1000 or more users. It manages not just the independent operation of each 

- user, but also is focused on supporting a group of users working together: file locking and sharing, system monitoring, inter-job messaging, etc. 

• Interfaces well with most web and computer industry standards including SQL, ODBC, PDF, XLS/XLSX, XML, JSON, SMTP, FTP/SFTP, SSL/TLS, TIF/JPG/PNG, HTTP, OAUTH2, RSA and other cryptography standards. 

In the 30-plus years since its debut, A-Shell has been continuously developed and maintained, focusing on the needs of its community of application developers while also keeping pace with changes to modern computing environments. 

This documentation is regularly updated as new features are added and processes are improved. It always refers to the latest version of A-Shell. 

A-Shell Reference 

Page 3 

## **Subtopics** 

- Terminology 

- File System Organization 

- System Tables 

- Shell (Command Prompt) 

- General Questions and Topics 

- Compatibility 

A-Shell Reference 

Page 4 

## **TERMINOLOGY** 

Although A-Shell operates in the Linux and Windows environments, it borrows a number of architectural concepts along with associated acronyms and terminology from earlier operating systems, most recently AMOS but also its predecessors in the minicomputer world, particularly DEC RSTS, as well as other modern programming languages that the reader may or may not be familiar with. Several of the terms are defined here and subsequently referenced throughout this document without further elaboration. 

Please take a quick look down this page and read up on any terms with which you are not familiar. A few terms native to A-Shell are included at the bottom. 

## **AMIGOS** 

An AMOS component supporting certain extended terminal functions, particularly the ability to save/restore rectangular areas. A- Shell supports the main features via TAB(-1,148) and TAB(-1,149) (see Tab Functions), as well as TRACKER (see topic on this page). 

## **AMOS** 

An acronym for the Alpha Micro Operating System. AMOS was a microcomputer-based multi-user system running on the Alpha Micro family of computers. The AM computers were originally built around the Western Digital WD16 and later the Motorola 68K family of processors. The Alpha Micro was introduced in the late 1970s, with a heyday in the 80s and early 90s. It was revolutionary for its time, offering minicomputer-like capabilities at microcomputer prices, consequently attracting the attention of business application developers who thrived for a decade or so. Most of these independent developers were squeezed out of the market by Windows and UNIX, as networking improvements started to make Linux viable for multi-user applications and improving processor performance began to make the Windows-based business machines cost-competitive. A-Shell was originally conceived as a bridge for those developers wanting/needing to migrate their applications from AMOS to the more popular operating systems. 

## **ASB** 

- An acronym for A Shell Basic, A-Shell's application development language. 

## **ASB Subroutine** 

A-Shell Reference 

Page 5 

A subroutine written in ASB (A-Shell BASIC) which exists as a discrete file, is modify-able by the A-Shell programmer, and has the filespec extension ".sbx." This is in contrast to the _embedded_ subroutines, which do not exist as files and cannot be changed. 

## **ATE** 

An acronym for A-Shell Terminal Emulator, the standard client used for connecting to A-Shell servers via telnet or ssh. In addition to the typical capabilities common to terminals and terminal emulators, ATE also supports an extensive set of advanced client/server capabilities including support for building a Windows-based GUI, remote execution, file transfer, etc. See the separate ATE Reference for more information. 

## **AUI** 

An acronym for the A-Shell User Interface, a framework allowing applications to build GUI applications dynamically. Two unique aspects of AUI are that it allows for the possibility of integrating GUI elements into to existing plain text applications (incrementally, without requiring an all-or-nothing rewrite), and it supports client-side GUI over telnet/ssh connections, even when the server is Linux. See the AUI subroutine for more details. 

## **CGI** 

Acronym for Common Gateway Interface (not to be confused with computer-generated imagery), a web standard for - communicating between browsers and back-end programs via a web server. See A Shell as a CGI Engine and CGIUTL. 

## **Device** 

Aside from the more general meaning of a thing designed or adapted for a purpose, or in the computer context, a storage device like a disk drive, within the A-Shell context it refers to the first part of the DevPPN file system organization, which has the format <name><unit#> followed by a colon. The <name> part must be three or four alphabetic characters (not case sensitive), the <unit #> one to three digits, with the total length between 4 and 6 characters plus the trailing colon, e.g. DSK0:, SDA123:, BACK99:, etc. Historically the <name> was intended as a reference to a physical storage device, while the <unit#> was typically a partition within that device although in the Windows and UNIX environments, each A-Shell Device maps to an arbitrary path by means of DEVICE directives in the system configuration file. 

## **DevPPN** 

Hybrid abbreviation/acronym (Device Project Program{mer} Number}; a framework for organizing disk storage into Devices and PPNs. See the DevPPN topic in File System Organization for more details. 

A-Shell Reference 

Page 6 

## **Embedded Subroutine** 

A subroutine which is built-in component of A-Shell, cannot be changed, and does not exist as a file. This is in contrast to _ASB_ subroutines, which are written in ASB, exist as files, and can be changed. 

## **GDI** 

Acronym for Graphic Device Interface, a Windows component used by A-Shell to support graphic printing capabilities. See GDI Printing. 

## **INFLD** 

Pronounced "infield." The name of A-Shell's internal field-level keyboard input mechanism underlying all other keyboard input mechanisms, including the command prompt, ASB INPUT statements, Xcall input routines such as INPUT, SBXINP, and INMEMO, and the AUI edit control. See XCALL INFLD for a complete reference to its capabilities. 

## **InSight** 

An AMOS component supporting certain text-based mouse interactions. A-Shell supports some of those ancient methods among others; see Mouse Interaction. 

## **ISAM** 

Acronym for Indexed Sequential Access Method, a file structure supporting both direct and sequential access. Each ISAM file unit is actually made up of a data (.DAT) file and one or more index (.IDX) files. A-Shell actually supports two ISAM frameworks: the - traditional one and a more advanced version called ISAM A. See ISMBLD, ISMDMP and ISAM Files for more details. 

## **- ISAM A** 

- Newer / alternative variation of ISAM. See ISAM A for general information, including a comparison to ISAM. 

## **JOB** 

An instance of A-Shell, equivalent to a pid in the Windows or UNIX environments. Each JOB has a unique Job Name consisting of six upper case alphabetic characters, either specified by the -j command line switch or auto-generated. In the latter case, the format is TSKAAA thru TSKZZZ for interactive instances (with real terminals) or TASAAA thru TASZZZ for background tasks. Each JOB also has a corresponding Terminal (aka TRMDEF) with the same name, and a Job Number indicating its position in the 

A-Shell Reference 

Page 7 

Job Table, ranging from one thru the maximum number of JOBs recently in use. The names and numbers are reused as instances are released. Use JOBALC to display your own JOB name, and _Job Table_ on this page for related information. See also Job Table. 

## **JOB Table, aka JOBTBL** 

Table keeping track of JOB activity maintained in a file jobtbl.sys whose size is determined by the license in conjunction with the MAXJOBS directive in the system configuration file. Supports administrative commands such as SYSTAT, JSTAT, SEND, KILL, FORCE, etc. See also Job Table. 

## **LDF** 

An acronym for Language Definition File, A-Shell's version of the various language/locale settings supported by various operating systems. LDF files are stored in DSK0:[1,6] as _langabbr_ .LDF with a particular one being activated via the LANGUAGE directive in the system configuration file, or the SET command. Details may be queried via XCALL GTLANG. 

## **LOKSER** 

The historic name for a particular model of file locking built based on the underlying operating system's file locking capabilities and exposed mainly through variations of ASB file I/O statements such as OPEN, READ, and WRITE. Must be enabled in the LOKSER directive in the system configuration file or with the SET command. Applications that do their own QFLOCK-based locking may prefer to leave LOKSER disabled to avoid having to navigate the various LOKSER rules for file access. 

## **MAP** 

Noun / verb / adjective reference to variable declaration (see MAP STATEMENTS) in general or possibly to a type of collection (i.e. ordered map). 

## **MIAME** 

Historical acronym for Machine Independent Alpha Micro Environment (pronounced like the city in Florida). Although outdated, it continues to be used as the default base directory for A-Shell installations. See Configuration. 

## **MIAMEX** 

A-Shell Reference 

Page 8 

The name of a particular subroutine with over 200 sub-functions (i.e. "MIAMEX functions") for accessing A-Shell and host OS internals, system-level features and operations, and operations toO small or obscure to be worth separate subroutine implementations. 

## **MULTI** 

An AMOS software package supporting the ability to switch between multiple jobs within a single terminal/window/connection. Roughly equivalent to PolyShell in the A-Shell environment. 

## **P2P** 

Acronym for Peer-To-Peer, and network confirmation made up of workstations with file sharing capability. Typical environment for small Windows-based A-Shell installations (where any of the workstations can act as the "server" simply by hosting the file directories). 

## Server/Client 

A seemingly backwards variation of the more common "client/server" (architecture) which more aptly describes ATE-based systems. In the traditional client/server scenario (e.g. web browser application), the client is driving the action, running the primary application logic and making requests to the server for information. By contrast, in the ATE framework, the application runs on the server, which drives the action but makes requests to the ATE client to extend the capabilities of the server (e.g. displaying a GUI front-end, executing SBX routines and client-side Windows commands, retrieving information from the client environment, etc.) 

## **PolyTRACK** 

The historic name of a subsystem for managing multiple jobs from a single terminal, built around TRACKER by MicroSabio as a competitor to MULTI under AMOS. The equivalent product option under A-Shell was renamed PolyShell. 

## **PPN** 

An acronym for Project, Program{mer} Number; a two-level directory organization scheme consisting of two numbers from 0- 999, typically formatted as [p,pn], e.g. [7,6] or [257,0]. The first number is known as the "Project", typically used to group related files or programs, such as a module like AR or GL within a larger application. The second number, more cryptically known as the "Program{mer} Number" is in practice used for sub-grouping files by type or ownership or other attribution within a project. For example, a project 50, corresponding to, say, an order entry module, might be sub-divided into the the following: 

A-Shell Reference 

Page 9 

- `[50,0]   - RUN programs; the ,0 directory is automatically part of the project search path` 

```
[50,100] - Common source include files
```

- `[50,101] - Projection source files` 

- `[50,102] - Beta source files` 

```
[50,121] - Hector's development/test directory
```

```
[50,122] - Elvira's development/test directory
```

- `[50,400] - Common data files` 

```
[50,401] - Tuscaloosa division data files
```

```
[50,402] - Topolobompo division data files
```

```
[50,403] - Transylvania division data files
```

```
etc.
```

In the Windows and UNIX environments, PPNs are mapped to native directories with 6 digit names by expanding both parts into three digits, i.e. [1,4] maps to 001004, [50,122] maps to 050122, etc. 

Note that Project numbers 1 thru 9 are traditionally reserved for system use. See DevPPN for more details, the PPN system command to display existing PPNs, and the SYSACT system command for creating new PPNs. 

## **QFLOCK** 

A reference to the system file QFLOCK.SYS used for maintaining a variety of application-level inter-Job locks. Alternative or XS XS adjunct to the OS-level file locking system LOKSER. See XLOCK and FLOCK . 

## **SBR** 

Originally meaning "subroutine," the term now refers only to embedded subroutines. 

## **SBX** 

A-Shell Reference 

Page 10 

File extension identifying ASB subroutines. 

## **TCRT** 

An acronym (for Tab Cathode Ray Tube?) referring to a set of extended terminal commands invoked via TAB(-n,f) commands. The negative first parameter separates these commands from the standard TAB(row,col) commands for cursor positioning and identifies the group of commands such as display functions, color, layout, ATE functions, etc. See Terminal Functions for more details. 

## **Terminal, aka TRMDEF** 

The name for the terminal device—serial or network, real or virtual—attached to a JOB. Given that each JOB is attached to a Terminal of the same name, the distinction between them is mostly lost and can be ignored in modern networked environments. The concept of attaching terminals to JOBs was more salient in the days where terminal devices were hard wired to serial ports. See TRMDEFSP for additional details. 

## **TRACKER** 

The historic name of a subsystem for tracking the text-based contents of the screen, allowing text-based applications to save and restore areas of the screen in order to implement pop-up windows or toggling between logical screen displays, typically using the subroutines MSBOXXXS or SWPSBRXS and/or TAB(-1,201), TAB(-1,202) and TAB(-1,203).  The capability is built-in to A- Shell. Also see WSET.LIT. 

## **XCALL** 

An abbreviation for eXternal CALL, used as verb, noun or adjective, whether referring to the action, the target subroutine/module, or the variation of type of ASB control statement. The XCALL mechanism allows ASB to dynamically load and invoke subroutines/procedures/functions within external modules written in other languages, complete with parameter passing by value or reference, whether to access capabilities otherwise not available (e.g. pointers) or not efficient (e.g. low level raw memory access), or to tap into existing shareable libraries (DLLs or Linux .so files; see DYNLIBXS) to avoid reinventing the wheel. Historically XCALL routines were written in assembler; in the A-Shell world they are typically written in C, or even ASB itself, where the primary motivation would be modularity. A-Shell is distributed with a couple hundred standard XCALLs, to which most application developers add their own. See Subroutines for more details. 

A-Shell Reference 

Page 11 

## **FILE SYSTEM ORGANIZATION** 

A-Shell has its own system for the organization of files. The system is of course a tree structure like all modern operating systems, but it differs significantly from the native file systems of Linux and Windows. For details on how it is mapped onto the Windows and Linux file systems, and more details, see the following sections. 

## **Subtopics** 

- DevPPN Directory Structure 

- Filespecs 

- Ersatz Devices 

A-Shell Reference 

Page 12 

## **DEVPPN DIRECTORY STRUCTURE** 

The A-Shell directory structure is made up of the following components: 

- A "device" consisting of a three or four alphabetic character device name and a one to three digit unit number, such as 

- "DSK0" or “DOC12”. Devices are normally referred to with a trailing colon, i.e. DSK0: or DOC12: (identifying it as a device and separating it from the filename). 

- A PPN consisting of a pair of one to three digit numbers, such as 1,4 or 923,255. PPNs are often enclosed in brackets, i.e. 

- [1,4] or [923,255]. This is optional when the context is clear, such as `DSK0:1,4` but mandatory when combined with a filename, e.g. `DIR.LIT[1,4]` . 

Device names and unit numbers correspond historically to physical devices and partitions within each device. For example, a system might have two different types of physical disks, named DSK and DKX, each of which was divided into three partitions, e.g. DSK0, DSK1, DSK2 and DKX0, DKX1, and DKX2. The device name may be either three or four alphabetic characters long, while the unit number may be one to three digits, with an overall limit of six characters. So DSK123 and BACK27 are legal names, while DZ1234 and WACKY1 are not. 

PPN originally referred to “Project” and “Programmer Number”, but evolved to simply represent a two level grouping of individual directories. For the most part these PPN numbers are arbitrary, except that the project values one through seven are reserved for system files, and the [x,0] directory within each project has special meaning in the Command Search Path. 

The overall scheme is known as "DevPPN." 

When A-Shell is installed in Windows or Unix, its DevPPN directory scheme is mapped on top of the native multi-level path system by associating each device with an arbitrary path—think of it like a logical mount point—via DEVICE statements in the miame.ini file. Beneath the device directory, each PPN corresponds to a six-digit subdirectory with each of the two parts expanded to three digits. So [1,4] becomes 001004 and [123,45] becomes 123045. 

For example, if DSK0: is explicitly mapped to C:\VM\MIAME\DSK0\ then DSK0:[1,4] would implicitly map to C: \VM\MIAME\DSK0\001004\. Or in the Unix case, if DOC13: is explicitly mapped to /vm/library/documents/ then DOC13:[15,345] would implicitly map to /vm/library/documents/015345/. 

Aside from these A-Shell devices which are mapped to native directories, A-Shell also supports ersatz devices which map to A- Shell devices or PPNs. 

A-Shell Reference 

Page 13 

## **FILESPECS** 

A-Shell typically recognizes two types of filespecs: it’s own DevPPN filespecs and those native to the host operating system. 

DevPPN filespecs have the form: 

```
{device:}filename{.ext}{[p,pn]}
```

DevPPN filenames consist of 1-72 RAD50 characters; allowable characters are A-Z, 0-9, dollar sign ( $ ), hyphen ( - )  and underscore ( _ ). Spaces are not allowed. DevPPN filenames are not case sensitive, but in the Unix environment are mapped to lower case native filespecs. 

Extensions can be from 0 to 8 RAD50 characters. Multiple extensions are not allowed. 

Optionally, the order of the parts can be changed to put the [p,pn] in front of the filename, e.g. DSK3:[100,200]ABC.DAT 

Within ASB programs, file I/O statements recognize and accept both DevPPN and native filespecs. 

At the command prompt, filespecs used in System Commands are expected to be in DevPPN format. But many commands, including all of the wildcard commands, will allow you to specify a native filespec by enclosing it in quotes. For example: 

```
.COPY HOSTS.TXT="/etc/hosts" /NOD
```

```
.TYPE "/etc/hosts"
```

```
.SIZE "c:\vm\miame\bin\ashw32.exe"
```

```
.DIR HASH.DIR="/vm/miame/bin/ashell" /H
```

When using quoted native filespecs, you cannot use wildcards. 

## **Filespec recommendations** 

A-Shell Reference 

Page 14 

• A-Shell does not recognize spaces in file name, so it is strongly recommended that you avoid them when naming files in other (i.e., host) operating systems. 

• The same for apostrophes and quotes. They might work in Windows but will be a nightmare in Linux and of course will not work in A-Shell. 

- Obviously slashes are also off limits. Note that that Windows treats / the same as \, but Linux does not. 

A-Shell Reference 

Page 15 

## **ERSATZ DEVICES** 

In addition to the devices defined by DEVICE statements in the system configuration file, the DevPPN system also supports ersatz devices which act as aliases for DevPPN devices or device:[p,pn] directories. See ERSATZSP and Ersatz Definition Files for additional details on defining and using ersatz devices. 

While the main benefit of the ersatz device system is to allow users to assign meaningful names to their own device:[p,pn] combinations, it is also used with A-Shell itself to assign short aliases for the following system directories: 

|**Device:**<br>**[P,PN]**|**ERSATZ**|**System Account Purpose**|
|---|---|---|
|DSK0:[1,2]|OPR:|System operator account. This account has special privileges and is usually password protected. Logging into this<br>account might be considered analogous to logging in as Administrator under Windows or as the superuser under<br>Unix. Certain commands, for example, will only run, or have greater powers, when executed from this account.|
|DSK0:[1,4]|SYS:|"The" system account. This is the default location for all of the system commands (those with LIT extensions) plus<br>certain configuration files, such as the language files andersatz.ini.|
|DSK0:[1,6]|DVR:|Terminal driver and language definition file account. Under A-Shell, terminal drivers are embedded in the<br>executable, so the only files you will normally have in this account of the language definition files (e.g.<br>englsh.ldf).|
|DSK0:[1,7]|ASHCFG:|A-Shell configuration files, in particular, printer init (PQI) files.|
|DSK0:[2,2]|CMD:|Command files (i.e. those with CMD or DO extensions). These are the A-Shell equivalents of BAT files under DOS<br>or shell scripts under Unix.|
|DSK0:[7,0]|LIB:|Library files. Function key translation tables, color configuration files,ini.vue(VUE initialization file).|
|DSK0:[7,1]|HLP:|Help files. A-Shell tends to embed help which is associated with system commands in the commands themselves,<br>or use external PDF (Acrobat) or CHM (Windows Compiled Help) files, leaving this directory only for the help files<br>that are displayed from within the VUE command mode with the HELP command.|
|DSK0:[7,6]|BAS:|RUN files placed in this directory can be run from any other location.|
|DSK0:[7,376]||A-Shell sample program directory|



A-Shell Reference 

Page 16 

## **SYSTEM TABLES** 

In order to keep track of what is going on with and between JOBs, A-Shell dynamically creates and maintains two system tables. See the following topics for information on JOBTBL.SYS and QFLOCK.SYS. 

A-Shell Reference 

Page 17 

## **JOB TABLE** 

_Added November 2024_ 

A-Shell uses the term _job_ to refer to an individual instance or session, i.e a task or process in the lexicon of Windows and UNIX. Although each A-Shell is also a native host operating system task/process, and thus has a process id (pid), in the A-Shell context they are identified by job names and job numbers. Job names are one-to-six upper case characters, either specified by command line switch, or assigned automatically, in which case they are of the form TSKAAA, TSKAAB, ... or TASAAA, TASAAB, ... for foreground and background jobs, respectively. Job numbers range from one to the maximum concurrent number of jobs, with the numbers reused as jobs exit. 

- A-Shell jobs are tracked in a shared file JOBTBL.SYS, normally stored in the same directory as the A Shell Configuration File but specifically as specified by the QUEUESP, that is dynamically created when the first job is launched, and removed when the last job exits. For more information relating to the Job Table, see the following topics: 

## **System Parameters** 

- MAXINST:  maximum number of jobs allowed to originate from a single workstations 

- MAXJOBS:  maximum number of jobs to allow total 

- QUEUE:  location for both QFLOCK.SYS and JOBTBL.SYS 

## **System Commands** 

- SYSTAT:  detailed job table display/list 

- ASTAT:  dynamic job table display 

- JSTAT:  dynamic display of a single job 

- SEND:  send message to a job 

- KILL:  kill a job 

## **Subroutines** 

A-Shell Reference 

Page 18 

- MX_READJCB:  read job table records 

- MX_WRITEJCB:  write job table records 

- MX_KILL:  send signals to jobs (analogous to UNIX kill command) 

A-Shell Reference 

Page 19 

## **QFLOCK** 

_Added November 2024_ 

The QFLOCK.SYS file, created dynamically along with its sibling JOBTBL.SYS, keeps track of various kinds of inter-job lock queues. While A-Shell applications are free to implement their own locking schemes to manage race conditions, typically using system file locks either directly or as proxies, QFLOCK.SYS provides a convenient mechanism for managing multi-process access to files or any other abstract resource. Note that when a JOB exits, any entries it may have left in the QFLOCK.SYS are automatically cleared. See the following topics for more details: 

## **System Parameters** 

- QUEUE:  specifies location for both QFLOCK.SYS and JOBTBL.SYS 

- SBR=MXLOCK:  determines whether a JOB may lock itself out 

- SBR=AXLOCK:  affects handling of wildcard lock conflicts 

## **System Commands** 

- QUTL:  view/manage QFLOCK.SYS entries 

## **Subroutines** 

- MX_GETQUEUE:  read a queue block 

- MX_QLOCK:  lock QFLOCK.SYS 

- MX_QUNLOK:  unlock QFLOCK.SYS 

- MX_QRBLD:  rebuild QFLOCK.SYS 

- XLOCK:  general purpose lock operations 

- FLOCK:  file locking based on QFLOCK.SYS 

A-Shell Reference 

Page 20 

## **SHELL (COMMAND PROMPT)** 

The A-Shell _shell_ layer, aka the "command prompt" or "dot prompt," functions like the familiar Windows and UNIX shells: it provides an environment with its own set of commands, a scripting capability, and more importantly a launch pad for executing application programs. The most unusual aspects of the A-Shell shell are: 

• It supports its own virtual DevPPN-style file system structure and syntax that nevertheless maps directly on to the native (Windows or UNIX) file system structure. 

• It is transparent, or semi-permeable, in the sense that it offers the ability to see through it to the underlying OS or shell environment, including querying the native environment, scanning native directories, and even executing native programs. You have the choice of operating completely within the shell—for maximum portability between operating systems—or of incorporating features of the native environment—for maximum power and flexibility—without having to recreate them. 

## **Command Line Editing** 

In the case of a real terminal connection, when there are no commands or characters queued up, such as in a Command File or via redirection, the shell displays its prompt (typically a single dot; see SET.LIT to change it) and waits for the user to enter a command. In addition to ordinary text, the following special commands are available: 

|**Command **|**Single Key**|**Action**|
|---|---|---|
|Ctrl+R|Page Up|Cycle backwards through the command line history, one at a time|
|Ctrl+T|Page Down|Cycle forward through the command line history|
|Ctrl+U||Move cursor to beginning of line|
|Ctrl+H|Left Arrow|Move cursor left, non destructive|



A-Shell Reference 

Page 21 

|**Command **|**Single Key**|**Action**|
|---|---|---|
|Ctrl+L|Right Arrow|Move cursor right, non destructive|
|Ctrl+Q|Insert|Toggle insert mode|
|Ctrl+Z||Erase line|
|Ctrl+Y||Erase from cursor to end of line|
|Ctrl+A||Move cursor to start of prior word|
|Ctrl+W||Move cursor to start of next word|
|Ctrl+N||Move cursor to end of line|
|Ctrl+F||Insert a space|
|Ctrl+D|Delete|Delete character under cursor|
||Backspace|Move cursor left, destructive|



A-Shell Reference 

Page 22 

Note that except for Ctrl+R and Ctrl+T, these commands are identical to those supported by the INFLD field editor (see Keyboard Commands for the complete set) and largely shared with those of the VUE file editor. 

## **See Also** 

- System (or "Shell") Commands 

- Command Files (A-Shell scripting) 

A-Shell Reference 

Page 23 

## **GENERAL QUESTIONS AND TOPICS** 

This section provides information that may be of interest to people updating from older versions of A-Shell, or selecting a platform on which to run A-Shell, or moving A-Shell from one platform to another. 

A brief note on the confusing language of "update" and "upgrade" and "conversion." In this documentation, we use the terms as follows: 

- **Update** : this is a move from an older version of A-Shell to a newer version. It does NOT involve a software license, it does 

- NOT provide additional options or features, it (generally) does NOT cost anything and you will probably not even notice any difference between the old and new versions. The purpose of an update is to keep your software "reasonably current" in relation to what the developers of A-Shell are working on and distributing. A-Shell is constantly being improved, in large ways and small, with bug fixes and new features, and it is generally a good idea to keep your copy up to date. There are exceptions and special considerations, of course. 

- **Upgrade** : this is when you add features or capabilities to A-Shell, or when you increase the number of authorized users. 

- Such changes generally require issuance of a new software license, and make your software "bigger" than it was before, in the sense that you have expanded its capabilities by either numbers or features. For example: A-Shell has an add-on module called PDFX that allows you to easily create PDF files from reports. Adding PDFX to your system is an upgrade and requires a new license; see Updating the License if that is what you need to do. 

- **Conversion** : this is a platform change from Windows to Unix or vice versa, or from any A-Shell platform to any other. 

- Also note that the information in this section frequently parallels and/or overlaps with the A Shell Installation documentation, which see for related details. 

## **Subtopics** 

- Updating A-Shell 

- Conversion: Linux to Windows 1 

- Conversion: Linux to Windows 2 

- Questions on ATE, ZTERM, SSH, Printing 

A-Shell Reference 

Page 24 

- Conversion: AM-PC File Transfers 

- Performance in Large Systems 

A-Shell Reference 

Page 25 

## **- UPDATING A SHELL** 

A-Shell is an evolving software product, meaning that it is always changing. The developers of A-Shell work on it constantly, and new versions are churned out several times a month. 

In order to bring some degree of order to what otherwise might be a fairly chaotic and never-ending confusion about updates, the A-Shell versions are segregated into two major categories: 

• **Stable** : The stable version of A-Shell has not changed since its formal release date, which is usually months or years in the past. The software is being used by many firms, is recommended by MicroSabio, and can be counted on to not change. It is stable, dependable, reliable, risk-free. The only exception to the not-changing rule is bug fixes, which are usually minor and obscure. 

• **Development** : The development version changes weekly or even daily, and incorporates an endless stream of improvements and new features. These changes rarely have any effect on existing programs, but it is at least possible that they might. Therefore, the development version is intended primarily for software developers who are interested in the latest features and improvements in A-Shell. 

For most users of A-Shell and in most circumstances, the stable version is preferred. Although some organizations want to always have the latest and greatest version of the program, most prefer the stable version because it eliminates most of the risk of something going wrong. That risk is very low even with the development version, but it is even less with the stable version. 

- To determine what numerical versions equate to the current stable and development systems, please see the A Shell downloads page here. 

## **Version Numbering** 

A-Shell's version number consists of three parts, separated by periods. For example: 6.5.1688. 

- First digit: in over twenty years of development (as of 2020), A-Shell has had six "major major" version number changes. The 

- current one is "6," and that will likely remain true for quite a while. 

- Second digit: this indicates a "major" release of A-Shell. Also, there is another important element to this digit: 

EVEN numbered versions are stable/finished, ODD numbered versions were those under development. So A-Shell 4.7, 5.1, and 6.3, for example, were all development releases, whereas 4.6, 5.0, 6.2, etc., were all stable releases. 

A-Shell Reference 

Page 26 

- Third digit: this indicates the "build" number of A-Shell, and shows at a glance how many times A-Shell has been recompiled / 

- rebuilt and released to the world since its origin. 

To determine the version number of your currently-running version of A-Shell, enter ABOUT, SYSTAT or LICENS at the A-Shell prompt. 

## **Updating** 

A-Shell is used in many different ways by many different kinds of organizations. Some have in-house programmers and technicians that keep A-Shell up to date, others rely on consultants or advisors, some have relationships with a computer dealer or reseller or other firm. You should make sure that the responsible person or firm is the one updating A-Shell. 

## **Subtopics** 

- Which Version Should I Be Using? 

- Updating A-Shell Windows and ATE 

- Updating UNIX 

- Updating SOSLIB and EXLIB 

A-Shell Reference 

Page 27 

## **WHICH VERSION SHOULD I BE USING?** 

Unfortunately, there is no one-size-fits-all answer to this question. Possible—and only possible—answers are: 

- Do you get your application software plus A-Shell from a dealer / reseller / consultant? Ask them about which version is right 

- for you. 

- Do you get A-Shell directly from MicroSabio? You likely should have the latest stable version. 

- Are you a "bleeding edge" user or developer who always wants the latest version? Get the very latest available version. 

- The best source of information about versions—latest, stable, historical—is the A Shell downloads page on the MicroSabio website that deals with that subject. 

Remember that A-Shell is being continually updated by the developers. In other words, the target is always moving and today's "latest stable" version might be—will certainly be, at some point—tomorrow's historical version. If you are the person in change of keeping your copy of A-Shell or ATE up to date, then you should probably be updating approximately once a year. 

Also note that it is up to you, the person installing the update, to know what you are doing! You need to determine if the update is required or recommended, and what problems you might encounter during the process. The normal answers are yes (recommended) and none (expected problems), but you are nonetheless responsible for the process. Caution is advised. 

A-Shell Reference 

Page 28 

## **- UPDATING A SHELL WINDOWS AND ATE** 

For A-Shell running under Windows, and for ATE, A-Shell has a very nice, clean, simple update mechanism. Here is pretty much everything you need to know: 

In other words, go to the "Help" menu in A-Shell/Windows or ATE, and select "Check for Updates." The system will respond with something like this: 

All you need to do is decide if you want to perform the suggested update. If yes, then A-Shell will download a new copy of itself and run the installation program. 

That is really all there is to it, unless something goes wrong or you have special circumstances or needs. Be aware that A-Shell cannot update itself while it is running, so a dialog box will pop up and tell you to shut down A-Shell; simply exit A-Shell, and click on the "Retry" button. 

If something DOES go wrong or you DO have special circumstances or needs, then please follow the directions for Unix updates but substitute "Windows" or "ATE" for "Unix version." 

Note that the update process described here is actually the small tip of a very large iceberg of update controls and procedures. If you are a system administrator or other technical person who is responsible for updating large and/or many systems, please see - the "Automatic Updating" discussed in the A Shell ATE documentation. 

A-Shell Reference 

Page 29 

## **UPDATING UNIX** 

_Reviewed July 2020_ 

There is no "automatic" method for updating to Unix, but the manual update procedure is simple. This method also works for A- Shell/Windows, ATE, and all other supported versions of A-Shell. 

- Determine which version you are using now, and which version you wish to update to. Make sure you know what you're doing 

- here! 

- Go to the MicroSabio distribution folder on our webserver, and view the directory contents. It should look something like this: 

- "64rel" means "Version 6.4 standard release," etc. You will normally want to select the latest (highest numbered) release that 

- is followed by "rel." Numbers followed by "dev" indicate an under-development version, which you are welcome to download but which has not yet been declared "stable." 

- Click on the name of the applicable folder, such as "64rel" and see another folder display like this: 

- Note the file install-notes-linux.txt which will apply to all Unix installations. 

- The "el" numbers (EL5, EL7, etc.) refer to "Red Hat Enterprise Linux version number." We primarily focus on the Red Hat 

- Enterprise and CentOS distributions, which share a common kernel and core set of libraries; contact us to discuss the possibility of using other distributions. The A-Shell releases for the various -el# distributions are generally—but not always—upward compatible, and almost never downward compatible; e.g. the A-Shell -el6 release will run fine on Red Hat or CentOS -el7, but probably not -el8, and definitely not -el4. The version number applies to Linux from any of the major distributions such as Red Hat and CentOS. The A-Shell versions are generally upward compatible (the EL5 version will run fine on EL6 or EL7 systems) and are generally NOT downward compatible (the EL7 version of A-Shell will not run on an EL4 system). 

- Again, click on the name of the applicable folder, such as "bin-linux-el6" and see another folder display like this: 

- To get the latest version, click—sometimes twice—on the "Last modified" column header that the files will be sorted by date. 

- Unless you have reason for not doing so, you should also download the latest available version. 

A-Shell Reference 

Page 30 

- To download the file(s) you need, simply click on them. Go back up the directory tree to read the installation instructions if 

- needed. 

- "EFS" in the file/folder name refers to A-Shell Encrypted File System. You generally do NOT want to use this version, unless of 

- course you do. 

- See Unix Installation for more information about the "bin" and "tz" file types and how to deal with them. 

While you can repeat the Unix Installation steps for an update, since the installer will avoid updating most configuration files and files that you've added, most updates affect only the main ashell executable and consequently are released as compressed tar files (with names ending in **-upd.tz** ) containing only the updated executable. You can use any of these to replace the current A- Shell executable with the following procedure: 

Start by downloading the file into the bin directory (e.g. /vm/miame/bin). Then rename the existing ashell, typically by appending the current version edit number, which allows for a new copy to be installed without affecting the existing users running A-Shell. 

Note that after updating in this manner, any users currently executing ashell will continue to run the old version until they exist and launch a new session. This takes advantage of the fact (and assumes) that the new version is compatible with the old version in that way. This is virtually always true when updating within the same major.minor version, especially the stable release. You can monitor which users are still running the old version and which are running the new version via the `SYSTAT/N/VER` command. 

A-Shell Reference 

Page 31 

## **UPDATING SOSLIB AND EXLIB** 

The SOSLIB and EXLIB are libraries of files that will be of interest only to A-Shell developers, programmers and resellers. These libraries are updated by copying new versions over the top of previous versions. Click on the links at the beginning of this paragraph for information on where to find the current copies of the libraries. 

A-Shell Reference 

Page 32 

## **CONVERSION: LINUX TO WINDOWS 1** 

From a Microsabio bulletin board discussion "Suggested Platform - OS for A-shell " of November 2012. 

## **Question** 

My client is running A=Shell 4.8 on Linux, and is considering moving to Windows. They have approximately ten users on the system, and we originally went with Linux because it was a better choice than Windows for that many users. However, that was more than ten years ago. 

Would Windows now be reasonable for ten users? And if we convert to Windows, how much recompiling of their .bas files will be required? 

## **Reply** 

There is a range of possibilities for a Windows environment (P2P workgroup, domain server, ATS, Terminal Server), but all of them would work fine for 10 users if properly configured. 

Most ASB applications are disk-bound, rather than CPU bound, and rely on shared access to files with some kind of locking scheme. So in choosing a configuration, you should give more consideration to that aspect of performance. 

The peer-to-peer (P2P) workgroup is the simplest and probably the cheapest Windows configuration, but has the lowest file I/O performance and the greatest exposure to network problems, particularly if different versions of Windows are in the mix. / 

A domain server is a step up in terms of overall network reliability, but not a big step in file i/o performance. 

The ATSD (A-Shell Telnet Server) and Windows Terminal Server (along with its competitors - Citrix, etc.) put all the CPU and file activity load on the server (as in Linux), but end up giving you much better performance by eliminating all the network file sharing overhead. Given the same hardware, Linux will still be faster, but the point is probably moot given the performance of modern hardware. 

If your server is old, tired, or short on memory, ATSD might be a better choice since it has relatively tiny overhead (less than 10 MB per connection), and is probably cheaper. But any decent modern server with 4GB+ of RAM and a quad-core CPU can easily handle ten Terminal Services connections, and does give more flexibility in client devices. 

Note that ATSD, unlike Windows Terminal Server and its ilk, does not strictly require a "server" version of Windows; an ordinary "professional" version will work just as well, at least from A-Shell's perspective, for a system of modest size. This can further 

A-Shell Reference 

Page 33 

reduce your costs for licensing and the expertise required, if you don't have any other reason to use the features of a true Windows "server". At some point, perhaps above 20 users, the advantages of the "server" editions in terms of resource management become more substantial or even necessary. 

As for the recompiling, you may not need any, either for the platform change or the A-Shell update. Regarding the platform, the only issue would be if your application had extensions that specifically related to the Unix environment (e.g., referenced native filespecs, launched native LINUX commands via HOSTEX, etc.) As for the update, the old RUN format is still supported by both the runtime interpreter and the compiler. It is always possible though that in the intervening updates between 4.8 and the current 6.0, some fix, change or enhancement might inadvertently affect your app. 

The main compatibility issue that I know of is the switch from octal to decimal for the [p,pn] system in 5.0. This was done to expand the range of PPNs from 255x255 to 999x999, which was important to some developers with large sites subdivided by PPNs into companies, departments, profit centers, etc. The change does not affect RUN programs per se, unless you used a subroutine to manipulate PPNs that stored each as a single binary byte. Obviously, to handle 999, you need either two bytes or a three-character string.) If unsure whether that might be an issue, you should probably _grep_ your source for SUBROUTINEs and generate a list of all the different SUBROUTINEs you use, which you could either look up in our documentation or send to us for review. Fortunately it is usually pretty easy to swap out or upgrade such calls, assuming it's even an issue at all. 

A-Shell Reference 

Page 34 

## **CONVERSION: LINUX TO WINDOWS 2** 

" " From the Microsabio bulletin board discussion Is it feasible to switch from Linux to Windows Server? of December 2012. 

## **Question** 

Does it make sense performance-wise to switch from Red Hat Linux to Windows Server for an A-Shell system which typically has 70 users running programs on it at the same time? 

## **Reply** 

Given the same hardware, Linux handily outperforms Windows, particularly in larger environments like yours. That said, there are a number of possibly mitigating or extenuating considerations: 

1. Windows peer-to-peer should be ruled out of hand for this size system. So we'll assume some kind of server-based model (Windows Terminal Server, Citrix, GoGlobal, ATSD, etc.) for the remainder of the discussion. 

Note that these server-based models divide into two completely different categories, what I'll call RDP-style (Windows Terminal Server, Citrix, GoGlobal, etc.) and Telnet-style (ATSD). For the RDP-style (they don't all used RDP specifically, but the concept is the same), the logical screen (within the server) is replicated to the client screen by some pixel-based protocol. As opposed to the Telnet-style case where the server sends characters (bytes) to the client, which is responsible for maintaining its own state and updating the display based on the logic of the character and character-based commands that arrive. The input channel is pretty much the same for the two variations. 

2. For RDP-style protocols, you will need a much bigger server than you would for Linux, or for ATSD, because each connection is essentially a full-blown Windows environment on the server. It's not easy to estimate those memory requirements, but as a very rough approximation, I would take the MEMORY partition size specified in miame.ini and add about 10MB per telnet/ATSD connection, and about 50MB per RDP-class connection. That would be for plain text applications. Add another 10-20MB for GUI. 

3. In the old days, you'd have to squint very carefully at the previous paragraph. Nowadays, you may just get a server with 16GB RAM and not sweat the details. 

4. Likewise for CPU - in the Windows environment, all the display operations are GUI/pixel-oriented (as opposed to byte-oriented in the Linux/ssh environment - even when using ATE for a GUI front end), so it takes a lot more CPU power to update displays. So while a single core Pentium could manage your 70 Linux users, you'd want 8 cores or more for the Windows equivalent. But again, that's no big deal these days, so maybe another meaningless detail not to sweat over. 

A-Shell Reference 

Page 35 

5. If you go with an RDP-style environment (as opposed to sticking with telnet), you're probably looking at substantial licensing costs. (On the other hand, maybe all those workstations already have client licenses for other reasons, in which case the additional cost may be minimal.) 

6. A-Shell GUI operations in the RDP-style environment are actually simpler than in the telnet/ATE environment, because it acts more or less just like the Windows standalone environment. (The AUI layer which converts GUI calls into ATE messages, relays them to the client, and processes the responses, is bypassed. Instead, there is a more seamless screen-replication layer, which may involve more raw bits being transferred, but for many GUI operations is actually more efficient. Plus you eliminate the latency delays involved when an ATE command requires a response from the client.) 

7. For plain text applications, the situation is somewhat reversed. ATSD/telnet style communications are generally much more efficient than the RDP-style remote screen replication when it comes to displaying characters. The one exception is scrolling (like in long DIR or TYPE operation) where, in the telnet case, every byte must be transferred, whereas in the RDP case, the scroll may not be as smooth, but it can effectively skip much of the updating by just resynchronizing the display at the end of the scroll. (Admittedly this is a special case, but I do get asked why scrolling displays take longer with byte-oriented telnet than with bit-oriented RDP.) 

Fortunately, if you already have a Windows server at the site, which it sounds like you do, you can probably experiment on it without a lot of investment. Particularly if you're leaning towards the Terminal Server approach and already have it installed on another server, just install a demo copy of A-Shell/Windows on it and make an RDP connection to it. You may be able to get a preliminary feel for the performance just by playing with VUE, DIR, and some of the programs in the EXLIB. If you're leaning towards keeping the present telnet clients, you will have to install ATSD, but that isn't very difficult either. 

As for version, existing Windows Server installations of A-Shell (as of July 2025) range from W2008 to W2025. Although there are plenty of differences in Windows from one version to the next, those differences don't seem to matter much to A-Shell. In fact, if you use the ATSD/TELNET configuration, you don't absolutely need a real "Server" version of Windows; the "professional" version will work. For the relatively large system of 75 users, however, the server versions may provide better environmental support in terms of resource management, security, etc. 

Caveat: We have a couple of Windows server sites in the vicinity of 50 users, but yours might well be the biggest ever. In contrast, we have many Linux sites with hundreds of users. 

A-Shell Reference 

Page 36 

## **QUESTIONS ON ATE, ZTERM, SSH, PRINTING** 

A new A-Shell client, who is converting from an older system, asks several questions: 

- Do we really need to use ZTERM, or is connecting to the host using any ssh client and starting A-Shell from there sufficient? I 

- ask this because previously the users connected to the host using an ssh tunnel and ZTERM on top of that. I want to get rid of that scheme in favor of something simpler which I think it could be done just by an ssh session. 

• In the same topic, the FTP configuration is something I would like to change to a SFTP connection to the host box (Linux in this case) with an user jailed to the disk directories of A-Shell. Do you think this approach would have a problem when comparing to using the TCP/IP support of AMOS? Again I am trying to prevent the tunneling and going straight to the box using the ssh stack as much as possible. 

- Does A-Shell printing depend on any particular terminal emulation(s)? 

Following are extended discussions on each of these topics. 

I'm glad you asked about ZTERM, because I was under the impression that the client was actually committed to it. We still sell it due to a long-time agreement with the developer, but because he stopped doing any support or development on it more than a decade ago, we decided to create our own emulator. That A-Shell-based emulator is called ATE (A-Shell Terminal Emulator), and we fully support it as well as modernize/enhance the capabilities as time goes by. One of those being proper SSH2 / SFTP support! Another is the enhanced printing capabilities, both in redirecting Linux print requests via the Windows system, as well as supporting preview, print-to-PDF, print-to-email, etc., that I may have referred to in a previous message. 

Perhaps the biggest enhancements are in the area of GUI support, but I gather that the client's application currently has no need for GUI. Whether they are interested in adding some GUI enhancements to the application, I have no idea, and it may not be your concern either. But if you or the client expect to be using the application for a long time into the future, those GUI capabilities become ever more important. So take note! 

But even apart from "GUI-fyng" the application per se, there may be areas where they might benefit from improved communication capabilities between the application running on Linux and the resources of the Windows environment. There is a reasonably coherent summary of ATE on the MicroSabio ATE page, and there is a list of extended TAB(-10,x) functions in the A- Shell reference to give some idea of the kinds of server-to-client commands that are available. Many of these overlap the ZTERM ESCAPE Sequence commands, in which case ATE also supports the same ESCAPE sequences for upward compatibility.) 

A-Shell Reference 

Page 37 

Most of the A-Shell/ZTERM users have migrated to ATE, and nearly all of the new A-Shell/Linux users choose ATE. But, it is a commercial product with a cost associated; you can see the prices on our website. To avoid those costs, or due to prior preference, some sites use other emulators, ranging from commercial ones like Anzio and AlphaLAN, to free/open-source emulators like Putty. As long as the emulator supports an emulation that is compatible with A-Shell and the features used by the application, it should work. The specific emulations that A-Shell supports are AM62A, AM62C, AM65, AM75, and WYSE50. It also supports a "generic" terminal emulation that works through the Linux TERMINFO database, allowing emulations that are known to Linux, such as VT220, VT320, etc. to function, although the capabilities are generally pretty limited. (The AMOS terminal driver system was quite advanced for its time and encouraged applications to take advantage of terminal features; the scheme was theoretically terminal independent, except that they then came out with their own line of terminals which certain tweaked capabilities to coerce most users into buying the more expensive AMOS terminals.) I haven't seen your application, so I don't know what features are being used, except that I do know that it uses the protected fields, i.e. TAB(-1,13) and TAB(-1,14), which probably rules out the use of generic emulations. Other features that are common in AMOS applications but possibly dependent on the AMOS terminal emulations are insert/delete, line drawing, save/restore, and status lines. Although it may be somewhat self-serving, my general opinion is that the difference in cost between ATE and a free emulator typically isn't worth the effort to identify and work around these issues, not to mention losing access to some of the really useful features, like printing. 

Regarding printing, no, A-Shell does not depend on any terminal emulator for printing. Printers can be defined to Linux, similar to how they are defined to AMOS, and A-Shell can print to those printers via PRINT.LIT or XCALL SPOOL, just like it does under AMOS. A text configuration file is used to associate the logical printer name known to the application, with the system print queue name known to the Linux operating system. The ability to print back to the terminal, for redirection to real or virtual Windows print devices, is just a bonus. 

Regarding the SSH tunnel and SFTP, I agree that getting rid of the tunnel would make your life easier. Since ATE (and other emulators like Putty) support SSH2, there is no need to use a tunnel; just SSH directly to the server. In the case of ATE, you can launch SFTP transfers via the same SSH terminal channel/port, which also simplifies firewalls. Jailing or sandboxing the users is possible in the normal way, based on the way you configure the SFTP service on the server, but if the application is driving those transfers (using the ZTERM ESCAPE sequences), then it probably assumes that the SFTP home directory is the real home directory, so re-homing might require some slight modification to that code, if it exists. 

One feature which ATE does not offer, but ZTERM does, is an interactive file transfer user interface. We deliberately excluded that because we felt that in most cases, it was an invitation to abuse, i.e. it was better to limit file transfers via the application logic, rather than to encourage users to transfer files back and forth unsupervised. But if that's the way you like to work, we recommend using one of the free SFTP-capable file transfer clients, such as FileZilla. One of our A-Shell developers also makes 

A-Shell Reference 

Page 38 

available a free one called MadFTP which has some features to make it integrate slightly better with A-Shell, i.e. sharing the login, knowledge of A-Shell directories, etc. But it isn't quite as sophisticated/powerful as FileZilla. Either one can be put on to the ATE menu bar via a simple application startup command, so further integrate it into the terminal environment, if so desired. 

Another detail I forgot to mention earlier about file transfers: A-Shell supports the ZTXFER.LIT command that may be used from the AMOS dot prompt (or A-Shell dot prompt) to transfer files, as an alternative to the application-driven transfer method. ZTXFER with no arguments gives the help info: 

```
.ZTXFER
```

```
ZTXFER usage:
```

```
To send from Host to PC:
```

```
ZTXFER{/switches} host-name PC-name or ZTXFER{/switches} host-name
```

```
To send from PC to Host:
```

```
ZTXFER{/switches}{a host-name=PC-name or ZTXFER{/switches} =PC-name
```

```
Switches:
```

```
/A forces ASCII mode
```

- `/2 requests new FTP/SFTP implementation if avail (faster)` 

```
/ATE use ATE terminal channel (automatic for PC -> ATSD)
```

```
Source file name may contain * wildcard (ATE/Unix only; no /2)
```

A-Shell Reference 

Page 39 

For example: 

```
.ZTXFER AAA.BBB c:\temp\AAA.BBB
```

```
.ZTXFER CCC.DDD = c:\temp\AAA.BBB
```

The above would transfer the AAA.BBB file from the current directory to c:\temp\aaa.bbb, and then transfer it back to ccc.ddd. 

The file transfer protocol and authentication would be determined by terminal emulator configuration; for ZTERM it would be FTP; for ATE it would be SFTP. 

But, as mentioned before, the assumption within ZTXFER is that the current directory as seen by the application, matches the directory as it would be seen by the {S}FTP server. If that were not true because of jailing/sandboxing/re-homing, an adjustment would have to be made somewhere to convert from one to the other. (It wouldn't be too difficult, but would require some tinkering.) 

A-Shell Reference 

Page 40 

## **- CONVERSION: AM PC FILE TRANSFERS** 

A client attempt to transfer files from an Alpha Micro computer to a PC using ZTERM, on the way to their happy future with A- Shell, reports the following: 

I am not having much success with ZTXFER. I have programmed and built command files for porting over my clients files from the Alpha to a Win7 Pro workstation using the ZTXFER program. Major issues. It runs exceeding slow, maybe 2 kbs per second. It also fails about every 5th transfer. It especially fails on .dat and .mmo files (do I need the /C switch?), however some port ok. Most frustrating is if it fails there is no way to either cancel , exit, reset terminal, etc. If I use task manager to end task it will stop but as soon as I open ZTERM again it just keeps going until it fails again. 

Our response to the client was: 

The /C switch for ZTXFER only applies when copying to AMOS, not from, so that's not an issue here. 

Our best guess as to the cause of the lockup is handshaking, i.e. that the serial connection from the ZTERM workstation to the Alpha is not wired for RTS/CTS handshaking, and/or ZTERM has not been configured for that handshaking. As a rule, XON/XOFF is not reliable with file transfers, and file transfers are not reliable without working handshaking. The symptom is typically the one reported, i.e. it works for a few files and then locks up. 

A good way to test handshaking is with a barber pole display, like this one: 

```
program BARBER,1.0(100) ! barber poll
```

```
MAP1 I,F
```

```
MAP1 BAR$,S,79
```

```
? tab(-1,99);  ! smooth scroll (probably not supported, but no harm to try)
```

```
FOR I = 33 TO 111
```

```
    BAR$ = BAR$ + chr(I)
```

A-Shell Reference 

Page 41 

```
NEXT I
```

```
FOR I = 1 TO 1000
    ? BAR$
    BAR$ = BAR$[2,-1] + BAR$[1,1]
```

```
NEXT I
```

```
END
```

That should output about 80K characters, which should take about 40 seconds as 19200 baud, or 20 at 38400. If the handshaking isn't working, it will probably become scrambled noticeably after several seconds. Until you can get that to work reliably, file transfer is going to be painful. 

Other than improving the baud rate, about the only other thing you can do is run it on multiple terminals at the same time in parallel. I remember once doing a conversion like this with 5 transfers running, and me going around from one to the next to check on them, move to new PPNs, restart after errors, etc. for the better part of a weekend.) 

Of course getting ethernet working will make it a hundred times faster, at least, so it's worth a little effort. But I don't know much about the hardware of a 2000VME machine. One tip: if you do get it working, you will need to add the -n switch to the FTPD startup so that FTP will be compatible with the DevPPN syntax. 

A-Shell Reference 

Page 42 

## **PERFORMANCE IN LARGE SYSTEMS** 

_Added February 2018_ 

_A reseller says: "My client has approximately 250 users, wants to migrate to A-Shell, and can create—through virtualization— pretty much any environment and operating system. What environment—Windows or Linux—should I recommend to the client for best performance, and why?" Our response follows._ 

In our experience, the limiting factor in overall system performance for typical A-Shell systems is disk I/O, which is dependent on a combination of factors including the physical performance of the disk hardware, cache performance, latency/bandwidth between the disk and the user memory, and locking performance. 

The worst architecture is Windows P2P (peer-to-peer) LAN, which has a big disadvantage due to inherent complications related to communication and data transfer between the individual workstations and the file server. They are also difficult to manage because of the degree of independence between the workstations, problems with different OS versions, security concerns, etc. Consequently, we do not recommend P2P architecture for systems larger than about 20 workstations. 

The best performance will be a Linux (CentOS or RHEL) system with local (not NAS or SAN) dedicated disks: local to avoid the latency of communication across some kind of network connection, and dedicated to avoid file locking delays inherent when a disk subsystem is shared between multiple computers. Virtualization is not a significant factor, but a multi-core "server class" (e.g. Xeon) CPU is. In the Linux environment, workstations should be connected over SSH2 connections, preferably from ATE (AShell) clients. 16GB RAM should be more than adequate for 250 users. 

For sites that want to stick with a purely Windows solution, the next best thing would be a Windows server where all of the processes run directly on that server. Because of the higher overhead of Windows processes, this requires a more powerful server, with a lot more memory than for the Linux case, but if you can build a server capable of hosting simultaneous Terminal Service sessions for all your users, then that will be an acceptable solution. It doesn't have to be Terminal Services/RDP; it could also be TELNET/ATE, or Citrix, or one of the other similar protocols which effectively turn the workstations into mere terminals rather than independent computers merely sharing the server's disk resources. Any of these designs will have a higher price-toperformance ratio compared to the Linux solution, but with enough resources should give adequate performance. Since this design only makes sense in the presence of significant local technical knowledge, you should defer to them to determine adequate RAM and CPU resources. 

## **See Also** 

- The Performance section of this document 

A-Shell Reference 

Page 43 

## **COMPATIBILITY** 

## **Data File Compatibility** 

Both random data files and ISAM 1.x files (.IDA and .IDX) are 100% compatible between A-Shell and AMOS. It is possible to transfer them as direct binary images between machines. 

Sequential files are compatible, but stored in the local operating system format. For AMOS, this means each end of line is marked with a Carriage return/Linefeed pair. This is true also of Windows, although sequential files can sometimes terminate with a **^Z** end-of-file marker. Under Unix, new lines are indicated with a single character, **\n** (linefeed). A-Shell is capable of reading both DevPPN-format and host-system-format sequential files. All newly created files are normally written in the current host-system-format. 

You can force A-Shell to use CRLF terminators in sequential output under Unix by setting OPTIONS=CRNL in miame.ini; see Configuration for details. 

Despite the minor format differences between sequential files on the various platforms, you can generally just transfer them between systems with no conversion, since all of the major A-Shell utilities (VUE, COMPIL, INPUT, etc.) will accept either format. 

VUE will accept files with either style of line terminator and always write them back in the native format, providing another way to convert source programs if necessary. You can override the terminators used by VUE with the CRLF=<Boolean> entry in the ini.vue file. Note that you should not save Unix configuration files and scripts with CRLF terminators, and this may render them undecipherable to Unix. If you are using the native operating system executable version of VUE for such, you can prevent this by creating an /etc/ini.vue file which contains CRLF=FALSE. 

ISAM 2.0 or ISAM Plus files are implemented using C-ISAM by Informix or D-ISAM by Byte Designs. Because of this, the format of the data and indices are not compatible, and the files must be transferred by first dumping them with ISMUTL.LIT on the host system, and then reloading them with the A-Shell version of ISMUTL.LIT. 

For those who object to this procedure as being too slow, due to the need to manually run ISMUTL to generate the new files and especially due to the time it takes to dump the old files on some slower machines, we have developed a pair of utilities which speed up and simplify this process; see the SOSLIB. 

## **Program Compatibility** 

A-Shell Reference 

Page 44 

The A-Shell runtime interpreter (RUN.LIT) is compatible with programs compiled under most versions of AMOS using either the 1.3 (OCMPIL.LIT) or 1.4 (COMPIL.LIT) compiler. It is not compatible with the RP files generated by BASIC _plus_ . On the source code side, the A-Shell compiler is compatible with all AlphaBASIC source code written for the version 1.3 compiler, and virtually all source code written for the version 1.4 compiler as well. The A-Shell compiler also supports most of the BASIC _plus_ source code (but not the compiled object code.) See PLUS Extensions for details on which BASIC _plus_ code is supported. 

The A-Shell compiler (either COMPIL or OCMPIL) will nearly always generate the exact same RUN file, right down to the hash code, as will the corresponding AMOS COMPIL and OCMPIL will. Thus, except for BASIC _plus_ , you have compatibility in both directions for both your source code and compiled programs. 

## **- A Shell and MIAME** 

A-Shell was originally developed as part of a larger system called the _Machine Independent Alpha Micro Environment, "_ MIAME" for short (pronounced like the beach in Florida). MIAME is no longer considered a viable product or software environment apart from A-Shell, but many references to MIAME remain in the A-Shell system. 

A-Shell Reference 

Page 45 

## **SETUP** 

A-Shell Reference 

Page 46 

## **- A SHELL INSTALLATION** 

This section describes the procedure for physically installing A-Shell on your computer. Since the procedures differ slightly between Windows and Unix, each is described separately. If you are updating as opposed to doing an original installation, see the documentation on Updating A-Shell. 

## **Subtopics** 

- Before Installation 

- Windows Installation 

- UNIX Installation 

- After Installation 

A-Shell Reference 

Page 47 

## **BEFORE INSTALLATION** 

Review the following notes and make sure you are aware of the various issues involved before beginning the installation. 

## **File System Setup** 

Although A-Shell itself can exist in any directories, for system administration purposes it may be wise to try to separate it from other application and operating system directories, if possible. This is less of an issue under Windows, where you typically have only one file system (or partition) available, and thus the best separation you can achieve is to give A-Shell its own directory tree, and possibly its own share name. Under Unix on the other hand, it is normal to have multiple file systems, and there are some particularly good reasons for defining one or more individual file systems to keep A-Shell separate from the rest of the operating system: 

- Individual file systems can be separately backed up and restored. 

- Separate file systems are naturally insulated from each other, so that any corruption that occurs in one will not spill over to 

- another. This will not only protect A-Shell from problems caused by some other application but also protect you from being accused by your system administrator of allowing your application to corrupt the system. 

- Since different file systems can be mounted at the same mount point (though not at the same time), you have the ability to 

- easily switch to another version of your data or application (backup, test, archive, etc.) temporarily without making any changes to A-Shell or your application. (This works best when you have "extra" scratch file systems available which you can restore a tape to.) 

- Putting your A-Shell application in a separate file system will eliminate the possibility that you can bring the system down 

- by filling up the disk. You may still cause your application to halt when it runs out of space, but the operating system will not be affected. 

## **Installation Overview** 

The core A-Shell installation consists of a single directory tree, normally named /vm/miame or \vm\miame. The top level contains the main configuration file, miame.ini. Below that is a bin directory containing the binaries—i.e., A-Shell's main programs and libraries—and a DSK0 directory tree with multiple sub-directories for system commands and general shell 

A-Shell Reference 

Page 48 

## variables and control file. 

Depending on the size and complexity of your application, you may create one more more additional pseudo-device directory trees adjacent to DSK0 or anywhere. That is something you would set up manually after finishing the basic system installation; see DEVICE. 

## **Security Key** 

After installation, it is necessary to install the security key that was supplied at the time of purchase. This process is described in the After Installation notes. If you don’t have a security key, A-Shell will run in demo mode, which is fully functional except for nag messages and being limited to a the single user. 

## **Updating** 

For Windows, updates are most easily accomplished via the _Help > Check For Updates_ menu, which checks for the existence of an update, and if found, gives you the option to proceed. The update routine is identical to the install except that it doesn't give you the option of a target location. 

For Linux, use the same process as for the original installation. 

Under all operating systems, the installation process will detect that (or ask if) an update is being performed and will not overwrite any existing configuration files. Any configuration files that might have new fields added, or differing formats, are stored in example form with .new extensions. If the function key translation tables are updated, the original ones will be saved with .ifs (.ifx) and .vus (.vux) extensions. 

The ash_install script used for installing and updating A-Shell under Unix will execute two special customization scripts— pre_ash_install and post_ash_install—if they exist in the custom subdirectory of the specified target directory tree. These allow you to customize the update process, perhaps saving, renaming, or removing certain commands or files, etc. See the sample 

A-Shell Reference 

Page 49 

scripts included with the release for further notes and examples. 

## **Multiple Installations** 

It is possible to install A-Shell several times on a single machine, in different paths, which enables entirely separate A-Shell environments. While this is generally not recommended for end-users, who are typically running A-Shell as a single-purpose application, multiple environments can be very useful for developers and resellers for a variety of purposes: development versus production systems, duplicating customers' systems, etc. The recommended directory structure is to have all virtual machines located in the \VM or /vm directory. Each A-Shell installation would live one directory level below this identified by its machine name and the MIAME environment variable pointing to this subdirectory. It is recommended that the first A-Shell installation on a machine be made in the default directory \VM\MIAME or /vm/miame. 

## **Hardware and Performance** 

The days of agonizing over how to spend your limited hardware budget in order to get acceptable performance are pretty much over. Modern computers are so powerful and so fast that all A-Shell applications, with very few exceptions, will run at nearly unbelievable speeds. However, there are still some basic principles to consider when deciding on how to deploy and configure a multi-user system for best performance: 

## **Operating System** 

Linux is generally much faster than Windows, especially in the area of multi-user disk I/O. It also requires a lot less memory per user. At the opposite extreme is the Windows peer-to-peer ("P2P") LAN environment, where file sharing can get bogged down in network communication between multiple PCs. If you don't have a lot of disk I/O involving simultaneous access to shared files, a P2P LAN is probably the simplest and most familiar Windows configuration, especially for those who already have such a LAN in place. Somewhere in the middle would be a Windows server configuration where the workstations are just running as terminals (i.e. connected via RDP or ATE/telnet), in which case you eliminate the network/file sharing overhead. 

A-Shell Reference 

Page 50 

## **CPU** 

For multi-user systems, the more CPU cores, the better. A-Shell applications are rarely limited in speed by CPU issues, so this isn't a major consideration. 

## **Memory** 

Most A-Shell applications are quite comfortable with less than 20MB per user, which is quite small by modern standards. That said, all operating systems will benefit from lots of extra memory for disk cache and other internal uses. 

## **Disk Drives** 

SCSI is far faster than SATA or IDE, even in a virtual hardware environment. Since most A-Shell applications will be limited in speed by disk access times rather than CPU performance, this is probably one of the most important considerations. On the other hand, most modern disk drives are very fast, especially SSDs. 

## **Directories** 

An often overlooked consideration is how many files you allow to accumulate in a single directory. With huge disk capacities, you may be tempted to accumulate years worth of report files. However, a better approach is to move those files to archive directories so the active directories don't have to deal with overhead of scanning over thousands of files for every file lookup. A good rule of thumb is to keep the number of files in any active directory below 1000. 

## **More Information** 

Given the pace of change in the computer hardware environment, the information presented above may be accurate or - hopelessly out of date. For more information and the latest discussions on this subject, see the relevant discussions on the A Shell forum. 

A-Shell Reference 

Page 51 

## **WINDOWS INSTALLATION** 

For purposes of A-Shell installation there are basically three types of Windows environments: 

- Single users 

- Local area networks (LANs) of modest size. 

- Other networks: this broad category includes large LANs, WANs, networks with remote users, networks where multi-user 

- access and/or network traffic are significant concerns, and every other network situation that is other than the two simple environments mentioned above. See Windows Performance for more information. 

## **Single User Installation** 

A-Shell/Windows is normally downloaded from the MicroSabio web site and installed on a PC like any other Windows program. To install, follow the normal Windows software installation procedure—that is, download the appropriate Windows installation program from the MicroSabio downloads page and then run program, following the prompts and answering the questions. The - installation procedure will optionally create a shortcut for Launching A Shell, and you're off and running. The final step is to run A-Shell, go to _Help...Check for Updates_ , and install the latest version of the software. 

## **Subtopics** 

- Windows Network Installation 

- Files and Registration 

- Installation Problems 

- Machine Names 

- Drive Mapping 

- Windows Printers 

- Windows Performance 

A-Shell Reference 

Page 52 

## **WINDOWS NETWORK INSTALLATION** 

Most Windows instances of A-Shell are installed into relatively small local area networks, with or without a central file server. If this is your situation, then you're in the right place. If your network situation is more complex, see Windows Performance. 

Note that "server" as used in the following discussion does not mean "dedicated Windows Small Business Server" or any other centralized computer upon which the other computers in the network are dependent. It simply means "the place where A-Shell data files and programs are located." This CAN be a dedicated file server, but it can also be just one of the regular PCs on the network that has been designated as the location of the A-Shell data and programs. 

The objectives in a typical Windows installation of A-Shell are simple and straightforward: 

- Have a shortcut or start-menu item on each PC so that the user can quickly and easily get A-Shell running 

- Load application data and programs on a server so they are accessible by all PCs running A-Shell 

- Create an environment for easy, manageable and coherent A-Shell updates in the future 

The shortcut that executes A-Shell can retrieve the A-Shell program from either the local PC or the server. Which is better? Well, that depends. 

- Do you have an old / tired / slow network, such that you do everything possible to minimize "get from server" calls? Then 

- putting A-Shell on the local PCs makes more sense. 

- Do you have a modern, 100-MB (or faster) network where everything is always loaded off the server? Then put A-Shell on the 

- server too. 

- When it comes time to update A-Shell, do you want each individual PC user to update at her convenience, and to make her 

- own decision to update? If yes, then install A-Shell on the individual PCs. 

- Do you want to control future updates of A-Shell from a central location—which requires making everybody on the network 

- stop using A-Shell so you can update? If yes, then put A-Shell on the server. 

As you can see, there are variables involved—and there is no right or wrong way to do this. 

## **Subtopics** 

- Recommended Steps 

A-Shell Reference 

Page 53 

- Alternative Steps 

A-Shell Reference 

Page 54 

## **RECOMMENDED STEPS** 

In most cases, and in the absence of information suggesting otherwise, MicroSabio recommends that the A-Shell installation program be run FROM EACH of the PCs that will be running A-Shell. While this seems a little redundant, and is in fact a little redundant, there are reasons for doing it this way. So here are the recommended steps: 

- 1 Create the folder on the server where A-Shell is to be installed. You can use any name you want, but MicroSabio recommends —for historical purposes and the sake of consistency—the folder "VM." You also need to create a network share, which should also be named "VM." Note: DO NOT share the entire c:\ drive; this is guaranteed to create headaches. 

- 2 Working on one of the workstation PCs (not the server), download the applicable version of A-Shell for Windows from the MicroSabio downloads page. 

3 From the workstation, install A-Shell by running the installation program. When asked for the location into which to install A- Shell, enter: \\servername\VM\miame. As you will see the \vm\miame\ part is already included; just replace c:\ with \ \servername\. 

- 4 Finish running the installation program. 

5 Run A-Shell to confirm that all is well. A few LOG and DIR commands is enough. What we're confirming is that the desktop shortcut you created actually executes A-Shell as intended, and that miame.ini—A-Shell's initialization file—is being found and processed. Don't proceed until you're happy and convinced that all is working, by which we mean that you click on the desktop shortcut and A-Shell runs as expected. 

At this point, the workstation you've been working on should be perfectly set up for A-Shell, and you know how to run the installation procedure. Now go run it again—the same steps, starting with #2 above—on each of the PCs that will be using A- Shell. 

It would appear that you are installing the same software into the same location multiple times. That is actually true. But the installation program is smart and knows to not actually copy files that are already present and up to date, and the installation is being rerun not for the A-Shell files but for Windows files over which A-Shell has no control. Subsequent installations will be much faster than the first one, and at the end of the process each PC will be properly and completely set up. 

The final step of the process is performed after you have finished installing A-Shell from each of the PCs. It does not matter which PC runs this procedure, but it needs to be done after all the installations. 

A-Shell Reference 

Page 55 

6 While running A-Shell, go to _Help...Check for Updates_ . This will insure that you have the latest copy of A-Shell on the server. Run the installation as you have the other times, and you're done. You only need to run this once, and not from each PC. 

Note that you must not run A-Shell from any one PC while you are installing from another PC. 

Also note that despite the multiple installations, all the PCs are running off the same server-based copy of A-Shell. 

A-Shell Reference 

Page 56 

## **ALTERNATIVE STEPS** 

It is perfectly fine to install a unique (not shared) copy of A-Shell on each PC, if you think there will be some benefit from that approach. One possible reason for this approach is that you want individual PC users to be in charge of their own updates. Obviously, each user must be running her own copy if she wants her own update. 

When you run the A-Shell installation program, use the default install-to directory of c:\vm\miame. This puts a copy of all the A- Shell files on the local machine, and miame.ini will be configured to run that copy of A-Shell. 

However, you must manually modify the Windows shortcut or start menu command that invokes A-Shell so that it knows to look on the server for the initialization file miame.ini. 

Refer to Installation Problems and the discussions about miame.ini for information on the necessary modifications and, if necessary, troubleshooting steps. 

A-Shell Reference 

Page 57 

## **FILES AND REGISTRATION** 

By default, most Windows programs install themselves in a folder called c:\program files\<company name>\<program name>. A-Shell, by contrast, installs itself in the folder c:\vm\miame, although this can be changed by the user at the time of 

installation. If you need or want to change the installation directory, you can do so without penalty or complication. However, A- Shell uses its unconventional installation directory tree for historical and functional reasons, and you should make sure you know what you're doing before changing the installation folder. This is especially true if other people or computers are involved in your A-Shell environment. 

As noted above, A-Shell stores its primary configuration information in ordinary files within the A-shell directory tree rather than in the Registry. This allows the entire A-Shell system—both application and data—to be backed up, copied, or moved, with ordinary file system commands. A few caveats: 

- ATE uses the Registry to store connection profiles, although they can be exported to and imported from files. 

- A-Shell's main configuration file, miame.ini, contains references to file locations. Depending on whether they are fully 

qualified, or based on environment variables, you may need to adjust them if you move the entire directory tree to another location. 

- User-customized settings, such as initial window size and position, color scheme, etc., may be saved via File > Save Settings 

- either within the main A-Shell directory tree or in the Windows standard user-specific %APPDATA% directory. These are not critical and can easily be re-customized, but should be noted if you want to make a complete backup or move. 

- A-Shell and ATE both use the Registry to save user interface history information, such as XTREE configurations, last printer 

- selected, last dialog positions, etc. Again, these are not critical to operation. 

- One or more external COM DLLs may get registered with Windows during installation. These registrations would be broken by 

- relocation of the directory tree; the simplest remedy for that would be to re-run the installer/updater pointing to the new location. 

A-Shell may be installed multiple times on a PC. If it is installed in different folders, and you can keep the start-up icons and commands separate, then different versions of A-Shell can exist and run on the PC without problem. If you install a new version over the top of an old one (i.e., into the directory where A-Shell already exists), then obviously the old program files will be overwritten with the new ones. Note, however, than none of the configuration files will be overwritten, and all of your previous settings and values—including anything written onto A-Shell disks and other devices—will be preserved. 

A-Shell Reference 

Page 58 

## **Subtopics** 

- File Locations 

A-Shell Reference 

Page 59 

## **FILE LOCATIONS** 

When you use Windows File Explorer to look at the A-Shell "tree," you should see something like this. In this case, the base or root A-Shell folder is called "Ashell." 

## **- A Shell Root Folder** 

As mentioned elsewhere, A-Shell can be installed in a location of your choosing or in the default folder of c:\vm\miame. This folder contains three critical and several miscellaneous files. The critical ones are: 

|**Filename**|**Contents / Usage**|
|---|---|
|coname.dat|Name of licensee.|
|miame.ini|System configuration file which sets critical parameters for the overall<br>operations of A-Shell. Also includes license code which, along with coname.dat,<br>enables the non-demo operation of A-Shell.|
|ashlog.log|A-Shell log file. SeeASHLOG<br> for more details.|



## **backup** 

Like most Windows programs, A-Shell uses a third-party program to handle the install and uninstall operations. The files in this folder were created by the installation program, and are copies of all the files that have been overwritten in previous updates. If and when you either revert to a previous version of A-Shell or uninstall A-Shell, the installation program will read this folder to determine which files should or should not be overwritten or uninstalled. 

**bin** 

A-Shell Reference 

Page 60 

This folder, "binaries," contains the programs and program libraries that Windows executes when running A-Shell. A-Shell itself is contained entirely in the program file ashw32.exe. The folder contains several other programs (.exe files) that are, or may be, used in conjunction with A-Shell. The DLL (dynamic linked library) files execute various special functions within A-Shell. A-Shell will work fine without the DLLs—until you try to use the function in A-Shell that needs a particular DLL. 

## **cache** 

see below 

## **doc** 

This folder contains a file called ashelp.mdf, which means "A-Shell help menu definition file." See Help Menu Links on how to modify this file and change the look and function of the A-Shell help menu. The folder also may have a readme.txt file. 

## **dsk0** 

This folder contains all of the DSK0: PPNs you have on your A-Shell system, with each PPN being its own Windows folder. The PPN DSK0:[2,2], for example, is a folder in Windows called, using the example from above, c:\ashell\dsk0\002002. 

If you use SYSACT to create a PPN in A-Shell, say [40,40], then a new folder will show up in dsk0 called c:\ashell\dsk0\040040. If you create a new folder using File Explorer, c:\ashell\dsk0\033033 for example, then a PPN DSK0:[33,33] will show up in your A- Shell environment. 

## **icons** 

This folder contains all of the icons used in A-Shell. 

## **cache, permcache** 

These folders (a) are used by ATE but not by A-Shell, but (b) frequently show up in the A-Shell folder due to an overlap between ATE and A-Shell. If you see them in your A-Shell tree, they can be either deleted or ignored with no ill effects. 

A-Shell Reference 

Page 61 

## **INSTALLATION PROBLEMS** 

There is very little that can go wrong during a Windows installation of A-Shell, and it is likely that if something does go wrong, the problem is related to something unexpected done by the installer. Unless there were some problems during the installation process itself, and the files A-Shell requires in order to run were not actually installed on the PC, there are basically two places to look for problems. 

## **Config File** 

- First, make sure you understand the A Shell Configuration File and how it works. If A-Shell does not start up properly, it is likely that some file specification in miame.ini is pointing at a wrong or non-existent location, or a required command in the ini file is mis-formatted or misspelledd. 

## **Start Command** 

Secondly, check the Windows start command (shortcut) that is invoking A-Shell. The command line should have two parts, as shown below. Note that if the path in which A-Shell was installed includes spaces (like "Program Files"), then the file specs on the target line will (and must) have quotes around them. 

- The first part of the command line specifies the file specification of the program to run—i.e., A-Shell. The program and file 

- name is ashw32.exe and it should be at the end of a file specification that begins with "c:\...." If A-Shell was installed in the c: \vm\miame folder, for example, the first part of the target command should look like this: 

## `C:\vm\miame\bin\ASHW32.exe` 

- The second part of the target line, which begins after the first part and a space, should begin with "-i" and be followed by a 

- space and the full file specification for the A-Shell initialization file (normally "miame.ini"). If A-Shell were installed as above, then the second part of the target line would look like this: 

- `-i C:\vm\miame\miame.ini` 

If A-Shell were installed in the C:\Program Files\MicroSabio\Ashell folder, the full command line should look like this: 

- `"C:\Program Files\MicroSabio\Ashell\bin\ASHW32.exe" -i "c:\program files\microsabio\ashell\miame.ini"` 

The "Start In" specification of the A-Shell shortcut should be blank. 

A-Shell Reference 

Page 62 

See the following for specific problems that you may encounter. 

## u **Missing or Invalid MIAME** 

If you see this error, it is because A-Shell is trying to run but cannot find or process the required initialization file (normally "miame.ini"). This would normally indicate that the "-i <ini file spec>" argument on the launch command line is missing or incorrect. See Specify Ini File for related information. 

A similar and related error message for a missing ini file is shown below. This normally occurs if A-Shell has previously been set up properly and has run as expected, but the ini file has been moved or renamed. 

## u **Cannot INIT DSK0** 

This error (below) normally occurs when the statement in your miame.ini file that specifies the location of DSK0: is entirely missing. The three lines below show what happens as A-Shell tries to execute A-Shell's default startup command, ASTART, and there is no DSK0: on which to find that file. Solving this problem should be easy; simply add the DEVICE statement in miame.ini, or perhaps remove the semicolon in front of it that is turning it into an inactive command (i.e., a comment). 

```
?Cannot INIT DSK0:ASTART.CMD[2,2] - device does not exist
```

```
?Cannot INIT DSK0:ASTART.DO[2,2] - device does not exist
```

```
?Cannot INIT DSK0:ASTART.LIT[2,2] - device does not exist
```

A properly formatted statement in miame.ini for defining DSK0: would look like either of these: 

```
DEVICE=DSK0 "c:\program files\microsabio\ashell\DSK0\"        ; Pathname for DSK0:
```

A-Shell Reference 

Page 63 

```
DEVICE=DSK0 c:vm\miame\dsk0\
```

## u **Command Will Not Execute** 

If you get a screen like the one shown here, it normally means that your `DEVICE=DSK0:` statement is present but invalid. The problem is likely a misspelling or bad punctuation. Remember that paths with spaces in them must be quoted. 

A-Shell Reference 

Page 64 

## **MACHINE NAMES** 

_Rewritten April 2015_ 

In a peer-to-peer (P2P) network environment, A-Shell/Windows uses the computer name to establish a unique ID for each session. The computer name is sometimes referred to as the Machine Name and can be found and set in the My Computer System Properties dialog. It is critical that each workstation on the network has a unique Computer Name, although it is unfortunately common for installers to overlook this step when installing new machines. 

When a new A-Shell session is launched, it scans the job table to see if there is an existing record for this machine/instance, and if so, it assumes that the prior session was terminated uncleanly, such as by rebooting the PC, and re-uses that same JOB table record so as to avoid accumulating orphaned JOB table entries. If there are multiple machines with the same name, A-Shell will be fooled into thinking that a new and distinct session is actually a restart of a previously aborted one, causing the earlier session's JOB table record to be overwritten. This is likely to lead to the first session aborting with a cryptic "your job table has been zapped" message. Outside of A-Shell, the duplicate computer names will cause a variety of other problems that are best avoided. 

To help identify this error before it becomes a more serious problem, A-Shell (see History, below) generates its own unique identifiers for each machine during installation; it can then use that information to identify duplicate machine names when new sessions are launched, thus allowing the problem to be detected and resolved right away. In order for this to work, you must run the installer/updater to update each workstation, rather than manually installing the update by copying files. 

The installer/updater establishes a unique identifier for each machine and saves it in the HKLM section of the registry, to be used to determine whether an instance with the same machine name as an existing instance is actually the same machine or not. If so, then the new instance can safely overwrite the old one. But if not, an error message is displayed and the new session is not allowed to start. 

The error message will indicate the machine name, the user name and JOB name of the offending existing instance, and the unique identifiers (8 hex digits) for the two machines. You can use the `SYSTAT/CU` switch to display the unique identifiers for existing sessions, which may be helpful in tracking down the offending duplicate-named machine. 

Also note that the issue only affects P2P networks; ATE, Terminal Server, and Unix systems are not subject to the problem and are not affected by the update. 

## **History** 

A-Shell Reference 

Page 65 

- 2015 April, A Shell 6.1.1408:  A-Shell now detects duplicate machine names. 

A-Shell Reference 

Page 66 

## **DRIVE MAPPING** 

_Updated April 2022_ 

The astute reader will have noticed that we rather glossed over the issue of drive mappings in the preceding discussion. Indeed, the essence of a network installation is setting up drive mappings so that each workstation can reference shared directories on the server. It is assumed that the installer will have enough expertise to create those drive mappings using the standard Windows procedures. However, there are a couple of subtleties worth mentioning here. 

First, the server must "share" the drive that will hold the files common to all of the workstations. This much is obvious. However, although it may be desirable, it is not absolutely necessary that the workstations actually create a drive mapping to it. Instead, you can use the UNC (Universal Naming Convention) notation to reference the server and share name instead of the mapped drive letter. For example, assuming the server’s machine ID is "BIGBOY", and A-Shell is installed in the directory C:\VM\MIAME, you might share that directory as "MIAME" and then refer to it from all machines on the LAN in various contexts, including the install program, as \\BIGBOY\MIAME. 

This technique has the advantage of eliminating the need to define a drive mapping to the server for every workstation, and eliminates any possibility of different workstations ending up with different mapped drive letters. If you decide to use the more traditional mapped drive letter approach, it is strongly recommended that you choose a relatively high drive letter (like X:) to reduce the possibility that you run into a workstation that has so many devices mapped that the desired letter is already taken up. 

The only known disadvantages to using the UNC name of the server rather than creating a drive mapping are that you may experience a delay the first time you try to connect —while a dynamic network connection is established—and in some cases, such as after a period of inactivity, some servers may begin to drop UNC connections. This could cause a problem if the inactive application had files open. 

Another subtlety to note is that since data transfer over the network is subject to bottlenecks, it is often desirable for performance reasons to define one or more devices (logical disks) that reside on each local workstation for the purpose of holding print files, temp files, that don’t need to be shared. This assumes that the application provides an option of where to send different categories of files, such as DSK1: for the master data files, DSK2: for print files, etc. 

Note that whenever sharing directories, it is strongly advised—for both performance and security reasons—to share the smallest directory tree that includes all the necessary subdirectories. In other words, instead of sharing the entire C: drive, share the directory that contains miame.ini and the DEVICE directories beneath it. 

A-Shell Reference 

Page 67 

## **WINDOWS PRINTERS** 

Like all other versions of A-Shell, A-Shell/Windows uses the PRINTER command line in miame.ini to define the default spooler name. This name, in turn, is usually associated with a configuration file for that printer, called sys:<spoolername>.ini or ashcfg:<spoolername>.pqi, the contents of which are discussed in detail in Printer Configuration in this document. The main aspect of printer configuration to be dealt with at this point is simply to identify the printers which will be used by the application, and to install and configure the necessary drivers so that each workstation can refer to each printer by a common descriptive (i.e. "Invoice Printer #1") or network (i.e. \\prtsrv\invoice1) name. This name will then be associated with the spooler name via the DEVICE statement in the spooler configuration file. 

In most cases, it is no longer necessary to manually install a local printer driver for network printers, provided they can be accessed via the \\machine\sharename. 

Applications that embed their own ESC sequences into print files for the purpose of controlling printer functions (e.g. condensed print), may need to use a printing mode called "PASSTHROUGH" printing. PASSTHROUGH printing is somewhat unusual in the mainstream world of Windows, and thus many printer drivers (and in some cases the printers themselves) do not support it. If uncertain, you can always use the Generic Text Only printer driver (provided the printer hardware supports it – try the driver Test page to confirm that.) Refer to Printer Configuration for more details about PASSTHROUGH vs. non-PASSTHROUGH printing. 

A-Shell Reference 

Page 68 

## **WINDOWS PERFORMANCE** 

_Added April 2022_ 

Here are some tips to help you maximize A-Shell performance in a Windows environment: 

- If your network is large, containing many PC's and applications unrelated to A-Shell, try to reduce traffic hitting the A-Shell 

- server by putting it on it's own subnet, if possible. 

- File sharing is quite efficient for read-only and text files, but not so much for record-oriented files, since each record-level 

- access may require querying many other PCs to see if they have an updated version of the record. To minimize that problem, if practical, open files only when you are actively using them, as opposed to opening all the files at the start of the program and closing them all at the end. 

- Applications that implement file locking using XLOCK or FLOCK, rather than READL (i.e. LOKSER protocol), may run faster 

- using the 'C' version of A-Shell. 

- Using a domain (with all users signed into it) results in more efficient and secure LAN performance than informal P2P 

- networks. 

- For files that don't need to be shared—print files, sort files, etc.—it's much faster to put them on each client PC then on the 

- shared server. Typically this is done by defining a DEVICE, e.g. WRK0:, that points to a directory on the C: drive, i.e. each client PC's C: drive, rather than on the server, and then use that device for the appropriate class of files. 

- If the LAN access becomes too slow, or especially if some clients connect over a WAN, telnet (ATE/ATSD) connections will be 

- much faster than P2P connections. The standard P2P model offers the best CPU and screen I/O performance, but the worst disk I/O, which is usually the bottleneck. ATE/ATSD connections offer the reverse set of trade-offs. 

A-Shell Reference 

Page 69 

## **UNIX INSTALLATION** 

_Reviewed and revised July 2020_ 

A-Shell/Unix releases are binary specific for a particular machine and architecture. However, the procedure is pretty much the same, regardless of the flavor of Linux / Unix. Where there are important differences, they will be noted. 

Note that the document uses the term "Unix" to mean "Unix, AIX, HPUX, Linux and all Unix-variants." We of course recognize the differences between the operating systems. But because they all work about the same with regard to A-Shell, and the A-Shell commands are the same for the entirely family, we've chosen to use "Unix" as the family name. 

A-Shell/Unix is downloaded from our web site in the form of one or more "cpio" files, typically named ash-###-???.bin, where "ash" indicates "A-Shell," ### indicates the version and build number, and ??? indicates the target platform. The file name ash-6.5.1676.7-el5.bin, for example, indicates A-Shell version 6.5, build 1676.7, for Enterprise Linux version 5. Often the file will have an additional extension, either Z or tz, in which case it first needs to be uncompressed, using `uncompress <file>.Z` or `tar xvzf <file>.tz` . 

To install the A-Shell software, copy the cpio file to a convenient location, such as /tmp, and log into Unix using your normal user id. _Do not log in as the superuser (root)_ . Then enter the following: 

```
$ cd /tmp
```

```
$ su
```

```
[Enter root's password if requested]
```

In the examples below, we assume you are installing from a cpio file, with an A-Shell build number of 827. For the installation from a file, replace the same filename given below with the actual one you downloaded. 

## **For Linux** 

```
# cd /tmp
```

```
# cpio -iuB ash_install < /tmp/ash-6.5.1663.0-el7.bin
```

A-Shell Reference 

Page 70 

## **For AIX:** 

```
# cd /tmp
```

```
# uncompress ash-xxxxx.bin.Z                                 (if .Z extension only)
```

```
# cpio -icuB ash_install < /tmp/ash-xxxxx.bin
```

## **Then, for all platforms:** 

```
# chmod +x ash_install
```

```
# ./ash_install
```

```
# exit
```

The ash_install script will prompt you for the directory location for the object and runtime files (we suggest /vm/miame for both) and for the name of the file or device you are installing from (which will be the same as the one you extracted the ash_install script from above.) 

The ASH_INSTALL script will execute two special customization scripts (PRE_ASH_INSTALL and POST_ASH_INSTALL) if they exist in the custom subdirectory of the specified target (object) directory tree. These allow you to customize the update process, perhaps saving, renaming, or removing certain commands or files, etc. See the sample scripts included with the release for further notes and examples. 

The process will only take a couple of minutes. At the end, it will remind you to set up your MIAME and PATH environment variables and edit miame.ini as needed. 

## **Subtopics** 

- UNIX Downloads 

- File Ownership and Privileges 

A-Shell Reference 

Page 71 

- Advanced Privilege Settings 

- Setting Up UNIX Logins 

- Modifying the User .Profile 

- Backspace Key Operation 

- Enabling the Use of KILL.LIT 

A-Shell Reference 

Page 72 

## **UNIX DOWNLOADS** 

_Reviewed July 2020_ 

This page explains some of the finer points of selecting and downloading A-Shell for Linux and AIX. Here the number and variety of packages is such that rather than providing direct links to each of them, which would require constant synchronizing/updating of the web page with the download directories, we instead allow you to browse the download directory tree directly. All file names in those directories follow a common naming convention: 

```
prod-#.#.####.#-platform{-options}.pkgtype
```

For example: 

```
ash-6.2.1548.1-el7-efs.bin
```

## **Filename Components** 

## _prod_ 

A-Shell product or module: 

|**prod**|**A-Shell Software Product**|
|---|---|
|ash|A-Shell|
|vue|VUE|
|compil|Compiler|
|psh|P-Shell|
|ate|A-Shell Terminal Emulator|



A-Shell Reference 

Page 73 

**prod A-Shell Software Product** 

## _#.#.####.#_ 

is the full version number; for example, 6.4.1548.2 

## _platform_ 

target platform and version: 

|**platfor**<br>**m**|**Operating System**|
|---|---|
|el5|RHEL5/CentOS5|
|el6|RHEL6/CentOS6|
|el7|RHEL7/CentOS7|
|el8|RHEL8/CentOS8|
|aix|AIX 4.3+|



A-Shell Reference 

Page 74 

|**platfor**<br>**m**|**Operating System**|**Operating System**|
|---|---|---|
|aix53+|AIX 5.3+||
|pi|Raspbian (|Raspberry Pi<br>)|



## _options_ 

specific additional features or variations: 

|**options**|**A-Shell Software Product**|
|---|---|
|efs|Encrypted File System|
|tw|Triad / WrenchHead Catalog|
|upd|File contains just an update/replacement of main executable|



## _pkgtype_ 

type (file format) of the package: 

A-Shell Reference 

Page 75 

|**pkgtype **|**A-Shell Software Product**|
|---|---|
|bin|Complete release in CPIO format; see the previous page for unpacking instructions.|
|tz|Compressed tar file, typically containing just the main executable; unpack with**tar -xvzf****_file_**.|
|tar.Z|Alternate form of compressed tar; unpack with**uncompress****_file_.Z**then**tar -xvf****_file_**|



## **32 vs 64 Bit** 

All A-Shell binaries are 32 bit and are fully compatible with both 32 and 64 bit Linux and AIX operating systems, so there is no need to identify this in the package names. The only issue relating to 32/64 bit that often arises in the Linux world relates to the availability of certain auxiliary libraries that A-Shell may seek to dynamically load in order to support a particular feature. Since the 32 and 64 bit libraries are installed into separate directories, you may be confused into thinking that the library you need (e.g. libncurses or glibc or libpcre) is installed, when only the 64 bit version is installed. The solution to this kind of problem is - just to manually install the necessary library, explicitly specifying the 32 bit (typically "i686") version. See the A Shell forum for questions and answers in this area. 

## **Linux Distributions and Versions** 

Although the A-Shell source is compatible with and therefore can be made available for a wide range of the most popular Linux distributions and versions, the same cannot be said for the binary executables. So it is important to select the right binary download for your distribution/version. For whatever reasons, the A-Shell user base has overwhelmingly favored the RHEL (commercial) and CentOS (open source) distributions, so those are the environments on which A-Shell is focused. Conveniently, both use the same version number sequences, and in fact are effectively equivalent as far as A-Shell is concerned, so they are referred to as using the common platform abbreviation **-el#** (e.g. -el7 for RHEL7 / CentOS7). If you don't see the version number you are looking for, then use the next lower one—e.g. if a CentOS 6 download is not available, use the CentOS 5 download instead. The A-Shell binaries can be assumed to be upward compatible unless specifically noted to the contrary. 

A-Shell Reference 

Page 76 

For other Linux distributions, such as Ubuntu, contact MicroSabio to arrange for a new binary to be built. Or, consider Docker ... 

## **Docker** 

A public Docker image for A-Shell is compiled/bundled for CentOS 7 which, if your OS supports Docker, may simplify the process of installing A-Shell together with the necessary compatible components. To access and download the available images, use the - command **docker search microsabio** . Search for "docker" on the A Shell forum for helpful information on working with the A- Shell Docker container. 

## **AIX** 

In the AIX world, there is a major division between versions up thru 5.2, and versions 5.3 and beyond. Because this involves both hardware and operating system compatibility factors, and because AIX 5.3 was released long ago (2004), earlier versions are no longer supported. For customers still running an old AIX box which they cannot upgrade to a newer version because of hardware or budgetary limitations, we can only suggest considering a sideways move to Linux. Or remain on A-Shell 6.0. The same A-Shell 6.2 or 6.4 binary will work with all versions of AIX from 5.3 and beyond. 

## **Version Numbers and Links** 

A-Shell is continually evolving. Since it is not possible to offer software packages that simultaneously 

- have all the latest new features including, possibly, some as-yet-undetected bugs 

and 

- are entirely bug-free and the beneficiary of extensive testing 

MicroSabio therefore offers A-Shell in two forms, as indicated by the version number: 

- An even numbered version of A-Shell is stable. No changes are being made to the software other than bug fixes. 

- An odd numbered version of A-Shell is a development version. The most recent version (i.e. highest number) is under active 

- development—i.e., it is being updated regularly, which normally means every few days and in some cases more than once a day. 

- The two most recent versions—i.e., highest numbers—are one of each: a stable version and a development version. The A Shell download folders provide several recent versions of both development and stable versions. 

A-Shell Reference 

Page 77 

## **FILE OWNERSHIP AND PRIVILEGES** 

After completing the script, and before proceeding to the configuration steps below, you may need to adjust the ownership and access privileges for the files and directories installed. The script sets the group ownership to group 100, which may not be appropriate for your system. Consult your operating system documentation for the CHGRP, CHMOD, and CHOWN commands for details. 

A good starting point would be to create a user group (e.g. "ashell" or perhaps the name of your application) and add all applicable users to that group. Then assign the entire A-Shell directory system to that group. Assuming you installed in /vm/miame, you could do this under most Unix flavors as follows: 

```
# cd /vm/miame
```

```
# chgrp –R ashell *
```

The above commands would assign every file in the entire directory tree starting from /vm/miame to the ashell group. You could then provide unlimited access to all files for all members of that group, as well as the actual file owner, very simply with the following commands: 

```
# cd /vm/miame
```

```
# chmod –R ug+rwx *
```

This sets the read, write, and execute flags for both the owner and group for all files in all subdirectories starting from the /vm/miame. 

If you are concerned about unauthorized users having the ability to overwrite important parts of the A-Shell installation, then you should set up a special user (or root) to be the owner of all the files distributed as part of A-Shell, and then allow only that user to have write privileges for those files. As an example, you might protect the files in the /vm/miame/bin and /vm/miame/dsk0/001004 directories as follows: 

```
(while logged in as root)
```

A-Shell Reference 

Page 78 

```
# cd /vm/miame
```

```
# chown –R root *
```

```
# chmod 750 bin/*
# chmod 640 dsk0/001004/*
```

For all the files in the /vm/miame/bin directory (where the ashell executables normally are,) the above commands would allow read/write/execute access to the root user, read/execute to users in the ashell group, and no access to other users. The idea is similar for the /vm/miame/dsk0/001004 (aka SYS: or DSK0:[1,4]) directory, except that those files don’t need the execute bit, since they are never really executed by Unix. Instead, they are handled like data by the A-Shell interpreter. 

Use the Unix ls –l command to verify the correct settings, which might look something like this: 

```
# cd /vm/miame/bin
```

```
# ls –l
```

```
-rwxr-x---   1 root     ashell    827127 Jan 31 17:06 ashell
```

```
#
```

```
# cd /vm/miame/dsk0
```

```
# ls –l
```

```
drwxr-s---   2 root     ashell       512 Jan 31 17:27 001002
drwxr-s---   2 root     ashell      2048 Feb  2 11:47 001004
drwxr-s---   2 root     ashell       512 Aug 12 02:41 001006
drwxr-s---   2 root     ashell       512 Jan 31 17:17 002002
drwxr-s---   2 root     ashell       512 Jan 21 15:29 007000
drwxr-s---   2 root     ashell      2560 Jan 31 17:19 007006
```

A-Shell Reference 

Page 79 

```
#
```

```
# cd 001004
```

```
# ls –l
```

```
-rw-r-----   1 root     ashell      2474 Jan 31 17:03 time.lit
```

```
-rw-r-----   1 root     ashell      3024 Jan 31 17:03 type.lit
```

```
-rw-r-----   1 root     ashell      2396 Jan 31 17:03 ver.lit
```

```
<etc>
```

```
#
```

If you have files in a lot of directories (corresponding to many PPNs) you can use the –R (recursive) switch to chmod as follows to act on all of the subdirectories at once: 

```
# cd /vm/miame/dsk0
```

```
# chmod –R 640 *
```

```
# chmod 750 *
```

The first CHMOD command above would set read/write privileges for the owner and read privileges for users in the **ashell** group for all files in all subdirectories of /vm/miame/dsk0. (The –R switch causes the command to descend the directory tree recursively.) The second CHMOD command then adds the execute flag to all of the files in the /vm/miame/dsk0 directory, since these files are actually directories, and directories must have the execute flag set. 

**Warning:** Under most Unix implementations, the execute flag must be set in all directories in order for users to be able to access those directories. Thus while the execute flag is not needed for most A-Shell files, such as *.RUN, *.LIT, and *.DAT, it is essential for the directories themselves. 

A-Shell Reference 

Page 80 

**Another warning:** Shared data files in your application must offer read and write access to all users, so it would probably be unwise to limit write privileges to the file owner for such files. Putting your *.RUN files (which don’t need to be written to by all users) in a separate PPN (e.g. [p,0]) from your data files would make it easier to fine tune the access privileges at the directory level rather than the file level. 

If you don’t care at all about security, and it doesn’t bother you if certain files have their executable flag set even though they are not really executables, then you can just set all the read/write/execute flags for all of the files as follows: 

```
# cd /vm/miame
```

```
# chmod –R 777 *
```

In this case, the owner and group attributes don’t matter, since everyone is allowed all types of access. 

Most versions of the chmod command support a syntax for adding or removing privileges, without having to replace the current privileges with a single specified value set. For example, `chmod –R a+rw *` would add the rw privilege bits (for all three levels – user, group, other) to all files in the current directory tree, without removing the x privilege bit from any files or directories that already have it set. Replacing the "a" with some combination of "u" (user/owner), "g" (group), and "o" (other) would limit the effect to the specified categories. Also, replacing the "+" with a "-" would remove rather than add the privilege bits. 

A-Shell Reference 

Page 81 

## **ADVANCED PRIVILEGE SETTINGS** 

Aside from the privilege considerations discussed above, there are a couple of more advanced settings that you will need to consider, and if desired, carry out manually in order to enable certain auxiliary utility operations such as CHAT, SEND, KILL, and LOKUTL. The basic problem is that unlike AMOS, where assembly language commands or subroutines can read from and write to any region of memory, including the monitor and other JOBs’ partitions and control blocks, under Unix it is generally not possible for one JOB to see or affect any other JOB’s private information, nor is it possible to see the kernel’s private memory. There are two general cases to consider here. 

The first is the case of a utility that needs to see or affect another JOB, such as KILL, SEND, or CHAT. To allow this, the sender and receiver must either both be running under the control of the same effective user, or the sender must have root (superuser) privileges. The second case occurs when we need to access kernel information (such as the lock list, or the list of active processes.) In that case, we must have superuser privileges. Since having every user log in as the same user, and especially as the superuser, would defeat all of the safeguards which help make Unix a more reliable operating system than AMOS or Windows, we need a way to temporarily obtain the necessary privileges in a way that is out of the control of individual users to abuse. The SETUID mechanism allows us to do this, by providing a special bit in the directory entry for an executable command which causes the user of that command to assume the privileges of the owner (creator) of the command, but only while executing the command. As an example, the Unix utility ps (process status) uses this technique to allow anyone with sufficient privileges to execute ps to temporarily acquire the superuser privileges necessary to read the kernel’s process table in order to display a list of what every process is doing. 

The A-Shell utilities KILL.LIT, SEND.LIT, and CHAT.LIT fall into the first category of commands described above, since they require that both the sender and receiver either share the same effective user ID, or that the sender be the superuser. Of the two alternatives, we prefer the former, since as a general principal it is wise to limit the use of superuser privileges to the bare minimum. So instead, we can use the SETUID bit to cause everyone that is running under ashell to have effectively the same user privileges. For example: 

```
# cd /vm/miame/bin
```

```
# chown ashusr ashell
```

```
# chmod +s ashell
```

A-Shell Reference 

Page 82 

The above commands, we first make the user **ashusr** be the owner of the **ashell** executable, and then we use the **chmod +s** command to turn on the SETUID bit. Thus all users executing **ashell** will assume the effective identity **ashusr** while they are in A-Shell, and thus then can use SEND, CHAT, and KILL on each other. (You must first create a user called **ashusr** .) Note that this "effective" user ID does not conflict with the login ID, which remains distinct, and which is used in utilities such as SYSTAT to allow you to distinguish the users from each other. 

Because of the dangerous implications of the KILL command, there is another level of safety involved in enabling its use which is described in section following titled "Enabling the Use of KILL." 

The second case of utilities (those that need superuser privileges to access kernel information) are mostly taken care of by the standard operating system installation, and are not of particular to concert to A-Shell. There are a couple of exceptions though, most notably the **lslk** (list locks) utility, which is used by A-Shell’s LOKUTL.LIT (under Unix versions) to access the list of locked files and records. Since this utility comes from a shareware source you may need to manually install it (either in the same directory as the **ashell** executable or somewhere in the PATH) and, if not already done, change the owner to **root** and set the SETUID bit using CHMOD +S as shown below: 

```
# cd /vm/miame/bin
```

```
# chown root lslk
```

```
# chmod +s lslk
```

In most cases, lslk is distributed with and installed by A-Shell, but you may still need to perform the above steps since the ownership and privileges may get overwritten by the steps described in File Ownership and Privileges above. 

Another utility similar to lslk which may be distributed with A-Shell (or obtained from the web) is lsof, which displays a list of open file handles by user. You would also want to set the ownership and privileges for it exactly as for lslk, even though it is not integral to A-Shell. 

A-Shell Reference 

Page 83 

## **SETTING UP UNIX LOGINS** 

The actual technique for setting up Unix logins varies among Unix flavors, and is outside the scope of this document. However, since many A-Shell users are used to a rather casual security atmosphere under AMOS in which there may have been no formal user definitions, it is worth discussing the basic strategies that are available here. 

The simplest strategy is to define a generic user (e.g. "ashusr" or just "user") and let everyone log in as that same user. If this lack of refinement doesn’t bother you, it doesn’t bother A-Shell. The only detrimental side effect is that SYSTAT will not be able to give you any useful clues as to who is who (unless they are all on serial connections and you recognize the port numbers.) It may be possible to overcome that shortcoming by setting the A-Shell user name within A-Shell based on some kind of application logic, but this strategy is not workable if you want to use Unix utilities such as mail, which depend on the user login to establish identities. 

At the opposite extreme is the traditional approach of setting up a separate Unix login for each real user, which offers advantages such as allowing SYSTAT to be able to display each user’s login name. The main down side to defining individual Unix logins is that it can be a lot of administrative work (if you have a lot of users.) However, most flavors of Unix provide some way of simplifying this (e.g. template user profiles, sharing of home directories, etc.) so it generally doesn’t require much more than assigning a login name and password for each user, letting the rest of the settings (group, home directory, shell, etc.) default to the template value. The other main complication with having individual user logins for each user is the security problem of not being able to send signals to each other, but the SETUID trick described in the previous section effectively works around that problem. 

A-Shell Reference 

Page 84 

## **MODIFYING THE USER .PROFILE** 

There are three or four minor modifications that usually need to be made to the .profile ("dot profile" or shell initialization) file for each user to set the necessary environment variables and optionally launch A-Shell automatically after login. All of this can be done interactively from the shell prompt each time a user logs in, but it is much cleaner to make it all happen automatically. 

On the theory that an example is worth more than just an explanation, a typical user .profile (in this case for the Korn shell under AIX) is shown below, with A-Shell modifications, followed by explanations. Note that your .profile will probably be different, but similar. 

```
PATH=/usr/bin:/etc:/usr/sbin:/vm/miame/bin:/usr/ucb:$HOME/bin:
```

```
MIAME=/vm/miame
```

```
TERM=am62a
```

```
export PATH MIAME TERM
```

```
set +o monitor
```

```
ashell main
```

```
exit
```

In the PATH statement, we just added the A-Shell executable directory (/vm/miame/bin), so that users could execute **ashell** (or more importantly, **vue** ) from anywhere. You might argue that this is unnecessary in a turnkey system, since the only time users would ever launch **ashell** is from within this same file, in which case it would make just as much sense to call out the full /vm/miame/bin/ashell path on the last line. Similarly, even if you wanted to use the A-Shell **vue** editor instead of **vi** , you could always put a link to it in a directory that was already in the PATH, such as /usr/bin. However, adding it to the PATH is clearly preferable if you plan to go in and out of A-Shell many times. Note that the delimiter is the colon (:). It can also avoid a lot of confusion if you are having problems launching background sessions with XCALL ASHELL or SUBMIT, and it may be necessary for certain utilities such as KILL and LOKUTL, which in turn execute native Unix commands (ASHKILL and LSLK) which are expected to be in the PATH (and which are typically stored in the same directory as the **ashell** executable.. 

A-Shell Reference 

Page 85 

`MIAME=/vm/miame` defines the environment variable MIAME, which is used by A-Shell to locate miame.ini. Again, you could get by without defining this variable since you can always specify miame.ini on the startup command (e.g. `ashell –i /vm/miame/miame.ini` ) 

TERM=am62a is shown here for those cases where the login script (specifically the TSET command) is not managing to set the TERM variable correctly. If you are using a known terminal type (am62a, am62c, am75, wyse50, hz1500, vt420) then it is essential that the TERM variable get set correctly to one of those names (using the spelling and case as given in the list above.) Otherwise, A-Shell will not recognize your terminal type, and will be forced to use the TERMINFO database, which is at best, not as good. Of course it is less than ideal to hard code your terminal type in your login script—it is much better to have the login routine prompt you—but this at least demonstrates the brute force approach. 

If you want to use the am62a emulation with Unix utilities (such as the vi editor) then you will need to define a TERMINFO entry for it. Since am62a is not a standard Unix terminal type, we provide a TERMINFO source, am62a.tis which you can add to your TERMINFO database with the following command (execute as root from the /vm/miame directory): # tic –v am62a.tis 

The export statement is needed to make the preceding environment variables visible to programs running outside of the shell (such as A-Shell). 

SET +O MONITOR is only needed when you are using PolyShell and a "job control" shell, such as the Korn Shell (ksh) or Born Again Shell (bash). It turns off the shell’s trapping of the job control signals so that PolyShell can use them itself. 

ASHELL MAIN launches A-Shell (assuming it is in the PATH and the MIAME environment variable defines the location of 

miame.ini) and tells it to execute CMD:MAIN (CMD or DO) as a startup command. If that command file brings up your main menu, and you want the user to go directly back to the Unix login prompt when exiting from your main menu, then add a HOST command at the end of your main.cmd file, as shown here: 

```
:R
```

```
LOG DSK1:[20,0]
```

```
RUN MAIN
```

```
HOST
```

A-Shell Reference 

Page 86 

When HOST command is executed, the A-Shell session is terminated, returning execution control to the login profile script, where the next command to execute (based on the example above) is EXIT. This logs you out of Unix. Depending on the connection type, you may then go back into the Unix login prompt, or perhaps your Telnet connection window will close and disappear. 

Another way to force the A-Shell session to terminate after the program completes is to use the –e switch on the A-Shell command line. 

A-Shell Reference 

Page 87 

## **BACKSPACE KEY OPERATION** 

Within A-Shell, the BACKSPACE key on a PC keyboard should work just as you would expect the RUB key to work (backspacespace-backspace.) However, if you work at the Unix prompt with a terminal emulator, you may find that the backspace key terminates the command line. This can be very frustrating. To get the BACKSPACE key to work like you would expect (and to change the interrupt command from BACKSPACE to CTRL+C) try typing the following commands (or adding them to your profile.): 

```
$ stty intr \^C
```

- `$ stty erase \^?` 

- `$ stty echo` 

A-Shell Reference 

Page 88 

## **ENABLING THE USE OF KILL.LIT** 

Because the normal Unix security rules do not permit one process to send signals to another (unless they both belong to the same user or the sender is the superuser), the A-Shell KILL.LIT utility invokes a command called ASHKILL rather than accessing the standard Unix KILL command directly. It is up to you to create the ASHKILL file according to the type of security you want for this potentially dangerous function. In most cases, the thing to do is to make a copy of the standard KILL executable called ASHKILL. (It is typically located in the /usr/bin or /bin directories.) To avoid mixing A-Shell files up with the operating system files, it is recommended that you put ASHKILL in the MIAME bin directory (e.g. /vm/miame/bin). 

If you only want the superuser to be able to use the KILL.LIT command, or if you have already set the SETUID bit on the A-Shell (as described above) so that every A-Shell JOB is effectively owned by the same user, then there is nothing else to do. Otherwise, if you want ordinary users to be able to execute KILL.LIT, then configure ASHKILL to temporarily give the user superuser privileges with the following commands: 

```
$ su root
```

```
<enter root password>
```

```
# cd /vm/miame/bin
```

```
# chown root ashkill
```

```
# chmod +s ashkill
```

## `# exit` 

Another option is to create a script called _ashkill_ that uses more sophisticated logic to decide whether the current user (perhaps on the basis of his logon identity) should be allowed to kill other users. 

A-Shell Reference 

Page 89 

## **AFTER INSTALLATION** 

After the formal installation is complete, as described in the preceding pages, there are a number of miscellaneous configuration and follow-up steps to be performed before the installation can be considered complete. These include reviewing and adjusting the miame.ini file, installing the security key, possibly transferring programs and data from another machine, etc. Instructions for these topics follow. 

## **Subtopics** 

- Modifying MIAME.INI 

- Installing the Security Key 

- Transferring from AMOS 

- Folding Filenames to Lower Case 

- Selecting a Terminal Emulation 

- Running A-Shell 

- Log File Maintenance 

A-Shell Reference 

Page 90 

## **MODIFYING MIAME.INI** 

Before proceeding with installation of the security key, it is a good idea to review miame.ini to make sure that it references the proper local drives and directories. This is particularly necessary for A-Shell/Unix if you didn't install the software in the default directory. Refer to Configuration for more details, paying particular attention to the DEVICE parameter. Attempting to launch A- Shell with references to incorrect or non-existent paths in miame.ini is virtually guaranteed to result in confusion and mysterious symptoms. 

A-Shell Reference 

Page 91 

## **INSTALLING THE SECURITY KEY** 

A-Shell runs in one of two modes: licensed or demonstration. To run in demonstration mode, it is necessary only to install the software and run it; when prompted for the serial number, simply enter "0000." 

To run A-Shell in licensed mode, and thereby avoid the demonstration mode message, you need to enter three data elements: a serial number, a company name, and a security key (also called the "Product Installation Code" or "PIC"). This information is available from MicroSabio or your reseller, and is normally provided when you purchase your original or updated A-Shell license. 

- The serial number is a four-digit number. 

- The company name is not sensitive to case or to punctuation (spaces, hyphens, etc.), but otherwise needs to be entered 

- exactly as provided. 

- The security key (also called a "product installation code", or "PIC") is not case-sensitive, but is sensitive to punctuation and 

- spacing. It is a 29 character string which encodes information about the licensed company name, number of nodes, operating system, and other options such as ATE, PDFX, AXL, etc. The key is made up of numbers and letters only, plus three hyphens. Note: very old versions of A-Shell used a different key format than described here. 

To install or re-install the security key, see the next topic, Updating the License. 

## **Comments** 

The security key is requested the first time A-Shell is invoked. For Unix, this is achieved by typing **ashell** at the host machine command prompt, assuming the necessary Environment Variables were defined. For Windows, you generally launch A-Shell by clicking on the icon. 

The key is stored in miame.ini, and re-validated each time you launch A-Shell. The company name is stored in a file referenced by the CONAME parameter within miame.ini (typically dsk0:coname.dat[1,4].) If either is invalid, it will give you the option of reentering it (which is useful for converting from demo mode to a proper license). 

You can force A-Shell to prompt you for a new key (which is necessary for updating your node license) by using the LICENS command from the dot prompt. 

The company name and security key are intimately related. This means that you cannot change the company name without impacting your A-Shell license. If your firm's name is Smith Jones & Wilson, and then Wilson leaves the firm, you _cannot_ simply 

A-Shell Reference 

Page 92 

change the A-Shell company name so that it now displays Smith & Jones. If you do so, the license will fail and A-Shell will revert to demo mode. If you want to change the company name, you must contact MicroSabio or your reseller. 

Attempting to run more nodes than the key allows will result in a message similar to the following: 

```
?A-Shell 4-node license already in use
```

The number of nodes and all options are noted in the license banner that displays for a few seconds on startup. You can also view detailed information about the license from the dot prompt using the ABOUT command. Under A-Shell/Windows, you can also view similar information on the Help...About dialog box. 

Note that the definition of a "node" is slightly different for different operating systems. For A-Shell/Windows, a node is simply a PC, and any number of windows may be running A-Shell on each PC without using up node licenses. (In the case of Windows Terminal Server and Citrix, A-Shell attempts to determine when multiple A-Shell sessions originate from the same workstation, but this is not always possible.) Under A-Shell/Unix, generally each A-Shell session counts as a separate node. So a PC with a terminal emulator running two sessions over Ethernet for example would use up two node licenses. The exceptions to this are (1) that an A-Shell session can spawn another one with no penalty, and (2) all sessions running underneath a single instance of PolyShell count as a single node for licensing purposes. 

## **Subtopics** 

- Updating the License 

- License Options 

- LICENS Error Codes 

- Troubleshooting Licensing Issues 

- What Expiration Means 

- Other License Matters 

A-Shell Reference 

Page 93 

## **UPDATING THE LICENSE** 

_Revised and Reviewed July 2020_ 

There are several reasons why you might need to update your A-Shell license: increase the numbers of licensed nodes, extend your software maintenance contract through a new date, add options, change company name, or change platforms. In all cases, make sure you have received clear and unambiguous license information before beginning. Having somebody tell you over the phone that the company name is "Smith and Company," for example, is likely to cause problems; is it Smith and Company? Smith & Company? Smith & Co, Inc.? J. SmithCo? It may not make a difference to you or Smith, but it does to A-Shell. 

To update the A-Shell license: 

- Log to the system operator account OPR: 

- Type LICENS followed by the ENTER key. 

There are two things that can happen at this point: either LICENS will run, or it will not, in which case A-Shell displays `?LICENS?` . If LICENS runs, then you need only to follow the prompts and enter your new or updated information. If it does not run, then this means that your version of A-Shell is very old and may no longer be supported; contact Microsabio to investigate. 

If LICENS runs as expected but the license info you enter is declared invalid, see the topics LICENS Error Codes and Troubleshooting Licensing Issues. 

## **Comments** 

The company and license key fields are NOT case-sensitive. 

The "Maintenance Expiration" date will not prevent A-Shell from running unless you update A-Shell beyond your maintenance expiration date. If your expiration date is 15 January 2026, for example, and you install a new version of A-Shell on 16 January 2026 or after, A-Shell will revert to demo mode and require that you get an updated license. The basic rule is, don't update A- Shell unless your current maintenance expiration date is in the future. 

Information about the A-Shell license is also available with the ABOUT command, and from the _Help...About_ menu under A- Shell/Windows. 

A-Shell Reference 

Page 94 

If the existing company name needs to be changed (it was misspelled, firm has a new name, you need to add "Inc.", etc.), you must simultaneously get a new security key from MicroSabio and change the company name on your system. Both the new key and the name company name can be entered by use of the LICENS command. 

A-Shell Reference 

Page 95 

## **LICENSE OPTIONS** 

Here is a complete listing of the options available in A-Shell. In order to be useable, each of these options must be enabled via the product key. 

|**Licens**<br>**e**<br>**Code**|**Full Name of**<br>**Licensed**<br>**Option**|**Description**|
|---|---|---|
|POLY|PolyShell|Permit multiple sessions from a single A-Shell node. Applies only in Unix environments, is<br>meaningless in Windows.|
|ISMA|ISAM-A|Enables the use of the ISAMA (aka d-ISAM, aka ISAM-Plus) file system.|
|ATE|A-Shell Terminal<br>Emulator|Allows telnet-connected PCs to create user sessions on Unix systems. Improves performance in PC<br>networks.|
|ATS|A-Shell Telnet<br>Service Daemon|Implements telnet on PC. Is normally required for terminal connections under Unix, improves<br>performance in PC networks.|
|PDFX|PDFX|Generates and post-processes PDF files.|
|ASQL|ASQL|Provides connectors to SQL databases and thereby bi-directional data exchange with those<br>databases.|
|AXL|A-Shell XLS|Provides a function library with which to read and create XLS/XLSX files—i.e., Excel and other|



A-Shell Reference 

Page 96 

|**Licens**<br>**e**<br>**Code**|**Full Name of**<br>**Licensed**<br>**Option**|**Description**|
|---|---|---|
||Library|spreadsheets.|
|EM|Expiration<br>Message|Causes alerts to pop-up as license expiration date nears.|
|GRP|Group License|Allows the subdivision of an A-Shell license, thereby insuring that a given subgroup of A-Shell users<br>cannot use more than their allocated number of nodes.|
|SNL|Strict Node<br>Licensing|Causes each foreground session to count against the license. Otherwise, sessions from the same PC<br>usually share a node.|
|EFS|Encrypted File<br>System|Provides secure file encryption at a layer "below" programmer control, so programmer doesn't have<br>to deal with encryption issues.|
|CGIX|CGI Exemption|Exempt CGI sessions from the license count, so as to permit a large and unknown number of<br>simultaneous CGI sessions.|



A-Shell Reference 

Page 97 

## **LICENS ERROR CODES** 

When you run the licensing program LICENS to install a new license, the normal and desired result is a final response from the program saying "License Valid!" Given that things don't always work as expected, however, a "License Invalid!" response is not beyond the realm of possibility. If and when this happens, knowing WHY the new license data was rejected can be helpful. The table below shows the meaning of the error codes that may be shown in brackets immediately following the negative message. 

|**Error **|**Description**|
|---|---|
|2|Bad encryption key|
|3|Bad company name|
|4|No node license|
|5|PolyShell not licensed|
|6|Key applies to other platform|
|7|License expired|
|8|EXE date beyond end of maintenance license|
|9|Key in old format|
|10|ATSD not licensed|



A-Shell Reference 

Page 98 

|**Error **|**Description**|
|---|---|
|||
|11|Support use only|
|12|MAC not valid|
|13|Serial number too large, or invalid|



A-Shell Reference 

Page 99 

## **TROUBLESHOOTING LICENSING ISSUES** 

_Reviewed July 2020_ 

The A-Shell license program and process has been in place for many years, and has never been shown to have a problem or to produce invalid results. If you having a problem, it is likely because either you or the person who provided the license has overlooked something. Here are some suggestions for finding the problem. 

## **Confirm your license** 

If you are having trouble with any aspect of A-Shell (including ATE) licensing, the first thing to do it to make sure that your license is and says what you think it is. Use the following steps to check for discrepancies, oddities, unexpected results, etc. 

- Run ABOUT from the prompt. 

- If you are using A-Shell/Windows or ATE, check the _Help...About_ box for confirming info. 

- Run SYSACT from the prompt. 

- Run LICENS from the prompt while _not_ logged in to OPR: 

## **- A Shell Version 6.2.1425** 

In February 2016, the A-Shell license key format was changed to xxxxxxx-xxxxxx-xxxxxx-xxxxxxx (seven characters, two sets of six characters, seven characters). If you are trying to use a key of that format in a version of A-Shell before 6.2.1425, that's the problem; it won't work. Please request another key in the "old" format. The format of the old key, by the way, in characters, is 4-4-3-6-8. Note also that the old style key was all lower case letters, whereas the new style is all capitals. 

## **ATE Issues** 

Run ABOUT from the prompt; it will show the license options for the ATE aux license independently of the main server license. In addition, next to "ATE Licensing:" it will list "Client", "Auxiliary (aux.lic)", AND/OR "Server". If it lists "Client" in addition to one of the other two, that means that the ATE client supplied its own license, even though the server could have done so. (This could be the reason for the confusion between the features included in the server-based license and those in the client-based license.) Also note that in this case, the information displayed will be relative to the aux license, even though that won't necessarily be what the client is actually using. To check what the client is actually using for licensing, see Help > About on the ATE menu bar. 

A-Shell Reference 

Page 100 

If you are using A-Shell/Windows or ATE, check the _Help...About_ box for confirming info. In the case of ATE, near the bottom, after "Additional license information:", it will indicate "(Server supplied)" if the license info came from the server. If it doesn't say that, then the information will be relative to the license which is local to the ATE client. 

A-Shell Reference 

Page 101 

## **WHAT EXPIRATION MEANS** 

_Reviewed July 2020_ 

One of the key data elements of the software license and key is the "maint. expir." date. The "maintenance expiration" date works like this: 

- Regardless of the expiration date, A-Shell will run properly; the maintenance expiration date has nothing to do with the 

- normal _running_ of A-Shell. A-Shell will keep running forever, regardless of the maintenance expiration date—unless you try to update, as explained in the following notes. 

- The expiration date has only to do with your ability to _update_ A-Shell. 

- As long as the expiration date has not passed—i.e., your software maintenance is "current"—there are no restrictions or 

- limitations on your ability to update A-Shell. 

- When the expiration date is in the past, then your ability to update is limited. The general rule is: don't update A-Shell if the 

- maintenance expiration date is in the past. 

More specifically, here is how that works: 

- When A-Shell runs, it checks its own release date against the maintenance expiration date. If the A-Shell date is newer than 

- the expiration date, then A-Shell will run, but it judges the software license to be invalid. An invalid license means that A-Shell will operate only in demo mode, which in turn means that only one user is permitted and annoying "nag" messages appear frequently. 

- Note that the comparison of the A-Shell date and the expiration date do not involve _today's_ date. In other words, it doesn't 

- matter when you perform the update; what matters are the dates of A-shell and the expiration date. 

## **Practical Concerns** 

I just got a new A-Shell license. Must I install it? 

No. You _should_ install it, so that when you check the status of your A-Shell license, it shows the same date as your most recent authorized license. However, you don't _need_ to install it unless/until you are planning to update your A-Shell software. 

My license has a maintenance expiration date of 15 October 2019. Can I install the latest update? 

A-Shell Reference 

Page 102 

No. The latest version of A-Shell is more recent that 15 October 2019. Therefore, if you install that update, the date of the A- Shell program will be more recent than your expiration date, and A-Shell will revert to demo mode. 

My license has a maintenance expiration date of 15 October 2019. What version of A-Shell can I install? 

- Anything with a release date before 15 October 2019. Check the A Shell History documentation, and determine what is the newest version of A-Shell that was released before 15 October 2019. You can install that version of A-Shell, or any one that is older. 

I accidentally updated A-Shell to a version that's newer than my license, and I'm now able to run only in demo mode. What do I do? 

Contact MicroSabio or the firm from which you bought A-Shell, and get an updated license. Once you install the new license, with an expiration date in the future, A-Shell will run in licensed mode. 

- If you are unable or unwilling to install an updated license, then you can try installing an older version of A-Shell. Check the A Shell History documentation, and install a version of A-Shell with a release date before the maintenance expiration date on your license. 

How to I check the maintenance expiration date? 

Get to the A-Shell prompt and enter LICENS or ABOUT. In A-Shell/Windows, you can also check _Help...About_ on the menu bar. 

A-Shell Reference 

Page 103 

## **OTHER LICENSE MATTERS** 

_Reviewed July 2020_ 

## **Unfamiliar License Options and Terms** 

Although you will be familiar with most of the options that show up in your license, there are a few terms that may not be so familiar. 

LFS stands for Large File Support, referring to support for files larger than 2GB. This is not a pay-for feature (although perhaps it should have been). It appears as a "license option" just because it seemed like a handy place to put it. It is more precise to call it an attribute of the _build_ , as opposed to the license. Generally, all current versions of A-Shell support LFS, except perhaps the Windows "C" version. 

W32IO is a similar kind of thing - this is a build option, not a licensing option. It means that we're using the WIN32 I/O routines, as opposed to the standard "C" library I/O routines. 

VI(5.65.7) is a reference to the Victor Imaging library. That originally was a kind of licensing option (in that we did charge for it) but like the other two just described, doesn't relate to any bits in the actual PIC code. 

COM, an acronym for Microsoft's _Component Object Model_ , was an extra-cost option for A-Shell when it was introduced quite some time ago. It is no longer charged for, and may show up in both Windows and Linux licenses. Note that the COM interface is always enabled in A-Shell, and works regardless of whether "COM" is displayed with the license information. 

## **- Exceed A Shell License** 

If you exceed your A-Shell license ("authorized nodes") by trying to log in when all available nodes are in use, you will be a message saying "node counted exceeded," and you will not be able to log in. 

## **Exceed ATE License** 

If you exceed your ATE license authorization—i.e., you try to connect as the sixth ATE connection in a system where five ATE nodes are licensed—you will get a "nag" message but will be allowed to operate. 

## **Group Licensing** 

A-Shell Reference 

Page 104 

Beginning with A-Shell 6.3.1540 of December 2016, A-Shell provides an option for group licensing. This allows fine tuning of the license usage by providing a means of reserving and/or limiting the license usage relative to license groups. For example, in a fifteen user license, you can reserve two licenses for "admin" users, and/or limit the "remote" users to no more than five licenses. 

When group licensing is enabled, via an option encoded in the A-Shell license, A-Shell will call BAS:ASHUSR.SBX on startup. Contact MicroSabio for further specifications on how to implement the group licensing routine. 

In A-Shell 1785 of March 2025, the capabilities of the group licensing mechanism were expanded. Details are not documented due to possible security issues; contact MicroSabio if interested. 

A-Shell Reference 

Page 105 

## **TRANSFERRING FROM AMOS** 

If you are migrating from AMOS, A-Shell provides binary file compatibility with all of your data files and in most cases your program source code (*.bas, *.bsi, etc.) as well. The only files that must be converted are any ISAM PLUS files, which you must first dump using ISMUTL, and then use a binary transfer method to get the dumped file to the Unix or Windows box, where you can reload it using the A-Shell version of ISMUTL.LIT. 

Source files (BAS, CMD, DO) and other text files are binary compatible between AMOS and Windows. Under Unix, these files normally have line terminators of LF instead of CRLF, but since A-Shell can accept either format, the easiest approach is to just transfer all your files using the binary transfer method. The main down side of not using an ASCII or text transfer method to transfer your source files to Unix is that VUE will give you a warning that the file is in DevPPN format and will be converted. (You can, however, turn off the warning; see CVTWARN.) On the other hand, by not converting the line terminators from CRLF to LF, you preserve the hash code and size of the files, which allows you to verify the transfer results by comparing the hash codes using DIR/H and/or VERIFY which are implemented on both AMOS and A-Shell. 

RUN files compiled under AMOS should run as is under A-Shell. In most cases, you can recompile the source code and regenerate the identical RUN file, although this takes some care to use the right compiler switches. In most cases, however, it makes more sense to use the full range of ASB enhancements (see the COMPIL /x:2 and /px switches), which will result in RUN files which may work the same as before but are no longer compatible with the original AMOS RUN format. See VERSYS.LIT for a way to examine the RUN file compatibility level. 

Because of the difference in directory structures between AMOS, Windows and Unix, it is virtually impossible to do wildcard transfers of files involving multiple PPNs and devices. Instead, it will be necessary for you to manually specify the Unix or Windows path that corresponds to the PPN for each directory. (See the discussion of the DEVICE parameter of miame.ini for information on how PPNs are mapped to directories.) The only way around this with FTP transfers is to use an FTP package that allows programmatic scripting. 

A-Shell Reference 

Page 106 

## **FOLDING FILENAMES TO LOWER CASE** 

One additional consideration when transferring files to Unix is that the filenames must all be folded to lower case. If your PCbased FTP package does not support an option for this (a problem with the built-in W95 ftp.exe), then we advise getting one that does (such as ZTERM or WS_FTP Pro.) If that is not practical, or you forget and end up with thousands of files with mixed upper and lower case names, there is a utility script called **trlcs** in the /vm/miame/bin directory which will properly fold one or more filenames (based on a wildcard spec) in a single directory to lower case. It does, however, require that you execute the command in each of your directories. For example: 

```
$ cd /vm/miame/dsk0/020001
```

```
$ trlcs '*'
```

```
$ cd ../020002
```

- `$ trlcs '*'` 

- `<etc>` 

(Note that if a wildcard specification is given, it must be quoted.) If for some reason you do not have the **trlcs** command, you can create it by typing in the following and then using CHMOD +X TRLCS to make it executable: 

```
# trlcs: converts wildcarded files to lower case names
```

```
if [ $# != 1 ]
```

```
then
```

```
  echo "trlcs converts names of files in wildspec list to lcs"
```

```
  echo "usage: trlcs \047wildspec\047  (wildspec must be quoted)"
```

```
else
```

```
  for f in $1; do
```

```
        mv $f `echo $f | tr A-Z a-z`
```

A-Shell Reference 

Page 107 

```
  done
```

```
fi
```

A-Shell Reference 

Page 108 

## **SELECTING A TERMINAL EMULATION** 

Under A-Shell/Windows, selecting a terminal emulation is usually a one-setting-fits-all affair. Typically one specifies the default driver PCTDVG in the CONSOLE statement in miame.ini and that’s the end of it. Under Unix, it can be a bit more complicated because you could be connecting from a variety of different types of terminal devices or terminal emulation software. 

Typically, Unix will attempt to establish the terminal type when you log in, either by querying the terminal directly, or by prompting the user. It then saves the terminal type in the TERM environment variable, which in turn, A-Shell queries to determine which terminal driver to use. If A-Shell does not recognize the terminal type as being one of those that it supports internally, it will use a generic terminal driver that works through the Terminfo database via the curses library. (This assumes that the terminal type is defined in the Terminfo database!) The generic driver is adequate for many applications, but it is not nearly as sophisticated as the drivers embedded into A-Shell. For example, it will not provide very good function key support, nor 132 columns, nor status line support. For this reason, we recommend that if at all possible, you use one of the following terminal types: 

|**TERM**<br>**type**|**Description**|
|---|---|
|aixterm|AIX window emulation.|
|am62a|AM62A emulation. This is perhaps the most common in the AMOS world. Field attributes, monochrome.|
|am62az*|ZTERM-enhanced version of AM62A. Use only with ZTERM 2000 build 144 or higher. Supports variable rows.|
|am62c|Color version of AM62A.|
|am62cg|ATE-enhanced AM62C|
|am62cz*|ZTERM-enhanced version of AM62C. Supports variable rows.|
|am65|AM65 emulation. Similar to AM62A, but uses mode rather than field attributes. Also supports 42 rows.|
|am65g|ATE-enhanced AM65|
|am65z*|ZTERM-enhanced version of AM65.|
|am75|AM75 emulation. Essentially a color version of the AM65.|
|am75g|ATE-enhanced AM75|



A-Shell Reference 

Page 109 

|**TERM**<br>**type**|**Description**|
|---|---|
|am75z*|ZTERM-enhanced version of AM75.|
|cgi|Special pseudo-driver which is automatically set when running in CGI mode.|
|dumb|Dumb tty (hard-copy style) terminal. Useful for running background tasks to avoid cluttering log file with terminal-<br>specific ESC sequences.|
|h1500|Hazeltine 1500 emulation. Uses tilde as a lead-in sequence. Not recommended.|
|vt220|VT220 emulation. This is often a reasonable choice for console devices that might otherwise use "ansi", "scoansi", or<br>"linux" terminal emulation.|
|vt220a|(Linux only) Special version of vt220 emulation that uses no delay on the aux port commands. This is mainly of<br>interest to users of a particular proprietary emulation package.|
|vt420|VT420 emulation. Supports both 7 and 8 bit versions.|
|wyse50|Wyse 50 emulation. Similar to AM62A but does not support addressable status lines, certain smart box operations.|
|wyse5g|ATE-enhanced Wyse 50.|
|wyse5z*|ZTERM-enhanced version of Wyse 50. Supports variable rows.|
|wyz50|(Linux only) Special version of Wyse 50 adapted from the original DOS version of ZTERM (by John Pruitt.) Requires<br>ersemu.dllto work with ZTERM.|



The terminal type names stored in the TERM environment variable should always be in lower case. (A-Shell, like AMOS, confuses things by displaying the names in upper case when within A-Shell.) 

*  The ZTERM-enhanced versions shown above all require ZTERM 2000 Build 144 or higher. In addition, you will have to manually set up the TERM environment variable, which you can do in one of two ways. One is to plug the "z" name into the Terminal Identity field on the Emulation tab of ZTERM’s configuration dialog (e.g. specify "am62az" or "wyse5z"). The other is to manually assign the TERM environment variable before launching A-Shell, such as TERM=am62az). Note that although ZTERM allows you to specify the number of display rows within its configuration screens, it is best to leave it at the default setting there and only change it from within A-Shell. Otherwise, your software will not be able to determine the current number of rows via 

A-Shell Reference 

Page 110 

the TRMCHR subroutine. Too change the number of display rows, use SET TERM HEIGHT command or Set Number of Columns. VUE and EZTYP will allow you to toggle between 24 and 42-row display mode. You can also set the initial number of rows in the INI.CLR file; see Color Configuration. 

The ATE-enhanced versions shown above all require ATE (A-Shell Terminal Emulator). You can select the emulation in the ATE configuration dialog; it will automatically communicate that to the server, setting the TERM environment variable accordingly. The ATE enhancements include support for the main ZTERM ESCAPE sequences (for file transfer, etc.) as well as the full range of ATE functions. 

A-Shell Reference 

Page 111 

## **- RUNNING A SHELL** 

Once the software is installed, and the applications to be run have been loaded into the correct accounts, A-Shell is ready to run. Under Unix, type "ashell" at the host machine command prompt; under Windows, select the A-Shell icon from the Start menu or desktop icon. 

A-Shell will respond with its prompt, and you are free to enter any AMOS commands that have been defined. To terminate the A- Shell session, enter the command "host" at the A-Shell command prompt. 

- Refer to Launching A Shell for details on the command line options and other details of launching A-Shell (and PolyShell). See System Commands for details on the commands that can be entered from the A-Shell command prompt (aka the "dot prompt"). 

A-Shell Reference 

Page 112 

## **LOG FILE MAINTENANCE** 

A-Shell's primary log file—ashlog.log, typically in the %MIAME% directory—is self-maintaining. It rolls over to ashell.001, .002, .etc, up to a reasonable limit and then erases the older ones. 

But in the UNIX environment, it does create one continuously growing log file, OPR:SPOOL.LOG, which records details of submissions to the system print queues. Depending on how much printing your application performs, you may want to set up a cron job to execute every so often to roll it over. See LOGROLL for a handy command for this purpose. 

A-Shell Reference 

Page 113 

## **CONFIGURATION** 

This section and the two following, System Parameters and Printer Configuration, serve as references to the configuration files and settings which are critical to successful operation of A-Shell. You should browse through this material, immediately before or after installing A-Shell, to get a sense of what kind of options exist. Later, you will probably use this as a reference document to get precise details on specific system parameters that you want to change. 

## **Subtopics** 

- MIAME Environment Variable 

- A-Shell Configuration File 

- Color Configuration 

- Help Menu Links 

A-Shell Reference 

Page 114 

## **MIAME ENVIRONMENT VARIABLE** 

The first thing A-Shell does upon being launched is look for its main configuration file. By convention, the configuration file is called miame.ini, though in keeping with the Unix convention, the filename is given in lower case, ("miame.ini") on both Unix and Windows system. 

Unless overridden via a command line switch, the location of the configuration file is given by the MIAME environment variable. This variable is generally defined in a system configuration file, such as AUTOEXEC.BAT or /etc/profile, though may be defined at any stage using the appropriate system command, as shown in the following examples: 

```
MIAME=/vm/miame; export MIAME    (Unix)
```

The actual pathnames used may be changed of course, but it is recommended that the MIAME directory is made a subdirectory of **/vm** (to enable multiple virtual A-Shell machines to be configured), and the parent of the directories which correspond to the devices where the application files are stored. 

A-Shell itself allows the location and name of the configuration file to be overridden with the **-i** switch. This is particularly useful, and is standard procedure, for A-Shell/Windows, since it enables a desktop icon in the program manager to be configured with properties to auto-start A-Shell without the need to set an environment variable in AUTOEXEC.BAT or elsewhere. For example: 

```
ashell -i /vm/miame/miame.ini   (Unix)
```

```
c:\vm\miame\bin\ashw32.exe –i c:\vm\miame\miame.ini   (Windows)
```

If the location of the configuration file is given by the MIAME environment variable, then the file must be called miame.ini. If it is given via the **-i** switch, then it may have any valid filename. 

A-Shell Reference 

Page 115 

## **- A SHELL CONFIGURATION FILE** 

The System Parameters which define and configure the A-Shell operating environment are specified in the main A-Shell configuration file, which is normally called miame.ini. This is a standard text file that must be edited with VUE or another text editor to make changes. Each line of the configuration file is in the form of an equation defining a particular system parameter. Some of these are so critical that A-Shell cannot run at all without them, while others are more for fine-tuning the system or achieving better compatibility with a particular application. A typical A-Shell configuration file is shown below. Note that anything to the right of a semicolon (comment marker) is ignored. 

```
SERIAL=3401OJGI-6280-BNJ-400695-L1109B   ; Serial # and key
```

```
CONAME=C:\VM\MIAME\CONAME.DAT            ; Licensee file
```

```
FILES=40,40     ; 40 files, 40 ISAM
```

```
ERSATZ=C:\VM\MIAME\DSK0\001004\ERSATZ.INI    ; Ersatz defs
```

```
LANGUAGE=C:\VM\MIAME\DSK0\001006\ENGLSH.LDF  ; Language defs
```

```
CONSOLE=NETUNIQUE,PCTDVG    ; Console device
```

```
;Device definitions
```

```
;Use this format for an individual ppn
```

```
DEVICE=DSK0:[1,4] C:\VM\MIAME\DSK0\001004\  ; Individual ppn def
```

```
;Use this format for logical disks with implicit \###### ppns
```

```
DEVICE=DSK0 C:\VM\MIAME\DSK0\   ; Pathname for DSK0:
```

```
;Subroutine aliases (alias-name:ashell-name)
```

```
ALIAS=INPUT:INFLD
```

```
ALIAS=SPOOL:EZSPL
```

```
SBR=CCYY:50,MALLOCSORT
```

A-Shell Reference 

Page 116 

```
LOKSER=ON     ; LOKSER; ISAM sequence checks
PRINTER=LP0     ; Set printer default to LP0
MEMORY=500K     ; A-Shell memory partition
```

```
QUEUE=100,DISK:C:\VM\MIAME\QFLOCK.SYS     ; Q blocks
```

The file is processed only at the start of an A-Shell session, so for any changes to it to take effect it is therefore necessary to exit A-Shell and start a new session. 

Under Windows, the install program will configure your initial miame.ini to match your install directory, allowing you to at least 

launch A-Shell with no manual configuration changes. Under Unix, however, you will need to adjust miame.ini manually before - Launching A Shell for the first time, unless you installed it in the default (/vm/miame) directory. 

You can embed system environment variables in any of the filespecs in miame.ini by using the %ENV-VAR% notation. Some examples: 

```
CONAME=%MIAME%/coname.dat
```

```
DEVICE=TMP0:[1,1] %TMP%\
```

See System Parameters for detailed information on the individual parameters specified within the A-Shell Configuration File. 

The ini file also permits an optional [MIAME] section header at the top, thereby making it easier to use standard INI-processing routines, including INIXxs for updating it. 

A-Shell Reference 

Page 117 

## **COLOR CONFIGURATION** 

Color configuration is an entirely optional step, and may be skipped without penalty. 

Although application programs have the ultimate control over the colors that appear on the screen, for applications that do not assume such control, it is possible to customize a number of aspects of the color display by configuration a color initialization file. 

When A-Shell launches, it checks if the file DSK0:INI.CLR[7,0] exists, and if so, processes it. If you update the file, or wish to experiment with different color configurations, you can force a new color initialization file to be processed using the SET command (SET TERM COLORINI <color ini file>). 

|**Setting**|**Description**|
|---|---|
|VUECLR|Allows you to set up the color scheme used by VUE.|
|EZCLR|Defines the color scheme used by EZSPL (and EZTYP/EZVUE).|
|INFCLR|Defines the color scheme used with INFLD.|
|SCNCLR|Defines the initial color scheme to be used when A-Shell launches. The default is 6,0 (green on black).|
|MMOCLR|Defines the color scheme used with INMEMO.|
|SCNSIZ|Defines the initial number of rows and columns.|



## **Example** 

A typical INI.CLR file is shown below. Note that lines that start with semicolons are ignored (comments). The numbers correspond to the color numbers which may be used in the SET TERM FCOLOR # and SET TERM BCOLOR # commands (or in the TAB(-2,x) and TAB(-3,x) print statements). Note the embedded comment lines that explain the color numbers and the various statement parameters. 

- `; Color Definition File` 

- `; Color legend: 0=blk, 1=wht, 2=blu, 3=mag, 4=red` 

- `;        5=yel, 6=grn, 7=cyn` 

A-Shell Reference 

Page 118 

- `; VUECLR=override?,edit fg,edit bg, command fg,` 

- `;        command bg, help fg, help bg,` 

- `;         status/info fg,bg` 

```
VUECLR=Y,6,0, 5,0, 7,0, 1,0
```

- `; EZCLR=override?,text fg,bg, border fg,bg` 

- `;         cmd fg,bg, sts fg,bg, help fg,bg,` 

- `;         highlight fg,bg, menu fg,bg, brief menu fg,bg` 

```
EZCLR=Y, 6,0, 6,0, 5,0, 0,9, 1,3, 3,6, 5,0, 7,0
```

- `; INFCLR=override?,display fg,bg, edit fg,bg` 

- `;         negative fg,bg, update fg,bg,` 

- `;         message fg,bg, original msg line fg,bg, forms fg,bg` 

```
INFCLR=Y, 1,0, 5,0, 4,0, 7,0, 5,0, 6,0, 9,0
```

- `; MMOCLR=Y,border fg,bg, text fg,bg, arrows fg,bg, prompt fg,bg,` 

- `;         status line fg,bg, protected fg,bg` 

```
MMOCLR=Y, 6,0, 7,0, 5,0, 5,0, 5,0, 10,0
```

- `; SCNCLR=override?,screen text (fg), screen background` 

- `; The following sets up magenta on black` 

```
SCNCLR=Y,3,0
```

- `; SCNSIZ=rows,cols` 

```
SCNSIZ=18,60
```

A-Shell Reference 

Page 119 

Most of the lines begin with an "Override?" option. When set to Y, the color scheme defined on that line will override the default color scheme normally used for that function, or the one which a program has specifically asked to use. Setting it to N is nearly the same as commenting out the line entirely, except for situations where no other color scheme had been set up or specified for that function. 

You may set any color number to –1 to indicate that it should use the color which happens to be current at the time the function begins. (Setting all of the numbers to –1 will effectively defeat any color changes within the function.) Also note that making the foreground and background numbers in any pair the same effectively makes that text impossible to see. This is generally a very bad idea, except in some isolated cases. For example, some people don’t like the status line information displayed by EZTYP; you can eliminate it by setting the status line pair of the **EZCLR** line to 0,0 (black on black). 

A-Shell Reference 

Page 120 

## **VUECLR** 

The VUECLR line allows you to set up the color scheme used by VUE. The first pair of numbers defines the foreground and background colors used for the editing display. The second set defines the colors used in command mode. The third set defines the colors used with for HELP displays. And the fourth pair defines the colors used for status and other information displays. In the example above, this would be green on black for the display mode, yellow on black for the command mode, cyan on black for the help displays, and white on black for the status displays. 

A-Shell Reference 

Page 121 

## **EZCLR** 

The EZCLR line defines the color scheme used by EZSPL (and EZTYP/EZVUE). The concept is the same as that for VUECLR except the color pairs refer to the EZTYP display mode ("text"), graphic line drawing characters used for borders, command mode, status line, help (pop up) display, highlighted search strings, printer selection menu mode, and the brief version of the printer selection prompt/menu. 

A-Shell Reference 

Page 122 

## **INFCLR** 

The INFCLR line defines the color scheme used with INFLD. The pairs refer to display of data (without editing), editing mode, negative numbers (red), the redisplay of a field after it has been edited, the message line (bottom line of screen), the original color of the message line (so it can be returned to its original state), and the color used for forms characters. Note that applications have the option of specifying all of these colors explicitly for each field edited or displayed. If you set the "override" field to Y, this will override any colors specified by the application. However, if the application does not specify colors, then it is not necessary to set override to Y. (In other words, if you set the override option to N, it will only override the color scheme on fields for which the application did not establish its own color scheme.) 

A-Shell Reference 

Page 123 

## **MMOCLR** 

The MMOCLR line defines the color scheme used with INMEMO. Here the pairs refer to the color used to draw the border around the memo, the color of the text within the memo, the color of the navigation arrows (which display on the border), the color of the prompts (top and bottom titles), the color of any status messages, and the color of protected text. Note that these colors also apply to the PCKLST subroutine and any other utility which internally uses INMEMO. The comments about the override field given above for INFCLR apply here as well. 

A-Shell Reference 

Page 124 

## **SCNSIZ** 

The SCNSIZ line defines the initial number of rows and columns. The default is 24 by 80. Under Windows, rows may range from 1 to 50, and columns may range from 1 to 160. Under Unix, it depends on the capability of your terminal emulator. In most cases, you will be limited to 24 by 80 or 24 by 132. In the case of ZTERM (Build 144 or higher), the number of rows may vary from 1 to 50. 

A-Shell Reference 

Page 125 

## **HELP MENU LINKS** 

The contents of the A-Shell/Windows Help menu are easily configurable. It is recommended that you take a minute to set up documentation and other help links appropriate for your type of installation. Configuration is accomplished via the text file ashelp.mdf, which is installed into the DOC subdirectory. A sample copy of the file, as it is included with A-Shell, is shown below. 

The documentation set-up step is entirely optional; the presence or absence of documentation files will not affect the operation of A-Shell. If the documentation files are missing, or if the set-up file ashelp.mdf is damaged or contains invalid data, or even if the entire documentation folder/directory is missing, A-Shell will run without problem—although also without, of course, documentation. 

```
;This file sets up the selections on the A-Shell Help menu.
```

```
;
```

```
HELP,"h1",SEP
```

```
HELP,"&A-Shell Reference",REG,"http://www.microsabio.net/dist/60rel/doc/conref/00ashref.htm"
```

```
;
```

```
HELP,"&Release Notes",REG,"http://www.microsabio.net/dist/60rel/doc/ashdevnotes/00ashdevnotes.htm"
```

```
;
```

```
HELP,"h2",SEP
```

```
;
```

```
HELP,"A-Shell &Documentation Home",REG,"http://www.microsabio.com/documents.html"
```

```
;
;Add your app's docs here...
```

```
HELP "h3",SEP
```

A-Shell Reference 

Page 126 

The above ashelp.mdf produces the following _help_ menu: 

The lines that start with semicolons are comments and are ignored. 

The first field on each line (HELP) indicates that it applies to the Help menu. The second field indicates the text that will appear in the menu item, unless the menu type (third field) is "SEP" (i.e. separator), in which case the second field just needs to be a unique string used internally for identification. The third field indicates the type of menu item. The most likely choices are SEP (separator) or REG, which means that the file or URL in the fourth field will be launched according the Windows file-type association in the Registry. The fourth and last field is the document file or URL to be launched. If it is a file spec, you must include the complete path, unless it is in the DOC subdirectory (where the ashelp.mdf file itself is located.) 

You can (and are encouraged to) edit this file, using any text editor. In addition to removing or commenting out links that you don't want, you can add links for your own application documentation, as well as any links to sites frequently referenced by A- Shell users, such as government, shipping, legal, search, dictionary, etc. 

A complete listing of available A-Shell documentation is always available from the A-Shell web site on the downloads...documents page. 

A-Shell Reference 

Page 127 

## **SYSTEM PARAMETERS** 

Following is a list of the A-Shell system parameters, also known as directives. These are terms that are used as verbs in the A- Shell configuration file, miame.ini. All lines except comments must begin with one of these directives followed by an equals sign. They are listed here in alphabetic order, and may appear in any order within miame.ini, except for SERIAL, which must be the first non-comment line of the file and is therefore listed first in the following table. See Boolean Arguments in Ini Files if needed. 

|**Parameter**|**Description**||**Parameter**|**Description**|
|---|---|---|---|---|
|SERIAL|Define A-Shell serial number||LOKSER|Specify LOKSER operation|
|ALIAS|Specify A-Shell subroutine aliases||MALLOCLIMIT|Specify limit on dynamic memory allocations|
|ALTRUNEXT|Define alternate RUN extensions||MAPIDA|Enable/disable ISAM Plus extension mapping|
|ALTSBXEXT|Define alternate SBX extensions||MAXINST|Specify max A-Shell instances per workstation|
|ATETIMEOUT|Set the ATE timeout period||MAXJOBS|Specify maximum number of jobs total|
|CHARSET|Specify A-Shell character set||MAXLOCKS|Specify max locks to track for LOKSER|
|COMPRGEXT|Define additional files that can be executed||MEMORY|Specify A-Shell memory partition|
|CONAME|Specify location of licensee name file||MMAPLIST|Specify files to be automatically memory mapped|
|CONSOLE|Define console device format & default driver||NOTRACE|Disables specific XCALL traces|



A-Shell Reference 

Page 128 

|**Parameter**|**Description**||**Parameter**|**Description**|
|---|---|---|---|---|
|DEVICE|Map devices to host machine pathnames||OPTIONS|Set miscellaneous A-Shell options|
|EFSEXT|Specify extensions to be encrypted.||POLYKEY|Define PolyShell hot key|
|ERSATZ|Specify ERSATZ definition file||PRINTER|Define default printer name|
|FILES|Specify A-Shell FILE buffers||QUEUE|Specify A-Shell queuing system|
|FKEYWAIT|Specify delay following function key lead in||QUITKEY|Define or disable Unix QUIT key|
|FLDATTR|Enable/disable field attributes||SBR|Tune operation of A-Shell subroutines|
|FONT|Specify A-Shell font face (Windows only)||SSD|Define returned SSD sequence|
|IATIMEOUT|Define idle timeout||SWAPKEY|Define PolyShell swap key|
|IJCFREQ|Define frequency of IJC clock||SWAPWAIT|Specify delay after screen swap|
|INCLUDE|Include specified file||TRACE|Activate debugging options|
|JOBPREFIX|Specify jobname prefix for auto-named jobs||TRMDEF|Define terminal characteristics|
|LANGUAGE|Specify language definition file||UMASK|Specify default file creation mask|



A-Shell Reference 

Page 129 

|**Parameter**|**Description**||**Parameter**|**Description**|
|---|---|---|---|---|
|LOGDIR|Specify location of ashlog.log file||XONXOFF|Enable or disable XON/XOFF protocol|



A-Shell Reference 

Page 130 

## **SERIAL** 

## **SERIAL= Security key** 

The SERIAL directive must be present in order for A-Shell to run. In older versions of A-Shell, SERIAL had to be the first line of the initialization file except for comments. While that is no longer true, it still is normally the first line of the ini file. 

If the security key field is set to _DEMONSTRATIONXX_ , then A-Shell will operate in demonstration mode. If the field is set to _XXXXXXXXXXXXXXX_ , then the first time A-Shell is invoked, then the security key will be requested: 

```
A-Shell Serial Number:
```

```
A-Shell Serial # nnnn security key:
```

```
Company name:
```

You should then enter the serial number, security key and company name as received with the A-Shell software license. This key will then overwrite the SERIAL line in miame.ini. An incorrect security key will cause A-Shell to operate in demonstration mode. 

Use the LICENS command from the A-Shell prompt to force A-Shell to prompt for a new security key. 

The security key and company name must match. Case and punctuation of the company name are not important. 

Note that the SERIAL line in miame.ini can be replaced with an `INCLUDE=<fspec>` line, where <fspec> is the full native filespec of a file which contains SERIAL. This feature allows sites supporting multiple A-Shell installations to maintain just one miame.ini for _all_ the installations, while storing the one thing that is unique—the SERIAL specification—in a separate file. 

A-Shell Reference 

Page 131 

## **ALIAS** 

_Rewritten May 2024_ 

## **ALIAS=oldsbr:newsbr** 

The ALIAS directive allows you to redirect Xcall _oldsbr_ to Xcall _newsbr—_ i.e. to treat _oldsbr_ as an alias for _newsbr_ . 

An example of this in nearly every A-Shell installation is SPOOL being aliased to EZSPL via the following: 

## `ALIAS=SPOOL:EZSPL` 

(EZSPL is an enhanced, upward compatible version of the original SPOOL subroutine. Rather than implement both variations separately, A-Shell includes only EZSPL and redirects Xcall SPOOL to Xcall EZSPL via this alias method.) 

## **Comments** 

The maximum number of ALIAS directives is 50. 

The _oldsbr_ and _newsbr_ names must be six or fewer characters. 

The ALIAS scan occurs only once per {V}Xcall statement, i.e. the _newsbr_ name is not re-scanned for another ALIAS match. So if you have `ALIAS=A,B` and `ALIAS=B,C` the statement `Xcall A` will redirect to B (not C), but `Xcall B` will redirect to C. 

If _newsbr_ and _oldsbr_ are the same, then the ALIAS effectively redirects the call from the internal/embedded subroutine to the external (SBX) version. See History below. 

ALIAS applies to VXcall as well as Xcall, and to internal subroutines as well as external (SBX) routines—again, provided the names are six or fewer characters. 

ALIAS can be used to effectively disable a subroutine by redirecting it to a subroutine that does nothing such as PRIV. 

The ALIAS mechanism only makes sense if the two subroutines have compatible parameter lists. If you need a subroutine which is similar to one we already offer but with different parameters, you can probably create your own SBX version as a wrapper to the existing one. See SBX Subroutines for details on writing your own subroutines. 

A-Shell Reference 

Page 132 

To add functionality to an existing internal Xcall subroutine via a wrapper, you can use ALIAS to redirect calls to an SBX of a different name (the wrapper), and then within that SBX you can Xcall the original internal subroutine via a second ALIAS. For example, to create a wrapper for an internal subroutine A, you might start with `ALIAS=A,AX` and `ALIAS=AY,A` so that Xcall A is redirected to AX.SBX. Within your AX.SBX wrapper you can then call the original embedded A subroutine via `Xcall AY` ,relying on the second ALIAS to redirect `Xcall AY` to the original A subroutine, and the fact that the ALIAS table is only scanned once per Xcall so the redirection from AY to A is final. 

## **History** 

- 2024 May, A Shell 7.0.1759.1:  Support the case where _oldsbr_ and _newsbr_ are identical to replace an internal subroutine with an external SBX version under the same name. Previously this would have done nothing. 

A-Shell Reference 

Page 133 

## **ALTRUNEXT AND ALTSBXEXT** 

_Added January 2019_ 

## **ALTRUNEXT=<ext>** 

## **ALTSBXEXT=<ext>** 

The keys ALTRUNEXT and ALTSBXEXT define, respectively, alternate RUN and SBX extensions. 

Each of the above keys takes a single 1-3 character extension, which is automatically added to the internal COMPRGEXT list, as well as to the relevant search path, where it will be found BEFORE the corresponding standard extension in each directory of the search path. 

The intended usage is to define extensions for test or 'beta' modules that can be easily deployed and removed without overwriting the stable RUN and/or SBX modules. For example, assume we have the following in miame.ini: 

```
ALTRUNEXT=RNX
```

```
ALTSBXEXT=SXX
```

After deploying a release of your package (mixture of RUN and SBX modules), you might later need to fix or enhance a particular program. To avoid affecting the stable version while working on it, you can add the pragma `++PRAGMA FORCE_EXT "RNX"` (or "SXX" for a subroutine) to the source so that the compiled version will have the specified alternate extension. When the alternate version is placed into the same directory where the production version resides, the ALTXXXEXT definition will cause it to be loaded in preference to the standard production version, allowing you to easily test the new version. If you decide there is a problem, just erase the new version, which will cause A-Shell to resume using the standard version. Otherwise, you can rename the test version to replace the production version. 

## **Notes** 

- For each directory in the program search path (e.g. [p,pn], [p,0], BAS: ), it will check first for the alternate extension, and 

- only if not found will it check for the standard extension. If neither is found, then the search continues with the next directory in the search path. 

A-Shell Reference 

Page 134 

• The alternate extension search logic only applies when then extension is not explicit in the command, e.g. would not apply to `RUN FOO.RUN` or `RUN FOO.RNX` or `VXCALL "FOO.SXX"` . 

• Defining an alternate extension does incur some overhead due to the need for additional directory lookups, so is not recommended unless you actually intend to use the feature. The overhead, however, is likely to be fairly insignificant, except perhaps in cases where you have very large directories. 

• For subroutines, the alternate extension will be cached just like the standard extension, and subject to the same automatic refresh logic which insures that the version in memory gets updated or removed when the corresponding version on disk does. The one difference between the behavior of a subroutine with the alternate extension and one with the standard SBX extension is that the alternate version cannot be manually loaded from a non-standard directory (e.g. `LOAD MYDEV:FOO.SXX` ). The problem here is that the automatic refresh logic, after not finding the corresponding module on disk in the search path, will conclude that it has been deleted and thus will remove it from memory and revert to using the standard version. 

• If in doubt about which RUN module version was actually loaded, you can activate the FOPENS trace (e.g. SET TRACE FOPENS ON), which will trace the load operations in the ashlog.log file. For example you will see something like this: 

```
OpenFile1: C:\VM\MIAME\DSK0\150277\FOO.RUN, fh=-1, err=2 [214 us], ...
```

```
OpenFile1: c:\vm\miame\DSK0\150000\foo.run, fh=-1, err=2 [355 us], ...
```

```
OpenFile1: c:\vm\miame\DSK0\007006\foo.rnx, fh=716, err=0 [371 us], ...
```

The above indicates that it first tried foo.rnx and .run in [150,277]; the RNX lookup might not be traced if the file isn't present. The another unsuccessful attempt in [150,0], and finally it finds foo.rnx in DSK0:[7,6]. 

• For subroutines, use the subroutine trace ( `SET TRACE XCALL ON` ) for a similar trace, e.g. the following traces a subroutine TSTSBX statement, first checking for both the alternate and standard extensions in [150,277], before finding the alternate extension in [150,0]... 

```
<FOO:25> xcall TSTSBX,S7[BONJOUR]
```

```
<FOO:TSTSBX:25> OpenFile1: c:\vm\miame\DSK0\150277\tstsbx.sbx, fh=-1, err=2 [264 us],...
```

```
<FOO:TSTSBX:25> OpenFile1: c:\vm\miame\DSK0\150000\tstsbx.sxx, fh=872, err=0 [86 us],...
```

A-Shell Reference 

Page 135 

```
<FOO:TSTSBX:25> Executing c:\vm\miame\DSK0\150000\TSTSBX.SXX ...
```

• For subroutines, you can also use the MAP statement after running the program to see the names and extensions of the cached routines, although that won't indicate the locations from where they were loaded. 

## **History** 

- 2019 January, A Shell 6.5.1654:  Function added to A-Shell 

A-Shell Reference 

Page 136 

## **ATETIMEOUT** 

_Added December 2014_ 

## **ATETIMEOUT=<milliseconds>** 

ATETIMEOUT allows you to change the default ATE command/response time out from the standard 7500 milliseconds to something else. Depending on your network, you may find that 7500 is too low, producing spurious timeout conditions, or too high. 

## **History** 

- 2014 December, A Shell 6.1.1399:  Function added to A-Shell. 

A-Shell Reference 

Page 137 

## **CHARSET** 

## **CHARSET=<charset name>** 

```
Examples:  CHARSET=US
```

(Windows only) CHARSET is used to specify the character set used by the application, per the table below. Note that the CHARSET options may be abbreviated to the characters shown in parentheses in the table, but they must be in upper case. 

|**CHARSET**|**Notes**|
|---|---|
|US|(Default) Standard ASCII.|
|UK|British national replacement character set. The # or £ keys return<br>ASCII character 35, and character 35 is always displayed as £.|
|FRENCH (FR)|French AZERTY|
|GERMAN (GER)|German|
|PORTUGUESE<br>(PORT)|Portuguese|
|SPANISH (SPA)|Spanish|
|SWISS|Swiss|
|ITALIAN (ITAL)|Italian|
|DANISH (DAN)|Danish|
|SWE-FIN|Swedish/Fin|
|LATIN1|Use 8 bit Latin1 characters. (All of the non-ASCII characters<br>referenced above would need to be specified as 8 bit values in the<br>range of 128-255.) Equivalent to OPTIONS=LATIN1.|



A-Shell Reference 

Page 138 

CHARSET is related to, but not the same, as the symbol set parameter on the FONT directive (which see). The font symbol set is mainly of internal significance to A-Shell, while the character set specified with CHARSET must match up with the way your application encodes non-ASCII characters. It is highly recommended that you use the 8 bit LATIN1 character set for displaying non-ASCII characters, rather than one of the 7 bit national replacement character sets, since Latin1 is much more portable and standard under Windows. 

In order for any of the character set choices above, other than US and LATIN1, to be effective, you must specify the OEM symbol set in the FONT directive. 

The CHARSET directive replaces the special terminal driver names previously used with the CONSOLE directive (which see) to specify national replacement character sets. That is, setting the terminal driver to PCUK (rather than PCTDV) has no effect; you must instead specify `CHARSET=UK` . 

A-Shell Reference 

Page 139 

## **COMPRGEXT** 

_Added January 2019_ 

## **COMPRGEXT=<list of extensions>** 

COMPRGEXT defines additional file extensions recognized as compiled programs. 

The list of extensions must be comma-delimited, with no spaces or other characters. The specified extensions are added to the built-in list (RUN, SBX,LIT) which is used by the file loader to determine whether the file needs to be set up for execution. Files with extensions not in the list are treated as raw data and will not be runnable. 

The maximum length of the RUNEXT list, not including the built-in extensions, is 64 characters. 

Note that adding extensions to the COMPRGEXT does not automatically add them to the program search path. It only makes it possible to run them with an explicit command (e.g. `RUN TEST.RNX` ). Note that for subroutines, it is not possible to specify 

explicit extension in the XCALL statement, but it is possible to do so with the VXCALL statement, e.g. `VXCALL "FOO.SXX", ARG1` . SP SP See ALTRUNEXT / ALTSBXEXT . 

## **History** 

- 2019 January, A Shell 6.5.1654:  Function added to A-Shell 

A-Shell Reference 

Page 140 

## **CONAME** 

## **CONAME= filespec of company name file** 

The CONAME directive specifies the name and location of the file containing the A-Shell licensee name. On installation of A-Shell, the security key field is tied to a specific company name (the licensee company), which is stored in the file specified in the CONAME directive in miame.ini. This is done by prompting for the licensee when entering the security key after A-Shell is run for the first time: 

## `A-Shell Licensee (company name):` 

The location of the coname file is specified in terms of its native operating system (e.g. c:\vm\miame\coname.dat) rather than in DevPPN format. You may, however, place it in a directory which also maps to a PPN to allow easy access from within A-Shell. For example, applications may read this file as a form of copy protection, since, although it is a straight text file, alteration of its contents will cause A-Shell to operate in demonstration mode. 

Since the CONAME file must be shared by all users on a network, it must be placed on the server, and referenced either via a mapped drive letter or a UNC (\\server\share\path\coname.dat) name. 

A-Shell Reference 

Page 141 

## **CONSOLE** 

_Reviewed and revised, July 2020_ 

## **CONSOLE=<idformat>{,drivername}** 

CONSOLE establishes an internal identifier for the instance, and optionally a terminal driver. Over the years is has devolved to become a nearly bottomless pit of complexity and confusion, but fortunately, in 99% of the cases, you can just set it to the following: 

```
CONSOLE=NETUNIQUE,<tdvname>             ; windows networks
```

The <tdvname> parameter should be either PCTDVG or PCTDV, with the only difference being that the PCTDVG version implements certain GUI improvements, such as the conversion of text message boxes to Windows dialog boxes. 

Historically, certain national replacement character set variations of the terminal driver were supported, such as PCUK and PCFR. This function has been taken over by the CHARSETSP directive. 

The NETUNIQUE option on the CONSOLE directive generates a unique identifier for each A-Shell session, made up of the computer name, followed by a colon and a numeric suffix indicating the instance number. The computer name may be set via the Windows Control Panel, using the Networks applet under W9x and the System applet in subsequent versions. Other options exist, but are for all practical purposes obsolete now. 

You can see these identifiers with `SYSTAT/C` . You can also retrieve your own identifier with the subroutine GETUSN. 

If you establish meaningful computer names, then these console identifiers are probably more useful than AMOS-style job names. But since job names are so embedded in ASB applications, A-Shell also generates them using the TSKAAA, TSKAAB, etc. format. If you don't like the dynamically generated job names, you can override them by using the `j <jobnam>` command line switch, or you can create a cross-reference association between console identifiers and job names using TRMDEF statements. 

Because the console device name is used by the TRMDEF parameters, the CONSOLE statement must occur before any TRMDEF specifications. 

## **History** 

A-Shell Reference 

Page 142 

- 2015 May, A Shell 6.1.1408: Windows enhancement: A-Shell now detects duplicate machine names. Previously, this would have led to the nth instance on machine 2 overwriting the JOBTBL record for the nth instance on machine 1. In order for this to work, you must run the installer/updater to update each workstation, rather than manually installing the update by copying files. It is also important to update the six system commands, described in the next topic, although the installer will normally take care of this for you. 

The installer/updater establishes a unique identifier for each machine and saves it in the HKLM section of the registry, to be used to determine whether an instance with the same machine name as an existing instance is actually the same machine or not. If so, then the new instance can safely overwrite the old one. But if not, an error message is displayed and the new session is not allowed to start. 

The error message will indicate the machine name, the user name and jobname of the offending existing instance, and the unique identifiers (8 hex digits) for the two machines. You can use the `SYSTAT/CU` switch to display the unique identifiers for existing sessions, which may be helpful in tracking down the offending duplicate-named machine. 

Note that duplicate named machines can cause all kinds of problems for Windows networking, but it is not always detected. This feature should help avoid the ensuing problems in both A-Shell and in the network in general. 

Also note that the issue only affects P2P networks; ATE, Terminal Server, and Unix systems are not subject to the problem and are not affected by the update. 

A-Shell Reference 

Page 143 

## **DEVICE** 

_Revised August 2025_ 

## **DEVICE=devn basedir/** 

## **DEVICE=devn:[p,pn] dir/** 

## **DEVICE = devn:[] dir** 

The DEVICE directives allow you to map DevPPN filespecs to Unix- or Windows-style directories. The _devn_ part of the DevPPN filespec (known as the "logical disk") consists of a three or four alphabetic character device name, followed by a one to three digit unit number, up to a maximum combined length of 6 characters (e.g. DSK0 or BACK99). The _p_ and _pn_ components are each one to three digits, ranging from 1-999 for _p_ and 0-999 for _pn_ . Note that although the the DevPPN logical disk is by convention all upper case, in actual usage, DevPPN filespecs are entirely case INsensitive; XYZ37:MyFile.DAT and 

xyz37:myfile.dat are equivalent.) The case sensitivity of the _basedir_ or _dir_ , on the other hand, depends on the host operating system, but by convention is typically all lower case. 

There are three variations of this mapping: 

• The first, and most common, maps a DevPPN-style logical disk (e.g. DSK1) to a base directory path (e.g. /vm/miame/dsk1/). The trailing slash on basedir/ is mandatory. The PPN equivalents are then set up as subdirectories of this base directory using the format <base directory>/######, corresponding to devn:[###,###]. So for example if DSK1 maps to /vm/miame/dsk1/ then DSK1:[1,4] would map to /vm/miame/dsk1/001004. Note that the trailing colon, required to separate the devn from a filename or [p,pn] or in other contexts to identify a token as a devn instead of a filename, is omitted from this version of the DEVICE syntax. 

• The second variation overrides the implicit PPN subdirectory scheme just described, by specifying a complete and explicit directory to be associated with a specific devn:[p,pn]. The trailing slash on dir/ is mandatory. 

• The third variation is similar to the second but is reserved for logical devices that have no [p,pn] component associated with them. See the separate topic Devices without PPNs for a more thorough discussion. 

As an example, consider the following two DEVICE statements on a Unix-based host: 

A-Shell Reference 

Page 144 

```
DEVICE=DSK1:[31,3] /usr/tmp/
```

```
DEVICE=DSK1 /vm/miame/dsk1/
```

Together, these statements would be used by A-Shell / MIAME to map the DevPPN specification dsk1:test.dat[31,5] onto the path /vm/miame/dsk1/031005/test.dat, and the DevPPN specification DSK1:TMPCMP.DAT[31,3] to /usr/tmp/tmpcpy.dat 

The file name is always converted to lower case as part of the mapping operation. The case of the directory component depends entirely on the case of the basedir in the DEVICE statement (lower case by convention). 

In Windows network environments, you can substitute UNC-style names (Universal Naming Convention) in place of the DOS drive letter in these DEVICE statements. For example: 

```
DEVICE=DSK1 f:\vm\miame\dsk1\
```

```
DEVICE=DSK2 \\kahuna\ashell\dsk2\
```

In the first DEVICE directive, logical device DSK1: is defined as being on the F: drive (which presumably is a mapped network drive.) In the second, DSK2: is defined as being at a location defined by the share name "ashell" on the server named "kahuna". The advantage to the UNC approach is that it eliminates the need to map the same (or any) drive letter on each client workstation to the server, thus simplifying the setup of client workstations in a network. The only known downside to this approach is that due to a bug in Windows 95, SYSTAT will not be able to report the number of free blocks on any device which is defined this way. But this is a relatively minor concern, and the bug is fixed in later versions of Windows. 

Although not recommended, if you insist on mapping DevPPN-style devices to directories that contain spaces, you can do so by enclosing the directory specification in quotes, as in this example: 

```
DEVICE=XYZ0:[1,1] "C:\Program Files\COOL.STF\ZTERM For Windows\"
```

It should be noted that due to the automatic generation of pathnames from PPNs, and because DevPPN-style filenames are restricted to 81 (72.8) characters (as well as the case problem under Unix) there are many files that cannot be accessed via an DevPPN file specification. This mapping of an DevPPN file specification (using the definitions described here) is performed by by an internal conversion subroutine known as fspec2host. To solve the file-inaccessibility problem, if the DevPPN specification passed to the conversion subroutine contains a directory separator character ( / or **\** ) then no attempted mapping to a 

A-Shell Reference 

Page 145 

pathname takes place. Under A-Shell, programs could be written to directly manipulate any files on the system (file protection permitting), for example: 

```
open #1,"c:\autoexec.bat", input
```

```
..
```

In order to access a file in the current working directory whose name doesn't fit the 72.8 limit, or which contains upper-case characters or no extension under Unix, then it is necessary to specify a path containing the current directory symbol " **."** , for example: 

```
kill "./core"
```

The following special form of the DEVICE directive may be used to define a device that references user memory: 

```
DEVICE=MEM: MEM:
```

Technically, you could use any device name for the logical name (the first MEM:) but the physical name (the second MEM:) must be MEM: (in upper case, with the colon on the end). 

If you already have a PPN-specific MEM: or MEM0: device defined, then it must be defined first, i.e.: 

```
DEVICE=MEM0:[1,1] /tmp
```

```
DEVICE=MEM: MEM:
```

Make sure there is no MEM: in your ersatz.ini file; ERSATZ devices are processed first. Obviously, if you are using the MEM: ersatz, you will want to make other arrangements. However, it you are too committed to using MEM: as an ersatz disk device, then you could use some other logical name to refer to user memory. For example, `DEVICE=RAM: MEM:` would define a logical device named "RAM:" which referred to the physical device MEM: (user memory). 

## **Notes** 

A-Shell Reference 

Page 146 

Only those devices defined explicitly with a DEVICE line are allowable in an DevPPN file specification. All others will report _Device does not exist_ or _Invalid filename_ messages, depending on the context. 

If the configuration file contains both full device/PPN definitions (syntax two) and a default device definition for a given drive (syntax one), then the full device/PPN definitions must appear first. 

Under Windows, the host pathname may include the drive letter and a colon at the start, followed by the full pathname beginning (and ending) with a directory separator character; or, it may use the UNC format \\server\sharename\path\. 

## **Symbolic links** 

In the Unix environment it is possible to create symbolic links to directories such that a single directory might be accessible by two (or more) paths. To fully accommodate this situation, you may want to define the same DEVICE multiple times for the different names, so that in situations where A-Shell may need to translate from the native directory (or alias) to the DevPPNstyle equivalent, it will find the native directory, regardless of which alias is being used. For example, if you have a symbolic link from /vm/sites/xyz to /vm/miame, then the following DEVICE statements might apply: 

```
DEVICE=DSK0 /vm/miame/dsk0/
```

```
DEVICE=DSK0 /vm/sites/xyz/dsk0/
```

The first entry will be the one used whenever translating from an DevPPN-style spec to native; the second one would come into play only when reverse-translating from a /vm/sites/xyz/dsk0/... native directory back to DSK0:. See "Issue when using " - symbolic link on the A Shell forum for further details. 

## **Caution** 

If you use DEVICE to define specific a specific PPN (as opposed to entire DSKs), make sure that the PPN so defined does not _also_ exist in the location defined for the DSK. If you create a situation where the PPN exists twice, then DIR will display the files in _both_ locations. This is a special case of a larger problem with DIR, in that DIR scans the raw directory, then for each entry found, tries to display it as if it were an DevPPN file, using a backwards translation from the raw directory spec to the DevPPN equivalent. This causes DIR to find things, both files and directories, that might otherwise not be quite what was intended by a particular set of DEVICE definitions. The only solution would be to then do another forward translation of the found DevPPN spec 

A-Shell Reference 

Page 147 

back to the native spec to compare when that native spec matched the one found by DIR, but that would slow DIR down considerably. 

## **Examples** 

For both Windows and Unix, the host pathname may contain system environment variables, using the syntax %VAR%: 

```
DEVICE=USR0:[1,1] %HOME%/
```

```
DEVICE=TMP0:[1,1] %TMP%\
```

```
DEVICE=DSK0 %MIAME%\dsk0\
```

The first example makes USR0:[1,1] map to the current user's home directory (assuming that the environment variable HOME was defined by the user's shell). Note that even though the normal syntax for environment variables under Unix is $VAR, A-Shell uses %VAR%. 

The second example makes TMP0:[1,1] map to the user's TMP directory (in this case assuming that the TMP environment variable was defined on the PC, either for the machine or for the login user). 

The last example illustrates that the environment variable can be combined with other static elements. 

## **See Also** 

- "No-PPN" devices (syntax three) 

## **History** 

- " - " 2025 April, A Shell 7.0.1771:  Add support for No PPN devices. 

A-Shell Reference 

Page 148 

## **DEVICES WITHOUT PPNS** 

_Written April 2025_ 

Beginning with version 7.0.1771 of April 2025, A-Shell supports a "no-PPN" variation of the DEVICE system parameter, allowing it to support individual arbitrary directories as devices without any PPNs. 

## **DEVICE = dev#:[] path** 

Examples (two no-PPN devices followed by a single-PPN device) : 

```
DEVICE = TMP0:[] "%TEMP%"
```

```
DEVICE = TMP1:[] "C:\TEMP"
```

```
DEVICE = BIN0:[1,1] "/vm/miame/bin"
```

Note that the no-PPN DEVICE definition syntax is similar to the single-PPN version, except without anything inside the []. When referencing the no-PPN DEVICE in code or on the command line, you never specify the [p,pn], whereas with the single-PPN device, if you don't specify the [p,pn] it will default to your current [p,pn] (probably failing unless it just happened to match the one [p,pn] on the device). 

The effect is similar to defining a single-PPN DEVICE and then creating an ERSATZ definition to point to that dev#:[p,pn]. The main advantage of the ERSATZ approach is that you can eliminate the device #; the main disadvantage is that it requires two matching definitions (one in the MIAME.INI, the other in an ERSATZ file.) One other advantage to the no-PPN DEVICE is that you can create a series of such definitions using the same base device but different unit numbers (as in the example above) and then perform combined searches on all of the units belonging to that device by just omitting the device # in the wildcard spec. For example, again assuming the above two DEVICE definitions, consider the following: 

```
.LOG BAS:
```

```
.DIR TMP:MYFILE.*
```

A-Shell Reference 

Page 149 

Because TMP: is the (automatic) base device for TMP0: and TMP1:, omitting the device # in a wildcard command line context, acts like a wildcard (in this case matching both TMP0: and TMP1:). And since these are no-PPN devices, our current P,PN (7,6) has no bearing on where it searches (as would be the case with a single-ppn ERSATZ definition). 

Note that although the ground work for this is embedded into A-Shell, to successfully reference such devices at the command prompt you'll need to update the LIT commands: 

```
DIR.LIT    3.4(178)
```

```
COPY.LIT   3.4(149)
MOVE.LIT   3.4(149)
ERASE.LIT  3.4(138)
PRINT.LIT  3.4(139)
SIZE.LIT   3.3(103)
DEVTBL.LIT 3.3(106)
```

The DEVTBL display was also modernized to eliminate pointless references that only made sense in the AMOS world, and to replace them with indicators of single-PPN and no-PPN devices. 

Several other LITs were recompiled with minor internal updates at the same time; use UPDCUR to update them. The updated LITs remain compatible with prior versions of A-Shell. 

A-Shell Reference 

Page 150 

## **EFSEXT** 

## **EFSEXT=ext1 {,ext2, ext3,...ext10}** 

EFXEXT specifies which file extensions are to be encrypted. An encrypted file will be created if the following conditions are met: 

- The file is being created with either OPEN for output or ALLOCATE 

- The extension is in the EFSEXT list 

- A-Shell's Encrypted File System (EFS) is licensed and enabled 

- EFS has not been disabled via `XCALL ASFLAG,1024` 

Note that EFS is an entire system for file encryption and security. It is not included in the standard release of A-Shell, must be licensed as an option, and should be carefully considered before being implemented. If you are interested in implementing this filing system, see the documentation on the subroutine EFS and contact MicroSabio to discuss. 

A-Shell Reference 

Page 151 

## **ERSATZ** 

## **ERSATZ=Pathname** 

```
Example:  ERSATZ=C:\VM\MIAME\DSK0\001004\ERSATZ.INI
```

Ersatz devices are defined in ERSATZ definition files, which should be located in the file and path given (in host operating system format) in the ERSATZ directive lines. Any number of ERSATZ directive lines may be present in the configuration file. 

Ersatz definitions allows you to add to the list of definitions without having to close and re-launch the A-Shell session. If there are multiple ersatz definition files, only the last one can be updated this way while A-Shell is running. The way it works is that if A-Shell attempts to look up an ersatz definition and it is not found, and at least 30 seconds have passed since the last time it reloaded the ersatz definition file, in then reloads the last ersatz definition file to see if there are any new definitions. The 30 second limit is to prevent excessive thrashing if a rash of undefined ersatz names are encountered in sequence. 

Any ERSATZ devices containing CPU numbers will be ignored. 

The maximum number of ERSATZ device definitions allowed is 1000 for A-Shell/Unix and A-Shell/Windows/32. 

The maximum length of the ERSATZ filespec is 160 characters. 

## **Subtopics** 

- Ersatz Definition Files 

A-Shell Reference 

Page 152 

## **ERSATZ DEFINITION FILES** 

_Updated October 2014_ 

Ersatz devices are defined in one or more ersatz definition files, each of which is activated by a corresponding ERSATZ statement in miame.ini. By convention, these files are stored in the DSK0:[1,4] directory, with the first (and main) one being called 

ersatz.ini. If there are additional ersatz definition files, these are typically named xxxxx.ERZ where xxxxx is some kind of helpful allusion to the source or nature of the definitions contained in that file. 

Each ersatz definition file line must match one of the following formats: 

## **ersatz-device: =real-device:{[p,pn]}** 

## **++include real-device:file.erz{[p,pn]}** 

## **ersatz-device: =%INCDEV%:{[p,pn]}** 

## **Definitions** 

## _ersatz-device_ 

the name of the ersatz device being defined: one to ten alphabetic or numeric characters, starting with an alphabetic character, and immediately followed by a colon. 

## _real-device_ 

the name of a "real" device, defined via a DEVICE statement in miame.ini. It must be immediately preceded by the equals (=) symbol, and immediately followed by the colon. The real device names must be three or four alphabetic characters, followed by one or two numeric digits, with a maximum length of five combined characters. 

## _[p,pn]_ 

an optional directory. If not included, then the ersatz device name can be used just like a real-device name in file specifications, meaning that you can optionally include a [p,pn] at that time. 

## _file.erz_ 

A-Shell Reference 

Page 153 

an arbitrary file name and extension of another ersatz definition file to "include" (i.e. effectively insert) into the current file. Note that contrary to the normal convention of ersatz definition files being in DSK0:[1,4], the ++INCLUDE feature is most useful with ersatz definition files that are stored on some other device. See %INCDEV% below for more details. 

## _%INCDEV%_ 

This literal pseudo-environment variable may be used in place of a real-device reference within an ersatz definition file that has been ++INCLUDE'D, and will be interpreted as the real-device that was in the ++INCLUDE statement. See ERSATZ ++INCLUDE Statements for more details. 

Whenever A-Shell attempts to decode an DevPPN-style filespec, it compares the device part of the specification against the ersatz definitions first, before then comparing against the DEVICE definitions from miame.ini. So it is actually possible to "redirect" a real device by redefining it as an ersatz. For example, the ersatz definition DSK1:=DSK0: would effectively redirect all DSK1: references to DSK0:, even if DSK1: was a real device. 

If the device is not found in either the list of ersatz definitions or real device definitions, then the last loaded ersatz file (i.e. the one referenced in the last ERSATZ statement in miame.ini) will be reloaded, assuming that a minute has passed since the last time it was reloaded. So you can effectively add ersatz definitions without re-launching A-Shell, although the value of this is limited since re-launching A-Shell only takes a few seconds. 

## **Examples** 

Valid ersatz file entries look like this: 

```
SYS:=DSK0:[1,4]
```

```
LIB:    =DSK0:[7,0]
DSK100:  =DSK99:
AA12345678:=ZZZ12:[345,678]
```

The ersatz definition file that is distributed with A-Shell and invoked by default, ersatz.ini, looks like this: 

```
OPR:=DSK0:[1,2]
```

A-Shell Reference 

Page 154 

```
SYS:=DSK0:[1,4]
```

```
DVR:=DSK0:[1,6]
CMD:=DSK0:[2,2]
LIB:=DSK0:[7,0]
HLP:=DSK0:[7,1]
BOX:=DSK0:[7,2]
BAS:=DSK0:[7,6]
SBX:=DSK0:[7,6]
MAC:=DSK0:[7,7]
ASHCFG:=DSK0:[1,7]
PTR:=DSK0:[1,7]
ASHLPD:=DSK0:[1,25]
FAXWRK:=DSK0:[1,26]
ASHBAS:=DSK0:[907,6]
ASHINC:=DSK0:[907,16]
```

Another example: 

```
++include SOS6:SOSLIB.ERZ[1,4]
```

Within an ersatz definition file that has been ++INCLUDED, the following would be legal: `SOSFUNC:=%INCDEV%:[907,10]` 

A-Shell Reference 

Page 155 

## **History** 

- 2014 October, A Shell 6.1.1393: Add ++INCLUDE capabilities 

A-Shell Reference 

Page 156 

## **ERSATZ ++INCLUDE STATEMENTS** 

_Added October 2014_ 

ERSATZ definition enhancement: ersatz definition files may contain ++INCLUDE statements of the form: 

## **++INCLUDE dev:file.erz[p,pn]** 

In addition, the dev specified in the ++INCLUDE statement may then be referenced from within the included file using the pseudo-environment variable %INCDEV%, e.g. 

```
ADCJSON:=%INCDEV%:[907,10]
```

The combination of these two enhancements facilitates the ad-hoc addition of modular sets of current-device-relative ersatz definitions. As an example, for the 2014 A-Shell Developer Conference, we created a set of ersatz definitions, in the file ADC.ERZ: 

```
ADCARY:=%INCDEV%:[908,61]
ADCCGI:=%INCDEV%:[908,62]
```

```
ADCJSON:=%INCDEV%:[908,63]
```

Because there is no explicit device reference, these ersatz directories can be installed on any available device on the target machine, assuming no conflicting PPNs. Let's say we want to use an existing device DSK29:. To install the ersatz definitions copy the ADC.ERZ file to any ppn on DSK29, let's say DSK29:[1,2]. Then just add a ++INCLUDE reference to it in the main system ersatz.ini: 

```
++include DSK29:ADC.ERZ[1,2]
```

Note: "main system ersatz.ini" refers to last one referenced in miame.ini, since that is the only one that will be reprocessed on the fly, which is an essential part of this scheme. 

Now, without re-launching A-Shell, you can use those ersatz definitions, i.e. `LOG ADCJSON:` 

A-Shell Reference 

Page 157 

Aside from ad-hoc ersatz additions like this, the feature is also useful for maintaining different versions of the same ersatz definitions. For example, you might have a set of ersatz definitions for your application, but you also want to maintain two versions, the stable version and the development version. With this scheme, you can use a single app.erz file containing your ersatz definitions, and just install it and the associated directories on two different devices. By avoiding the need to explicitly reference the devices, you avoid the hassle of having to convert the device reference to match the actual device where you installed it, as well as the confusion that occurs when you forget to do that. 

**Warning:** If the applicable ERSATZ statement in miame.ini comes before the DEVICE statement that defines the device referenced in the ++INCLUDE, it won't be resolved until after A-Shell is launched and a subsequent reference is made to the ersatz. Failed references trigger a re-scan of the ersatz definitions, after a small time interval. So that generally isn't a problem. BUT, in the case of the APN.LIT compiler command line, it only gets one chance to define the ersatzes, so if you are using this technique, move the ERSATZ statement(s) below the DEVICE statements. 

## **History** 

- 2014 October, A Shell 6.1.1393: Add ++INCLUDE capabilities 

A-Shell Reference 

Page 158 

## **FILES** 

## **FILES=<# File buffers>,<# ISAM buffers>** 

```
Example:  FILES=40,40
```

In order to keep track of files opened within programs, A-Shell allocates internal file buffers within the _memory partition;_ see the MEMORY directive. Each file buffer requires approximately 80 bytes, and each ISAM buffer approximately 300 bytes. In order to save memory, or to support an extended number of files, the number of buffers may be changed, according to the following rules. Note that the buffer values refer to the maximum number of files which may be simultaneously open at any one time. 

ISAM buffers are only used for ISAM 1.x files. If your application makes use of only sequential, random, and ISAM PLUS files, the number of ISAM buffers may be set to zero. Sequential, random, and ISAM PLUS files require only a single FILE buffer each. An ISAM 1.X file requires two FILE buffers and one ISAM buffer for the initial open of the main index, while each subsequent secondary index requires just one FILE buffer, and one ISAM buffer. 

## **Notes** 

The default number of buffers is 40 FILE and 40 ISAM, in order to maintain compatibility with earlier versions of A-Shell. 

The FILES parameter only adjusts A-Shell’s internal resource allocations; you may need to adjust the parameters for your operating system locking mechanism to allocate enough locking resources for large numbers of open files. 

The operating system and/or environment may further impose limits on the maximum number of open files. Under Unix, there are typically kernel configuration variables which set the limit, although it may be further limited by the shell. 

A-Shell Reference 

Page 159 

## **FKEYWAIT** 

## **FKEYWAIT=<# ms>** 

```
Example:  FKEYWAIT=50
```

(Unix Only) Most "function keys" send multiple bytes. In order to distinguish between a true multi-byte sequence and a series of individual single-byte keystrokes, A-Shell considers the time delay between the first byte (the "leadin") and the following byte. In practice, this means that whenever A-Shell sees a byte that could be a "leadin" (typically ESCAPE or CTRL+A), it does a timed input operation for the next byte. If one or more bytes arrive within the specified interval, then it is considered a multi-byte sequence, otherwise the initial byte is treated as a stand-alone character. Under normal circumstances, the default five milliseconds wait is sufficient, but still short enough that you don’t notice the delay. However, in some cases, the delay between the "leadin" and the following bytes can be substantially longer. One example of this occurs when using rlogin instead of telnet to log into a remote system. In that case, you may need to specify a much longer delay, perhaps as much as 200 ms. 

If the FKEYWAIT value is too short, function keys may stop working properly, and will instead typically put some kind of garbage on the screen. However, the longer the wait, the longer you have to wait before an individual ESCAPE or CTRL+A is acted on. For example, in VUE, the ESCAPE character switches between edit and command mode. If you like to switch quickly between these modes, you may find that a 200 ms delay in response to the ESCAPE key is unbearable. So the advice is to use experimentation to get the FKEYWAIT value as low as possible without causing your function keys to break up. 

Since the required FKEYWAIT value may change from terminal to terminal, you may also change this on a job-by-job value at runtime using SET; type `SET /?` from the A-Shell prompt to display help info. 

A-Shell Reference 

Page 160 

## **FLDATTR** 

## **FLDATTR=ON/OFF     (default is ON)** 

FLDATTR is used to disable "field" attributes, to avoid display problems caused by programs assuming "field" emulation, when the actual display device is operating as a "mode" terminal. See FIELDEMU under OPTIONS for a discussion of the difference between "field" and "mode" emulations. 

When FLDATTR is off, "field" attribute commands, such as reverse video and underline, are ignored. Doing without your reverse video and underline highlights is better than having them spill over the screen incorrectly, as would otherwise happen if your application was not written to support both field and mode emulations. 

`FLDATTR=OFF` is equivalent to `OPTIONS=NOFLDATTR` . 

A-Shell Reference 

Page 161 

## **FONT** 

## **FONT=<facename> {,<symbol set>}** 

```
Examples:  FONT=Courier New   (default)
```

```
           FONT=Lucida Console, ANSI
```

Under A-Shell/Windows, FONT may be used to specify two aspects of the font: the face name and the symbol set. The face is the name that appears in standard font selection dialog boxes (including the one on A-Shell's Edit menu), such as Courier New or Lucida Console. It is case sensitive. If not specified, A-Shell will select what it thinks is the best font from the available choices— i.e., those installed on this system. Common choices are Courier New, Lucida Console, and Consolas.. 

The symbol set may optionally be specified as OEM, ANSI, or DEFAULT. If not specified, OEM is used. 

The face name will be overridden by a font specified in the default.ash or other settings file. See the –Settings File switch and the Settings Menu...Font topic for more details. However, the symbol set will affect all subsequent font selections, even overriding a previously saved font in the settings file. 

The only fonts suitable for A-Shell are those that offer a fixed pitch, so that typically limits you to Courier New, Lucida Console, and Consolas. Miame Terminal and Andale Mono were frequently used in older versions of Windows and A-Shell, but they are no longer convenient; Miame Terminal because it is a bitmap font that doesn't scale well, and Andale because it is available only for a fee. 

The symbol set determines which characters are available and how they are numbered. Most of the fixed pitch fonts support both OEM and ANSI. Fortunately, both character sets use the same values for the ASCII printable characters 32-127, so it probably makes little difference in most applications which one you use. Furthermore, both character sets include the Latin1 characters in the range 128-255, and although they are mapped differently, if you specify OPTIONS=LATIN1 A-Shell will convert both mappings to match the Latin1 mapping used under AMOS (such as with the AM65A terminal). 

Historically, the main problem with the ANSI character set in A-Shell was that it didn't include the line drawing characters, but this is no longer an issue since A-Shell renders them graphically. The only remaining shortcoming is its lack of a few special characters available in the alternate character set via TAB(-1,65) thru TAB(-1,77) commands (raised dot, end of line, horizontal tab, paragraph, dagger, section, cent, quarter, half, trademark, copyright, register mark). On the other hand, the OEM character 

A-Shell Reference 

Page 162 

sets (except for the MIAME Terminal version) do not include a Euro symbol. With ANSI , you can display a Euro symbol via TAB(-1,253) or chr(128). 

Note that Windows applications such as A-Shell can only make "requests" for a particular font. The system then provides a font that is the best match for the requirements given. Thus, you can easily end up with an unexpected font if your system does not have the requested font installed. For example, if you ask for Andale Mono but it isn't installed, it should try to select something with similar capabilities, hopefully (but not necessarily) ending up with a font reasonably like Courier New. 

## **Comments** 

- The actual font and symbol set in use is identified on the A-Shell/Windows Help...About box. 

- In order to use a national replacement character set, you must specify the OEM symbol set. See the CONSOLESP and 

- CHARSETSP parameters. 

A-Shell Reference 

Page 163 

## **IATIMEOUT** 

_Updated May 2025; see History_ 

## **IATIMEOUT=<minutes>** 

```
Example:  IATIMEOUT=60
```

IATIMEOUT activates an inactivity timer that will shut down a session if it has been inactive—no keyboard input or ASB/LIT instructions—for at least <minutes>. In practice, the actual delay until the timeout is detected and the job is shutdown may be as much as twice the specified number of minutes. The default value is 0, meaning no inactivity timer. 

The –cgi command line switch automatically sets the IATIMEOUT to 7 seconds. 

See _History_ note below. 

## **Comments** 

The process of determining whether a session is truly inactive is fairly complicated. Since the objective is to close down jobs that have obviously been abandoned, rather than precisely limit users to N minutes of inactivity, the timing program was built to err on the side of too long rather than too short. Consequently, as mentioned above, the actual timeout period may be quite a bit longer than the setting. 

## **See Also** 

- AG_IATIMEOUT 

- MX_IATIMEOUT 

## **History** 

- 2025 May, A Shell 1772: When the inactivity timer expires, as long as the session is running an application program and not waiting on an ATE operation (e.g. XTREE, GUI INFLD, etc.), it will now beep and present a message box telling the user the session is about to time out, allowing up to 10 seconds to cancel the timeout. In addition, provided the SIGHUP TRACE option is enabled, inactivity checkpoint messages will be added to the ashlog for periods of inactivity lasting 1/4 of the IATIMEOUT value. This improves forensic confidence that the timeout is working as expected, as users are often doubtful!. 

A-Shell Reference 

Page 164 

## **IJCFREQ** 

## **IJCFREQ=<seconds>** 

```
Example:  IJCFREQ=10
```

IJCFREQ activates a timer interrupt that checks for "Inter Job Communication" (IJC) messages. These include inactivity timeout checks (see IATIMEOUT), and SEND.LIT and KILL.LIT under A-Shell/Windows. (The Unix version of these commands uses the more powerful and direct Unix signals.) The default value is automatically determined based on the number of users licensed, and will be in the range of 5 to 30 seconds. To disable the timer and the corresponding functions, set IJCFREQ to zero. Note that in the Windows world, checking for IJC messages involves reading a record from jobtbl.sys on the server, and thus you don’t want to make it any more frequent than necessary. But if you set the value too high, you could have to wait for a long time to get a response from a KILL or SEND command. 

A-Shell Reference 

Page 165 

## **INCLUDE** 

## **INCLUDE=filename** 

```
Example:  INCLUDE=f:\miame\trmdef.ini
```

INCLUDE is the equivalent of the C #include or the ASB ++INCLUDE directive. It forces the inclusion at that point of another file which itself contains any of the valid configuration file commands, with the exception of INCLUDE itself. 

The typical use of this directive is to reference a file containing TRMDEF statements, as shown in the example above. 

Another way you might use this directive is to separate the statements which may differ from one user to another from the main body of miame.ini. 

Note that most users can get by without including a trmdef.ini file, since A-Shell will, by default, generate names of the form TSKAAA, TSKAAB, etc., for the jobs and terminals as needed. trmdef.ini is only relevant if you want to predefine certain job and/or terminal names to be associated with specific terminal devices. 

The INCLUDE directive may replace the SERIAL[SP] directive as the first line of the file, provided that the file being included starts with a SERIAL line. This is useful if you want to have identical miame.ini files across many systems, each referencing a separate file for the SERIAL information, i.e. `INCLUDE=SERIAL.INC` . 

A-Shell Reference 

Page 166 

## **JOBPREFIX** 

## **JOBPREFIX=<up to 3 prefix characters>** 

```
Example:  JOBPREFIX=JOB
```

```
Default:  JOBPREFIX=TSK
```

JOBPREFIX allows you to override the default jobname prefix ("TSK") which is used to generate unique job names. The prefix is normally 3 characters, to which A-Shell appends a sequentially generated suffix (e.g. "AAA", "AAB", etc.) resulting in job names like TSKAAA, TSKAAB, TSKAAC, etc. 

Job names can also be specified by the TRMDEF statement or by use of the `–j <jobname>` command line argument. 

A-Shell Reference 

Page 167 

## **LANGUAGE** 

_Rewritten December 2023_ 

## **LANGUAGE=pathname** 

A-Shell uses a language definition file (aka LDF) to define certain language- and locale- dependent parameters, such as: 

- translations of words for dates, yes/no, etc. 

- numeric formatting: use of commas, decimal points, currency symbol 

- date formatting: month-day-year vs day-month-year, separators 

- collating sequence 

The specified _pathname_ must be fully qualified; by convention the LDF files are stored in the equivalent of DSK0:[1,6]. 

The LDF file format is equivalent to the AMOS 2.x language definition file format. Several standard variations are supplied with A-Shell: ENGLSH, BRTISH, FRENCH, FRANGL, PORTUG, SPANSH, ITALIA, etc. Contact MicroSabio for information on creating your own variants. 

A-Shell automatically relies on the LDF for several built-in functions such as those mentioned above. Applications may also query the LDF via the GTLANG subroutine, which see for a list of the specific parameters. 

## **Examples** 

```
LANGUAGE=C:\VM\MIAME\DSK0\001006\ENGLSH.LDF
```

```
LANGUAGE=/vm/miame/dsk0/001004/brtish.ldf
```

## **See Also** 

- SET 

- GTLANG 

A-Shell Reference 

Page 168 

- DATES 

- IDTIM 

- ODTIM 

- VAL() 

- USING 

## **History** 

- 2009 January, A Shell 5.1.1136:  LDF enhancements: New LDF files (each named by appending an "X" to the existing name) have been created to add a standard Latin 1 character collating sequence for the upper 128 characters. This may be an interim measure until we decide whether there is any reason not to just update the standard LDFs with the collating sequence. Until then, if you are interested in the collating sequence, either rename the "X" version to the standard name, or change the ERSATZ statement in miame.ini to reference the "X" version of the LDF. 

A-Shell Reference 

Page 169 

## **LOGDIR** 

## **LOGDIR=<native directory specification>** 

```
Examples:  LOGDIR=/vm/miame/dsk0/001002
```

LOGDIR allows you to specify a directory for the A-Shell log file (ashlog.log); absent any such specification, the log will be found in the same directory as miame.ini.  You must specify a directory using native operating system syntax, but you may optionally include environment variable names (such as $MIAME in one of the examples above.) 

A-Shell Reference 

Page 170 

## **LOKSER** 

_Rewritten June 2023_ 

## **LOKSER=['ON' | 'OFF'] {,FORCE_WRITE}** 

This directive specifies whether LOKSER is to be activated. LOKSER is a file locking scheme involving a combination of OS-level locking operations and rules governing file access. When _not_ enabled, all file operations are lock-free from the standpoint of the operating system, requiring applications to employ some other kind of A-Shell locking mechanism such as XLOCK or FLOCK in order to coordinate multi-user access. 

When LOKSER is enabled: 

- Random files opened in mode RANDOM are effectively opened exclusively. 

- Random files opened in mode RANDOM'FORCED are shared 

- In shared mode, the READ statement reads without locking while READL reads and locks the record. WRITE unlocks the record after writing (requiring a prior READL), while WRITEL locks, writes, and then unlocks. UNLOKR can be used to unlock a record without writing. 

- Attempts to read a locked record, or to open a file in a mode that conflicts with another user already having the file open, unless the WAIT'FILE or WAIT'RECORD option is specified on the open, will generate one of the LOKSER-related errors 37 (file in use) or 38 (record in use). 

- Other LOKSER-related errors include 42 (record not locked) and 44 (LOKSER queue full due to too many locks being held at once). 

- ISAM sequence checking—a set of rules dictating the sequence of ISAM File Statements—is activated, generating ISAM error 39 on any violation. 

ISAM-A operations always act as if LOKSER is enabled, i.e. they use OS-level file locking regardless of the LOKSER setting. However, they do respect the FORCE_WRITE option if enabled. 

A-Shell Reference 

Page 171 

The FORCE_WRITE option requests that file updates be flushed to disk immediately. It is generally supported for random file WRITE operations under Windows, and for ISAM-A operations in all environments. But it drastically slows down performance and thus is not recommended. 

A-Shell Reference 

Page 172 

## **MALLOCLIMIT** 

## **MALLOCLIMIT=<size in bytes>** 

```
Examples:  MALLOCLIMIT=32M
```

MALLOCLIMIT is useful for changing the default dynamic memory allocation limit of 8MB. This mainly affects sorting, which, if the SBR=MALLOCSORT option is specified (which see), can allocate and take advantage of large amounts of memory. A situation where you might want to increase the limit would be under Windows (where you probably have huge amounts of physical memory per workstation) if you were sorting files larger than 8MB. For example, if you were often sorting files of up to 32MB in size, setting the MALLOCLIMIT to 32M would make sure sorts run many times faster. A situation where you might want to decrease the default MALLOCLIMIT would be on a large, older, multi-user Unix system where memory might be a bit tight. Although any memory allocated for sorting would be released back to the system pool as soon as the sort was complete, Unix systems often will delay making the memory available to another process until the situation becomes desperate. This is based on the historical case where Unix processes tended to be short-lived, and thus efficiencies could be gained by delaying all memory cleanup until the process exited. 

The MALLOCLIMIT limit will also affect the size of the largest file that can be brought entirely into memory by the VUE editor. 

Note that the limit is stored as a 32 bit unsigned variable in units of bytes, so it will wrap back to zero at 4096M. Thus the maximum value is 4095M. 

A-Shell Reference 

Page 173 

## **MAPIDA** 

## **MAPIDA='ON' | 'OFF'** 

Under AMOS, ISAM Plus files are given the same extensions as their ISAM 1.x counterparts, namely .IDA for the data files and .IDX for the index files. Under A-Shell, however, C-ISAM or D-ISAM are used to implement ISAM Plus. This gives the data files extension .DAT; the index files have the same extension. 

Many programs are likely to use the LOOKUP and KILL statements on ISAM Plus data files. If MAPIDA is specified as true, then an extension of .IDA will be mapped onto an extension of .DAT if no file with extension .IDA exists. 

Care must be taken specifying MAPIDA if ISAM 1.x applications are to run concurrently with ISAM Plus. It is possible that some minor programming changes will be required in terms of LOOKUP and KILL. 

A-Shell Reference 

Page 174 

## **MAXINST** 

## **MAXINST=##** 

```
Example:  MAXINST=1
```

(Windows only)  MAXINST allows you to limit the number of A-Shell windows or sessions that can be run simultaneously on one workstation. If not specified, then there is no particular limit. The main reason for setting a limit, especially a limit of one, would be to eliminate the confusion that arises when inexperienced users don’t realize they have a session already going (perhaps because it is minimized) and so they open another, perhaps repeatedly. This, by itself, is not a problem for A-Shell, but it may be a problem for the application, if, for example, the user has a record locked in one of the sessions and then leaves it there indefinitely because they forgot about the session. 

A-Shell Reference 

Page 175 

## **MAXJOBS** 

## **MAXJOBS=##      ; set job table size to ##** 

## **MAXJOBS=*##     ; set size to ## times licensed nodes** 

MAXJOBS specifies the maximum size of the job table (jobtbl.sys). jobtbl.sys gets automatically allocated to this size whenever an instance of A-Shell is launched and there is no pre-existing jobtbl.sys. (Like qflock.sys, it gets removed automatically as well when there are no active A-Shell jobs, and can be removed manually if for some reason the automatic removal fails and you want to re-initialize it.) If you fill up the job table, the next attempt to launch an instance of A-Shell will get a job table full error. However, you can fix that by simply adjusting the MAXJOBS parameter and launching A-Shell again, at which point it will expand the table. (It is not necessary to get all users out to perform this expansion.) The second form of the directive is preferable since it results in the file automatically expanding as you increase the number of licensed nodes. The only penalty for making the job table excessively large is the few extra microseconds it takes to scan the table when looking for active jobs (so when in doubt, make it larger.) If you don’t specify a MAXJOBS parameter, a complicated and classified formula will be applied to arrive at a reasonable size. 

A-Shell Reference 

Page 176 

## **MAXLOCKS** 

## **MAXLOCKS=##** 

```
Example:  MAXLOCKS=500
```

MAXLOCKS specifies the maximum number of locks (per job) that A-Shell will keep track of for enforcing the LOKSER rules on ISAMPLUS UPDATE'RECORD and DELETE'RECORD operations. According to the rules under AMOS, UPDATE'RECORD and DELETE'RECORD must only be used on records that were previously locked, and it uses the LOKSER lock queue to enforce this. A-Shell implements LOKSER via the natural locking facility of the native operating system, which does not permit it to easily scan the lock list. Thus it uses its own internal list to keep track of which records have been locked. 

The default for MAXLOCKS is 100, which should be more than enough in most cases. The only likely reasons why you might want to override this would be if you wanted to disable the rule (i.e. allow unlocked records to be updated or deleted, even when LOKSER is on.), in which case you would specify MAXLOCKS=0, or if your application allowed a user to lock more than 100 records at a time, in which case specify an appropriately large number. The lock list requires 8 bytes per lock, and is allocated separately from the memory partition and thus does not subtract from any other specified allocation size. 

A-Shell Reference 

Page 177 

## **MEMORY** 

## **MEMORY=<workmem size>{,sbxmem size{,cachelimit}}** 

```
Examples:   MEMORY=700K
            MEMORY=700K,200K
```

```
            MEMORY=2M,400K,500K
```

MEMORY configures certain memory allocation sizes used by each A-Shell user. 

The first number specifies the size of the ASB work area. If no MEMORY statement is specified, the default work area size is 512K. This work area is used for a variety of purposes, including variable storage, the CALL/RETURN stack, allocation of dynamic arrays, string stack, and if sufficient in size, for sorting files, and compiling, and editing programs. 

The ASB MEM() function displays the amount of free memory available in the main work area. Note, however, the program itself —and any modules loaded by the LOAD command—is stored in dynamically allocated memory outside of the ASB work area. 

The second parameter specifies the amount of memory to be provided for any SBX subroutine call. If not specified, the default is 384K. In either case, if the main work area has sufficient free space at the time the subroutine is executed, then that will be used instead. (So if you call a lot of SBX routines, it might be more efficient to make your main work area large enough to accommodate the needs of your largest SBX.) 

The last parameter specifies the maximum amount of memory to be set aside for caching of SBX subroutines and other modules that are automatically loaded on demand. The default is 200K. Such modules are kept in memory for a period of about 10 minutes after their last access, or until the specified limit is exceeded. At that point, modules are discarded on a LRU (least recently used) basis. 

## **Notes** 

A number of A-Shell operations that require additional memory, such as BASORT, COMPIL.LIT, and VUE.LIT, may take the liberty of allocating it outside of the ASB work area. See the MALLOCLIMIT directive for details on limiting those allocations. 

A-Shell Reference 

Page 178 

The minimum practical amount of memory to execute many of the system commands is about 350K. 

You can also specify the memory size on the A-Shell command line. 

## **History** 

- 2016 July, A Shell 6.3.1518: Memory enhancement: Move the string expression stack out of the main partition into a separate module which now auto-expands as needed. This should eliminate the most common and yet most unpredictable cause of outof-memory (or stack-overflow) errors, which are related to operations on strings whose size is not obvious or easily predictable. 

The main partition (specified by the first and/or second values in the MEMORY statement) is now used mainly for mapped variable storage, call stack, and command files. The actual RUN files are loaded separately. `SYSTAT/M` shows the minimum available memory in the partition since the beginning of the session, allowing you to perhaps gauge how much larger-thannecessary your partition allocation is. 

A-Shell Reference 

Page 179 

## **MMAPLIST** 

## **MMAPLIST=<fspec>** 

(Unix only) MMAPLIST allows you to specify a list of files that should automatically be memory-mapped whenever they are opened. _<fspec>_ should be a fully qualified filespec, although it may contain environment variables using the %ENVVAR% syntax. The specified file should contain a list of DevPPN-style or native filespecs, one per line, for the files you want to automatically memory-map. Blank lines are ignored, and anything after a number sign (#) is treated as a comment. Ersatz devices are allowed. For example: 

```
#List of files to be memory mapped
```

```
c:\vm\miame\dsk0\100005\myfile.dat # native allowed
```

```
MYAPP:MYDATA.DAT    # ersatz allowed
DSK0:MYIDX.DAT[100,5]  # standard DevPPN allowed
```

The above list specifies three files to be memory mapped whenever they are opened. Note that DevPPN specifications are recommended over native ones since they are not sensitive to changes in the device definitions. In the example above, the device where MYAPP: is could be redefined without having to change the MYAPP: reference in this file. But if c:\vm\miame was relocated to d:\vm\miame, you would have to remember to also edit this file to fix the native filespec. 

Memory mapping gives you much better file i/o throughput, at the cost of more memory usage. It works best on files that have a lot of access relative to their size (SERCH index files are a particularly good example.) There are other ways to memory map files, such as using the subroutine ASFLAG or by loading the files directly into memory and using OPTIONS=AUTO_MEMOPEN in miame.ini. This method has the advantage of being entirely independent of your application, allowing you to tune your system or just experiment with memory mapping, without making any changes to the application itself. 

A-Shell Reference 

Page 180 

## **NOTRACE** 

_Written January 2024_ 

## **NOTRACE=name1,name2,...** 

NOTRACE disables specific traces that have been more generally enabled. It only supports XCALL traces; so if TRACE=XCALL, 

either in the miame.ini or at run time via the SET command or system message window, the names listed in NOTRACE will still not be traced. 

You may have any number of NOTRACE directives, and each one can have one or more XCALL names listed, but they must be comma-delimited, with no spaces. For example: 

```
NOTRACE=TRIM,FILL,MIAMEX,STRIP
```

## **History** 

- 2024 January, A Shell 7.0.1754:  Function added to A-Shell. 

A-Shell Reference 

Page 181 

## **OPTIONS** 

_Updated December 2013 (Added STR0)_ 

## **OPTIONS=option {,option} {,option}...** 

The OPTIONS directive is used to set various options that don’t fall neatly into another category. You can specify several options on a single line separated by commas, or you can specify them using multiple OPTIONS directives. 

Note also that the values for these options may be queried or changed by the subroutines MX_GETOPTIONS or MX_SETOPTIONS. 

|**Options**|**Description**|
|---|---|
|ABSLOOKUP|CausesLOOKUP()to return a positive value.|
|ASHELL_RUNSBR|CausesASHELLXSto execute commands as true subroutines.|
|AS400|Special AS400 Telnet option.|
|AUTO_MEMOPEN|Causes OPEN to see if file is already in memory.|
|AUTOTPRINT|Causes PRINT statements to act likeProportional Font Text Objects<br>—i.e., create static text controls).|
|BRKALC|Pre-fill random files with ]]]]]]].|
|CRLF|Terminate sequential files with CRLF.|
|CRNL|Same as CRLF.|



A-Shell Reference 

Page 182 

|**Options**|**Description**|
|---|---|
|AUTODLGSTATE|Make the MBF2_DLGSTATE option be the default for all dialogs. If you set it as the default, the only way to turn it off for<br>individual dialogs would be to useMX_SETOPTIONS<br> (GOP2_AUTODLGSTATE ) to clear the flag before creating the dialog.|
|EFFUSR|Returns "effective user name."|
|EFS|Various options related to "EFS," A-Shell's encrypted file system|
|EXITWAIT|Causes A-Shell to wait for a keyboard response before closing the window down due to the –e switch, thus giving you a<br>chance to read any final screen messages before the window is destroyed.|
|EXTFIO|Allows access to contiguous files that are NOT a multiple of 512 bytes.|
|FSPECNATIVE|Allow more flexibility for native file specs.|
|FIELDEMU|Emulate field terminal attributes.|
|FPROUND|Apply rounding factor of .000005 to INT and FIX.|
|GUI_SPC_IND|Tokenizes horizontal fixed-pitch spacing for use in variable-spacing GUI screens|
|HEXDEC|Special hexadecade date processing.|
|ISAM_IDXLOK|Causes the entire ISAM index file to be locked whenever it would otherwise only be necessary to lock the "rock" (i.e.<br>during index update operations.) For reasons that no one understands, this actually seems to give better results in some<br>Windows network environments.|
|LATIN1|Remap OEM character set to Latin1.|



A-Shell Reference 

Page 183 

|**Options**|**Description**|
|---|---|
|||
|LONGDIR|CausesDIR.LITto use the 10.4 format by default. Equivalent to system command SET LONGDIR.|
|NOAUTOX|Disables auto expansion of ISAM & INMEMO files; same as NOISAM_AUTOX.|
|NOAUTOXLT|(Windows only) Disables the automatic translation of thePG-UPandPG-DNkeys under A-Shell/Windows toCTRL+Rand<br>CTRL+T. This way you could translate the keys to something else. SeeFIXTRN.LIT<br>.|
|NOFLDATTR|Discards field attributes.|
|NOINSTRX_PCP|NoINSTR<br> precompiled patterns.|
|NOISAM_AUTOX|Disables auto expansion of ISAM and INMEMO files; same as NOAUTOX.|
|NOJOBMAP|(Unix only) Preventsjobtbl.sysfrom being memory mapped. Normallyjobtbl.syswill be memory mapped or not<br>depending on whetherqfock.sys(i.e. whether the QUEUE= parameter specifies "DISK" or "MEM"). The option is mainly<br>of interest for debugging or other exotic situations.|
|NOSPACEATTR|Eliminates the automatic space associated with the on/off field attributes.|
|NOWHEEL|Disables the otherwise automatic conversion of the mouse wheel events intoUP/DOWN-ARROWkey presses.|
|NOXABORT|Prevents user from closing window containing an active program.|



A-Shell Reference 

Page 184 

|**Options**|**Description**|
|---|---|
|NTTS|Identifies A-Shell instances like NT Terminal Server sessions.|
|NUMPAD_COMMA|Converts the "." key on the number pad to a comma for the convenience of locales which use comma as the decimal<br>point.|
|RAWTABS|(Unix variants only) Causes A-Shell to output raw tab characters rather than converting them to spaces. It would only<br>be useful if your terminal emulator had some kind of special tab handling feature.|
|RC_DIMX|Tells the compiler to allowDIMXstatements in /RC mode.|
|SBX_RUNDIR|Alters the search path for SBX modules.|
|SEQLOK|Enables locking on sequential files for Unix.|
|STR0|Causes numeric conversions to string, whether implicit or explicit, via str(x), to retain the leading zero for fractional<br>values between -1 and 1. Normally the leading zero is stripped in all cases. For example, if x=0.5 and y=-0.3, str(x) and<br>str(y) would normally return ".5" and "-.3" respectively, whereas with<br>`OPTIONS=STR0`set, the output would be "0.5"<br>and "-0.3".|
|STRICT|Causes A-Shell to emulate various AMOS functions.|
|TRKTOPSTS|Causes PolyShell to treat the top status line as part of the screen.|
|XABORT|Generates error 255 when user tries to close window if program running.|
|XTAUTOFILTER|Automatically sets the XTF2_AUTOFILTER flag for allXTREEcalls, enablesXTREEauto-filtering.|



A-Shell Reference 

Page 185 

## **History** 

- 2013 December, A Shell 1369:  Add STR0. 

A-Shell Reference 

Page 186 

## **ABSLOOKUP** 

This option causes the ASB LOOKUP statement (and corresponding BASIC _plus_ function) to always return a positive value. Otherwise, in order to more closely mimic AMOS, it will return a negative value if the file is an exact multiple of 512 bytes (since this makes it most likely that the file was originally random or contiguous, and thus you would have returned a negative LOOKUP value under AMOS.) Note that while this is a nice trick, it is not infallible, since the chances are 1 out of 512 that a sequential file will also be an exact multiple of 512 bytes. We strongly recommend that you review the use of LOOKUP in your programs and convert your logic to use ABS() to convert negative values to positive, rather than simply negating the value. 

A-Shell Reference 

Page 187 

## **ASHELL_RUNSBR** 

Note: this switch was previously known as AMOS_RUNSBR. 

This switch causes ASHELLXS (previously known as AMOSXS which is still supported) to execute most commands (anything except CMD and DO files) as true subroutines within the current process, rather than in another process, as would otherwise be the normal behavior for A-Shell. For example, `XCALL ASHELL,"RUN XYZ"` would run the XYZ program within the current process, using the current job environment. This is how most versions of AMOS.SBR worked under the old AMOS operating system. CMD and DO files cannot be executed within the current process, so they will run in a separate process regardless of the ASHELL_RUNSBR switch. 

Aside from making the A-Shell version of ASHELLXS act more like the original AMOS versions of AMOS.SBR, the other advantage of the ASHELL_RUNSBR switch is that it is much more efficient. We recommend that you use this switch, and would have made it the default behavior, except for historical compatibility. There may be situations where the use of a separate process is actually better, particularly when you don’t want side effects from the subroutine process to linger, either on the screen or in the job’s current environment. For example, any screen output generated by the subroutine will remain on the screen after return to the caller if the subroutine executes within the current job/process. Otherwise, the screen output of the subroutine will appear in a different window, or in a different virtual screen, which will be discarded when it returns. Similarly, any changes to the job’s environment, such as the current PPN or other status settings will be discarded if the subroutine executes in a separate process, but will be retained if the subroutine executes within the current process. For example, consider: 

```
xcall ASHELL,"LOG DSK1:100,2"
```

```
xcall ASHELL,"SET HEX"
```

The commands above make no sense if `OPTIONS=ASHELL_RUNSBR` is not specified, since the effect of the command (changing the ppn or a job status setting) would otherwise be lost as soon as the command completed, since it would be taking place in a separate job and process from the caller. 

When Xcall ASHELL runs a command within the current job, it guarantees the child process will have a certain amount of memory, even if it has to be specifically allocated on the fly. The amount defaults to 360K, but can be specified with the second SP argument to the MEMORY parameter in miame.ini. 

A-Shell Reference 

Page 188 

## **AS400** 

(Unix only) This is a rather weird option that was implemented to overcome some kind of shortcoming in the AS400 implementation of Telnet, and would only apply (if then) in a situation where AS400 users were connecting via Telnet to A-Shell running on a Unix machine. The problem was that when the user typed too fast, bursts of BACKSPACE and other control characters would mysteriously be dumped into the input buffer. With this option turned on, A-Shell filters those characters out. 

A-Shell Reference 

Page 189 

## **AUTO_MEMOPEN** 

This option causes every ASB random file OPEN to first check to see if the file being opened is already in memory. If so, it accesses the memory copy as if the filespec had specified MEM: directly. 

The idea of this option is that it permits you to experiment with, or take advantage of the MEM: device (described above) without actually modifying your programs to specify MEM: in the file open statements. 

For example, consider the following open statement: 

```
OPEN #CH, "DSK2:MYFILE.DAT[123,222]",RANDOM,RSIZE,RFILE
```

If `OPTIONS=AUTO_MEMOPEN` is set, then the OPEN will first check to see if myfile.dat is in user memory. If not, then it works normally. But if it is, then it uses the memory copy. So to make a particular report program run faster, you could just manually load the file (e.g. . `LOG DSK2:MYFILE.DAT[123,222]` ) before running the program. 

It must be noted that this is only practical for files that are not updated by a program. Any updates would be written to memory, not disk. Caution should be exercised to make sure you don't inadvertently leave the file in memory and then run a program that performs updates on it, thinking the updates were being written to disk. 

## **Comments** 

AUTO_MEMOPEN also applies to sequential input files ( `OPEN #CH, FILE$, INPUT` ) and LOOKUP. See DEVICE for details on defining the MEM: device. 

A-Shell Reference 

Page 190 

## **AUTOTPRINT** 

This option causes all PRINT statements in RUN programs to be treated as Proportional Font Text Objects. In other words, they will generate static text, proportional font controls. This can be useful for quickly establishing how well your application would work with all proportional fonts. (It can also be turned on and off with SET, i.e. `SET {NO}AUTOTPRINT` .) 

A-Shell Reference 

Page 191 

## **BRKALC** 

This option causes A-Shell to pre-fill random files with a repeating pattern of close square brackets "]]]]]]]]]]]]]..." when they are allocated. 

## **History** 

- 2009 October, A Shell 5.1.1163: BRKALC outputs **all and only** brackets to the file. Previously, it output "MIAME" after every 27 brackets. This was useful in some cases for visually confirming that the file was allocated by A-Shell, but undermined one of the purposes of filling a new file with brackets (to make unwritten records sort to the end). 

The old documentation said: "This option causes A-Shell to pre-fill random files with a repeating pattern of close square brackets "]]]]]]]]]]]]]]]]]]]]]]]]]]]MIAME" when then are allocated. In the early days of A-Shell this was the default, but it is not necessary for AMOS compatibility and slows down (slightly) the process of allocating a new file, so it is now available only by setting this option." 

A-Shell Reference 

Page 192 

## **CRLF** 

(Unix only) This option forces A-Shell/Unix to terminate sequential file print lines with CRLF (e.g. 0x0D 0x0A) instead of the normal NL or LF (0x0A) used under Unix. There are two good reasons why you might want to use this option. One is in a situation where you are creating files under Unix that you want to share with some other operating systems that require the CRLF line terminators (like Windows, DOS, or AMOS.) Since the INPUT LINE statement is implemented under A-Shell in such a way as to throw away superfluous CR line terminators (if immediately followed by a LF), the addition of the extra CR on the end of print lines will not adversely impact A-Shell. The second reason is that you are having trouble getting your Unix printers to automatically supply the carriage return when goes with each new line. Although this can generally be handled by a filter, having A-Shell simply add the necessary CR for you is an acceptable approach in some cases. 

A-Shell Reference 

Page 193 

## **EFFUSR** 

This option (short for "Effective User") also applies only under Unix implementations, in which case it forces A-Shell to return the "effective user name" instead of the "login user name" in any function that requires this information such as the SYSTAT system command. 

A-Shell Reference 

Page 194 

## **EFS OPTION** 

_Reviewed August 2016_ 

## Following are the various EFS_xxx options that may be used in conjunction with A-Shell's encrypted file system. 

|**Options**|**Description**|
|---|---|
|EFS_OUT_AMOS|This causes any output file (sequential) which is created using an DevPPN-style name<br>to be automatically encrypted. (e.g.<br>`OPEN #1, "REPORT.PRT", OUTPUT`)|
|EFS_OUT_HOST|This causes any output file (sequential) which is created using a Unix-style name to be<br>automatically encrypted. (e.g.<br>`OPEN #1, "/tmp/report.prt", OUTPUT`)|
|EFS_ALLOCATE|This causes theALLOCATEfunction (to create a contiguous file) to automatically<br>encrypt it.|
|EFS_ALCINDEX|This causes the ISAM-A ALLOCATE'INDEXED command (to create a new ISAM-A file)<br>to automatically encrypt it.|



A-Shell Reference 

Page 195 

## **EXTFIO** 

This option (short for "Extended File I/O") relaxes the normal A-Shell regulation that any file opened for RANDOM (contiguous) access must be an exact multiple of 512 bytes in length. This might be handy if you want to use ASB to read/write some kind of unstructured binary data. It also removes certain AMOS peculiarities which seem of dubious value, such as the automatic stripping of isolated carriage returns from strings in INPUT and INPUT LINE statements. 

A-Shell Reference 

Page 196 

## **FIELDEMU** 

(Windows only) This option causes A-Shell/Windows to emulate 'field' attributes (i.e. like the AM62A) rather than the 'mode' attributes which are otherwise normal under Windows (as well as the AM65 and VTxxx terminals.) In the normal 'mode' operation, all video attributes (such as reverse and underline) work just like dim and bright, except that the on and off commands cause a space to be output (unlike dim and bright, which do not.) That is, the attribute for a character is determined by the chronological sequence of attribute commands which preceded the display of the character. 

When the FIELDEMU option is active, the attribute for a character is determined by the position of that character on the screen relative to attribute on/off commands which may be embedded in the display. The chronological sequence of the commands has nothing to do with it. For example, consider the following statements: 

```
PRINT TAB(-1,0);
```

```
PRINT TAB(10,15);"What am I?";
```

```
PRINT TAB(10,9);TAB(-1,32);TAB(10,25);TAB(-1,33);
```

In field operation, the "What am I" string will appear in reverse video, even though the reverse ON command (-1,32) was sent chronologically later than the "What am I?" string. However, in mode operation, no reverse video will display at all, because no characters were actually displayed after the reverse video on command and before the OFF (-1,33) command. 

To allow the above program to work correctly in both field and mode environments, it should be changed as follows: 

```
? TAB(-1,0);
```

- `? TAB(10,25);TAB(-1,33);TAB(10,9);TAB(-1,32);` 

- `? TAB(10,15);"What am I?";TAB(-1,33);` 

The first TAB(-1,33) is superfluous in mode operation, and only serves in field operation to limit the screen flash that would otherwise appear when the TAB(-1,32) command is given. Since the TAB(-1,32) is sent before the "What am I?" string, as well as positioned to the left of the string, the string will appear in reverse in both field and mode environments. 

A-Shell Reference 

Page 197 

Finally, the last TAB(-1,33); is superfluous in field operation (given that we already stored a reverse-off attribute in that position in the previous statement) but it is needed in the mode environment to prevent subsequently output characters from appearing in reverse. 

The sole purpose for implementing the `OPTIONS=FIELDEMU` feature is to allow programs that were written strictly for field devices (like AM62A terminals) to work properly under A-Shell/Windows. Previously, the only option available to prevent such programs from displaying their attributes all mixed up was to specify `OPTIONS=NOFLDATTR` , which simply disabled the field attributes. 

If your programs are able to run in both field and mode environments, then they will probably run faster and cleaner under A- Shell/Windows in the normal 'mode', since the performance advantage of certain field operations on a serial terminal (like moving a menu bar up and down) is lost in Windows where there is no noticeable screen I/O bottleneck. 

Two other notes about the implementation of field attributes: 1) unlike on the AM62A terminal, A-Shell will automatically terminate the field spillover effect at the end of the line, rather than letting the attribute spillover to the end of the screen. Technically this is incorrect, but it is so rare for software to be deliberately written to take advantage of that spillover, and so common for the spillover to produce an unwanted screen flash, that we decided this was an improvement. 2) A-Shell does not currently support the blinking attribute. 

Under A-Shell/Unix, the choice of Mode vs. Field is determined entirely by the choice of terminal driver, which in turn is determined by the TERM environment variable setting. 

A-Shell Reference 

Page 198 

## **FSPECNATIVE** 

_Added July 2017_ 

When set, the rules for converting filespecs which do not contain native directory separators are changed to allow more flexibility for native file specs. Under these rules, any character in the set of "<>(){};=/\" plus space, TAB, CR and NL, and comma— unless there is a "[" present—will cause the filespec to be interpreted as native (as-is). The only clean-up performed on such filespecs is to remove trailing blanks. If the blanks are followed by any non-blank, including a dot (extension), they are left as is. 

- " " See the A Shell forum topic FILE NAMES 6.1 AND 6.4 for a lengthy discussion of the issues, motivations and ramifications behind this. Same feature added to 6.5.1610.0. 

## **History** 

- 2017 July, A Shell 6.4.1552: Function added to A-Shell 

A-Shell Reference 

Page 199 

## **GUI_SPC_IND** 

Turning on OPTIONS=GUI_SPC_IND causes PRINT statements to be "tokenized" so that each token is positioned at the place where it would have been positioned if using fixed pitch. It also converts tokens made of hyphens (---------) or equals signs (=========) to graphic horizontal lines. For more detail, see the examples under the topic OPTIONS=GUI_SPC_IND. 

A-Shell Reference 

Page 200 

## **HEXDEC** 

This rather strange option invokes two features related to "hexadecade" date notation (in which 1-Jan-2000 is coded as "0101A0", 15-Jun-2014 is "0615B4", etc.) which can possibly eliminate a lot of Y2K conversion programming in some legacy applications. 

The first feature causes the VAL() function (whether called explicitly or implicitly, by assigning a string to a numeric variable) to accept a single leading hex digit. Thus, `VAL("A5")` would return 105. This may allow ASB routines which add and subtract dates to continue to work, even with hexadecade format dates. 

The second feature causes PRINT to scan the output for strings which look like hexadecade dates (e.g. ##/##/A#) and convert any such pattern to the 'standard' notation. For example, `PRINT "12/15/A2"` would display 12/15/02. This feature may eliminate much of the need to manually clean up the output when switching to hexadecade date format. 

Note that all of the above would probably only make sense if you were also using INFLD’s hexadecade feature. 

The HEXDEC PRINT formatting logic also applies to XCALL PRINT. 

A-Shell Reference 

Page 201 

## **LATIN1** 

(Windows only) This option applies only when the (now deprecated) Miame Terminal font is being used. When invoked, it causes A-Shell to re-map the OEM character set used by the Miame Terminal font to implement the ISO 8 bit Latin1 international character set. By setting your Windows keyboard format to US International or equivalent, you can use the Windows compose sequences to input accented characters, and A-Shell will properly save them so that they will be displayed properly on any display device supporting the Latin1 character set. 

Note that the Miame Terminal font is no longer recommended. For more information on fonts, see the system parameter FONT. 

A-Shell Reference 

Page 202 

## **NOAUTOX** 

Disables auto expansion of ISAM and INMEMO files (same as NOISAM_AUTOX). 

The auto-expand feature can be turned off for individual files by creating a <file>.NOX file in the same directory where the <file>.IDX and <file>.IDA files reside. If they are in different directories, create a .NOX file in each location. Note: 

- If you have multiple IDX files, you will need a .NOX for each (unless you only want to disable the auto-expansion for a 

- specific IDX). 

- The .NOX file does not have to have any size. You can create it with the MAKE command (to create a 0 byte file), or with VUE 

- or whatever. It is just the presence of the file in the directory that matters. 

- All auto-expansion operations, including those disabled due to the NOX file, will be recorded in the ashlog.log file. 

A-Shell Reference 

Page 203 

## **NOFLDATTR** 

(Windows only) This option (short for "No Field Attributes") causes A-Shell to "throw away" screen attributes that are field oriented (such as TCRT functions 32,33,34,35, etc.). The motivation for this would be to avoid screen attribute chaos when running an application on a "mode" display device (such as a VGA monitor,) when the application was only written to support "field" terminals. See FIELDEMU above for a more sophisticated way of dealing with this problem. Note that `OPTIONS=NOFLDATTR` is equivalent to `FLDATTR = OFF` . 

A-Shell Reference 

Page 204 

## **NOSPACEATTR** 

The switch OPTIONS=NOSPACEATTR eliminates the automatic space associated with the on/off field attributes (TCRT commands 21,22,30-35,100-105). Currently this only applies to the AM75{G} Unix emulation, and was implemented to provide compatibility with applications developed with a very old AMOS terminal driver standard in which mode emulation drivers did not automatically add the space which otherwise was added by field terminals directly. Note that if OPTIONS=NOSPACEATTR on the server side, the option will be automatically forwarded to ATE. 

A-Shell Reference 

Page 205 

## **NOWHEEL** 

This setting OPTIONS=NOWHEEL disables the otherwise automatic conversion of the mouse wheel events into UP/DOWN-ARROW key presses when the focus is not on a control that captures the mouse wheel directly (such as XTREE, multi-line INFLD, etc.). 

The default behavior allows you to use the mouse wheel to scroll within certain environments that are otherwise text-only (like VUE). But in some cases the default behavior is undesirable, for example: 

- On laptops with sensitive mouse pads, you may get spurious cursor motion just from brushing your palm against it (very 

- annoying in VUE). 

- In screen contexts where there may be a mixture of controls that scroll (like XTREE) and those that don't (like a single line 

- INFLD), users may attempt to use the mouse wheel with the intent to scroll an object like XTREE, when in fact the focus is on a control like INFLD where the conversion of the mouse wheel to an UP/DOWN-ARROW may trigger unwanted exitcodes (3 & 5), leading to further confusion. 

Note that VUE supports its own version of this switch (in the ini.vue and command mode) MOUSEPOS <boolean>, which see for information on the relationship of this setting and that one. 

Also, the mouse wheel is disabled in INFLD self-combo fields (which exit on the first down arrow key); otherwise it is too easy to end up with several additional down arrow key events which would then be interpreted according to logic impossible for the user to predict. Self-combos within XTREE continue to operate as before. 

## **History** 

- 2020 June, A Shell 6.5.1681:  NOWHEEL now also disables the mouse wheel within a combo box field. 

A-Shell Reference 

Page 206 

## **NOXABORT** 

(Windows only) This option prevents a user from closing the window while a program is running by clicking on the "X" button or hitting ALT-F4. With or without this option, such an action will bring up a dialog box warning the user about the reasons not to abort that way and suggesting the proper way to exit. But without this option, the user can choose to ignore the warning and click on the "OK" button to proceed with the abort anyway. With this option, the "OK" button is deactivated. See XABORT option. 

A-Shell Reference 

Page 207 

## **NTTS** 

(Windows only) This option forces A-Shell to identify instances in the same way that it does if it detects the presence of NT Terminal Server (or the subsequently renamed Windows Terminal Server, aka Remote Desktop, aka RDP). This would also apply to non-Microsoft remote client variations such as Citrix and possibly other environments which don't fall into the typical peer-topeer or ATE models. Without this option, you may end up with multiple instances assigned the same ID, causing them to clobber each other in the job table. The downside is that it prevents multiple instances running on the same client from sharing an A- Shell license. 

A-Shell Reference 

Page 208 

## **RC_DIMX** 

This switch tells the compiler to allow DIMX statements in /RC mode. DIMX is not supported by AMOS, so this doesn't make sense, but it may be useful in cases where you know you won't try to execute the DIMX statement but just want to have a single copy of the RUN program that runs on AMOS and A-Shell. 

A-Shell Reference 

Page 209 

## **SBX_RUNDIR** 

This option alters the search path for SBX subroutines, replacing dev:[p,0] with the current RUN file location. Normally, the search is: current [p,pn], [p,0], BAS: When OPTIONS=SBX_RUNDIR set, search is: current [p,pn], .RUN location, BAS:. 

## **See Also** 

- SBX Loading and Cacheing 

A-Shell Reference 

Page 210 

## **SEQLOK** 

(Unix) This option enables locking on sequential files when LOKSER is enabled. In old versions of A-Shell, sequential files under Unix were not subject to locking rules (other than VUE, which implements its own locking scheme). 

A-Shell Reference 

Page 211 

## **STRICT** 

This option causes A-Shell to emulate some of the more restrictive characteristics of AMOS that are not always wanted. (The presumed motivation would be to prevent you from getting too comfortable with bypassing such limitations, making it difficult to port back to AMOS.) As of Build 791, the only example of this is the "protection violation" error you get when trying to write to a file outside your project. (Since neither Windows nor Unix has any such arbitrary restriction, A-Shell normally ignores it.) But if you want to a "protection violation" whenever you attempt to write outside your project, then set OPTIONS=STRICT. 

A-Shell Reference 

Page 212 

## **TRKTOPSTS** 

This causes PolyShell to treat the top status line as part of the screen, to be saved and restored when switching sessions. Note that this behavior is automatic for the bottom status line, but the top status line by default is intended for messages that are associated with the user or terminal, rather than the session. 

A-Shell Reference 

Page 213 

## **XABORT** 

(Windows only) Without this option, an attempt to close the A-Shell window by clicking on the "X" button or hitting ALT-F4 while a program is running, will display a dialog box warning you of the reasons why this might not be a good idea. If you ignore the warning and choose to abort anyway, the program will be aborted without any good chance of recovery. (See NOXABORT to prevent that possibility.) OPTIONS=XABORT presents a different approach by generating an ASB error #255 instead of displaying warnings. Then your ASB program can decide the best way to handle the situation, possibly by ignoring the error, possibly by closing the program gracefully and then exiting A-Shell. 

A-Shell Reference 

Page 214 

## **XTAUTOFILTER** 

_Written July 2023_ 

- This option enables auto filtering for all XTREE calls, eliminating the need to set the XTF2_AUTOFILTER flag on each individual XTREE. Note, however, that when the feature is enabled globally this way, but not explicitly for the individual tree (via XTF2_AUTOFILTER), then the initial state of the filter buttons will be hidden, but can be activated (made visible) via the context menu. This is intended to make it easier to enable auto-filtering globally without having to worry about the overcrowding of narrow column headers or general clutter caused by the filter buttons in trees where filtering may not be important. 

As with most other MIAME.INI options, you can also query and/or set the option via the MX_GETOPTIONS, MX_SETOPTIONS calls, here using the flag GOP2_XTAUTOFILTER flag (&h40000000). 

Also note that in the ATE environment, the flag is automatically passed from the server to the client. 

A-Shell Reference 

Page 215 

## **POLYKEY** 

_Updated August 2015_ 

## **POLYKEY=key    (or ^key)** 

```
Examples:  POLYKEY=^W     (Control W)
           POLYKEY=|      (vertical bar)
```

POLYKEY defines the hot key that can be used to switch between sessions, but there are two completely different cases: 

• PolyShell Server Side: If the server session of A-Shell is running PolyShell, the key is transmitted to the server where it triggers a switch between server-side sessions. The key will be "hot", except when you have shelled out via HOST.LIT or HOSTEX.SBX, or when running in GUI mode. Also see SWAPKEY. 

• Client Side: If the server session is not running PolyShell and the client is ATE, or in an A-Shell/Windows standalone or P2P environment, then the key is processed on the client side, causing the next A-Shell/Windows or ATE instance in the task list to be activated, put on top, and given the focus. If there are only two such instances, the key will toggle between them, equivalent to ALT+TAB. If there more than two such instances, repeated uses of the key will advance you through the set of sessions in sequence. You may also use CTRL+TAB as an alias for the same operation. 

## **History** 

- 2012 August, A Shell 1255:  Support for the Client-Side switching added. 

A-Shell Reference 

Page 216 

## **PRINTER** 

## **PRINTER=<dflt ptr name>{,screen pict ptr{,NODLG}}** 

```
Examples:  PRINTER=LASER
```

```
           PRINTER=LASER,MYJET
```

```
           PRINTER=LASER,MYJET,NODLG
```

PRINTER is used to define the A-Shell default printer, i.e. the printer to be used if no printer name is specified in a SPOOL or PRINT command. This name specified is the name that the printer is to be known by within your applications (i.e. the AMOS Spooler Name). To get further configuration information about the specified printer, including how it is known to the operating system, printer ini files are used. See Printer Configuration for further details. 

Optionally, you may define a separate printer name that will be used for screen pictures only. If defined, the screen picture command (CTRL+P) will skip past the printer selection, saving precious keystrokes when taking screen pictures. You may also specify a third parameter, the keyword "NODLG" (not case sensitive) which complete eliminates the screen picture dialog options; it just sends the screen picture to the specified printer with no option to add a comment, view it, opt not to delete the picture file, etc. See Screen Pictures for more details. 

A-Shell Reference 

Page 217 

## **QUEUE** 

## **QUEUE=<Blocks>,MEM: | DISK:<Filespec>** 

```
Unix Example:                QUEUE=100,MEM:C:\VM\MIAME\QFLOCK.SYS
```

```
Windows (or Unix) Example:   QUEUE=100,DISK:C:\VM\MIAME\QFLOCK.SYS
```

A-Shell uses a pool of "queue blocks" to keep track of locks and other shared system resources. While AMOS uses the queue for a variety of operating system functions, including LOKSER, A-Shell uses it primarily just for maintaining locks placed by XLOCK, FLOCK, and similar custom locking subroutines. (LOKSER-style locks are handled directly by the native operating system.) Thus, the required number of queue blocks is simply the maximum number of concurrent XLOCK and FLOCK (or similar) locks. Specifying an unnecessarily large queue file will have a _minor_ impact on performance. 

The queue may reside either in memory (MEM:) or on disk (DISK:), though as of A-Shell 4.8, memory based queues are only supported under the Unix versions of A-Shell. (A-Shell 4.9 adds the capability for A-Shell/Windows.) Memory queues are quite a bit faster, but this is not significant unless your application makes a large number of XLOCK or FLOCK calls. 

Whether QFLOCK is disk-based or memory-based, a complete pathname (including filename) must be given. The name is usually qflock.sys, and it must reside in a directory accessible by all users, typically the same directory where the shared miame.ini is located. Memory based queues are implemented under A-Shell/Unix as memory-mapped files, so even though all accesses are performed in memory, the file will appear in the directory. (In addition, a small control file named qflock.lck will be created in the same directory.) 

## **Notes** 

The QUTL utility may be used to display the contents of the queue, as well as to manually remove locks placed by another user. 

The queue file is created automatically by the first user to launch A-Shell, and deleted automatically by the last user to exit (provided there are no locks currently in use). On a normal exit, A-Shell will purge the queue of all locks owned by the current user, but if a job or user should crash out of A-Shell for whatever reason, locks may be left in the queue. (Use QUTL.LIT to manually remove such locks.) Should the queue file become corrupted, it can always be removed manually (provided it is not currently in use) since the next user will recreate it. 

A-Shell Reference 

Page 218 

Prior to Build 4.6, the qflock.sys file also held two records for each job which functioned like the job table records under AMOS. As of Build 4.6, this information is kept in a separate file called jobtbl.sys. 

The jobtbl.sys file is also created and deleted automatically alongside qflock.sys. See MAXJOBS. If, for some reason you have to manually delete one of them, it is best to delete them both. 

**Warning:** Although these files will be recreated automatically, they should not be removed while there are active users! Removing a disk based (DISK:) qflock.sys will cause all locks for any current users to disappear. Removing a disk based jobtbl.sys file will cause existing users to abort with a " _jobtbl/queue zapped_ " error the next time they execute a command or perform any function that updates the job accounting information. Removing memory based (MEM:) versions of these files (by deleting them from the disk directory) will not appear to affect currently running users, since they will continue to use the copy in memory. However, the next user to launch A-Shell will create new copies of these files in memory, leading to a situation where there are two (or even more) "pools" of users that don't know about each other. Locks placed in one "pool" will not be visible in the other, which could lead to file corruption due to locking failure. So if there are any users currently running A-Shell (even if they appear to be "dead") it is preferable to manually remove the users (either with the QUTL.LIT "ZAP" function or via the operating system) before deleting the jobtbl and qflock files. 

The maximum number of queue blocks is 65,535. 

A-Shell Reference 

Page 219 

## **QUITKEY** 

## **QUITKEY=key    (or ^key)** 

```
Examples:  QUITKEY=^\     (Control backslash)
           QUITKEY=~      (tilde)
           QUITKEY=       (no quit key) (default)
```

(Unix only) QUITKEY defines the key which Unix uses to abort a running process. Normally, the Unix "Quit" key is CTRL+BACKSLASH. Hitting this key while a process is running causes the SIGQUIT signal to be sent to the process. Since this signal is un-trappable, it invariably causes the process to abort with a core dump. The only defense an application has against this key is that it can be redefined or even disabled (prior to it being used.) Because of the obvious danger posed by the ability to abort A-Shell and cause a core dump just by hitting a key, the default is for the key to be disabled while A-Shell is running. 

A-Shell Reference 

Page 220 

## **SSD** 

## **SSD=nnn-nnn-nnn-nnn-nnn-nnn-nnn-nnn** 

This parameter is more for programmers of A-Shell than end users. A-Shell contains a rudimentary but effective SSD emulator, which enables the eight numbers returned by the SSDIAG program to be exactly specified. It is these numbers, padded with leading zeros to three digits, which follow SSD on the command line. It is not a true SSD simulator since it is not based on an actual SSD number, but it does enable the same PIC code to be used for any software protected by a real SSD by simply specifying the same sequence of numbers as returned by SSDIAG.RUN on that machine. 

The SSD emulator does not emulate all aspects of the SSD, so it is important that the SSD is written to and read from in the same manner as by the SSDIAG program. The read/write sequence (in ASB) required is: 

```
io(514) = 0
```

```
for SSD'LOOP = 1 to 8
```

```
    io(514)=(2^SSD'LOOP)+1
    print io(512)
```

```
next SSD'LOOP
```

Failure to use this read/write sequence within an application will still generate a unique PIC on each A-Shell machine, assuming they are given differing eight-number sequences. In this case, however, it is not guaranteed that if the eight numbers produced by SSDIAG from a real SSD are used, that the PIC used on the original machine will in fact work on the machine running A-Shell. 

A-Shell Reference 

Page 221 

## **SBR** 

## **SBR=optioncode {,optioncode} {,optioncode}** 

SBR is used to specify various configurable subroutine options to account for local variations in some otherwise standard subroutines. These variations are typically the result of someone modifying a standard subroutine to suit their purposes. An example of this the subroutine COMMON, which many people have modified to change the number and size of the saved modules. Rather than have several implementations of each subroutine which can differ, various SBR options can be specified to tune the operation of such subroutines. 

|**Option**|**Description**|
|---|---|
|AMOSJOB1|Causes JOBNAM to return the name of the parent job.|
|AMOS_RUNSBR|Deprecated. Use OPTIONS=ASHELL_RUNSBR<br>.|
|AUTO_DLG_MAX|Maximizes dialogs, helpful for tablets and net-books.|
|AUTO_TABX|Automatically converts all Tab controls to TabX controls.|
|AXLOCK|Causes A-Shell to duplicate the behavior of XLOCK under AMOS.|
|BSMID5|Affects sequential search in SERCH.|
|BUBBLESORT|Obsolete, but documented by way of explanation.|
|CCYY|Affects the way INFLD and IDTIM guess at the century.|



A-Shell Reference 

Page 222 

|**Option**|**Description**|
|---|---|
|COMMONNDR|Non-destructive read in COMMON.|
|EZPRTX|Causes EZTYP to use EZPRTX.|
|GETOFD_NOCOM|Use old style Open/Save File dialogs inMX_GETOFD<br>.|
|GET_CRNL2CR|Automatically sets the &h02 flag inXcall GET<br>.|
|INFLD_V1|Eliminates the need to specify the V parameter to INFLD.|
|INFDEF|Specifies type codes to INFLD.|
|INFLD143|Affects the operation of<br>**J**justified types in INFLD.|
|INFLDB3|Causes INFLD to add blank spaces for comma-formatted fields.|
|INFLDCBRJ|Right-justifies text label.|
|INFLDEDIT|Provide support for a variation of INVUE.|
|INFLDLDROP|Special handling for type "L" operation in INFLD.|
|INFLD_KEEPALIVE|Sends a few bytes every 15 seconds while waiting for input.|



A-Shell Reference 

Page 223 

|**Option**|**Description**|
|---|---|
|||
|INFLD_PRINTS|Maps ^P to File > Print Screen rather than to the text-based screen print/capture.|
|INFLD_NOPRINTS|Disables ^P screen print function..|
|VINFLDPS|Impacts the operation of types "P" and "S" inINFLDXS.|
|LSTLINSTRIP|Strips comments from command line before returning them toLSTLIN.LIT.|
|MALLOCSORT|Affects the memory allocation strategy ofBASORTXS.|
|MESAGRTN|Changes behavior ofMESAG.|
|MSGNUM|Changes the number of packets available toCOMMONXS.4|
|MSGSIZ|Changes the size of each packet available toCOMMONXS.|
|MXLOCK|ForcesAG_XLOCKto conform exactly to standard documentation.|
|PCKLST_GUI|Use XTREE (GUI) in place of PCKLST (text)|
|PRINT_TIME|Allow for the time to be added to the report header.|



A-Shell Reference 

Page 224 

|**Option**|**Description**|
|---|---|
|PRINT_JOBUSN|Allow for the user name to be added to the report header.|
|PRINTNOFF|Eliminates form feed character in PRINT.|
|PRTCHK1|Causes PRTCHK to return 1 if printer is found, 0 if it is not.|
|SUBMIT2|Forces a new process to be the grandchild of the current process.|
|TRIMCTL|Causes TRIM to remove leading and trailing control characters.|
|TTI_PGRW|Affects how INFLD type codes<br>**$**and<br>**H**are handled.|
|XMASCB_OPEN|Optimizes file open/close in XCALL xMASCB, ignores redundant open, explicit close;<br>auto-close at program end.|
|XPPPNOCT|Affects how XPPN displays PPN value.|
|XTREE|Enables various operations for all XTREEs.|



A-Shell Reference 

Page 225 

## **AMOSJOB1** 

This causes the JOBNAM subroutine to return the name of the parent job rather than the current job, when the current job was launched via ASHELL[XS] and the ASHELL_RUNSBR switch is not active. This mimics one aspect of the way Xcall AMOS worked under AMOS—i.e. that the child process was still the original job. Note that under A-Shell, the child process is truly a separate job and thus cannot share any memory based information, unless the ASHELL_RUNSBR switch is active. 

A-Shell Reference 

Page 226 

## **AXLOCK** 

The AMOS version of XLOCK has a bug in which an attempt to get a wildcard lock (e.g. X,0) will appear to succeed (i.e. return MODE 0) even when you already have a conflicting lock (X,Y). One could argue whether a lock previously set by the same user should be considered a conflict or not, but it is hard to justify returning a status of success when the wildcard lock was, in fact, not set due to the conflict. Yet, in the rarified world of programming, there are those that consider this a feature rather than a bug. For those, we have the AXLOCK option, which causes A-Shell to copy the AMOS bug. For all others, the default behavior is to return an error status (MODE set to your own job number) to indicate that there was a conflicting lock, set by yourself, and that the wildcard lock request was not set. Note that there is a similar issue relating to how to handle a request to obtain a lock that you already have, for which the MXLOCK switch was created. 

A-Shell Reference 

Page 227 

## **AUTO_DLG_MAX** 

This option causes AUI_CONTROL to automatically maximize any newly created dialog which is larger than the screen size (for single monitor systems). The intent is to help existing dialogs conform better to net book and tablet environments whose screens are smaller than the dialogs were originally designed for. Maximizing in this case actually reduces the size of the dialog, and scales all the controls within it accordingly. 

If the dialog is small enough to fit, but is partially off the screen, it is shifted so as to be entirely visible. 

## **History** 

- 2012 December, A Shell 6.1.1329:  Modified to work on multi-monitor systems. It now operates relative to the monitor over which the center of the dialog (in its original coordinates) appears. 

- 2011 April, A Shell 5.1.1214:  Added to A-Shell. 

A-Shell Reference 

Page 228 

## **BSMID5** 

This option affects the operation of the sequential search (BSMID=5) in the SERCH subroutine. If specified, then the sequential search begins at the record following the current record in the file. This is the normal operation in the U.S. If omitted, then the sequential search begins at the current record, which is the normal operation in the UK. 

A-Shell Reference 

Page 229 

## **BUBBLESORT** 

This option no longer has any effect. Historically, it was used to force BASORT to use the bubble sort algorithm, which was slow but didn't rearrange records with equal keys, like the other algorithms used to do. All of the sort algorithms now preserve the order of records with equal keys, eliminating any need for bubble sort. 

A-Shell Reference 

Page 230 

## **CCYY** 

## **CCYY:##** 

(default ## = 60) This code affects the way subroutines with date logic (e.g. INFLD, IDTIM, MATCH, etc.) guess at the century when only provided with a two digit YY. The two digit number (##) sets the minimum year which will be assumed to be part of the twentieth century. Any year below that will be assumed to be part of the twenty-first century. For example, if you specify `SBR=CCYY:25` and then supply a date to such a subroutine like 09/15/22, it will be treated as 15-Sep-2022. However, if the date you enter is 09/15/25, then it will be treated as 15-Sep-1925. This can be useful as part of a simplified workaround to the Y2K millennium problem in applications where the range of dates being dealt with is significantly less than 100 years. For example, a typical accounting system is only concerned with dates within a range of a few years. However, note that by itself, it doesn’t do anything for you unless you are storing your dates in some kind of format which can support century information. For example, if you are taking the result of IDTIM and storing it in a 4 byte binary format, or if you are using the INFLD type "j" to return the date in Julian format, then this CCYY trick can be helpful. But if you are merely calling INFLD to get a date in MMDDYY format and are then storing it in your files as MMDDYY, the CCYY trick doesn’t do anything for you except correctly determine whether 02/29/00 is valid or not; 02/29/2000 is but 02/29/1900 is not. 

For subroutines other than those explicitly referenced above, check the specific documentation to see whether it recognizes the SBR=CCYY:## setting. 

A-Shell Reference 

Page 231 

## **COMMONNDR** 

This option stands for "COMMON Non Destructive Read". Normally, a read operation in the COMMON subroutine destroys the packet, requiring it to be rewritten before it can be read again. However, some developers apparently got their hands on a version of COMMON, in days of yore, which did not have this unfortunate characteristic, and thus were eternally grateful for the addition of this sensible option. 

A-Shell Reference 

Page 232 

## **GETOFD_NOCOM** 

_Added February 2021_ 

## **SBR=GETOFD_NOCOM** 

(Windows) This option controls whether to use the Open/Save File dialogs as implemented in A-Shell 6.5.1698.0: 

When specified, A-Shell uses the older implementation of the Open/Save File dialogs in MX_GETOFD along with internal operations like File > Load. The default (i.e. when not specified) is to use the new implementation. 

## **History** 

- 2021 February, A Shell 6.5.1699: Added to A-Shell. 

A-Shell Reference 

Page 233 

## **EZPRTX** 

This option causes the EZTYP print file preview utility (aka EZVUE) to use the customizable SBX subroutine, EZPRTX, in place of its own logic for printing of a selected range of pages. This allows more sophisticated or application-specific printing logic to be used in place of the generic logic within EZTYP. For example, you may want to use different printer selection logic, or add logic to embed printer control codes into the selected pages to be printed. The source code to a generic sample version of EZPRTX.SBX is included in EZPRTX.SAM in [7,376]. Use it as the basis for your own customized version. There are additional notes in the source code about parameters and other technical details. 

A-Shell Reference 

Page 234 

## **INFLD_V1** 

This code eliminates the need to specify the V parameter to INFLD. Otherwise, if you fail to specify V, INFLD doubles the row. This is an historical artifact going back to the invention of the 24 row display, which doubled the size of the previous 12 row displays. 

A-Shell Reference 

Page 235 

## **INFDEF** 

## **INFDEF:{string}** 

Under AMOS, the INFLD subroutine supports a defaults file infld.def. This is used to contain default type codes which are always appended to any codes in a call to the INFLD subroutine. Under A-Shell, the same is achieved by specifying these type codes after a colon with the INFDEF patch. 

A-Shell Reference 

Page 236 

## **INFLD143** 

This code affects the operation of J justified types in INFLD. If specified, then a null input to a J-type field, as distinct from an explicit input of zero, will return ENTRY padded with spaces to _xmax_ , e.g. ‘      ’. This conforms to the operation of INPUT.SBR as supplied with AlphaACCOUNTING in the UK. If INFLD143 is not specified, then a null input would return ENTRY padded with zeros, e.g. 000000. This conforms to the operation of the assembly language subroutine as supplied by MicroSabio for AMOS. 

A-Shell Reference 

Page 237 

## **INFLDB3** 

Later versions of INFLD.SBR, and the C version used in A-Shell, output spaces to blank the fringe of comma-formatted numeric input types, dependent on the input size, decimal point specification, and so on. The old AlphaACCOUNTING INPUT.SBR subroutine (and very early versions of INFLD.SBR) were not so intelligent about this matter. For comma-formatted types (specifically $ type financial fields), they just output three blanking spaces regardless of field size. To accommodate older software, the INFLDB3 code has been implemented. If specified, INFLD will blank three spaces for comma formatted fields (‘M’, ‘$’ and ‘H’) to the right or left according to justification. Otherwise the number of spaces to blank will be determined exactly as a function of field size. Note that INFLD "prehistoric compatibility mode," which causes to INFLD to mimic nearly all of INPUT'S shortcomings and idiosyncrasies, and which can be invoked with SBR=INFDEF:|P, will also accomplish this effect. 

A-Shell Reference 

Page 238 

## **INFLDCBRJ** 

This parameter, INFLD Checkbox Right Justify, can be used to right justify the text label associated with an INFLD-created checkbox ( _type_ **|c** ). Without _type_ **R** , the text goes on the left and the box on the right; _type_ **R** reverses that. But in either case, the text itself is normally left justified within its space. `SBR=INFLDCBRJ` will force it to be right justified in its space. 

A-Shell Reference 

Page 239 

## **INFLDEDIT** 

The INFLDEDIT code may be used in conjunction with `ALIAS=EDIT:INFLD` to support a variation of INVUE.SBR written by Pat LaFollette that goes by the name EDIT. EDIT is very similar to INVUE, with the main difference being the return parameter. 

A-Shell Reference 

Page 240 

## **INFLDLDROP** 

The INFLDDROP code affects the operation of **L** type in INFLD. The default for an L type field is for the right arrow to move across the field until it hits the end, and then it exits, setting the appropriate exit code. With INFLDLDROP set, it exits immediately. 

A-Shell Reference 

Page 241 

## **INFLD_KEEPALIVE** 

(Unix) This sends a harmless byte sequence every 15 seconds while waiting for input within INFLD, which includes the dot prompt and ASB INPUT statements). This serves two purposes. First, it will prevent connections from being dropped due to lack of activity while they are actually in a program waiting for input. Second (and perhaps more important), it provides a mechanism for Unix servers to detect connections that have been dropped (without having to wait for the standard keep-alive timers to expire, which by default may run to 2 hours). This way, within 15 seconds of the connection being dropped, the server will send a packet, which cannot be delivered. This should trigger a retry timer which will try to resend the packet some number of times before concluding that the connection is dead. This process is generally much quicker than the keep-alive detections process. 

Note that under Unix, the retry timers are controlled by two files in the /proc filesystem: /proc/sys/net/ipv4/tcp_retries1 and tcp_retries2. The default values of 3 and 15, respectively, may be large for your liking, possibly taking as long as 15-30 minutes to close the dropped connection. You can set them as low as 1 and 2 for nearly immediate detection, at the possible risk of prematurely judging a temporarily sluggish connection to be dead. There are being many sites on the web with good documentation about the files in the Linux /proc filesystem. 

A-Shell Reference 

Page 242 

## **INFLDPS** 

The INFLDPS code affects the operation of **P** and **S** types in INFLD. The default is for a **P** type field to be a U.S.-format phone number, and an **S** type field to be a secure (non-echoed) input. This conforms to the operation of the standard AMOS version of INFLD. If INFLDPS is specified, then the meanings of the two types are reversed. This corresponds to the operation of INPUT.SBR with AlphaACCOUNTING in the UK, which uses type **P** for non-echoed passwords. 

A-Shell Reference 

Page 243 

## **LSTLINSTRIP** 

The LSTLINSTRIP code causes comments to be stripped from the end of command lines before returning them to Xcall LSTLIN. Note that this occurs inside LSTLIN so it does not apply to use of the CMDLIN system variable to retrieve the command line. 

A-Shell Reference 

Page 244 

## **MALLOCSORT** 

This code affects the memory allocation strategy of BASORT. Normally, BASORT uses only the "impure" memory within the user’s pre-allocated memory partition to perform the sort. Depending on how much is available, it decides between a pure quick sort (entirely in memory), a quick sort of a tag file of the keys, followed by a one-pass reordering based on the sorted keys, or in the worst case, the dreaded poly-phase merge in which the file is broken into pieces which are individually sorted and then merged back together. When MALLOCSORT is specified, BASORT will attempt to temporarily allocate as much memory as it needs (within reason) to perform the fastest possible sort. This only makes sense under Unix and Windows, where it is highly recommended, since it may dramatically speed up sorting in these environments which typically have lots of memory available for temporary use. 

## **See Also** 

- MALLOCLIMIT 

A-Shell Reference 

Page 245 

## **MESAGRTN** 

The normal operation of MESAG is such that a message type 1 is displayed followed by `CR TO RECOVER` , and a message type 2 followed by `CR TO CONTINUE` . If the MESAGRTN code is specified, then the operation of both these message types becomes identical, and they are displayed followed by `Press Return` . Also note that the text of this and other subroutine messages can be edited directly in SBRMSG.<lan>. 

A-Shell Reference 

Page 246 

## **MSGNUM** 

## **MSGNUM: <number>** 

This changes the number of packets available to the COMMON subroutine to the value specified after the colon. The default number of packets is six. 

A-Shell Reference 

Page 247 

## **MSGSIZ** 

## **MSGSIZ: <size in bytes>** 

This changes the size of each packet available to COMMON to the value specified. It may be used with the MSGNUM setting to tailor the implementation of COMMON to match that of equivalent AMOS installations. The default packet size is 150 bytes. 

A-Shell Reference 

Page 248 

## **MXLOCK** 

The XLOCK subroutine normally returns the job number of the job which is in possession of a lock in the MODE parameter, if an attempt is made to create a conflicting lock. Under AMOS, if an attempt is made to duplicate a lock which your job already owns, then a MODE of zero is returned, indicating success, even though no extra lock information is created. This, although contrary to the standard documentation, is the default operation under A-Shell. If the MXLOCK code is specified, then the operation of XLOCK conforms exactly to the standard documentation. An attempt to create a lock which conflicts only with a lock possessed by your own job, will still return a non-zero MODE, the job number of your own job. 

A-Shell Reference 

Page 249 

## **PCKLST_GUI** 

This switch causes PCKLST to use the GUI interface of XTREE. It is not quite the same as using `ALIAS=XTREE,PCKLST` , but very close. 

A-Shell Reference 

Page 250 

## **PRINT_JOBUSN, PRINT_TIME** 

These options allow for the time and/or user name to be added to the report header: 

```
SBR=PRINT_TIME      ; Add time (hh:mm am) to date in header
```

```
SBR=PRINT_JOBUSN    ; Add user name to date in header
```

If either option is selected, the "Run Date: mm/dd/yy" header string will be shortened to just "mm/dd/yy" with the time and/or user name appended. Note that the user name may be truncated to as few as 6 characters depending on the paper width and whether the time was also displayed. Also, if both are selected, the report title and coname strings will be truncated to 46 characters (down from the previous maximum of 50). 

A-Shell Reference 

Page 251 

## **PRINTNOFF** 

This switch affects the operation of PRINT and leading form feeds. In the default case, PRINT would put a leading form feed character at the top of the file. Under AMOS, this would generally not result in an extra blank page, due to a peculiarity of the AMOS spooler. However, under most other platforms, it probably would cause an extra leading blank page. To eliminate those, set `SBR=PRINTNOFF` . 

A-Shell Reference 

Page 252 

## **PRTCHK1** 

Some versions of PRTCHK return 1 if a printer is found and 0 if it is not. To get this behavior, add `SBR=PRTCHK1` to miame.ini. 

A-Shell Reference 

Page 253 

## **SUBMIT2** 

(Unix only) This switch affects the operation of SUBMITxs and SUBMIT.LIT, and the COMMAND parameter in printer initialization files. Each of these operations involves the Unix fork() function to create a child process in order to run a command outside the current process. In the normal case, the new process is a direct child of the current process, which makes the current process responsible for burying the child when it dies. This is often not convenient, and can have either of two undesirable side effects. One is that the current process can get stuck waiting for the child to complete. The other is that if the current process exits before the child exits, the child will become a zombie. .) 

`SBR=SUBMIT2` causes A-Shell to use a two-level fork(), which results in the new process being a grandchild of the current process. The first child exits immediately, which makes the grandchild an orphan, to be adopted by the init process (pid 1). The end result is that the current process is relieved of its parental responsibilities, eliminating the two problems mentioned above. 

In the case of the COMMAND= option in the printer initialization file, a more straightforward benefit is that XCALL SPOOL returns immediately to the program, regardless of how long the process invoked via the COMMAND= statement takes to complete. Without `SBR=SUBMIT2` , SPOOL would wait for the child process to complete before returning. 

A-Shell Reference 

Page 254 

## **TRIMCTL** 

This switch causes TRIM to remove leading and trailing control characters, as well as blanks, from the string passed to it. You can also get the same effect by passing a second, numeric, non-zero valued argument to TRIM (e.g. `XCALL TRIM,A$,1` ). 

A-Shell Reference 

Page 255 

## **TTI_PGRW** 

This rather obscure switch activates certain adjustments to the way in which the _type_ codes **$** and **H** are handled in INFLD. It also activates CTRL+G as the help key in INFLD and SEL1. 

A-Shell Reference 

Page 256 

## **XPPPNOCT** 

This switch causes XPPN to adjust the value of the returned P (project) and PN (programmer number) values so that even though they appear in decimal as if they were octal. For example, if you are in PPN [100,377], it would normally return 64 and 255, since those are the decimal equivalents of the octal values 100 and 377. But with SBR=XPPNOCT, it will actually return the decimal values 100 and 377. Note however, that such numbers may not fit in a single byte, so the P and PN parameters should be at least 2 bytes long. 

A-Shell Reference 

Page 257 

## **XTREE** 

_Revised and reviewed July 2020_ 

The following SBR= options add the corresponding features to the XTREE right-click context menu, as a global shortcut to adding them explicitly using XTREE'S PopupMenu, which see for more discussion. 

|**Switch**|**Description**|
|---|---|
|XTREE_EXPCSV|Exports tree contents to comma separated file.|
|XTREE_EXPTSV|Exports tree contents to tab separated file.|
|XTREE_EXPOPEN|Launches player for exported file type.|
|XTREE_PRINT|Prints the tree.|
|XTREE_SRCH|Display windows "Find" dialog.|
|XTREE_EXPCSV2XL|Exports tree contents to XLS format usingCSV2XL.SBX. Auto-<br>matically enables XTREE_EXPCSV2XLSX as well.|
|XTREE_EXPCSV2XLSX|Like XTREE_EXPCSV2XL except outputs to XLSX format, and also<br>includes selected formatting attributes such as cell colors.|



For example: 

```
SBR=XTREE_EXPCSV2XL,XTREE_EXPOPEN,XTREE_SRCH
```

Note that some of these context menu functions, particular the search option, may conflict with editable cell validation, since interaction with function the may trigger the cell validation, causing the tree to exit before it can process the function. To avoid the confusion this may cause users, in some cases the option should be left off the context menu, unless it is added explicitly via the PopupMenu option; explicit PopupMenu options will override the corresponding XTREE_xxx global directives. 

## **See Also** 

- XTAUTOFIILTER in System Parameters 

A-Shell Reference 

Page 258 

## **History** 

- 2020 June, A Shell 6.5.1682:  Add XTREE_EXPCSV2XLSX 

- 2018 January, A Shell 6.5.1626:  Add XTREE_EXPCSV2XL 

- 2012 December, A Shell 6.1.1326:  Function added to A-Shell 

A-Shell Reference 

Page 259 

## **SWAPKEY** 

## **SWAPKEY=key     (or ^key or numeric value)** 

```
Examples:  SWAPKEY=^]      (Control bracket)
```

```
           SWAPKEY=0xFF47  (F12)
```

(Unix with PolyShell only) SWAPKEY functions like POLYKEY, except for three important differences. The first is that the key is not truly "hot;" that is, it can only be used when the process is actually waiting for keyboard input. The second is that rather than swap you to the PolyShell menu, it will swap you directly to the next instance of A-Shell running under the control of PolyShell—or, the reverse if PolyShell is launched with the –x switch. The third difference is that, unlike POLYKEY, the swap key may be a multi-key sequence generated by a function key. To specify this, you can use octal, hex, or decimal notation to indicate the two byte value which is returned by the function key. Numbers beginning with 0x are treated as hex, those beginning with 0 are octal, and all others are decimal. For your convenience, here are the standard two-byte values for function keys in hex notation: 

|**Key**|**Hex**||**Key**|**Hex**|
|---|---|---|---|---|
|F1|0xFF75||F7|0xFF42|
|F2|0xFF74||F8|0xFF43|
|F3|0xFFD3||F9|0xFF44|
|F4|0xFFC0||F10|0xFF45|
|F5|0xFF40||F11|0xFF46|
|F6|0xFF41||F12|0xFF47|



A-Shell Reference 

Page 260 

## **SWAPWAIT** 

## **SWAPWAIT=<wait in milliseconds>** 

```
Example: SWAPWAIT=25
```

(Unix only) This directive allows you to specify something other than the default wait within the terminal driver when swapping screens or screen sizes. Currently this only affects the Wyse50 driver, and was implemented because the standard wait is a full 1 second, which is apparently necessary on some versions of the terminal but not on terminal emulators. The main downside of the extra wait occurs within PolyShell, where it delayed the repaint of the new screen when swapping sessions. To allow this to remain as flexible as possible, the default value of zero simply causes the terminal driver to use its normal wait time (which in the case of wyse50 is equivalent to `SWAPWAIT=1000` . So to minimize the wait, set SWAPWAIT to 1. 

In order to allow this to be set on a terminal by terminal basis, SET.LIT supports a SET SWAPWAIT {#} subcommand. If the {n} value is specified, it sets the SWAPWAIT time, otherwise it displays the current setting. 

## **See Also** 

• MX_GETSW, MX_SETSW 

A-Shell Reference 

Page 261 

## **TRACE** 

## **TRACE=option {,option} {,option}** 

This setting can be specified to cause various types of debugging trace messages to be output during normal A-Shell operation. Unless otherwise noted, TRACE messages are output to the file ashlog.log, typically in the same directory as miame.ini, or as specified by LOGDIR. This file is automatically "rolled over" when it reaches a certain size (generally 3 MB), with several prior versions archived as ashlog.001, ashlog.002, etc. Trace messages written to the log file may also be output to the System Messages Window. Some of the traces output directly to the screen, or as noted in the table below. 

Most of these settings can be adjusted with SET.LIT, and all of them can be queried and set using MX_GETTRACE / MX_SETTRACE. Note also that for Windows and ATE, they can be enabled/disabled via the System Messages window mentioned above. 

It is recommend that you enable the INOUT, BASERR, and SIGHUP traces by default (e.g. `TRACE=INOUT,BASERR,SIGHUP` ) as they leave a trail of information that is very useful for reviewing system activity and researching errors without creating an excess number of log entries. 

The following table shows the options used with the TRACE function. The "Used In" column specifies if the option applies to the TRACE system parameter ("INI") or to the SET TRACE command ("SET"). 

|**Option**|**Used In**|**Description**|
|---|---|---|
|AMOS|INI, SET|Logs information related to the use of XcallASHELLand operations that involve the launching of another ashell session.|
|AMSORT|INI, SET|Displays information (in a pop-up window) during sorting operations, showing the type of sort, current phase, memory<br>usage, etc. If sorts are talking a long time, this can be very useful for determining what is happening, and how much<br>memory you might need to improve the performance. (For very large sorts, we also offer an add-on "world class" sort<br>module that is much faster and more flexible, but requires a small license fee; contact us for details.)|
|ATE|INI, SET|Logs details of the GUI commands and responses sent between a server and an ATE client. Note that this command<br>might make sense to activate on both the server and the client, as they have different perspectives. This will result in<br>two log files, one on the server and on the ATE client.and responses.|
|BASERR|INI, SET|Logs all ASB errors, indicating if they were trapped or not, along with other details typically lost in the translation<br>between the user experiencing the error and the programming investigating it. Highly recommended for nearly all|



A-Shell Reference 

Page 262 

|**Option**|**Used In**|**Description**|
|---|---|---|
|||installations. BASERR|
|CGI|INI,SET|Logs details related toCGIUTL. Also see XCALL and SOCKS traces.|
|DEBUG|SET only|This is a catch-all for logging all kinds of information. It should only be used in focused circumstances, since the amount<br>of tracing data quickly becomes overwhelming. May also be activated via the –trace switch on the A-Shell command<br>line.|
|ERS|INI only|same as "EFS."|
|EFS|SET only|Traces the A-Shell stream (sequential file i/o) wrappers used when the Encrypted File System (EFS) is enabled. Also<br>sometimes "overloaded" to trace specific unrelated operations for debugging purposes, usually on a temporary basis|
|EXEC|INI, SET|Traces RUN, CHAIN, command line and XcallASHELLstatements.|
|FOPENS|INI, SET|Logs information about file opens (both programs and data). Under Windows, this also includes how many microseconds<br>it takes to open the file, which can sometimes be useful in identifying bottlenecks due to network issues.|
|FUNCS|INI, SET|Activates automatic tracing of function and procedure calls.|
|GDIPRT|INI, SET|(Windows only) Logs and/or displays information about processing of print directives.|
|GUI|INI, SET|(Windows only) Logs details about various low-level GUI operations. It is quite verbose.|
|INOUT|INI only|Writes debugging information toashlog.logas each new instance of A-Shell is opened or closed, indicating the number<br>of jobs running at that point. Highly recommended for virtually all installations.|
|ISAM|INI, SET|Logs ISAM operations.|



A-Shell Reference 

Page 263 

|**Option**|**Used In**|**Description**|
|---|---|---|
|JOBLCK|INI, SET|Causes all unresolved lock/unlock operations on thejobtbl.sysfile to be traced in the filejobtbl.lck.|
|JOBS|INI only|Logs details relating to the job table operations (quite verbose).|
|KBD|INI, SET|Logs keyboard operations (quite verbose).|
|LOCKS|INI, SET|Displays debugging information on the bottom status of the window related to record locking operations. In particular, it<br>provides a sense of how many retries or how long the job is waiting for access to a record. In the case of FLOCK, it will<br>also display all of the relevant locking parameters whenever the subroutine is forced to wait and whenever it exits with<br>a non-zero error code.|
|LP|INI, SET|(Possible in INI context, but not recommended.) Displays on the screen details about printing, including processing of<br>any EZSPL configuration file, plus the printer init commands, plus the actual communication or initialization operations<br>with the printer itself. Extremely useful for debugging printing problems. (SET TRACE LP ON, then using PRINT to print a<br>dummy file, likeersatz.ini).|
|MALLOC|INI,SET|Log details of all memory allocations.|
|QOP|INI|Logs details relating to queue block operations.|
|RW|INI, SET|Log all random/isam file reads and writes, INPUT and PRINT file operations, SERCH reads.|
|SIGHUP|INI, SET|Log receipt of SIGHUP (hangup) and SIGTERM (kill) signals, along with information indicating how the signal was<br>responded to, whether the program and ashell session were shut down, etc. We recommend you set this switch<br>permanently inmiame.ini(TRACE=SIGHUP) since they should be relatively rare and frequently either worth<br>investigating directly, or they provide an explanation for something else you are investigating.|
|SIGNAL|INI, SET|(Unix only) Same as the SIGHUP option, but also displays on the screen the name of any trapped signal received by the<br>process. SeeJob Terminations<br> for more information relating to handling of incoming signals.|



A-Shell Reference 

Page 264 

|**Option**|**Used In**|**Description**|
|---|---|---|
|SOCKS|INI, SET|Logs details about TCP (socket) operations, including those embedded in CGIUTL.|
|SQL|INI, SET|Logs information about SQL operations.|
|SYSERR|INI, SET|Display (in a pop-up window on screen) details about all errors. This is sometimes useful for see the system error<br>details corresponding to a particular A-Shell error, but can also be annoying since it presents the appearance of a<br>serious error having occurred, sometimes in situations that weren’t really very serious at all.|
|USRMEM|INI, SET|Log details about "user memory" operations – i.e. loading of programs, subroutines, function key translation files, etc.|
|XCALL|INI, SET|Logs most subroutine calls.|
|XDEBUG|INI only|Increases the verbosity of several other traces.|
|XTREE|INI only|Logs XTREE operations.|



## **See Also** 

• MX_GETTRACE, MX_SETTRACE 

A-Shell Reference 

Page 265 

## **SYSTEM MESSAGES WINDOW** 

To open the System Messages window, position the cursor anywhere in the A-Shell window except on a GUI control and press CTRL+SHIFT+DOUBLE-CLICK. The _A-Shell Developer Control Operations_ window will open, offering the following buttons: 

**Dump Control Info to Spreadsheet** outputs a list detailing all the current application-created controls in CSV format. This is mainly useful as an independent way (outside of looking at the application source code) of examining the attributes of the controls that aren't readily visible (bit flags, click codes, etc.) 

**Dump Menu Info to Spreadsheet** is like the previous option but for the application-added menu items. 

**Change Text Attributes** leads to a dialog allowing you to alter some attributes of the standard text used by PRINT statements. This is mostly useful for experimenting with approaches to systematically converting screens from text to GUI. 

**System Message Window** opens the System Message Window _._ See below for additional options once this window is open. 

**Print/Preview XTREE** outputs the currently active XTREE (if applicable) to a variation of the APEX preview/print utility, allowing the entire contents of the tree (not just the visible part) to be printed. 

## **- A Shell System Messages Window** 

Right click on the window to get a context menu of options: 

- Use the _Properties_ dialog to enable/disable the display of system trace messages 

- Activating a checkbox option in the _Properties_ dialog is equivalent to turning on the TRACE of the same name (either in 

- miame.ini or via the SET command). 

- Any enabled system TRACE option will result in the corresponding messages appearing in the ashlog.log file, and, while the 

- _System Messages_ window is open, in that window as well. 

A-Shell Reference 

Page 266 

- Unchecking the _Show System Traces_ option leaves the checked traces in effect (so they output to the ashlog.log) but stops 

- them from going to the _System Messages_ window. This might be useful in cases where you want to concentrate just on trace messages explicitly output from your application via TRACE.PRINT or DEBUG.PRINT statements. 

- Closing the _System Messages_ window does not deactivate any of the currently enabled traces; they continue outputting to the 

- ashlog.log file. 

- Clipboard operations: You can select/unselect individual lines in the _System Messages_ window by clicking on them, or by 

- using the _Select All_ option from the context menu to select them all. Use the _Copy_ option from the context menu to copy the selected lines to the clipboard. (From there, they can be pasted into other text editors, such as notepad or an email editor.) Since there are no integrated search or editing features, the recommend procedure for such is to select the desired lines (or all), copy to the clipboard, then paste into Notepad or your text editor of choice for further searching and editing. 

- The _Dump Font Cache_ option on the context menu outputs details about all the fonts currently used by A-Shell 

- The _Set Debug Mode_ option on the context menu is equivalent to the dot prompt command `SET DEBUG` . Since the DEBUG 

- switch often results in a considerable volume of trace messages, the ability to turn it on and off in the middle of a program is often very useful for obtaining debugging information without being overwhelmed by it. 

- Note that for some timing-dependent GUI operations, turning on the _System Messages_ window can sometimes affect the 

- timing to the extent that the issue you are trying to track may actually change or disappear. In such a case, minimizing the message window may help; otherwise, closing it entirely (and then extracting the messages later from the ashlog.log) may be the only option. 

- Abort Application Program provides an alternative way to send an abort signal (^C) to the application program in cases where 

- the keyboard may be locked or not responsive. 

## **See Also** 

- Using the Message Window 

## **History** 

- 2023 September, A Shell 6.5.1744:  Add the EXEC trace option to the System Messages Window properties dialog. Previously this was only settable via the SET command or the TRACE directive in the MIAME.INI. When set, each command-level command (RUN, CMD/DO, LIT) is traced.. 

A-Shell Reference 

Page 267 

- 2023 January, A Shell 6.5.1724:  Add context menu option to send ^C to the application. 

- 2014 October, A Shell 6.1.1384: Add _View A-Shell Log File_ to the _A-Shell Developer Control Operations_ dialog and rename the dialog to Developer Control Operations. 

A-Shell Reference 

Page 268 

## **TRACE OPTION EXEC** 

_Updated October 2025; see History_ 

The TRACE option EXEC traces RUN, CHAIN, command line and Xcall ASHELL statements. This is particularly useful for tracking user activity. Example trace formats: 

|**Context**|**Format**|
|---|---|
|RUN PROG1 (from dot prompt or command file)|<RUN:xxx> Exec(CHAIN):<br>c:\vm\miame\dsk0\007006\prog1.run|
|CHAIN PROG2 (from PROG1)|<PROG1:xxx> Exec(CHAIN):<br>c:\vm\miame\dsk0\007006\prog2.run|
|Xcall Ashell, "RUN PROG3" (from PROG2)|<PROG2:xxx> Exec(AMOS): Exec(AMOS):<br>RUN PROG3|
|LOG DSK0:100,150<br>(from dot prompt or command file)|<yyyy:xxx> Exec(CMDLIN) LOG DSK0:100,150|



So essentially you can search or filter for "Exec(" to easily pick up all the command lines and programs executed. It also traces the A-Shell launch command line, e.g. 

```
C:\vm\miame\bin70\ashw32.exe -i c:\vm\miame\miame.ini -j slave1 -ua stslave1
```

## or 

```
   /vm/miame/bin/ashell -i /vm/miame/miame.ini -erz /vm/miame/sys1/ersatz.ini -hei mystart
```

A-Shell Reference 

Page 269 

As with other TRACE options, you can set it from/in various contexts: 

|**Context**|**Statement**|
|---|---|
|Inmiame.ini|TRACE=EXECUTE|
|From the command prompt|SET TRACE EXECUTE ON|
|From within a program|xcall MIAMEX, MX_GETTRACE, trflags|
|From within a program|xcall MIAMEX, MX_SETTRACE, trflags OR TROP_EXECUTE|



The symbol TROP_EXECUTE is defined as &h80000000 in ashell.def. 

## **History** 

- 2025 October, A Shell 7.0.1779: When the EXEC trace is set, a line showing all of the A-Shell command line arguments is added to the ashlog. 

A-Shell Reference 

Page 270 

## **TRACE OPTION JOBLCK** 

_Added October 2016_ 

TRACE=JOBLCK causes all unresolved lock/unlock operations on the jobtbl.sys file to be traced in the file jobtbl.lck. The intent here is to make it easier to debug and resolve a rogue condition whereby a process has a lock on jobtbl.sys preventing other users from getting in or out of A-Shell. Under Unix you can use the lslk utility to see who has a lock on the file, but under AIX this appears to be nearly impossible, and under Windows it may be difficult. 

The jobtbl.lck file is created in the same directory as jobtbl.sys, and consists of human readable ASCII text lines in the following format: 

```
pid,op,recnovar
```

where pid is the process id, op is either "lock" or "unlock", and recnovar is 0 for the jobtbl header, else a number indicating the jobtbl record for that job number. For example: 

```
2415,lock,5
```

```
3723,lock,15
```

```
2415,unlock,5
```

```
3724,unlock,15
```

The above case indicates the following chronology: 

```
process 2415 locked the jobtbl record for job #5
```

```
process 3723 locked the jobtbl record for job #15
```

```
process 2415 unlocked the jobtbl record for job #5
process 3723 unlocked the jobtbl record for job #15
```

A-Shell Reference 

Page 271 

Since at this point the locks and unlocks match, on the next operation, the file will be truncated and started over again. 

If the option is enabled and you get a "unable to access jobtbl.sys" error, you can then display this file to hopefully identify which processes have locks on the file and can then investigate or kill those processes. 

## **History** 

- 2016 September, A Shell 6.3.1526:  JOBLCK added to A-Shell. Note that a stripped-down version of this feature was added in 6.2.1428.0. 

A-Shell Reference 

Page 272 

## **TRACE OPTION FUNCS** 

_Written August 2025_ 

TRACE=FUNCS activates automatic tracing of function and procedure calls (calling parameters and the return value), including XPUTARG operations. Some examples of how these traces show up in the ashlog: 

## **Function Call and Return** 

The following shows a function call to which two arguments, "today+3" and "" are passed. That function in turn makes two additional function calls before returning the result of "08/21/2025". Note that the nested calls are indented (2 spaces per level) and the function return is lines up with the function call... 

```
...<FNDATETIME:62e>     -> @0016ac( S50[today+3],S3[] )
```

```
...<FNDATETIME:1a3e>      -> @0000b4( S1[t] )
```

```
...<FNDATETIME:101>       -1 <- @0000b4()
...<FNDATETIME:1a50>      -> @00379a( S50[today+3],S3[] )
...<FNDATETIME:3ad6>      08/21/2025 <- @00379a()
...<FNDATETIME:1a66>    08/21/2025 <- @0016ac()
```

## **Procedure with a Parameter "doggie" Passed to It** 

The procedure passes "perrito" back to the same parameter before returning. 

```
...<ADDSVUE:2223>      -> @003af1( S30[doggie] )
```

- `...<ADDSVUE:c39>       xputarg @1=S30[perrito] ...<ADDSVUE:c41>       <- @003af1()` 

A-Shell Reference 

Page 273 

The overall effect is similar to what you can get by embedding trace.print statements at the start and end of each function and procedure, and after each XPUTARG, but doesn't require any editing or recompilation of the program. It just requires that you enable the FUNCS trace by one of the methods (SET, system message window properties, editing the MIAME.INI, etc.). For example: 

```
.SET TRACE FUNCS ON
```

It also requires that you have access to an LSX file matching the program so that you can decipher the @xxxxxx locations. See VIEWASHLOG.LIT for a related enhancement. 

A-Shell Reference 

Page 274 

## **TRACE OPTION XCALL** 

_Updated October 2025_ 

Logs most subroutine calls. Certain extremely common routines, like MIAMEX, are not logged, unless the XDEBUG trace is also activated. In CGIUTL, creates additional logging in cgiutl.log file. 

Beginning with A-Shell 7.0.1778, the xcall trace (e.g. `SET TRACE XCALL ON` ) traces return parameters for xcall subroutine calls. Previously, only the parameters passed to the subroutine were traced. 

For internal subroutines, the return trace is identical to the calling trace except it will show the updated parameter values. To take a simple example, the following traces: 

```
xcall XSTRIP,S20[  ABCD123  ],S3[123],F8[1]
```

```
<---- XSTRIP,S20[  ABCD  ],S3[123],F8[1]
```

... show the xcall XSTRIP being called with the first parameter "  ABCD123  " being changed to "  ABCD  " on return. 

Note that there are a few xcall routines, including STRIP (but not XSTRIP) which are converted by the compiler to internal functions, in which case they will not show up in the traces. 

For external (SBX) subroutines, it isn't necessary to list the entire parameter list on return because any explicit parameter 

updates require the user of XPUTARG, which is also separately traced. See the notes for 7.0.1776.0 below which covers XPUTARG tracing in the context of user defined functions but which applies equally to SBX subroutines. 

## **History** 

- 2025 October, A Shell 7.0.1778: See note above. 

A-Shell Reference 

Page 275 

## **TRMDEF** 

## **TRMDEF=Device, Jobname, Terminal, Driver** 

A-Shell will automatically generate job and terminal names in the form of TSKAAA, TSKAAB as each new job is launched. For most applications, this is perfectly acceptable—and virtually unavoidable for Telnet connections. But if you want to try to associate TRMDEF and JOB names with particular terminal devices, the TRMDEF facility may help you. 

The general idea is that whenever a new A-Shell session is launched, A-Shell first checks the Command Line Switches. If switch –j <jobname> has been specified, then that jobname is used. Otherwise, it determines the device name of the workstation, then checks if there are any TRMDEF statements which reference either all or part of that device name. If a match is found, then the JOBNAME, TERMINAL, and DRIVER specified in the TRMDEF statement will be assigned to the new job. Otherwise, the first available name of the type TSKAAA will be used instead. 

As an example, suppose the terminal device (as displayed by the –d switch to ashell or by `SYSTAT/C` ) is tty3a:5623. The part after the colon will change every time, but since tty3a is a regular serial port (as opposed to a network pseudo port) it will be the same each time. So if you wanted to make that terminal come up with the jobname and terminal name "ship," you could add the following statement to miame.ini: 

```
TRMDEF=tty3a,ship,ship,am62a
```

When this statement is processed by an instance of A-Shell whose device name starts with "tty3a", it will cause the jobname SHIP and terminal name SHIP to be assigned to that instance. (You could theoretically make the job and terminal names different, but this doesn’t really accomplish anything other than add to the confusion, since it is not possible to change the attachment between a job and a terminal.) The terminal type am62a will also be assigned, although in most cases it is preferable to omit the terminal type from the TRMDEF line so that the terminal specified in the TERM environment variable will be used instead. 

Under Windows , the device name is, in most cases, the workstation’s machine name (or "network ID") with a suffix identifying the window number appended (e.g. "SHIPPING-PC:01".) You could use this as the basis of the following TRMDEF statements: 

```
TRMDEF=SHIPPING-PC:01,SHIP1,SHIP1,PCTDVG
```

```
TRMDEF=SHIPPING-PC:02,SHIP2,SHIP2,PCTDVG
```

A-Shell Reference 

Page 276 

The first line above would apply to the first window opened by the PC whose machine name was "SHIPPING-PC", and the second line would apply to the second window opened by the PC. The terminal driver name (PCTDVG) is again optional; if not specified here, the default will come from the CONSOLE statement. 

For system administration convenience, you can put all of your TRMDEF directives in a separate file (trmdef.ini) which is included into the configuration file using the INCLUDE command. This file should contain one TRMDEF line for each terminal which is allowed to run the MIAME application. You may mark comment lines by starting them with a semi-colon or number. Note: The following section applies to Unix-based systems only: 

Although Unix does not have terminal drivers as such, it does have a table-driven equivalent ( _terminfo_ ), which enables fairly advanced screen handling to be performed in a terminal-independent manner, though it is nowhere near as good at it as AMOS terminal drivers. A-Shell makes use of terminal driver equivalents (written in C) in order to better handle attached screens, though a generic driver ( _GENERC_ ) is provided which does make use of the _terminfo_ database. 

Unix makes use of an environment variable TERM to indicate the terminal type in order to find the correct terminfo entries. A- Shell also makes use of this variable in order to determine which terminal driver to use. The **TERM** variable is analogous to the terminal driver name, except that it is not guaranteed to be restricted to six characters, and so is not returned directly by the gettdv() routine. The TRMDEF lines in miame.ini must therefore be kept in step with the terminal types defined on the system, with six-character equivalents of each terminal’s TERM variable setting. 

Note: The following section applies to Windows-based systems only: 

There is only one proper terminal driver embedded within the Windows version of A-Shell, although there are several variations: 

|**Driver**<br>**Name**|**Notes**|
|---|---|
|PCTDV|Standard Windows.|
|PCTDVG|Windows version only. Same as PCTDV except certain "GUI enhancements" may be<br>applied, such as displayingXCALL MESAGmessages in a dialog box rather than on line<br>24.|



A-Shell Reference 

Page 277 

|**Driver**<br>**Name**|**Notes**|
|---|---|
|PCUK|Standard UK (national replacement character set) version of PCTDV. The # or £ keys<br>return ASCII character 35, and character 35 is always displayed as £.|
|PCUKG|Same as PCUK but with the Windows "GUI enhancements" described above.|
|PCFR|French national replacement keyboard version. Same idea as PCUK|
|PCFRG|Same as PCFR but with the "GUI enhancements" described above.|



Note that TRMDEF directives are entirely optional, and in most cases, are best ignored, since unique job and terminal names of the form TSKAAA, TSKAAB, etc. will be created. 

The use of INCLUDE in order to separate terminal definitions is entirely optional. If TRMDEF commands are used, then they can equally well be given in the main MIAME environment definition file. 

A-Shell Reference 

Page 278 

## **UMASK** 

_Updated July 2025_ 

## **UMASK=filemask {,dirmask}** 

(Unix only) UMASK allows you to change A-Shell’s default file creation mask from 111 to something else. If you set `UMASK=000` , it will use the mask set by the shell. Otherwise it will use the specified mask. Note that the bits in the umask clear the corresponding bits in the file creation mask, which starts at 666 (rw-rw-rw-). So setting `UMASK=111` will result in no change to the rw-rw-rw- mask. But `UMASK=137` would result in rw-r---- (rw by the file owner, read only by members of the group, otherwise no access). 

Note that although you can't directly set the UMASK to 000, because that effectively sets it to the current default, in some environments you can work around that limitation by setting `UMASK=1000` . 

The optional second parameter, _dirmask_ , is used to set UMASK for directory creation: 

For example: 

```
UMASK=011,002
```

Remember that the bits in the UMASK cause the corresponding bits in the file or directory permissions to be cleared, so 002 corresponds to drwxrwxr-x. 

A-Shell Reference 

Page 279 

## **XONXOFF** 

(Unix only)  When ON, the ^S and ^Q keys can be used to stop and start rapidly scrolling output (such as from a TYPE or DIR command) as long as the program is not waiting for input, and as long as the current line handshaking discipline supports XON/XOFF. In most cases, while waiting for keyboard input, XON/XOFF is disabled to avoid conflicts with other uses of these keys. (One exception is VUE. In order to access the ^Q and ^S VUE commands, you can use the alternate sequences ^_Q and ^_S.) When XONXOFF is off, the ^S and ^Q keys do not do anything special. 

`XONXOFF=ALWAYS` is like ON, except that it leaves XON/XOFF control active even during input operations. This takes away the ability to use ^S and ^Q as input commands, but it eliminates a problem which can happen with some dumb terminals in which the turning off of flow control during the transition from a long output to an input can cause the last few characters of the previous output operation, which had been output by A-Shell but were still buffered by the operating system, to become garbled. The symptom of this problem could be seen in a long DIR/W operation, in which it would handshake correctly up until the last couple of lines at the end, just before returning to the dot prompt. 

In most cases, PAGE.LIT will accomplish the same thing (only better) for which you were trying to use CTRL+S and CTRL+Q. 

A-Shell Reference 

Page 280 

## **PRINTER CONFIGURATION** 

Printing is probably the most complicated and confusing area within A-Shell. There are a couple of reasons for this. 

- The print spooling facilities and capabilities vary widely among the platforms supported by A-Shell. 

- Network environments impose another layer of configuration complexity beyond what you may have been used to with 

- AMOS. 

Perhaps we could have approached this problem by developing an emulation of the AMOS spooler for each platform. However, this would have conflicted with one of the underlying design philosophies of A-Shell, which is to allow your application to coexist with other applications on a given platform, sharing common operating system facilities as appropriate. Therefore, since virtually all Windows applications spool reports via the Print Manager, it makes sense that A-Shell does too. Unix applications typically use one of the spoolers provided by the operating system, so again, A-Shell does the same. 

This approach may make it easier for a system administrator to integrate and manage A-Shell in an existing environment, but it does require that the administrator or installer create printer configuration files which define the interface between the logical printer names used within the DevPPN / A-Shell applications, and the corresponding real printers available in the physical establishment. The following sections describe this in detail. 

## **Subtopics** 

- Defining Spoolers 

- Ini File Directives 

- Troubleshooting Techniques 

- Supported Printer Interfaces 

- EZSPL 

- EZSPL Print Preview 

- Send File to Printer or Queue 

A-Shell Reference 

Page 281 

## **DEFINING SPOOLERS** 

A-Shell spoolers have names of one to six characters and are defined by means of an initialization file, normally abbreviated "ini" or "init," which is a small text file containing various configuration parameters. Under AMOS, these files were named <printer>.ini and were stored in the SYS: directory. Although A-Shell supports that method and will find and process those ini files, the recommended and preferred method is to use files named <printer>.pqi which are stored in the ASHCFG: directory. The extension PQI stands for "Printer Queue Initialization" and was chosen to minimize the likelihood of conflict or confusion with other file extensions, as well as other types of ini files. The actual content of .PQI files and .INI files is identical. 

The ersatz directory ASHCFG: is typically DSK0:[1,7] but can in fact be anything. By grouping the printer initialization files in a special directory (away from the standard release files) and by using a unique extension, it is easy to identify the available printer configurations on a system. However, when looking for a printer, if the ashcfg:<printer>.pqi file is not found, A-Shell will continue to look for SYS:<printer>.ini as before. 

To allow for a temporary override of the printer ini file without actually modifying or changing the active one, A-Shell will first check for <printer>.pqi in the %TEMP% directory. So the complete search path is: 

```
%TEMP%\<printer>.PQI
```

```
ASHCFG:<printer>.PQI
```

```
SYS:<printer>.INI
```

For example, if the application wants to spool to a printer called LASER1, then A-Shell will look for a printer ini file called %temp%\laser1.pqi or ashcfg:laser1.pqi or sys:laser1.ini which defines the configuration of that printer. 

If no printer name is specified in the `PRINT` or `XCALL SPOOL` statement, the default name is determined by the PRINTER directive in miame.ini. If there is no PRINTER directive, under Unix, A-Shell will look for a file $HOME/.PRINTER, from which the printer name will be read from the first line of the file, if found. If no default printer is defined, then A-Shell will attempt to print to the default printer for the host operating system environment. 

Unlike AMOS, where the printer initialization files are processed at system boot up, A-Shell ignores these files until you actually make a print request. This is possible because the printer ini files only specify interfacing information that can be processed at 

A-Shell Reference 

Page 282 

run time. Thus, any changes you make to a printer ini file will take effect with the next print request. Also, because the printer ini files are only processed when referenced by a print request, there is no harm in having printer ini files that do not refer to actual or available printers. 

There is no limit to the number of printer initialization files you may have. Thus, there is no limit to the number of logical A-Shell printers that may exist. There is also no limit to the number of logical A-Shell printers that may actually correspond to the same system spooler. Any given line in a printer ini file can be a maximum length of 256 characters. 

The exception to the rule requiring the existence of a printer ini file is that it is possible to use the Windows or Unix printer name directly, instead of the AMOS or A-Shell name. In that case, a default printer configuration will be used. For Windows, this consists of `DEVICE = <printer>, PASSTHROUGH=OFF` and `PITCH=AUTO` . Under Unix is would simply be `DEVICE = <printer>` . This technique is particularly useful under Windows in conjunction the subroutine MIAMEX 120, _Prompt for Window Printer_ , which allows the user to select a printer using the standard Windows printer selection dialog. 

Examples of typical printer initialization files for Windows and Unix are given in the following topic. Note that in all cases, the only mandatory parameter is DEVICE (or alternatively, COMMAND); all others are optional. 

## **Subtopics** 

- Printer Ini File Examples 

A-Shell Reference 

Page 283 

## **PRINTER INI FILE EXAMPLES** 

Following is an example of a typical Windows printer ini file. 

```
DEVICE=\\server\hp1 | HP LaserJet Series II
```

```
LPP=66
```

```
CPP=80,136
```

```
FONT=Courier New
```

```
CHARSET=ANSI
```

```
WEIGHT=400
```

```
PITCH=AUTO
```

```
ORIENTATION=PORTRAIT
```

```
TMARGIN=1
```

```
LMARGIN=0
```

```
PASSTHROUGH=OFF
```

```
PREFIX=SYS:LASER.PFX
```

```
SUFFIX=SYS:LASER.SFX
```

```
FORMFEED=ON
```

```
DELETE=OFF
```

```
BIN=UPPER
```

The typical Unix printer ini file is generally simpler: 

```
DEVICE=jet7
```

A-Shell Reference 

Page 284 

```
PREFIX=SYS:JET7.PFX
```

```
SUFFIX=SYS:JET7.SFX
```

```
FORMFEED=ON
```

```
AUTOFF=ON
```

```
STRIPFF=ON
```

```
DELETE=ON
```

```
BANNER=OFF
```

Any commands that are not recognized are just ignored. It should be noted that not all commands are interpreted by all implementations of A-Shell, and they are very much at the mercy of the capabilities of the host operating system. Note that the all parameters are optional except for **DEVICE** or **COMMAND** , one of which is critical. 

A-Shell Reference 

Page 285 

## **INI FILE DIRECTIVES** 

Below is a list of the printer initialization file directives, also called "parameters" or "commands." For each directive, there is a link to another page which contains a detailed description along with usage, syntax, suggestions and warnings. The directives are listed here in alphabetic order, but may in any order within the ini file. The only absolute requirement for printer ini files is that they contain one DEVICE (or COMMAND) entry. 

Directives that apply only to Windows or only to Unix are so noted at the start of the description for each. If not otherwise stated, the directive applies to both Windows and Unix. 

Under Windows, the PASSTHROUGH parameter has a very significant effect on nearly every other aspect of printing, so you may want to review it first. 

|**Command**|**Description**||**Command**|**Description**|
|---|---|---|---|---|
|APEX|Ignore server PREVIEW<br>setting, execute on client||LMARGIN|Specify left margin|
|AUTOFF|Add trailing form feed||LPP|Specify number of lines<br>per page|
|AUTODLGOK|Auto respond to some<br>pseudo printer drivers||ORIENTATION|Specify portrait or<br>landscape page<br>orientation|
|AUXPCDIR|Specify location of output<br>file||OVERLAY|Add specified file to<br>beginning of each page|
|BANNER|Add banner to beginning<br>of printout||NOABORTDLG|Disable display of<br>Windows "Abort?" dialog|



A-Shell Reference 

Page 286 

|**Command**|**Description**||**Command**|**Description**|
|---|---|---|---|---|
|BIN|Specify paper source||PAPERLENGTH|Set custom paper size|
|CHARSET|Specify character set||PAPERSIZE|Set paper size|
|COMMAND|Specify alternate<br>processing of print file||PAPERWIDTH|Set custom paper size|
|CPP|Specify columns per page,<br>hence font width||PASSTHROUGH|Set Windows mode|
|CRLF, CRNL|Force output lines to have<br>CRLF terminators||PITCH|Calculate font height and<br>width|
|CRNL|Same as CRLF||PREFIX|Prepend specified prefix<br>file to print file|
|DATATYPE|Send command to<br>Windows Print Manager||PREVIEW||
|DELETE|Delete file after printing||PRTCMD|Same as COMMAND|
|DEVICE|Associate A-Shell printer<br>with host printer||PRTCOPIES|Select mode for printing<br>multiple copies|
|DUPLEX|Enhances duplex printing.||STRIPFF|Remove form feed from|



A-Shell Reference 

Page 287 

|**Command**|**Description**||**Command**|**Description**|
|---|---|---|---|---|
|||||beginning of print file|
|FONT|Specify font||SUFFIX|Append specified suffix file<br>to print file|
|FONTHEIGHT|Specify font height||TMARGIN|Specify top margin|
|FONTWIDTH|Specify font width||WEIGHT|Specify weight<br>("boldness") of font|
|FORMFEED|Enable/disable form feed||XOFFSET, YOFFSET|Make minor positioning<br>adjustments.|
|HEADER|Add header to page(s)||XORIGIN, YORIGIN|Define offset from paper<br>corner.|



A-Shell Reference 

Page 288 

## **APEX** 

## **APEX = <Boolean>** 

This switch is nearly the same as PREVIEWpq, b ut is specifically for the ATE case where you want the PREVIEW option to be ignored on the server and only recognized on the client. Otherwise, activating PREVIEW on the server in a non-GUI environment might give you the text-mode preview, EZTYP. See APEX for operations. 

A-Shell Reference 

Page 289 

## **AUTOFF** 

## **AUTOFF = <Boolean>** 

(Unix only) This option (which defaults to off) may be turned on to have A-Shell itself take over the task of putting a trailing form feed on the end of a print file when required by your spooler switches. Note that in order for this to work, you must use a printer filter which never adds a trailing form feed. For SCO we supply one on our web site called **dumbnoff** (copy it to /usr/spool/lp/model). For most other Unix flavors, you can simply select a "dumb" or "null" printer filter (aka "driver" or "model"). 

AUTOFF can be used in conjunction with STRIPFFpq and FORMFEEDpq (which see) to reconcile different applications’ approaches to form feeds. 

A-Shell Reference 

Page 290 

## **AUTODLGOK** 

## **AUTODLGOK={class,}<dialog title>** 

This command makes it possible to automatically respond to a predictable dialog displayed by some pseudo printer drivers like PDF writers. Typically these will default to the same name as the source file, but with a PDF extension, and wait for the user to hit the SAVE button (or possibly to change the directory or filename first.) If you would rather just accept the default and not have to respond to such dialogs, you can this command to your printer initialization file: 

## **Parameters** 

_{class}_ is an optional Window class for the dialog (which you may be able to get from a Spy utility). If omitted, then the dialog will be recognized solely by its title. 

_<dialog-title>_ is the string appearing in the title bar of the dialog. 

## **Example** 

For example, for the popular PDF995 driver, you could use: 

## `AUTODLGOK=Pdf995 Save As` 

In this case, after A-Shell sends the file to the printer, it waits a few seconds to see if a dialog pops up with the specified title. If so, it sends an ENTER keystroke to it to just accept the default and proceed. 

## **Comments** 

Note that in most cases, the default directory will be set to match the directory used for the previous Save As operation by that driver. So before creating a thousand PDF files this way, you may want to first use the regular interactive method to establish the default directory. 

A-Shell Reference 

Page 291 

## **AUXPCDIR** 

## **AUXPCDIR=<pc path>** 

This command may be used in conjunction with DEVICE=AUXLOC: to specify where the output file will be placed on the PC. Normally this doesn't matter much because the file is usually deleted after printing, but in cases where that is not true, and especially for PDF generation, the location is rather important. 

For example, 

```
AUXPCDIR=%MIAME%\PDF
```

If <pc path> does not exist, it will be created, provided that its parent path exists. 

A-Shell Reference 

Page 292 

## **BANNER** 

## **BANNER = <Boolean>** 

(Unix only) BANNER _may_ invoke a printed banner at the start of each printout if such an option is available. On some Unix spoolers, a banner is unavoidable. The default is OFF, though this may be overridden by the correct switch to SPOOL. 

Under SCO Unix, you must use the `lpadmin –p<printer> -onobanner` command to enable the ability to ask for no banner. Failure to do this may cause the spooler to reject all print requests specifying no banner. You may also want to use the scoadmin utility to set the default number of banners to 0. See Troubleshooting Techniques. 

A-Shell Reference 

Page 293 

## **BIN** 

## **BIN = bin-ID** 

(Windows only) This command allows you to specify a particular paper source in a printer that has multiple paper sources. The choices for _bin-id_ are: 

|UPPER|LOWER|MIDDLE|MANUAL|AUTO|
|---|---|---|---|---|
|ENVELOPE|ENVMANUAL|LARGEFMT|SMALLFMT||
|LARGECAPACITY|FORMSOURCE|USER<#>|<bin ID number>||



Since some of these bin identifiers are rather cryptic, it may not be easy to determine what the appropriate name is for the bin you want to specify. Ultimately, this may require some trial and error, but you can at least get a list of the available bins in a specific printer, by adding one of the above BIN commands to your printer INI, then activating line printer trace mode and printing a sample file: 

```
.SET TRACE LP ON
```

```
.PRINT <printer>=SYS:<printer>.INI
```

This will cause a lot of tracing information to be displayed to the screen, including a list of all of the BIN names for the specified printer. 

## **Notes** 

Some printers may require that you manually configure them to allow the application to select the bin. See your printer documentation for details on that. 

If you specify a bin that the printer does not support, the result will be dependent on the printer driver. It may ignore the request, it may attempt to give you a closest match, or it may do something else. 

A-Shell Reference 

Page 294 

Some printers may implement "user-defined bins". The first 8 of these can be usually be referenced by "USER1" through "USER8". Note, however, that some printer drivers start the user-defined bins at something other than "USER1". If in doubt, use the tracing technique described above to display the list of available bins. 

When a printer supports a bin that is not recognized by name by A-Shell, it will appear in the list of bins (displayed when using SET TRACE LP ON) as a number. You can use any such number in the BIN command just like it was a bin name (e.g. BIN = 265). 

For what it’s worth, "USER1" is equivalent to BIN #256, "USER2" to BIN #257, etc. 

BIN works with both PASSTHROUGH=ON and with PASSTHROUGH=OFF. 

BIN is one of the printer ini file commands that has a GDI Printing Directive Equivalent. 

A-Shell Reference 

Page 295 

## **CHARSET** 

## **CHARSET = <charset name or number>** 

(Windows only) This optional command works in conjunction with the FONTpq command to determine the font character set that is selected. Choices are as follows: 

|**Value**|**Meaning**||**Value**|**Meaning**|
|---|---|---|---|---|
|ANSI (or 0)|ANSI character set<br>(default)||161|Greek|
|OEM (or 255)|OEM character set||162|Turkish|
|Symbols (or 2)|Symbol set||177|Hebrew|
|Default (or 1)|Default for selected font<br>face name||178|Arabic|
|77|Mac||186|Baltic|
|128|Shift JIS (Japanese Kanji)||204|Russian|
|129|Hangeul||222|Thai|
|134|GB2312||238|Eastern Europe|
|136|Chinese Big5||||



Note that merely specifying an exotic character set does not mean you will get it, because a font with those characteristics has to exist. If you specify both a font name (using the FONTSP parameter) and a charset, the character set will become most important if the requested font face name does not exist. This is why the default setting is ANSI rather than DEFAULT, because ANSI is what is expected. 

You must set `PASSTHROUGH=OFF` for CHARSET to be applicable. Also note that you can change fonts in mid report using the GDI print commands; see Print Directives. Also see FONTSP and WEIGHTPQ, which work together with CHARSET to determine the actual font selected. 

A-Shell Reference 

Page 296 

## **COMMAND** 

COMMAND may be used in place of (or in some cases, in addition to) DEVICE[pq] , in order to specify an alternate command or subroutine for processing the print file, which is also known as a "print filter." This can be especially useful when interfacing to non-printer devices such as faxes, email, archival systems, etc., as well as for performing special filtering operations on print files without having to change the application that created them. There are two forms of the command, named according to which system will be doing the processing." 

Only one COMMAND can be specified in a single printer ini file. 

A-Shell Reference 

Page 297 

## **HOST PROCESSING** 

## **COMMAND = <executable command line>** 

This specifies an arbitrary native operating system command to be executed. The command may optionally contain two optional and case-sensitive parameters: _$COPIES,_ which is replaced by the actual number of copies requested, and _$FILE_ which is replaced by the filename requested. If _$FILE_ is not specified, then the (native) print file name is appended to the end of the command line. Here are two examples: 

```
COMMAND = mylpr –n$COPIES $FILE
```

```
COMMAND = notepad.exe $FILE
```

If the requested print file request was for one copy of SYS:ersatz.ini, these would expand to something like the following:: 

```
mylpr –n1 /vm/miame/dsk0/001004/ersatz.ini
```

```
notepad.exe c:\vm\miame\dsk0\001004\ersatz.ini
```

The above commands assume Unix in the first case, with the default definition of DSK0: as /vm/miame/dsk0, and Windows in the second case, with DSK0: defined as C:\vm\miame\. 

Note that in this example, the _$file_ parameter is not necessary since the filename would have been appended to the end of the command line anyway. 

Also note that under Unix, the host command must be executable from the current command shell—i.e. be either an executable binary or a script. 

See the SBR option SUBMIT2 for related information. 

A-Shell Reference 

Page 298 

## **- A SHELL PROCESSING** 

_Updated February 2015_ 

## **COMMAND = SBX:<sbxname>{,<optional parameters>}** 

This form of the command invokes the specified SBX subroutine. In order to use this form of the command, you will have to have an appropriate SBX subroutine in DSK0:[7,6]. That subroutine will be "XCALLed" with the following parameters: 

## **xcall <SBXNAME>,status, fspec, printer, switches, copies, form {,<optional parameters>}** 

_Status_ is mapped B,1 and must returned with a positive number if you want the print operation to proceed. Else set it to 0 to cancel the print operation, or a negative number to signify an error. (It gets passed in as -1, so you don't need to set it to abort.) 

If _status_ comes back to the print processor set to 1 or more, then it will first check to see if the subroutine has changed the printer name. If so, it starts the print operation all over again with a different printer initialization file. Otherwise, it proceeds to process the current printer request as if the command had not been executed. This only has an effect if your printer initialization file also contains a DEVICE[pq] directive. 

The remaining parameters are all string format. You can convert _switches_ and _copies_ to numeric variables, but if you want to change them, convert them back to strings before passing the parameters back. 

Any parameters that are specified on the `COMMAND = SBX:` line will be added to the end of the parameter list, to be interpreted by the SBX subroutine. For example: 

```
COMMAND = SBX:EMAILP,4,"Subject","Intro, text..."
```

In the above example, EMAILP.SBX will be called with the following parameter list: 

```
XCALL EMAILP, STATUS, FSPEC, PRINTER, SWITCHES, COPIES, FORM, 4, "Subject", "Intro, text..."
```

The SBX subroutine may change any of the first six parameters ( _status_ thru _form_ ), and the changes will take effect before the print operation proceeds (assuming STATUS is set > 0.) 

Four sample routines (PFILTR, EMAILP, HTMLP, and GDIPRT) are supplied, with source, in the samples directory. PFILTR just prints out the parameters and allows you to update them before returning to the print processor. (This is very useful for 

A-Shell Reference 

Page 299 

learning/testing.) EMAILP launches the local email client and inserts the print file into the message (either in the body or as an attachment.) HTMLP wraps the print file with a simple HTML header and trailer (using a temporary file) and then displays it in your default browser (as a sort of preview utility). GDIPRT can be used under A-Shell/Unix, to forward the print file to be processed on the local PC. It requires ZTERM, ATE or A-Shell/Windows on the PC. 

## **APEX Export Extensions** 

APEX supports custom export/extension modules which use the same print filter interface specification, except that APEX will always pass two additional parameters ( _inifile_ and _flags_ ) following the _form_ parameter. So if you are adding custom parameters to a print filter routine, if you want the routine to be fully compatible with APEX, you should allow for those two parameters—and add your custom parameters after that. Because of this distinction, APEX includes a variation of the EMAILP subroutine, called PRTMAPI, with the parameters so adjusted. But had the APEX version been created first, it would have served just as well as EMAILP, except with slightly different COMMAND=SBX: syntax due to the additional parameters. See APEX Extensions for more detail. 

## **History** 

- 2014 November, A Shell 6.1.1398:  Print filter enhancement: The printer init statement `COMMAND=SBX:filter,...` now supports two optional macro arguments, $PREFIX and $SUFFIX, which evaluate to the current prefix and suffix options. For example, given the following printer ini file: 

```
DEVICE=TEST
```

```
COMMAND=SBX:PFILTR,$PREFIX,$SUFFIX
```

```
PREFIX=TEST.PFX
```

```
SUFFIX=TEST.SFX
```

the print filter PFILTR.SBX would receive "TEST.PFX" and "TEST.SFX" as the 7th and 8th arguments. The first 6 arguments to a printer filter are always preset to STS,FSPEC,PRINTER,SWITCHES,COPIES and FORM. 

A-Shell Reference 

Page 300 

## **CPP** 

## **CPP = <# columns per page> {,<# cols in condensed mode>}** 

(Windows only, PASSTHROUGH[pq] must be off) The CPP (columns per page) parameter works in conjunction with the PITCH=AUTO option (see PITCHpq) to establish a suitable font width. Note that if any of the first fifteen lines of the file (not counting trailing spaces) are longer than the first parameter specified, the CPP value is automatically switched to the second parameter, or 132 (if no second parameter specified), in order to accommodate applications that use condensed print on some reports. For example, consider the following: 

## `CPP = 80,140` 

If none of the first fifteen lines of the report are longer than 80 characters (not counting trailing spaces), then a font suitable for 80 characters across the page will be used. However, if any of those first fifteen lines exceeds 80 characters, then it will switch the entire report to a font suitable for 140 characters across the page. 

You can also let A-Shell adjust the font size to handle whatever the longest of the first fifteen lines is (again, not counting trailing spaces), by using this syntax: 

## `CPP = AUTO` 

Or, you can specify a fixed width for reports up to a certain size, and beyond that use the AUTO option: 

## `CPP = 80,AUTO` 

This might make sense if you print reports with far fewer than 80 columns, which you didn’t want to come out in an extra large font (to expand all the way across the page), but for reports beyond 80 columns, you just wanted them to use whatever font size would fit across the page. 

## **Notes** 

The main reason for specifying a "non-standard" second value in the CPP directive would be if for some reason your condensed (132 column) font were not quite small enough, resulting in a few columns being truncated. One typical case where this occurs is where a programmer took advantage of a 17 CPI condensed printing option to print 136 columns on an 8 inch line. By specifying a larger number of columns (e.g. 140), you will force a slightly smaller font to be used, eliminating the truncation problem. (This 

A-Shell Reference 

Page 301 

can also happen with printers having limited font scaling capability, although in that case, there’s no guarantee any particular size would have an effect.) 

## **History** 

- 2009 December, A Shell 5.1.1168:  "*" (asterisk) is now treated as equivalent to "AUTO." For whatever reason, this was apparently a common mistake or misunderstanding, aggravated by the fact that anything other than "AUTO" or a number was effectively treated as 132 (making CPP=80,*) appear to work, until you tried a file with more than 132 columns. In addition to recognizing "*", essentially anything non-numeric now results in the equivalent of AUTO. 

A-Shell Reference 

Page 302 

## **CRLF, CRNL** 

## **CRLF = <Boolean>** 

(Unix only) CRLF=ON may be used in conjunction with DEVICE=AUXLOC: to force the output lines to have CRLF (aka CRNL) terminators. This may be handy to eliminate the "stair step" problem that occurs under Unix when the printer does not automatically add a CR to each LF or NL character. 

To deal with the "stair step" problem in printer devices other than AUXLOC:, you typically select a printer filter to translate NL characters to CRNL during output. Or, you would configure the printer to automatically supply its own carriage return. 

A related setting in miame.ini is `OPTIONS=CRNL` , which causes all sequential output files created by A-Shell to have CRLF terminators instead of the Unix-standard LF terminators. This would eliminate the need for special CRLF handling in your printer INI, but may cause confusion with the ability of some other Unix utilities to act on those files, due to the non-standard line terminators. 

A-Shell Reference 

Page 303 

## **DATATYPE** 

## **DATATYPE = <string>** 

The command `DATATYPE=RAW` prevents A-Shell from doing any special processing relating to the CR, LF, and FF control characters. 

This may be necessary in order to embed raw graphics into print files, as may be needed with certain EPF (e.g. Zebra label printer) and PCL protocols. 

Otherwise, even though PASSTHROUGH[pq] mode sounds like it "passes everything through", in reality, you still get conversion of isolated LF into CRLF, and it still identifies page breaks by FF (i.e. chr(12)), calling a standard GDI printing routine to inform the printer of the start of a page. The LF to CRLF conversion would obviously alter any graphic image, and the page break call may have had unknown results, depending on the driver. 

A-Shell Reference 

Page 304 

## **DELETE** 

## **DELETE = <Boolean>** 

The DELETE switch controls whether the file is deleted after printing. (Default is OFF.) 

Under Windows, this option is under A-Shell’s control, and works reliably. However, under Unix, unless A-Shell is building a temporary file to pass to the spooler (which it does to implement certain features, such as STRIPFF, AUTOFF, PREFIX and SUFFIX), A-Shell has to rely on the spooler itself to delete the file when it is done being printed. This is accomplished by passing a switch to the line printer request command (e.g. lpr, lp, enq). In some cases, particularly with Unix, this option may be "deprecated" and may not even work, due to the security issues that arise when a user is allowed to indirectly delete files via the line printer daemon (which typically operates under a different security environment than the original user.) Refer to the documentation (or "man" page) for the line printer for your operating system for more details about this if it is found to be a problem. 

One way to overcome an inability of your spooler to delete files is to add the **–c** switch to your DEVICE[pq] command to cause the spooler to make its own local copy of the print file before printing it. This would allow your application to immediately delete the print file after sending it to the spooler, using the ASB KILL command. 

Another workaround would be to create an empty SUFFIX file, which will force A-Shell to create a temporary file combining your original file with the empty suffix. In this case, if you specify the DELETE option, A-Shell will delete the original file immediately after constructing the temporary file. The temporary files are located either in the same directory where miame.ini exists, or in a directory specified by defining an environment variable _**ASHTMP**_ (e.g _. export ASHTMP=/vm/tmp_ ). You could then create an automated procedure (using cron) to remove all of the undeleted temporary files from this directory, say, every midnight. 

A-Shell Reference 

Page 305 

## **DEVICE** 

_Revised and reviewed July 2020_ 

Windows: 

## **DEVICE = <printer device>** 

## **DEVICE = <printer device> | <alternate name>** 

Unix: 

## **DEVICE = <printer device> {optional switches}** 

This defines the host printer queue or device to be used for the given A-Shell printer whose name matches the name of the printer initialization file. The syntax and semantics of the device specification vary with the host operating system. Note that in addition to actual printers, A-Shell supports the pseudo-devices DEVICE = AUXLOC:, DEVICE = PROMPT:, and DEVICE = DISK:. 

## **Windows** 

**:** The <printer device> and <alternate names> may either be descriptive names for the printers as they appear in a standard Windows printer selection dialog box (e.g. , _PDF-XChange_ or _Brother HL-5250DN_ ), or in case of shared printers, a UNC share name, e.g. _\\server\hp2_ . 

In order to provide flexibility for heterogeneous networks where different workstations may see the same printers differently, you can specify two device names separated by a vertical bar, as shown here: 

## `DEVICE = HP LaserJet | \\server2\hp2` 

In this case, if the first name cannot be found, the second name is used. This can be useful in heterogeneous networks where it might be difficult for every workstation to refer to a particular printer by the same name. 

## **Notes** 

See History below for additional notes. 

A-Shell Reference 

Page 306 

Network printers do not need to be locally defined as long as the local machine can access the target printer by means of the \ \machine\sharename of the printer. To take advantage of this, the DEVICE directive must specify the \\machine\sharename by itself, or as the second choice (after the vertical bar) if there are two names (as in the example above). 

If it is not possible for all workstations in a network to refer to a shared printer by the same device name (or by either of a pair of alternate names under Windows), and if it is not possible for the application to allow different users to refer to the same printer by different names, then you may have to arrange for these workstations to have their own private ASHCFG: directory (or DSK0:[1,4]) so they can have different versions of a particular <printer>.pqi or <printer>.ini file. Refer to the DEVICE directive in miame.ini. 

If you are having difficulty figuring out the proper DEVICE specification for your printer, turn on line printer tracing (see Troubleshooting Techniques) and then print a sample file. It will display information showing you which printer names from the Registry it is trying to match against your device. 

Printer names given in the DEVICE statement under Windows are not case sensitive, and do not need to be complete. For example, "DEVICE=HP" will match "hp LaserJet" (but not "jet HP"). Be careful, however, to make the name long enough to be reasonably unique, because A-Shell will stop on the first printer that matches. So in the case of "DEVICE=HP", if you had both an "HP LaserJet 4" and an "HP DeskJet", it would match whichever one appeared first in the Registry. 

## **Unix** 

You must specify a valid printer queue name. These are the names that can be specified in the P switch of the _lpr_ (Unix) or _enq_ (AIX) commands. (A-Shell submits the file to the printing subsystem by creating and then executing an _lpr_ or _enq_ command line based the specified, file, printer, and other options.) 

A copy of the actual command line created and submitted for each print request, along with any error response, is written to the log file opr:spool.log. 

Because Unix spool commands may support additional switches that are not directly analogous to PRINT or XCALL SPOOL parameters, or otherwise not supported by A-Shell directly, you may add any such parameters after the spooler name, as shown here: 

```
DEVICE = laserque 1 -c -o sides=two-sided-long-edge
```

A-Shell Reference 

Page 307 

In this example, the spooler name is _laserque1_ , and the additional arguments _-c -o sides=two-sided-long-edge_ are added to the command line created which is automatically generated, based on the file, operating system, and other parameters passed to the A-Shell spool request. (The _-o sides=two-sided-long-edge_ option illustrates a way of implementing duplexing under Unix, even though the DUPLEXpq printer init command is not supported except under A-Shell/Windows.) 

The –c switch generally causes most Unix spooler commands to make a local copy of the file before printing it, thus eliminating conflicts which might otherwise occur if the application then proceeded to erase or modify that file before it was done printing. See the discussion about deleting files (DELETEpq) for more comments on this topic. 

## **History** 

2019 December, A-Shell 6.5.1672:  Add DEVICE=LASTPROMPT: function 

- 2019 November, A Shell 6.5.1671: If you know the exact and complete name of the printer, you can eliminate the normal logic which enumerates the available printers in order to determine the best match, by preceding the name with an asterisk. This could potentially be useful in certain environments where the printer enumeration operation was hanging, taking too long, or otherwise causing problems. For example: 

```
DEVICE = *PDF-XChange Printer 2012
```

- 2009 June, A Shell build 1150: If a printer is known to exist but A-Shell fails to find it in the matching logic, you can set the first character of the printer name in the DEVICE statement to lower case (e.g. DEVICE = hP Laser), in which case if it fails to find it in the directory, it will trust you and just try to open it blindly. (This has long been the procedure for printers using share names like \\server\name.) 

- 2009 May, A Shell build 1148:  Windows printer names can be up to 100 characters in length. The previous limit was 50. 

A-Shell Reference 

Page 308 

## **DEVICE = AUXLOC:** 

This causes the file to be redirected to the auxiliary port on the current terminal, which hopefully has been set up to further redirect the printout to an appropriate printer attached to the terminal or to the PC on which the terminal emulator is running. Note the trailing colon. 

Under Windows, DEVICE=AUXLOC: only makes sense when the Windows machine is acting as a telnet server (i.e. running ATSD), in which case, the client terminal or emulator would handle auxiliary port request the same as if the host was a Unix machine. 

If the client is ATE, the application can override the client's auxiliary port printer choice at runtime by sending the extended TAB command AG_SPOOLCFG prior to printing a file to the AUXLOC: device; see AG_SPOOLCFG for details. Or, it can use the following syntax: 

```
DEVICE = AUXLOC:<printername>
```

For example, DEVICE = AUXLOC:LASER would send the file to ATE client and then tell ATE to print it to the printer named LASER (overriding the current ATE printer configuration). Note that this would require that there either be a printer visible to the ATE client whose name started with "LASER", or that there was a sys:laser.ini or ashcfg:laser.pqi file already installed on the ATE client, containing the printer initialization commands to be used. 

Note that the <printername> could itself be a pseudo-printer specification, such as DEVICE=AUXLOC:PROMPT:, in which case ATE would prompt for the printer choice, even if ATE had previously be configured to print to a specific printer without prompting. 

Another ATE-only variation is the ability to force the PASSTHROUGH option on or off, but otherwise accept the existing ATE printer configuration. This is accomplished with the following syntax: 

```
DEVICE = AUXLOC:+GDI
```

or 

```
DEVICE = AUXLOC:+PASSTHROUGH
```

It is also possible to set the mode (GDI or Passthrough) in the printer name; see the topic Set Printer Mode Using Printer Name for more information. 

A-Shell Reference 

Page 309 

## **Note on Multiple Copies** 

See PRTCOPIESpq for information on how copies are handled with AUXLOC: printing. 

A-Shell Reference 

Page 310 

## **SET PRINTER MODE USING PRINTER NAME** 

It is possible to combine the +G{DI} or +P{ASSTHROUGH} option with a printer name, whether a printer ini file or a raw Windows printer name, in the DEVICE = AUXLOC: statement. For example: 

```
DEVICE = AUXLOC:\\SERVER\SHARE NAME+PASSTHROUGH
```

```
DEVICE = AUXLOC:HP Laserjet Series 37+PASS
```

## **Notes** 

- The mode may be specified with a few as 2 characters (e.g. +G or +P). The downside of this is that those pairs of characters 

- cannot appear within the printer name itself. 

- When printing to a printer by its raw Windows printer name or share name (i.e. not via a printer ini file), the default mode is 

- GDI, so there is no particular need to specify +GDI in that case. 

- When printing to a printer via a printer ini file, the printer ini file will override any mode specified in the DEVICE=AUXLOC: 

- statement. Even if the printer ini file has no PASSTHROUGH[pq] statement, that is equivalent to `PASSTHROUGH=ON` . 

A-Shell Reference 

Page 311 

## **DEVICE = PROMPT:** 

_Updated March 2013; see History_ 

The second special pseudo-device is PROMPT: and applies only to A-Shell/Windows. Instead of specifying the printer device, it causes a standard Windows printer-selection dialog to be invoked, allowing the user to select any available Windows printer. Again, note the trailing colon. 

The PROMPT: device should only be used with PASSTHROUGH=OFF, since it cannot be guaranteed that all printer drivers support PASSTHROUGH mode. 

When using the PROMPT: device, many of the other parameters within the printer initialization file may be overridden by the selection of the printer in the dialog. 

A print request sent to a printer named PROMPT, will, if no printer ini file is found, be treated as if DEVICE=PROMPT: and PASSTHROUGH=OFF. (This makes "PROMPT" a very useful default spooler name under A-Shell/Windows.) 

The printer selection dialog triggered by DEVICE=PROMPT: must be executed in a client A-Shell/Windows context. If it occurs in the context of an ATE connection to an A-Shell/Windows server (using ATSD), it will be automatically re-interpreted as DEVICE=AUXLOC:PROMPT: so that it gets forwarded to the ATE client where the printer selection dialog can be displayed. This however, defeats the effect of most other printer init commands in the printer ini file on the server, overriding them with options set in the ATE client Connection Properties > Printer dialog. To force the other options in the original (server-side) printer ini file to be processed on the client side, replace the DEVICE=PROMPT: in the server-side printer ini file with an explicit DEVICE=AUXLOC:printername where printername is the name of a printer ini file installed on the ATE client. (i.e. 

sys:printername.ini or ashcfg:printername.pqi). That printer ini file should be a copy of the original printer ini file on the server, with only the DEVICE statement changed to DEVICE=PROMPT: . 

The Windows default printer may be specified with the DEVICE directive: 

## `DEVICE=PROMPT(DEFAULT):` 

This is identical to PROMPT:, except that it ignores the last used printer and instead defaults to the system default printer. This is useful in places where printers come and go, and defaulting to the last used printer can cause confusion or worse when the last used printer is no longer present. 

## **Warnings** 

A-Shell Reference 

Page 312 

The _printername_ can be PROMPT, but if so, be careful not to include the trailing colon in the DEVICE=AUXLOC:PROMPT statement. While both PROMPT and PROMPT: will result in the printer selection dialog being displayed, PROMPT: (with a trailing colon) is a pseudo-device which does not have an associated printer ini file, while PROMPT (without the colon) is a logical printer name that can be associated with a printer ini file (which was the whole point of the exercise just described above). 

Although it is possible for the server-side and client-side printer ini files to have the same name, this is probably not a good idea. For one reason, you may confuse the two files when transferring them. And for another, if the server and client happen to share the same DSK0: (either because they are the same physical machine, or share a network drive on a LAN), then it would be impossible for the two variations using the same name to coexist. 

## **History** 

- 2024 February, A Shell 7.0.1755: Windows 11 printing refinement: A-Shell/Windows and ATE now force Windows to use the traditional print dialog rather than the newfangled Windows 11 version, which isn't well suited to our purposes. 

A-Shell Reference 

Page 313 

## **DEVICE = DISK:** 

The third special pseudo-device is DISK:, which as its name implies, leaves the file on disk, and it works under both A-Shell/Windows and A-Shell/Unix. There are two variations of this device as shown here: 

```
DEVICE = DISK:
```

```
DEVICE = DISK:g:\vm\miame\dsk0\301222
```

```
DEVICE = DISK:%ATECACHEDIR%
```

In the first example, the file is simply left in place rather than being sent to the spooler. In the second example, the print file is moved to the specified directory. (It must be an existing directory in the native host directory format.) In the third case, the file would be copied to the ATE Cache directory rather than printed. 

Case is not significant for Windows, but is for Unix. 

When printing to the DISK: pseudo-printer (including via ATEAPX.SBX), the target directory will be created if necessary. Note, however, that the parent directory must exist. 

A-Shell Reference 

Page 314 

## **DEVICE = LASTPROMPT:** 

_Added December 2019_ 

Beginning with A-Shell 6.5.1672, the printer pseudo device LASTPROMPT: uses the printer last selected in an A-Shell or ATE printer selection dialog. As with PROMPT:, it can be used with ATE AUXLOC: printing, i.e. 

```
DEVICE=AUXLOC:LASTPROMPT:
```

The above would send the printout to ATE via the AUXLOC: device, where ATE would then send it to the printer previously selected. 

Note that the PROMPT: device also uses the printer previously selected as the default printer in the selection dialog, while PROMPT(DEFAULT): useS the printer set as "the default" in your Windows printer definitions. 

## **History** 

- 2019 December, A Shell 6.5.1672:  Function added to A-Shell 

A-Shell Reference 

Page 315 

## **DUPLEX** 

## **DUPLEX = <option>** 

(Windows only, but see final paragraph below) This function enhances duplex printing. _Option_ may be H{orizontal} or S{hort} for short edge binding, or V{ertical} or L{ong} for long edge binding. Anything else disables duplex printing. 

DUPLEX is one of the printer ini file commands that has a GDI Printing Directive Equivalent. 

Note that although DUPLEX is only supported directly by A-Shell under Windows, you can effectively support a duplex option in Unix by creating multiple versions of your printer init command which include the required lpr command line options in the DEVICEpq directive. 

A-Shell Reference 

Page 316 

## **FONT** 

## **FONT = <font name>** 

```
Example:   FONT = Courier New
```

(Windows only, PASSTHROUGH[pq] must be off.) This command applies only to laser or graphics printers under Windows, and is used to specify the font face name in which output is to be printed. The default is for a fixed-pitch OEM-character-set font suitable for the printer. Note that Windows font selection is a "best match" affair, meaning that if the "perfect" font does not exist for your request, the closest available approximation will be selected instead. But this may not always be that close to what you wanted. 

Note that you can change fonts in mid-report using embedded Print Directives. 

A-Shell Reference 

Page 317 

## **FONTHEIGHT, FONTWIDTH** 

## **FONTHEIGHT = <# points>** 

## **FONTWIDTH = <# device units>** 

(Windows only, PASSTHROUGH must be off.) These two commands allow you to specify the height and width of the font to be used. They apply to Windows graphics printers only, and are largely superseded by the newer PITCH=AUTO and CPP commands, which are much easier to use in most cases. The FONTHEIGHT units are points (1/72") but do not include the vertical leading (between line spacing), and only integers are allowed. FONTWIDTH, on the other hand, is expressed in "device logical units" which are somewhat difficult to fathom, and may be relative to the font and device. The FONTHEIGHT and FONTWIDTH are not always independently selectable. Thus, some trial and error may be required. As an example, on most modern HP LaserJet printers with a built-in scalable Courier font, you can get a font suitable for 132 column 6 lines-per-inch printing with the following: 

```
PASSTHROUGH = OFF
```

```
FONT = Courier New
```

```
FONTHEIGHT = 12
```

```
FONTWIDTH = 18
```

## **Notes** 

You can change fonts in mid report using the embedded Print Directives. 

See the PITCH=AUTO command for a much simpler way to select a font size. 

FONTWIDTH and FONTHEIGHT override and thus effectively disable the PITCH[pq] command, so use only one method of selecting a font size or the other (preferably PITCH) within a single printer ini file. 

A-Shell Reference 

Page 318 

## **FORMFEED** 

## **FORMFEED = <Boolean>** 

Form feeds after each print job may be either enabled ( **ON** ) or disabled ( **OFF** ) after each print job. This command is identical to its AMOS equivalent. The default is ON, though this may be overridden by the correct switch to SPOOL. 

Note that under Windows printers and Unix, it can be tricky to avoid a form feed at the end of a printout. This is because both operating systems, in contrast to AMOS, tend to think of a spool requests as wholly autonomous, and thus it seems to make little sense to allow a report to just end in the middle of a page, since there is no way of knowing what the next report will expect. Under Windows, you may need to use PASSTHROUGH=ON to get FORMFEED=OFF to work. Under Unix, you can usually apply a filter to solve the problem. Refer to your operating system documentation for more information on printer setup and filters. 

The AUTOFFpq option (Unix only) provides a nearly foolproof way of dealing with optional trailing form feeds. 

A-Shell Reference 

Page 319 

## **HEADER** 

## **HEADER = <Boolean>** 

(Unix only) HEADER _may_ invoke a printed header at the top of the first page or all pages. Like BANNER[pq] , its actual implementation is up to the spooler, and may require that additional switches be passed after the printer device name (see DEVICEpq. The default is OFF. 

A-Shell Reference 

Page 320 

## **LMARGIN , TMARGIN** 

## **LMARGIN = <# columns>** 

## **TMARGIN = <# lines>** 

(Windows only; PASSTHROUGH must be off.) These commands define the left margin in characters and the top margin in lines. The actual physical size of the margin will therefore depend on the selected font pitch and line spacing. Note that the margins count towards the number of lines or columns per page. For example, if the LPP[pq] value is 66 but the TMARGIN[pq] value is 10, there will only be 56 printed lines per page. 

A-Shell Reference 

Page 321 

## **LPP** 

## **LPP = <# lines per page>** 

```
Example:   LPP = 62
```

(Windows only, PASSTHROUGH must be off.) The LPP command defines the number of lines to be printed on each page, and interacts with the PITCH setting. When LPP is specified and PITCH is not set to AUTO, the vertical line spacing (but not font size) is adjusted to squeeze that many lines onto the page. However, when PITCH=AUTO, the LPP value (defaulting to 66 if not specified) determines the height of the font selected. If LPP is omitted and PITCH is not AUTO, LPP will be computed based on the font and page size. Also note that the top margin (TMARGIN) will be included in the LPP value, so if LPP=66 and TMARGIN=4, then there will be only 62 printable lines per page. 

A-Shell Reference 

Page 322 

## **NOABORTDLG** 

## **NOABORTDLG = <boolean>** 

By default, when A-Shell is printing, it displays a typical Windows printing abort dialog, which allows the user to abort the printing operation before it completes. Although this is typical Windows practice, the abort dialog could be inappropriate for a couple of reasons. One is that all but the largest printouts are generated so quickly that the abort dialog is an annoying flash that appears and disappears before the user has a chance to even see what it said. The other is that you might not want to make it so easy for the user to accidentally abort a printout. Whatever the motivation, you can eliminate the dialog by specifying the NOABORTDLG = TRUE option. 

A-Shell Reference 

Page 323 

## **ORIENTATION** 

## **ORIENTATION = LANDSCAPE** 

(Windows only, PASSTHROUGH must be off.) The page orientation (portrait or landscape) may be specified for Windows laser or graphics printers. The default is PORTRAIT. 

The ORIENTATION directive overrides both the current printer default setting and any setting made by the user in the interactive printer selection/configuration dialog. It can only be overridden programmatically (by LANDSCAPE and NOLANDSCAPE switches in EZSPL Old Format). If you want to allow the user to have control over the orientation, omit the statement from the printer ini file and don't specify either of the related switches in the spool request. 

Note that paper orientation must be set at the time the printer context is initialized, so it cannot be set within the print file itself. 

Also note, however, as explained in the Defining Spoolers topic, that printer ini files are processed at the time reports are sent to the printer. This means that you can switch between landscape and portrait printing on a given printer, but you must have that printer identified twice to A-Shell: once as a portrait printer, once as a landscape printer. So when printing a landscape-oriented report, you would send the report to the printer called, for example, "HPland." When producing and printing portrait-oriented reports, they would be sent to the "HPport" printer. "HPland" and "HPport" are, of course, the same printer, which have only different (a) printer ini file names, and (b) ORIENTATION = lines. 

## **History** 

- 2011 December, A Shell 6.0.1241:  Windows printing refinement: The orientation in the printer dialog is now initialized based on the specification in the printer ini file or passed in the print request, rather than from the current printer settings. For related - " " details and further explanation, see the A Shell forum discussion PROMPT: Printer Preferences not taking place. 

A-Shell Reference 

Page 324 

## **OVERLAY** 

## **OVERLAY = <DevPPN filespec>** 

```
Example:   OVERLAY = ASHCFG:INVOIC.OVL
```

(Windows only, PASSHTHROUGH must be off.) If specified, the corresponding file is printed at the start of every page. The overlay file must be limited to a single page (with no form feed characters.) Typically, overlay files consist of GDI print commands (see Print Directives) to create the background of a form, or perhaps letterhead. This is logically equivalent to you including the same text at the start of every page of your report, but obviously, this way is much cleaner and simpler. Note that if you want to reset the printer "cursor" to the top of the page after processing the overlay, you can append a //MOVETO,0,0 command to the end of the overlay file. 

The filespec specified with the command assumes a default file extension of ".OVL." 

When converting from a pre-printed form printed in PASSTHROUGH mode to a laser generated form using OVERLAY, you’ll probably need to use PITCH=AUTO and CPP=80,132 to simulate the original printer font, and you may want to use the XORIGIN and YORIGEN commands to make up for the loss of ability to move the paper in the printer. 

## **See Also** 

• The A-Shell forum discussion "Generating forms on demand" has more information on strategies for replacing pre-printed forms. 

A-Shell Reference 

Page 325 

## **PAPERLENGTH, PAPERWIDTH** 

The printer init commands PAPERLENGTH and PAPERWIDTH allow you define custom paper sizes, if the driver supports it—which is a big if!. See related topics PAPERSIZE and Custom Paper Sizes. 

## **PAPERLENGTH = ###** 

## **PAPERWIDTH = ###** 

where ### are tenths of millimeters. Unfortunately, support for this feature varies widely among printer drivers. Some drivers do not support it at all. Others may support it only if you first set the driver default properties to "Custom" or "User defined" page size (which pretty much undermines the value of being able to set it from the software). In other cases, the feature is only supported in the latest version of the printer driver from the manufacturer. (This is a good general rule: whenever there is a problem with a printer, start by downloading the latest driver from the manufacturer website or the Windows update site.) 

If you attempt to set the paper length and width, and the driver does not support it, A-Shell will first try to set the paper to the PAPERSIZE value specified in your printer init or print file. (If you didn't specify one, then it will try PAPERSIZE=0.) If after that change, the driver still does not indicate support for individual page length and width, it will try again with PAPERSIZE=CUSTOM (aka 256). Finally if that doesn't work, it will log a trace message (regardless of the TRACE settings) which looks something like: 

```
Custom paper width/length not supported by printer driver!
```

If you SET TRACE LP ON, you will get more detailed trace messages showing the individual steps in the process. 

For printer drivers that don't support PAPERLENGTH and PAPERWIDTH settings in all modes, the most common workaround is to first set the printer to its "custom" paper size, which may then allow the application to override it with a different custom size. This is why A-Shell tries PAPERSIZE=256 (CUSTOM) automatically. 

HOWEVER, some drivers may indicate support for PAPERLENGTH and PAPERWIDTH, but in reality it only works when the printer is first set to CUSTOM. This problem can be detected in the LP TRACE as follows: 

```
DEVMODE Device:Brother HL-5250DN, Ver:793, Size:156, Extra:2360, ...
```

```
Requesting paperwidth override to 150.0 mm (5.9 in)
```

```
Requesting paperlength override to 140.0 mm (5.5 in)
```

A-Shell Reference 

Page 326 

```
Updated page size: 5100 x 6600 pixels
```

```
...
```

```
Final page size: 5100 x 6600 pixels (600 x 600 dpi); print area: 150,100,4950,6500
```

The clue here is that there was no attempt to set the paper size prior to requesting the paperwidth override, combined with the fact that the updated page size (5100 x 6600 pixels at 600 x 600 dpi, or 8.5 x 11 inches) doesn't match the requested size. 

In such a case, you should try adding PAPERSIZE=CUSTOM to the printer ini file to see if that resolves the problem, which in the case of this printer, does, as shown in this trace: 

```
DEVMODE Device:Brother HL-5250DN, Ver:793, Size:156, Extra:2360, bin=1, duplex=1, paper=1, orient=1,
copies=1, dmFields=0x1ff1f
```

```
Requesting papersize #256
```

```
Requesting paperwidth override to 150.0 mm (5.9 in)
```

```
Requesting paperlength override to 140.0 mm (5.5 in)
Updated page size: 3532 x 3300 pixels
```

- " " For more details and tips, see the A Shell forum discussion Custom paper sizes (case study). 

Note that unlike PAPERSIZE, PAPERLENGTH and PAPERWIDTH have no corresponding //GDI commands (primarily because the support for them seems to vary so much between printer drivers that the benefits of a non-printer-specific GDI command seem negligible, at least at the moment. 

A-Shell Reference 

Page 327 

## **PAPERSIZE** 

## **PAPERSIZE = <size>** 

where <size> can be any of the following standard size names, listed here alphabetically: 

|10X11|A6|ENV_C3|JENV_KAKU3|PENV_10_ROTATED|
|---|---|---|---|---|
|10X14|A6_ROTATED|ENV_C4|JENV_KAKU3_ROTATED|PENV_2|
|11X17|B_PLUS|ENV_C5|JENV_YOU4|PENV_2_ROTATED|
|12X11|B4|ENV_C65|JENV_YOU4_ROTATED|PENV_3|
|15X11|B4_JIS_ROATED|ENV_DL|LEDGER|PENV_3_ROTATED|
|9X11|B5|ENV_INVITE|LEGAL|PENV_4|
|A_PLUS|B5_EXTRA|ENV_ITALY|LEGAL|PENV_4_ROTATED|
|A2|B5_JIS_ROTATED|ENV_MONARCH|LEGAL_EXTRA|PENV_5|
|A3|B5_TRANSVERSE|ENV_PERSONAL|LETTER|PENV_5_ROTATED|
|A3_EXTRA|B6_JIS|ESHEET|LETTER_EXTRA|PENV_6|
|A3_EXTRA_TRANSVERSE|B6_JIS_ROTATED|EXECUTIVE|see Won't Fit 4|PENV_6_ROTATED|
|A3_ROTATED|CSHEET|FANFOLD_LGL_GERMAN|LETTER_PLUS|PENV_7|
|A3_TRANVERSE|see Won't Fit 1|FANFOLD_STD_GERMAN|LETTER_ROTATED|PENV_7_ROTATED|
|A4|see Won't Fit 2|FANFOLD_US|LETTER_TRANVERSE|PENV_8|
|A4_EXTRA|DSHEET|FOLIO|NOTE|PENV_8_ROTATED|
|A4_PLUS|ENV_10|ISO_B4|P16K|PENV_9|
|A4_ROTATED|ENV_11|JAPANESE_POSTCARD|P16K_ROTATED|PENV_9_ROTATED|
|A4_TRANSVERSE|ENV_12|see Won't Fit 3|P32K|QUARTO|
|A4SMALL|ENV_14|JENV_CHOU3|P32K_ROTATED|RESERVED_48|



A-Shell Reference 

Page 328 

|ell Reference||||Page 328|
|---|---|---|---|---|
|A5|ENV_9|JENV_CHOU4|P32KBIG|RESERVED_49|
|A5_EXTRA|ENV_B4|JENV_CHOU4_ROTATED|PENV_1|STATEMENT|
|A5_ROTATED|ENV_B5|JENV_KAKU2|PENV_1_ROTATED|TABLOID|
|A5_TRANSVERSE|ENV_B6|JENV_KAKU2_ROTATED|PENV_10|TABLOID_EXTRA|



"Won't Fit" notes in table: 1 = DBL_JAPANESE_POSTCARD; 2 = DBL_JAPANESE_POSTCARD_ROTATED; 3 = JAPANESE_POSTCARD_ROTATED; 4 = LETTER_EXTRA_TRANSVERSE 

If that list is too limiting, you can also specify the numeric code corresponding to the paper size. You can retrieve the list of supported paper sizes in symbolic and numeric format by printing with the LP trace turned on. See the _Tracing_ note, below. Also see Custom Paper Sizes. 

PAPERSIZE acts as a kind of alternative to the BIN command, in that A-Shell passes the request to the printer with the hopes that the printer will select the bin which contains the requested size. Most printers claim to support this capability, although the degree of support is questionable, and it may require that you first activate the feature through the printer's control panel or properties dialog. Similarly, it is almost always necessary for you to inform the printer of the size of paper you have in each bin (although perhaps there are some higher-end printers which have bins containing sensors to auto- detect the size. 

As with the BIN command, the printer may indicate "support" for more bins (and more paper sizes) than are actually "available", and A-Shell doesn't do much enforcement. 

So the main effect of specifying PAPERSIZE in the printer ini file is to force A-Shell to use that paper size to base any sizedependent calculations affecting the format or spacing of the output (as will APEX). 

PAPERSIZE is one of the printer ini file commands that has a GDI Printing Directive Equivalent. 

A-Shell Reference 

Page 329 

## **CUSTOM PAPER SIZES** 

It is possible to select a custom paper size by its name, rather than just its number, assuming that the paper shows up in the trace list of available paper sizes. This saves the step of running a test print with TRACE LP to see what number the custom paper was assigned, and also provides a degree of printer independence, since it isn't clear that the same number would be assigned to the custom paper by each printer. 

**Warning:** custom paper sizes is an area in which there is considerable variation between printer drivers. In some cases the driver properties dialog will allow you to define a custom paper size. In others, you may need to use the common Devices and Printers > Print Server Properties dialog to define a custom "form" (which may, or may not show up in the list of available paper sizes for a particular printer. But if it does show up, then you should be able to select it via PAPERSIZE=<name>. 

- " For more and related information, see PAPERLENGTH, PAPERWIDTH and the A Shell forum discussion Custom paper sizes (case study)." 

## **History** 

- 2011 March, A Shell 5.11209:  Added capability to A-Shell 

A-Shell Reference 

Page 330 

## **PASSTHROUGH** 

## **PASSTHROUGH = <Boolean>** 

(Windows only) This command applies only to A-Shell/Windows, and has valid values of **ON** or **OFF** (or YES/NO, TRUE/FALSE, etc.) with a **default** of **ON** . The terminology is somewhat confusing, so it may be better to think of the two options as follows: 

- "GDI Mode" (PASSTHROUGH=OFF) 

- "RAW Mode" (PASSTHROUGH=ON) (default) 

Windows applications normally use "GDI Mode", meaning they print via the Windows Graphic Device Interface (GDI), which in turn routes text and logical commands through the printer driver to produce text and graphic output on the printer device. GDI mode has several advantages: 

• Device Independence – the GDI presents a single, reasonably consistent virtual printer interface to the application, while the printer drivers supplied by the printer manufacturers take care of the problem of making the printer act accordingly. The ideal of device independence is limited, however, in the real world, by the differing capabilities of physical printers. But as long as we are dealing with laser or ink jet devices, i.e. "raster" printers that can address individual pixels, and we don’t get too exotic, we can expect reasonable uniformity. 

- Easy font selection using the Windows font mapper and font rendering facilities, without having to worry about which fonts 

- are internal to the printer. 

- Automatic font sizing via the PITCH=AUTO and CPP / LPP options in the printer initialization file. 

- Easy methods of producing graphic output (lines, rectangles, circles, images) using a set of high level, human readable text 

- commands. 

- Ability to select arbitrary colors using the RGB system. 

- GDI printing is the only way you can print to the new breed of low cost "Windows only" printers (which includes most 

- inexpensive ink jet printers.) 

The following printer initialization commands are limited to GDI mode only: FONT, WEIGHT, CHARSET, CPP, LPP, FONTHEIGHT, FONTWIDTH, PITCH, TMARGIN, LMARGIN, and ORIENTATION (and possibly others.) 

A-Shell Reference 

Page 331 

Therefore, GDI mode (PASSTHROUGH=OFF) would in most cases be the preferred approach. However, this method is substantially different in style from the way traditional AMOS applications print, which is much closer to RAW mode. Most importantly, GDI mode does not support the use of embedded escape sequences within the print file to set printer features (such as condensed print), which is common in applications being ported from AMOS. (This is the main reason why RAW mode, i.e. PASSTHROUGH=ON, is the default.) Another factor in the decision to make RAW mode be the default is that the vast majority of AMOS reports are "plain text", and a fair percentage of them are specifically intended for dot matrix printers with tractors (often with pre-printed forms.) For these kinds of print applications, most of the features of GDI mode are not only irrelevant, but they can get in the way. (And, RAW mode is certainly faster and more efficient, since it eliminates the need to "render" or "rasterize" the text, and greatly reduces the amount of data that must be sent down the wire to the printer. However, with the speed of modern PC’s, this may not be much of an issue any more.) 

As you might suspect, RAW mode printing (PASSTHROUGH=ON) is not very common in the Windows world. In fact, most printer drivers don’t even support it (and as mentioned above, neither can many physical printers, regardless of the driver.) Fortunately, there is a generic driver present on virtually all versions of Windows from W95 and up, which does support PASSTHROUGH printing (provided the printer hardware supports it.) It is listed under the manufacturer name "Generic" and model name "Text Only". You should use this driver whenever using RAW (PASSTHROUGH=ON) mode printing. 

PASSTHROUGH (raw mode) is required in the following cases: 

- Whenever the print file contains ESC codes into the printfile to access features of a specific printer (such as condensed print) 

- For all PCL reports containing PCL or Postscript commands 

## **Notes** 

When using PASSTHROUGH=ON, it is sometimes necessary to set the "spool format" for "RAW" (instead of the default, "EMF".). To accomplish this, click the **Start** button, then **Settings** , then **Printers** , and then right click on the printer icon(s) you are using with A-Shell. Click **Properties** , click on the **Details** tab, and then the **Spool Settings** button. Finally, change the **Spool Data Format** to **RAW** . For network printing, it may be necessary to do this for both the local and remote printers. The symptom of not doing this when it is needed is that when you print, you may hear the printer "hiccup" but nothing comes out. 

Although one generally settles on either PASSTHROUGH=ON or PASSTHROUGH=OFF for a particular printer, it is possible to override the PASSTHROUGH setting established in the printer initialization file. One way is to use the PASSTHROUGH and NOPASSTHROUGH flags in the SWITCHES parameter to XCALL EZSPL or to use the /PASSTHROUGH or /NOPASSTHROUGH switch 

A-Shell Reference 

Page 332 

with PRINT.LIT. Another is to embed the command in the print file itself, since PASSTHROUGH is one of the printer ini file commands that has a GDI Printing Directive Equivalent. 

Some printer drivers, typically lasers, even support the ability to send raw escape sequences—i.e. passthrough—even when otherwise in GDI—non-passthrough—mode, through the use of a special GDI //ESCAPE directive. 

A-Shell Reference 

Page 333 

## **PITCH** 

(Windows only) This command may be used as an alternative to **FONTWIDTH** and **FONTHEIGHT** to control the way A-Shell selects a suitable font size for the report. There are two variations: 

## **PITCH = ##** 

## **PITCH = AUTO** 

The first form is equivalent to FONTHEIGHT=##, but is largely superseded by the much more convenient second form, which auto-selects a suitable font size based on the printable area of the current paper in the printer as reported by the driver, the width of the longest line of the report, and the **CPP** and **LPP** values. 

## **Comments** 

**PITCH** is compatible with the **FONT** command (which only specifies a font face, not a size), but it is generally preferable to omit the **FONT** command and let Windows and the printer driver select the most suitable font face. It is not compatible with **FONTWIDTH** and **FONTHEIGHT** , both of which override and effectively disable **PITCH** . 

A-Shell Reference 

Page 334 

## **PREFIX, SUFFIX** 

## **PREFIX = <DevPPN filespec (default PFX extension)>** 

## **SUFFIX = <DevPPN filespec (default SFX extension)>** 

```
Example:   PREFIX = SYS:JET.PFX
```

If either PREFIX or SUFFIX or both are specified, the corresponding file is sandwiched as a prefix or suffix to the main file to be spooled, and the resulting sandwich is passed to the printer as if it were one file. (This prevents the possibility of another printer job slipping in between the prefix and main file if they were spooled as separate reports.) These optional commands provide a lot of flexibility in maintaining different logical versions of the same physical printer. Also note that the PREFIX and SUFFIX arguments on SPOOL override these parameters in the printer ini file. PREFIX and SUFFIX apply to both Windows and Unix. 

Under Unix, several printing options, including PREFIX and SUFFIX, involve the creation of temporary files. By default, these are stored in the same directory as miame.ini (which must therefore have write privileges for all users.) To put these files in another location (perhaps in a directory mapped to a PPN, create an environment variable ASHTMP and set it to the desired path (e.g. ASHTMP=/vm/miame/dsk0/001002). 

A-Shell Reference 

Page 335 

## **PREVIEW** 

## **PREVIEW = <Boolean>** 

This option forces the SSW_PREVIEW flag (524288 or &h80000) to be set in the switches, provided that the SSW_NOPREVIEW flag (1048576 or &h100000) has not already been set. This is equivalent to passing the /PREVIEW switch to PRINT.LIT, or setting the SSW_PREVIEW bit in the switches parameter to XCALL SPOOL. 

A-Shell Reference 

Page 336 

## **PRTCOPIES** 

## **PRTCOPIES = <Boolean>** 

This switch affects the way multiple copies are printed. When the switch is OFF, A-Shell passes the copies request to the spooler and lets it generate the copies. When ON, A-Shell itself generates the copies, either submitting the print request multiple times (under Unix) or just concatenating the copies into one combined document (Windows and aux port printing). The default is OFF for Unix and whenever outputting to the AUXLOC: device; the default is ON for local Windows printing. 

The OPTIONS=PRTCOPIES setting in miame.ini will override the PRTCOPIES=OFF option in the print ini file (i.e. force it ON), except when DEVICE=AUXLOC:. So if you want the ability to control this on a printer-by-printer basis, do not include OPTIONS=PRTCOPIES in miame.ini. 

The motivation for setting PRTCOPIES=ON would primarily be to avoid some kind of problem with the way that the print spooler or driver handles requests for multiple copies. Note, however, that in the case of auxiliary port printing (see DEVICE = AUXLOC:), having the server side generate the copies (i.e. sending the print file multiple times over the aux port channel) has some potential downsides: 

- the data has to be sent over the wire, potentially taking longer and/or using more shared bandwidth. 

- it may confuse the user into requesting multiple copies in the local printer dialog, thus ending up with copies on top of copies. 

This is why PRTCOPIES defaults to OFF whenever DEVICE=AUXLOC:. But, in order for the remote client PC to be able to generate the copies on its end, we need a way to communicate the copies request to it. Since no such feature is included in the standard auxiliary port implementation of terminals and terminal emulators, A-Shell can only support PRTCOPIES=OFF on the server side of auxiliary port printing if the client is ATE and both the server and client versions of A-Shell/ATE are 5.1.1208 or greater. If any of those conditions is not met, the server side will revert to PRTCOPIES=TRUE and send the print file over the aux port channel multiple times. If the conditions are met, then the server will add the copies parameter to the AG_SPOOLCFG command that it sends to ATE prior to sending the data over the aux channel. 

A-Shell Reference 

Page 337 

## **STRIPFF** 

## **STRIPFF = <Boolean>** 

This option was added to deal with a peculiar artifact of many AMOS reports: a form feed at the beginning of the print file. Under AMOS, the spooler had a feature to ignore such a leading form feed character if the last character received, at the end of the previous print request, was also a form feed. This apparently helped deal with a situation in which some reports may have ended in mid-page, without advancing to the top of form. This concept, however, is unheard of in the world of Windows and Unix (where the underlying printing philosophy is that each print job should stand entirely on its own, and not be affected or influenced by previous print jobs.) So, to avoid getting an extra blank page at the start of reports that have such a leading form feed character, you can either adjust your program to remove the extra form feed, or add STRIPFF=ON to your printer initialization file. 

A-Shell Reference 

Page 338 

## **WEIGHT** 

## **WEIGHT = <weight value (0 – 900)** 

(Windows only) This optional command applies to Windows printers only and affects the weight (boldness) of the font that is selected. The range of possible values runs from 0 (don’t care) to 900 (heavy) in increments of 100. The default is 400 (normal.) Note that, like CHARSET, not all possibilities may be supported; the information is merely a suggestion to the font selector which may or not be able to give you exactly what you are asking for. 

A-Shell Reference 

Page 339 

## **XOFFSET, YOFFSET** 

## **XOFFSET = ###** 

## **YOFFSET = ###** 

XOFFSET and YOFFSET are among the printer ini file commands that have a GDI Printing Directive Equivalent and to which, except for syntax, they are identical. See the GDI commands XOFFSET, YOFFSET for more information. 

A-Shell Reference 

Page 340 

## **XORIGIN, YORIGIN** 

## **XORIGIN=###** 

## **YORIGIN=###** 

XORIGIN and YORIGIN are among the printer ini file commands that have a GDI Printing Directive Equivalent and to which, except for syntax, they are identical. See the GDI commands XORIGIN, YORIGIN for more information. 

A-Shell Reference 

Page 341 

## **TROUBLESHOOTING TECHNIQUES** 

When debugging printer problems, including those relating to problems in your printer ini files, there are two general-purpose troubleshooting techniques that you should familiarize yourself with. 

## **Tracing** 

This technique applies under all A-Shell environments, and consists of activating "line printer trace mode". You can do this from the A-Shell command prompt (aka "dot prompt") as follows: 

```
.SET TRACE LP ON
```

Or, you can activate it in miame.ini by adding TRACE=LP anywhere after the first line of the file, typically near the bottom. 

When line printer tracing is active, each time you print something, you will see a bunch of debugging information displayed on your screen which, hopefully, may help you identify the problem. Note that since most such problems are not specific to the particular print file, you would typically just use the PRINT.LIT command to print a sample file. A good sample file to print is the printer ini file itself, e.g.: 

```
.PRINT LASER1=ASHCFG:LASER1.PQI
```

After resolving the problem, you can turn line printer tracing off with: 

```
.SET TRACE LP OFF
```

There are several other trace options. See the information for TRACE or for SET.LIT. Or just type `SET TRACE` from the dot prompt to get a list of the status of the currently available tracing options. 

## **SPOOL.LOG** 

The second general-purpose printer troubleshooting technique applies only to Unix and consists of a file opr:spool.log which logs information about every print request. Along with the time, date, and various information identifying the user, file, program, etc., it contains the actual Unix print request command and any response (error message or acknowledgement) returned by the command. This often makes simple errors (like "destination unknown") as well as much more subtle ones, which might otherwise take hours of debugging, immediately obvious. 

A-Shell Reference 

Page 342 

## **SUPPORTED PRINTER INTERFACES** 

A-Shell supports both of the "normal" printing interfaces: XCALL SPOOL (or EZSPL) and PRINT.LIT (or EZPRT.LIT). The former is used by applications, while the latter may be used in command files or typed interactively at the A-Shell command prompt. A- Shell also contains an implementation of the EZSPL spooler enhancement package, described in the following section. 

A-Shell Reference 

Page 343 

## **EZSPL** 

EZSPL ("easy spool"), originally developed by MicroSabio as a front-end to the AMOS spooler, provides some printing-related convenience features such as printer selection menus and file preview. The A-Shell version of EZSPL is quite similar to the AMOS version, but with some limitations and some extensions. Perhaps most importantly for those not interested in these features, they remain silent and hidden unless you go out of your way to activate them. Such people may safely ignore EZSPL. For those that are interested, this section briefly describes how EZSPL is configured under A-Shell. 

EZSPL is hooked into the front end of the spooler interface by substituting for SPOOL. This is accomplished through the subroutine ALIAS[SP] facility within miame.ini. In fact, A-Shell does not contain an ordinary SPOOL subroutine, so you have to use the EZSPL version. However, as mentioned above, EZSPL acts just like the ordinary one unless you create the necessary configuration files. 

## **Subtopics** 

- EZSPL Config File 

A-Shell Reference 

Page 344 

## **EZSPL CONFIG FILE** 

The first thing EZSPL (SPOOL) does upon being called is to look for configuration files, which consist of the following: 

```
EZ:<printfilename>.SFL
```

```
EZ:<programname>.SPG
```

```
EZ:<printername>.SPR
```

```
EZ:<termname>.SPL
```

```
MEM:SYSTEM.SPL
```

```
SYSTEM.SPL[p,pn]
```

```
SYSTEM.SPL[p,0]
```

```
EZ:SYSTEM.SPL
```

If none of these are found, then printing proceeds as if EZSPL did not exist. Otherwise, it opens the first file it finds and process the parameters contained within. 

Each of the statements in the config file must be in all upper case, with no spaces, except within a description field (e.g. "MENU = ON" and "menu = On" are invalid). Standard rules apply for Boolean Arguments in Ini Files. 

Individual sections may also be added to the configuration file according to user name. 

User name is determined by the native operating system logon procedure, and can be seen in the SYSTAT display or retrieved with GETUSN.. It is not case sensitive in this context. 

See EZSPL for the complete list and descriptions of EZSPL commands. 

## **EZSPL Sample Config File** 

```
MENU=OFF
```

A-Shell Reference 

Page 345 

```
TYPE=OFF
```

```
ASKPRT=OFF
PRTSPL=PDFX,PDF Printer
```

```
[jack]
MENU=ON
TYPE=ON
ASKPRT=ON
```

```
DEFAULT=JET2
PRTSPL=JET2,Jack's Jet Printer
```

```
[always]
PRTSPL=JET1,Common Jet Printer
PRTSPL=DRAFT,Oki draft
```

```
[default]
DEFAULT=JET1
```

In the above case, the first four lines are always processed. They could have been preceded with another [always] header, or combined with the other [always] section. The five lines under [jack] are only processed if the user is jack, in which case the boolean options would override the previously set ones, the DEFAULT printer would only apply if no printer had been previously specified (by the application or in miame.ini), and the PRTSPL line defining the JET2 printer would be added to the previous set 

A-Shell Reference 

Page 346 

of printers (currently containing only PDFX). The [always] section always gets processed. The [default] section would only be processed for users other than jack. 

This capability of adding sections for individual users allows a great deal of flexibility for large systems. 

## **Subtopics** 

- EZSPL SWITCHES 

A-Shell Reference 

Page 347 

## **EZSPL SWITCHES** 

The EZSPL configuration file command: 

## **SWITCHES = {+/-}#####** 

allows you to add, remove, or replace the SWITCHES passed in the XCALL EZSPL, XCALL SPOOL, or even XCALL EZTYP. 

For example, SWITCHES = +&h80000 would force EZSPL (including EZTYP) to act as if the &h80000 (GUI PREVIEW) switch had been set by the caller, and thus would launch the GUI Preview utility instead of the text preview. 

The main value of this switch is that it allows you to force EZTYP to use the APEX preview utility, provided you are running under A-Shell/Windows. 

A-Shell Reference 

Page 348 

## **EZSPL PRINT PREVIEW** 

One feature of EZSPL is the ability to preview any print file before, and perhaps in lieu of, sending it to a printer. The option to preview the file may be configured via the EZSPL configuration files. The preview utility itself (which goes by the name of EZTYP or EZVUE) allows you to scroll or page through the file, or to go direct to individual lines, pages, or to search for text strings. You may also print excerpts from the print file. The available keyboard commands may be displayed by entering " **?** " (question mark) at the EZTYP command prompt, and are briefly described in the table below: 

|**Command**|**Action**|
|---|---|
|Right Arrow|If the current screen width is normal, and the terminal device supports wide (132 column) mode, the right arrow key<br>will cause it to switch into wide mode. If already in wide mode, or the terminal does not support wide mode, it will<br>increase the left margin by 4.|
|Left Arrow|If the current screen width is wide, the left arrow key will switch the terminal back into normal (80 column) mode. If<br>the screen is already in normal mode, and the left margin is greater than 0, then it will decrease the left margin by 4.|
|Up Arrow|Scroll up one line|
|Shift Up|Switch display to short (24 row) mode. Also see T command.|
|Down Arrow|Scroll down one line|
|Shift Down<br>Arrow|If supported by the terminal device, switch to tall (42 row) mode. Also see the T command.|
|TAB|Increase left margin by 8.|
|Shift TAB|Decrease left margin by 8|
|+#|Go forward # pages (paper pages, not screen pages)|
|-#|Go backward # pages|
|=#|Go to page #|
|0-9|Scroll; the number determines the scrolling speed. Stop scrolling with any other keystroke.|
|B|Go back one page|
|E|(End) Go to the end of the document|



A-Shell Reference 

Page 349 

|**Command**|**Action**|
|---|---|
|F|To forward one page|
|H|(Home) Go to the start of the document|
|L#|Go to line #|
|M#|Set left margin to #|
|N {string}|Search for next occurrence of string specified, or if no string specified, of the string specified in a previous S (search)<br>or N (next) command|
|P|Print current page or a range of pages.|
|R|Recalculate pages (see notes below the table)|
|S <string>|Search for the first occurrence of the specified string|
|T|Toggle between tall (42 row) and short (24 row) display format. (This is only possible under A-Shell/Windows and with<br>certain ZTERM-specific terminal drivers under A-Shell/Unix.)|



The EZVUE utility displays on the bottom status line (if supported by the terminal device), the filename, plus the current line and total number of lines (L # / #) and the current page and total number of pages (P # / #). If the document is reasonably large, EZVUE will not initially scan all the way through the document to determine the total number of lines or pages. In that case, it will display a question mark next to its estimate of the total number of lines and pages. To force it to scan through the entire document to compute the number of lines and pages, you can use the R (recalculate) command. It will do this automatically if needed to carry out specific commands. 

If the document being displayed contains formfeed characters, then "pages" will refer to pages as printed (i.e. paper pages). Otherwise, "pages" will refer to screen pages. 

A-Shell Reference 

Page 350 

## **SEND FILE TO PRINTER OR QUEUE** 

The last step in the process of printing a file is the actual submission of the file to the operating system’s print service (according to the DEVICE or COMMAND parameters of the printer initialization file.) The details for this final operation are vastly different - - depending on the A-Shell platform; see the following discussions on A Shell/Windows or A Shell/Unix. 

- " " For some tips and ideas about on printing PDFs under Unix, see the A Shell forum discussion Printing PDF files (Unix to PC). 

A-Shell Reference 

Page 351 

## **- A SHELL/WINDOWS** 

A-Shell/Windows relies on the Print Manager to handle the physical spooling operation. Immediately after it hands the file off to the Print Manager, you should be able to see the file in the Print Manager’s queue, and from that point forward, it can be manipulated exactly like any other Windows report. 

The way in which the report file created by your application is handed off to the Print Manager depends on the PASSTHROUGH parameter in the spooler ini file. With PASSTHROUGH=ON, the print file is sent in raw form, which is similar to the way traditional AMOS applications sent files to the spooler. This method, however, may not be supported by "Windows-only" printers. If PASSTHROUGH=OFF, A-Shell reprocesses your print file through the Windows GDI system, which is similar to the way 99% of typical Windows applications work. This method gains you more flexibility (via the FONT, PITCH, ORIENTATION, and MARGIN printer ini file statements, as well as the ability to use A-Shell’s Print Directives), but doesn’t allow you to embed ESC sequences into the print file. (Instead of, for example, using an ESC sequence to select 17 pitch, you would instead use the FONT or PITCH directives in the printer ini file, or the SETFONT directive within the print file. 

## **Notes** 

Support for PASSTHROUGH mode varies from printer to printer. If you have trouble getting printouts to work at all, try toggling the PASSTHROUGH option in your printer ini file. 

If PASSTHROUGH doesn’t work with your particular printer driver, you may want to try using the "Generic / Text Only" driver. 

See Print Directives for details on embedding GDI directives in your print files. 

Whenever a printer is selected from the printer selection dialog, that printer becomes the default, for this user, for any subsequent A-Shell printer selection dialogs. Besides being convenient and intuitive for the user, this also means that any special configuration saved for the printer in the printer driver properties will be used as the default configuration. 

A-Shell Reference 

Page 352 

## **- A SHELL/UNIX** 

The various flavors of A-Shell/Unix complete the spooling process by executing some form of Unix system line printer command: 

SCO OpenServer (-R = delete): 

```
lp -dprinter {-R} {-onobanner} {-onofilebreak} {-ncopies} file
```

The –onobanner switch will be ignored by OpenServer (leading to annoying banner pages) unless you specifically enable it in the configuration screens (scoadmin) or via an lpadmin command line. 

AIX2 (-nb0 = nobanner, -rm = delete): 

```
print -printer {-nb0} {-rm}
```

AIX/3 thru AIX/5 (-r = delete, -Ban = banner, -Bnn - no banner): 

```
enq -Pprinter {-Ban|Bnn} {-r} {-Ncopies}
```

Linux (-h = nobanner, -r = delete) 

```
lpr -Pprinter {-#copies} {-h} {-r} file
```

Others (-h = nobanner, -r = delete) 

```
lpr -Pprinter {-h} {-r} file
```

## **Notes** 

Normally A-Shell does not display the line printer command that it submits, but for troubleshooting purposes, you can force it to by setting TRACE=LP in miame.ini, or with SET TRACE LP ON from the dot prompt. 

A log of all spooler requests is kept in the file opr:spool.log). This log gives information about the context of the print request (time, date, user, program, etc.), the actual command line executed, and any response received from the print subsystem. When the file reaches 3MB, it is renamed to spool.00# (number ranges from 1 to 4, for 4 archive copies) and a new one started. 

If your flavor of Unix requires something different from the above, then you can use the COMMAND statement in the printer ini file to specify an arbitrary command line. 

A-Shell Reference 

Page 353 

## **OPERATIONS** 

A-Shell Reference 

Page 354 

## **- A SHELL EXECUTABLES** 

_Reviewed and revised December 2023_ 

This section provides details on the command line options available for launching A-Shell and related programs. 

|**Command**|**Purpose**|
|---|---|
|A-Shell|The A-Shell environment—i.e., the dot prompt.|
|Compiler|The native host version of the ASB compiler.|
|PolyShell|(Unix only) A-Shell's multi-session utility which can launch and manage<br>multiple A-Shell sessions.|
|VUE Editor|(Unix only) The native host version of the VUE editor.|
|A-Shell Explorer|A variation of Windows Explorer tailored for use within A-Shell applications.|
|APN Editor|A-Shell Programmers' Notepad, an IDE-style editor, is launched with the<br>command<br>`pn.exe`. See theAPN documentation<br>for additional details.|



A-Shell Reference 

Page 355 

## **- A SHELL** 

## **Unix** 

## **ashell {-switches}** 

## **Windows** 

## **ashw32.exe {-switches}** 

This command is used to enter the A-Shell environment, and responds with the default A-Shell prompt " **."** (period). 

All Command Line Switches are optional, and all begin with "-" (hyphen) followed by the switch. If the switch takes a parameter, that follows the switch and a single space. For example: 

## `ashell -min -j job99` 

In addition to the pre-defined switches, you may optionally append a standard command to the end of the command line, which would be automatically executed on entering A-Shell. This command may be any of the standard system (.LIT) commands, or a .DO or .CMD command file, for example: 

## `ashell run dsk0:menu[7,6]` 

or: 

## `ashell menu` 

where MENU could be any AMOS-format command file loaded into the path corresponding to DSK0:[2,2]. Note that the first format would only work if the user was pre-logged into an A-Shell mapped directory; otherwise the run command will fail due to not being logged in. Use of a command file (as in the second example) can eliminate this problem if the command file starts with a LOG command. 

A-Shell remembers the previous command line that launched it, on a user-by-user basis. This means that if you launch it without any arguments, it will use same command line as it used last time it was launched. Also, if no previous command line known, and no command line passed, and no MIAME environment variable defined, it will default to looking for miame.ini in the path 

A-Shell Reference 

Page 356 

above the executable. Both of these are mainly intended to be useful in conjunction with auto-update routines, as well as possibly with ShellExecute and HOSTEX. 

The A-Shell application can terminate the session by simply chaining to the program HOST.LIT **,** or by just returning to the A-Shell Command Prompt if the –e switch was specified on the startup command line. 

## **Subtopics** 

- Command Line Switches 

- Command Line File 

- Command Line File Option CLX 

- Virtual Command Files 

- Initial Window Settings 

- Launch Background Process on Boot 

- Update A-Shell While Running 

- Process Exit Code 

A-Shell Reference 

Page 357 

## **COMMAND LINE SWITCHES** 

_Updated June 2025_ 

Below is a list of the A-Shell startup command switches, followed by extended descriptions where needed. Note that if A-Shell/Windows is launched with no command line arguments, and there is no Command Line File defined, it will repeat the command line from the previous launch. 

|**Switch**|**Action**|**Switch**|**Action**|
|---|---|---|---|
|ateonly|Causes A-Shell to abort if not being launched<br>from an ATE connection.|||
|b|Buffer Name<br>:Change name of screen snapshot<br>buffer|n|Suppress the A-Shell splash/license/welcome screen|
|ba|Buffer and Snapshot<br>: Activate snapshots, append|nc|Removes the caption bar, creating a caption-less window|
|bc|Overwrite Buffer File<br>: activate auto-snapshot|nm|No Menu<br>:Hides the A-Shell menu bar|
|cgi|Common Gateway Interface<br>(web programming)|noclx|Disables search for .clx and .cl files. Must be 1st argument|
|cgifast|FastCGI<br>:Higher performance variation of cgi|nothem<br>e|Disables the Windows "Theme" functions.|
|d|DisplayDevice Name|nrs|Removes the resizing border of the main window|
|debug|Set Debug mode; equivalent to SET DEBUG on<br>startup|ntts|Same as OPTIONS=NTTS<br> in miame.ini, but much more<br>convenient in situations where you need the feature for just<br>a couple of sessions such as for services|



A-Shell Reference 

Page 358 

|**Switch**|**Action**|**Switch**|**Action**|
|---|---|---|---|
|devate|Use ATE Device ID<br>causes A-Shell to use the ATE<br>device ID as session device name.|o|Specify alternateSettings File|
|dpm|ActivatesDPI Per Monitor Awareness<br> mode|q|Quiet Mode|
|e|For A-ShellExit|r|Specify amount ofMemory|
|erz|Specifies anErsatz File<br> of device definitions|s|Was 'standalone mode'; no longer applicable.|
|fastcgi|Alias for "cgifast"|silo|'silo mode' for use within or to simulate Docker single-<br>process environment|
|g|SpecifyAlternate Icon|t|Background Task|
|h|Ignore Hangup Signal|td|Use specificTerminal Driver|
|hd|Hangup Delay|trace|DebuggingTrace Mode|
|hei|Hangup Error Immediately|ua|Unattended Mode|
|hetcki|Hangup Error on Tcki|uo|Override User Name|
|hp|Hangup Parent|v|Version|



A-Shell Reference 

Page 359 

|**Switch**|**Action**|**Switch**|**Action**|
|---|---|---|---|
|i|Specify Ini File|w|Deprecated though still supported; use -o|
|j|Force the use of specifiedJobname|wp|Override the defaultWindow Position|
|k|Prompt for security key|wpx|Enhanced version of -wp; seeWindow Position|
|m|Maximize<br>: Force window to remain maximized|z|Invisible<br>operations|
|min|Minimize<br>:Force window to start minimized|zi|Invisible with Icon|
|mntsys|Mount System Device|zt|Same as -z, except that task appears in task list|
|mx|Remove Menu Buttons<br> from title bar|2|Child Session|



## **See Also** 

- MX_CLFLAGS 

## **History** 

- 2025 October, A Shell 7.0.1780: Add fastcgi as an alias for cgifast. 

- 2019 September, A Shell 6.5.1666:  Add dpm. 

- 2018 July, A Shell 6.5.1639: Add ntts. 

- 2016 February, A Shell 1506: Add mntsys and noclx. 

A-Shell Reference 

Page 360 

- 2013 December, A Shell 1371:  Add nc and nrs. 

A-Shell Reference 

Page 361 

## **ATE ONLY** 

_Added November 2025_ 

## **-ateonly** 

The switch **-ateonly** causes A-Shell to abort if not being launched from an ATE connection. This is likely to be most useful in an ATSD environment exposed to the Internet without the benefit of a VPN, providing simple means of minimizing the trouble caused by port scanners and other unauthorized agents trying to connect to your system. 

Unlike in the Linux environment, with ATSD it's up to you to handle the login, which can't occur until A-Shell has instantiated a job for the connection. The **-ateonly** switch allows A-Shell to terminate connections from non-ATE workstations before assigning a job to them. 

## **History** 

- 2025 November, A Shell 7.0.1781:  Function added to A-Shell 

A-Shell Reference 

Page 362 

## **BUFFER NAME** 

## **-b <buffer file name>** 

The **-b** switch allows you name the screen picture buffer file something other than the default of <jobname>.buf. Specify the buffer file name in DevPPN format. The default extension is BUF, and the default directory is MEM0:[1,1] (if it exists) or else the current directory. 

The screen picture buffer file is used for storing screen snapshots, which can be generated via one of the following methods: 

The CTRL+P command pops up a dialog which gives you the option of displaying the current screen buffer (which may contain several screen snapshots appended together), the option of which printer (if any) to print it to, and the option to clear the current screen buffer contents after printing. Accumulating many snapshots in a single screen buffer file may be useful for auditing or documentation purposes, or even as a way of allowing the user to refer back to prior screen in a multi-screen process. 

The INFLD _type_ code **|S** will automatically take a screen snapshot on exit from the field, without asking any questions. This can also be useful for auditing or documentation purposes (but will quickly create a very large screen buffer file.) You can add this globally using the SBR=INFDEF setting in miame.ini, although it may be more convenient to use the **–ba** or **–bc** command line switches instead of **–b** (see next). 

A-Shell Reference 

Page 363 

## **BUFFER AND SNAPSHOT** 

## **-ba <buffer file name>** 

The **-ba** switch is identical to **–b** except that it also turns on the auto-snapshot feature. This is equivalent to adding **|S** to every INFLD call as described above, but is certainly more convenient, particularly when used with specific background tasks. Otherwise you would either need to modify all your programs or to use a separate copy of miame.ini, one with `SBR=INFDEF: |S` and one without. 

A-Shell Reference 

Page 364 

## **OVERWRITE BUFFER FILE** 

## **-bc <buffer file name>** 

The **-bc** switch is identical to **–ba** except that if the specified buffer file already exists, it is deleted and a new one created in its place. 

A-Shell Reference 

Page 365 

## **CHANGE DIRECTORY** 

On exiting A-Shell/DOS, you are normally returned to the original DOS working directory, regardless of any PPN changes which occurred while A-Shell was running. If you wish the working directory to be set according to the last A-Shell PPN, then the **-c** switch should be specified. Thus a batch file to actually change the current working directory, via the LOG command would contain both switches: 

```
ashell -e -c log sys:
```

A-Shell Reference 

Page 366 

## **COMMON GATEWAY INTERFACE** 

The **–cgi** switch invokes a number of features which simplify the use of A-Shell and CGI (Common Gateway Interface) or web programming. One feature of the –cgi switch is an automatic 7 second inactivity timeout. CGI processes should be quick, usually completing in less than a second, but in any case there wouldn’t be any purpose in the process being inactive this long. 

More importantly -cgi swaps _stdout_ and _stderr_ so that normal screen output goes to _stderr_ instead of _stdout_ . The purpose of this seemingly senseless trick is to allow your CGI programs to continue to use PRINT statements (possibly for debugging, or possibly because you were converting a normal program to CGI use and didn’t get rid of all the PRINT statements) without interfering with the web output. By sending such output to the _stderr_ channel, not only does it stay out of the way of the web page but it can also be redirected to a file (convenient for debugging.) In order to output to the new web page, you must then use CGIUTL. 

_Stdout_ and _stderr_ refer to the "standard output" and "standard error output" streams of Unix programs. See the subroutine CGIUTL and the section on web programming for more details. 

A-Shell Reference 

Page 367 

## **DEVICE NAME** 

Each instance of A-Shell is assigned a unique CONSOLE device name. An instance may be a user terminal, or a window, for example. This console device name is used in conjunction with the TRMDEF commands in miame.ini in order to determine the job and terminal name to be assigned. When networks are involved, or Microsoft Windows, the console device name is not necessarily fixed, and can be assigned dynamically by the operating system. In order to assist in the construction of the TRMDEF entries, the **-d** switch may be used, which causes A-Shell to display the currently assigned console device name. Note that you can also display device names using `SYSTAT/C` . 

A-Shell Reference 

Page 368 

## **DPI PER MONITOR AWARENESS** 

_Written November 2019_ 

"Dpi Per Monitor awareness" was introduced in Windows 8 so that developers could take advantage of display characteristics that only make sense on high-resolution monitors. The **-dpm** switch in A-Shell implements this Windows function, and you must be running Windows 8.1 or greater to realize its benefits. Below are two examples showing how a monitor with resolution 3840x2160 displays text and graphics with the -dpm option being set (above and left), and without it. On a 1920x1200 monitor, there was no apparent difference between the "with" and "without" **-dpm** setting. 

Text only output: 

## **History** 

- 2019 September, A Shell 6.4.1666:  Add switch to A-Shell. 

A-Shell Reference 

Page 369 

## **EXIT** 

The **-e** switch is used in conjunction with the optional command name and forces A-Shell to exit to the host shell prompt on completion of the command. This is useful for preventing users from ending up at the A-Shell command prompt (where they might be lost or even do damage) if the application terminates unexpectedly. It is also useful for creating utilities that act like standalone native operating system commands but which require the A-Shell environment. 

As an example of the latter, imagine a Unix shop where the system administrator wants to be able to check on the status of A- Shell sessions, but doesn’t want to otherwise know anything about A-Shell (how to launch or terminate it.) You could create a shell script (call it "ashstat **")** that contained the following command: 

## `ashell -e do astat` 

This would execute dsk0:astat.do[2,2], which would log the user in and then launch ASTAT, something like: 

```
:R
```

```
LOG OPR:
```

```
ASTAT
```

Note that if input is piped into the ashell command by redirecting standard input, then the -e switch is assumed, and may not be overridden. 

The other way to auto-terminate an A-Shell process on the completion of a command is to have the command chain to HOST.LIT (if it is an ASB program), or to use a CMD or DO file that ends with the HOST command. In the ASTAT example above, you could have eliminated the –e switch from the ashell command line and instead added HOST to the end of the astat.do file. However, the **–e** switch is more convenient and more robust, since there is no way to accidentally get around it via some kind of program abort. 

A-Shell Reference 

Page 370 

## **ALTERNATE ICON** 

_Updated November 2015; see History_ 

The **–g** switch is used to force A-Shell/Windows and ATE to use an alternate icon. This icon appears in the About box, on the title bar, and on the task bar. Syntax may be any of the following. 

## **-g ####** 

Allows you to specify the internal numeric ID of an icon already embedded within the A-Shell executable. These are in the range of 1001-1050, but this typically isn’t very useful without some insider knowledge. 

## **-g resname** 

Similar to the first, except it allows you to specify the icon by its resource name. Again, you would need to have special knowledge about which icons are available. 

## **-g resname::dllname** 

This third option allows you to specify an icon by its resource name and the name of the DLL within which it resides. In this case, the DLL should be in the same directory as ashw32.exe was loaded from, or at least in the PATH. 

## **-g filename.ico** 

This fourth option is the easiest for most people to use, as it only requires that you supply an ico file. The file should be placed in the %MIAME%\icons subdirectory. The %MIAME% directory is set automatically to the directory where miame.ini was loaded from, unless manually set in your Windows configuration. 

## **History** 

A-Shell Reference 

Page 371 

- 2015 November, A Shell 6.2.1421:  Revise search for icon specified in **-g** command line switch to look specifically in the %MIAME%\icons directory before doing a more general search, so as to reduce the chance of finding an unexpected match. 

A-Shell Reference 

Page 372 

## **IGNORE HANGUP SIGNAL** 

The **-h** switch applies only to A-Shell/Unix and remote sessions connected via modem or telnet. When specified, the SIGHUP (hangup) signal is simply ignored. This was historically useful to allow a program (such as a posting program) to keep running even if its terminal connection was lost. However, its usefulness has been superceded by the default handling of SIGHUP, which properly turns the process into a background daemon. 

Note that regardless of the way you choose to handle the hangup situation, you can also have A-Shell produce a trace log documenting when it receives such a hangup signal and what it did about it. See the discussion of miame.ini TRACE statement for more details. 

A-Shell Reference 

Page 373 

## **HANGUP DELAY** 

The **-hd** switch is similar to the –h switch described above and applies only to Unix. It suppresses the ASB error #250, which would normally be generated, but removes and cleans up the process as soon as it goes into a terminal input wait state. 

This historic switch is probably no longer useful. If you don’t want to get an immediate error on receipt of the SIGHUP signal, just don’t specify any of the –h* switches. 

A-Shell Reference 

Page 374 

## **HANGUP ERROR IMMEDIATELY** 

The **-hei** switch causes an ASB error #250 to be generated immediately upon receipt of the SIGHUP (hangup) signal. The typical reason for receiving this signal is that the modem or telnet connection has been dropped, although it could also have been sent manually by another process using the kill command. The error will either cause your program to go to its trap routine, or if there is no trap routine active, to abort to the A-Shell command prompt. In either case, if the process doesn’t exit, A-Shell will terminate itself as soon as it stops to wait for terminal input. The idea here is to allow the process time to do any programcontrolled housecleaning that it cares to do, before being forcefully terminated. Note that -hei may be used in conjunction with -hetcki. 

If none of the –h* switches are specified, the default response to receipt of the SIGHUP signal is for the A-Shell process to become a background daemon but otherwise keep running normally, until such time as it stops to wait for keyboard input. Then, it will get the error #250, just as if –hei had been specified. 

A-Shell Reference 

Page 375 

## **HANGUP ERROR ON TCKI** 

The **-hetcki** switch causes A-Shell to treat "tcki" (check for keyboard input without waiting) operations equivalently to normal wait-for-keyboard operations, when deciding whether to terminate a session that has previously lost its terminal connection. Without this switch (or any other switch starting with –h), a process that has lost its terminal connection due to a disconnect will become a background daemon and continue to run until it stops to wait for input. At that point, an ASB error #250 will be generated. Merely checking for keyboard input without waiting—aka performing a "tcki"—would not have any effect on the program. 

Since the decision on whether a tcki operation should abort a program which has lost its connection may depend on the program, and therefore change during a session. 

A-Shell Reference 

Page 376 

## **HANGUP PARENT** 

The **-hp** switch is another variation on the **–h** switch described above. When specified, A-Shell performs the default handling of hangup conditions (as if no **-h** switch was specified) but then forwards the hangup signal to the parent process immediately before exiting. This has been found to be useful in certain Unix environments to force the telnet session to close properly, but should probably be avoided on the general principle that it is better to not to confuse the issue by sending signals that are normally managed by the operating system. 

The **–hp** switch is ignored by A-Shell if it is specified on the PolyShell command line. 

The "standard" technique for forcing a clean and total shutdown of a telnet session on exit from A-Shell is to launch A-Shell directly from the user’s login .profile, and follow that with an exit command. Thus when A-Shell exits, it returns to the .profile where it executes the Unix exit. 

Another technique is to use the ashgetty utility in place of the normal getty to handle the initialization and login on the terminal. Ashgetty allows you to make A-Shell take the place of the normal login shell, thus eliminating the possibility of normal operating system shell access outside of A-Shell. 

A-Shell Reference 

Page 377 

## **SPECIFY INI FILE** 

The **-i** switch allows you to override the default ini file, which is normally miame.ini in the path specified by the MIAME environment variable. Particularly in a development or support environment, it can be useful to have several different versions of A-Shell installed simultaneously in different directories, or to have multiple virtual machines set up. These could be complete copies of customers’ systems, with identical logical device configurations. In order to execute A-Shell on a specific virtual machine, it is either necessary to first set the MIAME environment variable, for example: 

```
SET MIAME=\VM\MACHINE1
```

```
ASHELL
```

or to override it with the **-i** switch: 

```
ASHELL -i C:\VM\MACHINE1\MIAME.INI
```

Note that unlike the MIAME environment variable, the value is the actual name of the configuration file, and does not represent a directory. 

A-Shell Reference 

Page 378 

## **JOBNAME** 

_Updated February 2017_ 

## **-j <jobname>** 

The **-j** switch forces A-Shell to use the specified jobname, provided it is not already in use. Otherwise A-Shell generates jobnames TSKAAA, TSKAAB, etc. (or uses the TRMDEF statements). 

The **-j** switch supports two optional suffixes: 

# will be converted into digit 1-9 to make the job name unique. Example: `-j jack#` will generate job names of JACK1, JACK2, etc.) 

% Same as #, above, but does not allow jobs originating from different workstations to share the same base jobname. This requires ATE to enforce the workstation identification aspect of that. 

## **Comments** 

**Warning:** If the specified jobname is already in use, the user will be prompted to kill the existing job (by sending the SIGKILL signal to it, generating ASB Error 251, generally followed by an exit.) And if the current launch command is executing in a background session (Unix), it will assume an affirmative response, i.e. will always try to kill a job with a conflicting name. 

(Windows) The **-j** <jobnam> switch will automatically replace a conflicting entry in the job table if the job has not shown any signs of life in the last minute. This refinement is intended to improve recovery from situations where a service job is aborted in such a way that it is unable to remove itself from the job table (such as a Task Manager abort), causing the auto-restart of the job to fail. 

## **History** 

- 2025 June, A Shell 7.0.1733:  The **-j** <jobnam> switch will now automatically replace a conflicting entry in the job table. See additional notes above. 

- 2012 August, A Shell 6.0.1255:  Add optional suffixes as described above 

A-Shell Reference 

Page 379 

## **MAXIMIZE** 

(Windows only) The **-m** switch forces the A-Shell/Windows window to launch in maximized mode, and it also eliminates the min/max/close buttons and system menu from the window title bar. The idea is to make it very difficult for the user to unilaterally or accidentally resize or close the window. This can be useful in situations where you want to, er, minimize, the _windows-ness_ of the application. 

A-Shell Reference 

Page 380 

## **MINIMIZE** 

(Windows only) The **-min** switch forces the A-Shell/Windows window to launch in minimize mode. This is similar to the **–z** and **–zi** switches, except that there will be a normal icon on the task bar, which you can click on to make the window visible. 

A-Shell Reference 

Page 381 

## **REMOVE MENU BUTTONS** 

(Windows only) The **-mx** switch is similar to **–m** (see above) except that it does not force the window to be maximized, and it even allows the window to be resized (by dragging the border.) Like **–m** , it removes the min/max/close and system menu buttons from the title bar, making it somewhat more difficult to accidentally "lose" the window. 

A-Shell Reference 

Page 382 

## **NO MENU** 

(Windows only) The **-nm** switch hides the A-Shell menu bar. This may be useful in conjunction with **-m** and/or **-mx** to limit the end-user possibilities for getting themselves into things they shouldn't. 

A-Shell Reference 

Page 383 

## **SETTINGS FILE** 

## **-o <settings file>** 

(Windows only) The **-o** switch allows you to specify a "settings file" other than the default (default.ash). An A-Shell "settings file" contains the options that are otherwise configurable via the Settings menu items (e.g. color definitions.) To make changes to those settings permanent, you can use the File menu Save Settings As dialog to save a new copy of the default settings file (default.ash) or create a separate settings file of a different name. In the latter case, you would need to use the -o switch to specify the alternate settings file's name. 

If only a filespec (with no directory) is given, then the directory is assumed to be the same directory as miame.ini was located in. And if no extension is given, ".ash" is assumed. 

This switch was previously –w, which is still supported but –o is preferred in order to avoid confusion with the –w switch of vue. 

If the full filespec of the settings file contains spaces, then you must enclose it in quotes. For example: `-o "c:\My Documents\my ashell settings.ash"` 

## **Comments** 

The **-o** <settings file> specification may contain embedded %env% variables. For example, when sharing a single %MIAME% directory between multiple users that may want to have independent settings without having to change the settings file name, you could use a standard -o value or something like: 

- `-o "%USERPROFILE%\Application Data\A-Shell\myapp.ash"` 

If the specified file is not found, A-Shell will also look for it in the %MIAME% directory, and that isn't found either, it will look for %miame%\default.ash. Regardless of which (if any) is found, when the user uses the Settings...Save option to save the settings, they will be written to the location specified by the **-o** switch. The effect of this is that users may start out sharing their window settings, but as they customize them, they start using their own private settings. 

A-Shell Reference 

Page 384 

## **QUIET MODE** 

_Updated February 2022; see History_ 

The **-q** switch tells A-Shell to silence its screen output. This is normally only applicable under Unix when you want to launch a child session (using XCALL HOSTEX) to perform some quick operation and you don’t want the user to see the resulting screen output. The normal approach, however, to this type of thing is to use the "Q" option in Xcall Ashell, which internally uses the **-q** switch under Unix and alternate techniques under Windows. 

Note that as of A-Shell 6.5.1711, the **-q** switch will also silence fatal abort messages. The only way to detect such conditions would then be to test the Process Exit Code. 

## **History** 

- 2022 February, A Shell 6.5.1711: Switch now silences fatal abort messages. 

A-Shell Reference 

Page 385 

## **MEMORY SIZE** 

## **-r <memory size>** 

The **-r** switch allows you to specify the memory "partition" size (in kilobytes) for this instance of A-Shell, overriding the MEMORY setting in miame.ini. You can specify one or two values, such as: 

- `-r 800,500` 

- `-r 600` 

The first example specifies 800K for the initial partition, and a minimum of 500K for execution of Xcall ASHELL and SBX subroutines. The second example specifies 600K for the initial partition, and leaves the default—or previously specified—size for subroutines alone. 

A-Shell Reference 

Page 386 

## **BACKGROUND TASK** 

(Windows only) The **-t** switch causes A-Shell to operate in a pseudo background mode which simulates the way a program would run under the AMOS Task Manager, except no log file is created. This switch is used internally by SUBMIT.LIT when running under Windows. Under Unix, you can use the normal shell syntax for running a program in background (i.e. by placing an "and" at the end of the command line.) Note that this option was previously implemented as **–b** . 

A-Shell Reference 

Page 387 

## **TERMINAL DRIVER** 

The **-td** switch allows you to force A-Shell to use the specified terminal type. Under Unix, this overrides the TERM environment variable, which would otherwise be used to determine the terminal type. Under Windows, it only applies in conjunction with ATS (A-Shell Telnet Server), in which case it overrides the terminal type negotiation that would normally be worked out between A- Shell and the telnet client. 

## **See Also** 

- Selecting a Terminal Emulation 

A-Shell Reference 

Page 388 

## **TRACE MODE** 

The **-TRACE** switch is only useful in troubleshooting situations. It causes an enormous amount of information to be written to the log file (ashlog.log) which can help in debugging difficult problems. 

Note that although the normal location for the ashlog.log file is in the same directory as miame.ini (or in the directory specified by the LOGDIR key in miame.ini), certain trace operations may occur before A-Shell has established either of those locations. For those traces, it uses the TEMP directory to create ashlog.log. This can be particularly useful in debugging problems relating to not being able to access miame.ini (such as networking problems). 

So if A-Shell fails to launch correctly and you can't figure out why, try adding "-trace" to the command line (in the properties of the shortcut) and then look at the copy of ashlog.log that will be found in the TEMP directory for the user. For windows, this is typically: "c:\Documents and Settings\<username>\Local Settings\Temp\ashlog.log." 

For Unix, it will be "/tmp/ashlog.log". 

Note that if the launch proceeds to the point where it starts to process miame.ini, subsequent log entries will go to the regular ashlog.log file in the directory where miame.ini is or as specified by LOGDIR. 

A-Shell Reference 

Page 389 

## **OVERRIDE USER NAME** 

_Reviewed and updated, September 2024; see History_ 

## **-uo launchname** 

When specified, the **-uo** switch creates a new entry in the existing hierarchy of user names: 

```
APP user (name specified by app via MX_SETUSRNAM)
```

```
LAUNCH user (name specified on command line with -uo)
```

```
REAL user (the name used to login in to the OS*)
```

Note that under Unix, the REAL user could also be the "effective" user--i.e. the owner of the A-Shell executable if the **+s** flag is set. See EFFUSRSP for information on how the various routines that return user name decide between those two. 

The REAL user name is always defined, since you need it to log in to the host OS. The other two levels are optional, but default to the level below it. For example, if you don't specify the **-uo** switch, then the LAUNCH user will be the same as the REAL user. 

To bypass the normal hierarchy and retrieve the LAUNCH or REAL user name directly, you can pass either "!" or "!!" to GETUSNXS, e.g.: 

```
USER$ = "!"
```

```
XCALL GETUSN,USER$  ! returns LAUNCH user in USER$
```

```
USER$ = "!!"
```

```
XCALL GETUSN,USER$  ! returns REAL user in USER$
```

Note that MX_SETUSRNAMXS, reset application user name, will effectively reset it to the LAUNCH user. 

The only way for an application to force the APP user name to the REAL user (overriding the LAUNCH user) would be to retrieve the REAL name with the GETUSN "!!" method, and then use MX_SETUSRNAMXS to set the APP user to match the REAL user. 

If the the **-uo** switch was used with this session of A-Shell, _launchname_ will be forwarded it to any child instance of A-Shell. 

A-Shell Reference 

Page 390 

## **History** 

- 2025 August, A Shell 7.0.1777:  Detects if the current session is running with the **-uo** switch, and if so, to forward it to any child instance of A-Shell. 

- 2024 September, A Shell 7.0.1762:  Updated to make switch work under Linux. Previously it was only working under Windows. 

A-Shell Reference 

Page 391 

## **VERSION** 

The **-v** switch displays the current version of A-Shell. This is displayed prior to any automatically executed command. A typical output might be: 

```
==== A-Shell/32 Ver. 4.9(925)c-2 running under MIAME Version 1.2(214) ====
```

```
                        (c) MicroSabio 1990, 2000
```

Note that the **-v** switch is entirely superfluous with recent versions of A-Shell, since the standard license message (which displays every time A-Shell is launched) includes all of the information shown by the switch. 

A-Shell Reference 

Page 392 

## **INVISIBLE** 

(Windows only) The **-z** switch causes the A-Shell session to be totally invisible, not even showing up in the task list, although it will still show in SYSTAT. This can be useful for special situations such as background daemons, CGI commands, etc. 

To make an invisible window reappear, the job itself can execute `XCALL MIAMEX,77,FLAG,` where FLAG is anything between 1 and 11, covering the various ways in which a window can be displayed; see the sample program MIAMEX.BP in EXLIB:[908,30] for more details. Or, you can remotely force the job to reappear using `SEND <jobname> !—` that is, send it a message consisting of a single exclamation point. This latter method uses the InterJob Communication (IJC) system which operates on a frequency set by the IJCFREQ setting in miame.ini. 

A-Shell Reference 

Page 393 

## **INVISIBLE WITH ICON** 

(Windows only) The **-zi** switch is similar to **–z** except that it also adds an A-Shell icon to the taskbar notification area (aka "system tray"). You can thereby make the window visible by double-clicking on the icon. 

A-Shell Reference 

Page 394 

## **CHILD SESSION** 

## **-2 <parent jobname>** 

The **-2** switch is normally only used internally (e.g. by Xcall ASHELL) to indicate that the session being launched is a "child" of the specified parent jobname. The main consequence of this is that the PLYJOB and GETJTB subroutines will be able to identify the parent in the JOBATT field. 

The miame.ini setting SBR=AMOSJOB1 will cause JOBNAM to return the parent jobname specified by the **-2** <parent jobname> switch, rather than the child job name. 

A-Shell Reference 

Page 395 

## **UNATTENDED MODE** 

This is useful for running programs unattended but not fully in background. The main effect is to convert any message boxes which would otherwise require user input to trace messages in the System Messages window or on the screen. 

Beginning with A-Shell 7.0.1778 of October 2025, the **-ua** switch has an additional side effect under Linux: it allows allow background jobs to sit at input prompts without aborting. Normally a process in background will terminate when it tries to input if it doesn't have a real terminal and there is no piped input available, which normally makes sense. But in some cases, it is useful to be able to launch a background task and let it wait for input to be forced to it via the FORCE command. In particular, this technique is used by ADB.LIT when debugging a process running in a background task launched by ADB.LIT itself. 

A-Shell Reference 

Page 396 

## **MOUNT SYSTEM DEVICE** 

_Added February 2016_ 

This switch allows defining a system logical device that will be searched ahead of SYS:, CMD:, and BAS: 

## **-mntsys dev:=path** 

For example: 

```
ashell -i /vm/miame.ini -mntsys asr65:=/vm/miame65/dsk0 log sys:
```

Assuming the specified path /vm/miame65/dsk0 existed and contained 001004, 002002, and 007006 directories, these would be searched prior to the corresponding dsk0:[1,4], dsk0:[2,2] and/or dsk0:[7,6] directories. 

This can be useful in situations where you want to test a new version of A-Shell without overwriting your existing DSK0: directories. 

## **History** 

- 2016 February, A Shell 6.3.1307: Function added to A-Shell 

A-Shell Reference 

Page 397 

## **ERSATZ FILE** 

_Added April 2019_ 

## **-erz <path>** 

allows you to specify a file containing ersatz device definitions to be processed prior to any ERSATZ statement(s) in miame.ini, regardless of whether the -erz switch comes before or after the -ini switch. <path> should be in native syntax, for example: 

```
ashell -i /vm/miame/miame.ini -erz /vm/env1/test.erz
```

This is intended to be a convenience in situations where you have multiple environments which could share miame.ini except for the ersatz definitions. 

Note that when there two or more definitions for the same ersatz device, the first one defined will take precedence. So any ersatz definitions in the file specified by the -erz command line will take precedence over any subsequent definitions. 

## **History** 

- 2019 April, A Shell 6.5.1559:  Function added to A-Shell 

A-Shell Reference 

Page 398 

## **WINDOW POSITION** 

## **-wp <placement spec>** 

## **-wpx <placement spec>** 

The **-wp** command line switch is used to override the default window position. The **-wpx** switch does the same thing with some additional capabilities. See "WPX Enhancements" below. 

The placement spec is made up of an optional monitor identifier prefix and a window position spec within that monitor. Monitor identifiers consist of the prefix letter "m", followed by a character from the set of (l,r,t,b,c) indicating left,right,top,bottom or center, followed by a colon: 

|**Spec**|**Placement**|
|---|---|
|ml|left-most monitor|
|mr|right-most monitor|
|mt|top-most monitor|
|mb|bottom-most monitor|
|mc|center monitor|



If not specified, or if the system has only one display monitor, the primary monitor is used. 

The window position spec consists of one or two characters from the same (l,r,t,b,c) set, followed optionally by one or two digits indicating the division of the vertical or horizontal space on the monitor. By convention, vertical position specifiers should 

A-Shell Reference 

Page 399 

precede horizontal (i.e. use "tl" for top left instead of "lt" for left top). The divisor digit(s) default to 2 if not specified. Some examples: 

|**Spec**|**Placement**|
|---|---|
|t|use top half of monitor; same as t2|
|br|use bottom right quadrant; same as br22|
|bc23|bottom half, center third of monitor|
|cc|centered vertically and horizontally, half width and height|



## **WPX Enhancements** 

Action is the same as for **-wp** except that the **-wpx** version also does the following: 

- restricts dialogs to the boundaries of the main window 

- disables saving updated dialog positions (for MBF2_DLGSTATE and OPTIONS=AUTODLGSTATE). 

- disables application-level saving of current window settings via the AG_WINSETTINGS command. 

## **Examples** 

- `-wp ml:l2    ! window occupies the left half of the left-most monitor` 

- `-wpx ml:l2   ! window gets the left 60% of primary monitor` 

- `-wp ml:l2    ! window gets the bottom right 40% of right monitor` 

## **History** 

A-Shell Reference 

Page 400 

- 2023 November, A Shell 7.0.1751:  Function added to A-Shell. 

A-Shell Reference 

Page 401 

## **USE ATE DEVICE ID** 

_New October 2024_ 

The **-devate** switch (UNIX only) causes A-Shell to use the ATE machine:## identifier (if available) for the unique session device ID, instead of the normal dev:pid (e.g. "pty/1:3424") format. 

## **History** 

2024 October, A-Shell 7.0.1754: Switch added to A-Shell 

A-Shell Reference 

Page 402 

## **NOTHEME** 

_Added November 2025_ 

## **-notheme** 

This switch disables the Windows "Theme" functions. The primary motivation is for stripped-down Windows environments or emulators such as Wine. At this point it's not yet clear how viable a platform Wine is for A-Shell or ATE, but the basic operations do seem to work. 

## **History** 

2025 November, A-Shell 1781:  Function added to A-Shell 

A-Shell Reference 

Page 403 

## **COMMAND LINE FILE** 

Although there are a lot of possible A-Shell command lines switches, and it would be inconvenient to have to type them every time, there are multiple ways to store one or more sets of them in a file, to be invoked later without having to retype them. Under Windows, the simplest approach is to store them all in the properties of the icon(s). Under Unix, you can create multiple script files that contain different complete command lines. 

Even with the above options, sometimes it is most convenient to be able to execute A-Shell simply by invoking the executable name (e.g. ashell.exe or ashw32.exe). For this kind of situation, we offer " **cl** " (command line) files. A **cl** file contains just the command line switches, not the name of the ashell executable. They work as follows. 

If A-Shell is invoked with no arguments, or if the first argument does not start with a "-", or if the A-Shell executable is not the standard one (ashell.exe or ashw32.exe), then it looks for a file in the same directory and with the same name as the ashell executable but with an extension of ".cl" (e.g. ashell.cl or ashw32.cl). If found it is expected to contain a single line of command arguments to A-Shell. The first line is thus parsed into tokens, and the tokens are inserted into the command line prior to any arguments which were on the original command line. This allows you, for example, to specify the "-i <inifile>" setting even when it is not possible to have it supplied explicitly on the A-Shell command line. An example may make this clearer. 

Let's take the case of CGI, in which you can specify an arbitrary executable path for the CGI program in the web form, but you may not be able to specify any arguments. Previously, the only way to use A-Shell as a CGI engine in this case would be to create a front-end script that in turn contained the full A-Shell command line. Now what you can do is put a copy (or just a link) of the A-Shell executable in new directory, say, /vm/web. Give its path as the CGI executable spec in the web form (i.e. /vm/web/ashell). Then create a /vm/web/ashell.cl file that contains the rest of the command line, e.g.: 

## `-i /vm/web/miame.ini -cgi cgigo 2>/tmp/cgi.err` 

When /vm/web/ashell starts up, since it was not passed any arguments, it will see the /vm/web/ashell.cl file and insert the contents (line 1 only) into its own argument list. Another example would be where you have some kind of existing module that is capable of invoking arbitrary external commands of the form: 

```
<command-executable-path> <file-arg>
```

The makers of this program perhaps expected you to use this facility to launch your own file editor, or print utility. But you want to use A-Shell to operate on the <file-argument> using your own custom logic. Previously, it would have been awkward to work with this command line, due to the need to predefine the MIAME environment variable, not to mention the problem of using a 

A-Shell Reference 

Page 404 

native filespec argument where A-Shell would have been expecting an AMOS command file name. Now, by setting up a **cl** file in the same directory as the ashell executable, you can invoke your own program on the <file-argument>, perhaps something like this: 

- `-i c:\vm\miame\miame.ini myprog` 

The assumption here is that 'myprog' is actually a DO file which will then receive the <file-argument> as its parameter, allowing you to then pass it on to an ASB program, using one of these basic techniques: 

```
;myprog.do
:R
log myppn:        ; you must log somewhere
run myapp $0      ; myapp will use LSTLIN to get $0
```

or 

```
run myapp
```

```
$0                ; myapp will use INPUT to get $0
```

Note that in the above example, the complete ashell command line after processing ashw32.cl would be: 

```
<ashell path>\ashw32.exe -i c:\vm\miame\miame.ini myprog <file-arg>
```

The important thing to see there is that the contents of the **cl** file got inserted into the command line after the name of the ashell executable but before the <file-arg> which was on the original command line. 

The other thing to note here is that the **cl** file must have the same name as the A-Shell executable and be in the same directory. If you have only one such special need, then it can probably share the same A-Shell executable and directory as your regular A- Shell users (since the regular users, at least under Windows, would presumably always be passing one or more -switches on the A-Shell command line, and thus would not use your .cl file.) But if you have need for multiple **cl** files, or you are launching A- Shell under Unix with no switches at all, then you will have to create one or more copies of (or links to) your A-Shell executable, each of which can then have its own **cl** file. 

A-Shell Reference 

Page 405 

## **COMMAND LINE FILE OPTION CLX** 

_Added February 2016_ 

## Command line file option: <executable>.clx e.g. ashell.clx or ashw32.clx 

Similar to the .cl file, the .clx file may be optionally placed along side the ashell executable in order to supply an alternate command line. But unlike the .cl file, which is only used if the original command line does not contain any switches, the .clx is used regardless of the original command line. This is useful in situations where you want to modify the ashell command line for all the users, without having to track down and modify all the individual user startup command or shortcut files. 

Also unlike the .cl files whose contents always augment the original command line arguments, the .clx command line may either replace the original command line, or be inserted prior to the original. To get the latter effect, add a " +" to the end of the .clx command line. 

For example, if the original command line is: 

```
ashell -i /vm/miame/miame.ini log bas:
```

and there is an ashell.clx in the same directory as the ashell executable, containing: 

```
-mntsys asr65:=/vm/miame65/dsk0 +
```

then the new effective command line will be: 

```
ashell -mntsys asr65:=/vm/miame65/dsk0 -i /vm/miame/miame.ini log bas:
```

If the "+" was removed from the end of the .clx file, then the new effective command line would simply be the executable followed by the contents of the .clx file, i.e. 

```
ashell -mntsys asr65:=/vm/miame65/dsk0
```

## **History** 

- 2016 February, A Shell 6.3.1307: Function added to A-Shell 

A-Shell Reference 

Page 406 

## **VIRTUAL COMMAND FILES** 

A-Shell startup command line commands can also be assembled into a virtual command file, consisting of multiple commands separated by '\n'. For example: 

```
ashw32.exe -e LOG BAS:\n:T\nJOBALC\nTIME\nEL -CFG
```

The above command line (after the -e) is equivalent to the following command file: 

```
:R            ; (this is automatic)
```

```
LOG BAS:
```

```
:T
```

```
JOBALC
```

```
TIME
```

```
EL -CFG
```

Note that the \n is case sensitive (must be lower). Also note that if using this technique under a Unix shell, you will need to 'escape' the backslashes by preceding them with a backslash, i.e.: 

```
ashell -e LOG BAS:\\n:T\\nJOBALC\\nTIME\\nEL -CFG
```

## **Notes** 

A-Shell attempts to analyze whether any \n characters occur in something that looks like a filespec. If so, it treats the \n as literal; else it treats it as a line break. For example: 

```
xcall HOSTEX,"$ASHELL log ashtst:\nvue c:\notes \nsize c:\notes.txt"
```

The above command line contains 4 \n sequences. The first and third are considered not part of filespecs and thus are converted to line breaks. The second and fourth, which are contained in the token c:\notes.txt, which is interpreted as a filespec because it starts with what could be a drive letter. 

A-Shell Reference 

Page 407 

Note the following tricks and considerations when trying to get "\n" to be treated as a line break: 

• If you want to follow a filespec with "\n", precede it by a space, as we did in the example above for the "\n" following "vue c: \notes". A trailing or leading space does not usually interfere with the interpretation of a filespec, so that shouldn't cause a problem. Without the space, in the example above, "c:\notes\nsize" would have been considered a single filespec. 

- Quoting the filespec doesn't help, since the quotes are generally removed by the shell or other command line parser before 

- we get to the code that looks for "\n". 

- A token is considered to be a filespec if it starts with \\ or with a letter followed by a colon. 

A-Shell Reference 

Page 408 

## **INITIAL WINDOW SETTINGS** 

Prior to build 1128 of 23 Oct 08, A-Shell looked for %miame%\default.ash unless a settings file was specified via the **-o** switch on the command line. In that case, if the specified filespec started with "%USERPROFILE%\Application Data\ATE" directory, and the file was not present, it would have looked in %MIAME%, but the File>Save function would have saved it to the %USERPROFILE% directory. 

Beginning with build 1128, the new scheme is that if no -o switch is specified, the search path is: 

```
%APPDATA%\<appname>\<cfgname>.ash
```

```
%APPDATA%\<appname>\default.ash
```

```
%MIAME%\<cfgname>.ash
```

```
%MIAME%\default.ash
```

where <appname> is "ATE" or "A-Shell" depending on the context. For ATE, <cfgname> is the name of the connection profile; for A-Shell it is the name of the ini file, or "default" if the ini file is miame.ini. 

If a **-o** file is specified, then it overrides the above rules, although if the file has no directory, the search path will be %APPDATA%\<appname> and then %MIAME%. This matches the prior search path when **-o** was used without a fully qualified path, except that %APPDATA% works better (and resolves differently) under Windows Vista and later. 

The File>Save and File>Save As menu items have been merged into a single File>Save... dialog, which allows you to save the current settings to one of the four locations/names above, and in addition contains a Save As button for more exotic options. It also contains a Delete button as a convenience for deleting a saved settings file (although it does not allow deleting the %miame%\default.ash file). And, it shows the filespec of the settings file that the current settings were loaded from. 

## The objectives of the above changes were: 

- To better support Windows Vista and later, which have a different location for which the %APPDATA% directory is not the 

- same as %USERPROFILE%\Application Data directory; 

A-Shell Reference 

Page 409 

• To make it easier for dealers, site managers, and individual users to manage their personal window settings without having to manually adjust their shortcut command lines. 

The new scheme is as security-lax as the old one (allowing anyone to overwrite the shared %miame%\default.ash), but the save function does always default to one of the %APPDATA% options (hopefully eliminating some of the accidental overwrites). The next step will probably be to allow the shared copy to be password protected. 

A-Shell Reference 

Page 410 

## **LAUNCH BACKGROUND PROCESS ON BOOT** 

A common question is how to launch an A-Shell background process on system boot. Essentially the concept is the same as launching any kind of independent background process, except that we need to insert our command somewhere that will get it executed automatically by the system boot process. Unfortunately, the details of that vary from one Unix platform to another, but to take an example, most Unix distributions have a script **/etc/rc.local** which gets executed towards the end of the boot process, and which is intended for launching application-level processes like A-Shell. 

Although you can put as many entries as you like into **/etc/rc.local** , I would recommend consolidating all your A-Shell related startup processes into a single script kept in the A-Shell bin directory (we'll call it **bgprocs** ) and then have rc.local execute it. (That way, when you set up a new system, or overwrite your **rc.local** , it's easy to reconfigure it. For example, you could insert into rc.local something like: 

```
echo "Launching A-Shell background processes..."
```

```
/vm/miame/util/bgprocs
```

(I recommend you create a special subdirectory below the $MIAME directory where you keep your own scripts, nice and separate from A-Shell stuff. In this case we're calling it /vm/miame/util) 

Your **bgprocs** script should reference a separate script for each of the processes you want to launch. This may seem like overkill, but it allows you to execute the individual scripts again later, as needed, to re-launch a background process by itself. So let's say we have two background processes we want to launch: 

```
# launch background process #1
```

```
/vm/miame/bin/bgpro1
```

```
# launch background process #2
```

```
/vm/miame/bin/bgpro2
```

Finally, each of the individual process launching scripts could look something like this... 

A-Shell Reference 

Page 411 

```
echo "Starting Background Processor #1..."
```

```
/vm/miame/bin/ashell -n -e -td DUMB -j BGPRO1 -i /vm/miame/miame.ini BGPRO1 >>
/vm/miame/dsk0/444123/bgpro1.lst 2>&1 &
```

**Important:** Remember to mark all of these scripts as executable (using chmod +x)! 

A few notes about the command line in the example above: 

**-n** will eliminate the splash message, which isn't very useful in the background process 

**-e** will cause the job to exit A-Shell if it drops back to the dot. (This is usually helpful for detecting whether the job is running, particularly in conjunction with the **-j** switch to set the jobname. If it stops running, you could probably just launch your **bgprocs** script again to restart it.) 

**-td DUMB** will tell it to use the DUMB terminal emulation, which will minimize the amount of escape sequence garbage that will appear in the output log 

**-j BGPRO1** forces the job to be named BGPRO1 in this case. That is of course optional, but is sometimes helpful for making it easy to spot whether a particular background server job is running. 

The **BGPRO1** following the ini file spec is the startup command. In order to get your background process running, you will 

probably need a command file (here it's cmd:bgpro1.cmd) to log the job to the right location and start the program running. 

**>> /vm/miame/dsk0/444123/bgpro1.lst** causes the output of the process to go into that file (useful for checking what happened later, and to keep it from going somewhere undesirable, like into the mail queue.) I recommend putting the output file in the same ppn where the process runs, although you have to specify it in native notation here. 

**2>&1** forces the _stderr_ output (file descriptor 2) to go to the same place as descriptor 1 ( _stdout_ ), so that any error messages coming from the operating system relating to the launch of A-Shell itself will also be captured there. 

As for keeping tabs on the background processes, it is recommended that they output their own status information to some kind of text file. The procedure SYSLOG in SOSLIB:[907,12] does a nice job of this, but if you do your own, make sure you add a timestamp to each entry. Also see the function Fn'Sprintf$() in SOSLIB:[907,10] which is very handy for outputting formatted messages and has a simple code for time stamping. 

A-Shell Reference 

Page 412 

Then you can create a relatively simple utility monitor program that uses `SYSTAT/L` to get a list of the jobs running (from which it can determine if each of the background jobs is running, either from their jobname or the program name column). So you display a little list, and provide some way to request to see the log for any one of them. (You can use EZTYP, or perhaps `TAIL <file>` for that.) If the job is not running, you can re-launch it by using `xcall HOSTEX,"/vm/miame/util/bgpro#"` or something like that. 

## **Example** 

Here is an example of such a screen that was set up for a customer with several background processors. It just has a onecharacter INFLD field for each process, where you can enter a code to display the activity log, reset the job, or ESC. Of course you can get much fancier with a GUI screen, perhaps creating a continuous multi-window monitor. 

```
SENSORS - Status and Maintenance of scales & scanners
```

```
Program   Job      Status     Action (A=Activity log, R=Reset, ESC=exit)
```

```
-------   ------   --------   ------------------------------------------
```

```
ACOUNT    ACOUNT  [OK]          A
```

```
ASCALE    ASCALE  [OK]
ASCAL2    ASCAL2  [OK]
CMBSCL    CMBSCL  [OK]
KSCALE    KSCALE  [OK]
CSCALE    CSCALE  [OK]
CARCAM    CARCAM  [OK]
```

A-Shell Reference 

Page 413 

## **- UPDATE A SHELL WHILE RUNNING** 

A common situation is the desire to install a new A-Shell executable, but you have several people still running the old one. The question is: 

Can you install a new version of the A-Shell executable without first getting all the old users to log out? 

The answer is yes; you can install the new version of the A-Shell executable while users are still running the old version without much difficulty at all. 

Unlike Windows, which identifies program modules by their file or module name, under Unix, program modules are identified by the inode (numeric id associated with the directory entry). So, even though all users will typically share a single copy of the "code" part of the A-Shell executable in memory, since it is identified by the inode and not the name, we can introduce a new version of the same executable without disturbing the existing version on disk or in memory. 

The cleanest procedure is to rename the existing A-Shell executable. I recommend renaming it to ashell_xxxx where xxxx is the edit number; this makes it easy to go back to the old version for testing or if you change your mind. Then copy the new A-Shell executable into the normal bin directory. 

As soon as you complete the step above, any new user launching A-Shell will get the new copy, and since the new copy has a different inode than the original, the new copy will be loaded, and then shared by all subsequent users, such that it is completely independent of the old copy. 

The above all assumes that the two versions are "close enough" to each other that they don't create compatibility issues between them. In general, as long as you are on the same major and minor version (5.0 or 5.1), there should be no problem. 

Of course you may still end up introducing confusion if the purpose of the update was to fix some bug, or to enable some new feature in your application, since it will be difficult to tell from the outside which user is running which copy. You can get a pretty good idea though by using the `SYSTAT/W` switch (wide mode, which shows how long the job has been logged in). If you note the time when you did the switch, and can do time clock arithmetic in your head, you can probably figure out which users are running which version. (This also points out one of the various reasons why it's good practice to not leave idle jobs logged in indefinitely.) Note that if you want to kill users, you can use KILL.LIT, or perhaps send them a message with SEND.LIT. 

It's easy to tell from inside an application which version of A-Shell you're running, using one of the subroutines which returns the version, such as MX_GETVER. Whenever you incorporate a newly introduced A-Shell feature into your application, it is good 

A-Shell Reference 

Page 414 

practice to check the version in the application before trying to use the feature, perhaps warning the user to update or avoiding the feature if the version is too old. 

A-Shell Reference 

Page 415 

## **PROCESS EXIT CODE** 

## _Written February 2022_ 

Under Unix, the ashell process will return an exit code that can be detected in a shell script to determine whether the launch succeeded or not. By convention, 0 indicates a successful launch, while anything else indicates an error, with the following being the most likely: 

|**Code**|**Meaning**|
|---|---|
|11|JOBTBL full|
|12|No license|
|13|No computer name (Windows)|
|14|QFLOCK.SYS corrupt|
|15|QFLOCK.SYS version incompatible|
|16|Jobname already exists|
|17|Error locking or accessing JOBTBL.SYS|
|18|Too many sessions sharing same client IP (Windows)|
|20|Exceeded maximum nodes allocated to group (group licensing)|



## **History** 

## - 2022 February, A Shell 6.5.1711: Add Unix launch code errors. 

A-Shell Reference 

Page 416 

## **COMPILER** 

_Rewritten November 2018_ 

## **compil {-switches} file** 

Example: 

```
compil -x:2 -m -a source.bas
```

The native OS **compil** executable is equivalent to the COMPIL.LIT program, except that it runs directly from the OS level rather than from within the A-Shell environment. Under Windows, compil.exe is a standard Windows application, opening a window and outputting to it during the compilation, and then closing it again. Under Unix, the compil executable is executed within the shell environment, outputting to _stdout_ . All of the switches and other behavior for the native executable and LIT versions are the same, except for the following subtleties: 

- In the native executable version, the switches must each be preceded by a dash, rather than a slash as in the LIT version, 

- and they must all precede the source file name, rather than follow it as in the LIT version. This is consistent with the normal conventions for switches in Unix and Windows command lines. 

- In the native executable version, the switches are case sensitive and must be given in lower case. They are case insensitive in 

- the LIT version. 

- Rather than offer three named variations (compil, ocmpil, complp) as with the LIT version, there is only one native executable 

- version: **compil** . You must use the **-13** switch to get the equivalent of OCMPIL, or the **-x:1** switch to get the equivalent of COMPLP. 

- The default amount of memory available for the native executable version is 2MB, whereas in the LIT version it is based on 

- the job's memory partition. Use the **-w:####** switch to increase it. 

- The Unix version of compil outputs to _stdout_ , allowing it to be redirected to a file. The Windows version outputs by default to 

- the windows, but there is a switch, -so, to output to _stdout_ instead. In either case, it is generally more convenient to use the -b (background) switch, which outputs errors to a .lst file. 

## **Switches** 

A-Shell Reference 

Page 417 

The following table lists switches which apply _only_ to the native compil executable. See COMPIL.LIT for the full list of switches. 

|**Switch**|**Description**|
|---|---|
|-about|Display 'about' information|
|-ini<br>inispec|Used to specify themiame.inifile containing theDEVICEandERSATZdefinitions needed in order for the<br>compiler to recognize AMOS-style++INCLUDEspecs.|
|-l|(lower case el) Causes the compiler to set the local working directory to match the source file (which will<br>also determine the default location for the output files)|
|-so|(Windows only)  Redirects the window output to_stdout_.|
|-w:####|Specify the amount of working memory to reserve (in K, e.g. -w:4000 is 4000K or about 4M)|
|-wait|Wait for the user to hit a key before closing the window after the compilation.|
|-z|(Windows only)  Hides the compiler window (analogous to the A-Shell command line switch -z)|
|-zt|(Windows only)  Same as -z but process may appear on the task bar|



## **Comments** 

Here is an example of launching the compiler under Windows PowerShell: 

A-Shell Reference 

Page 418 

```
> Start-Process c:\vm\apn\compil.exe -ArgumentList "-ini c:\vm\miame\miame.ini -w:4000 -x:2 -m -b -l -px -lf
c:\vm\miame\dsk0\150277\myprog.bp" -WindowStyle Hidden
```

Because the native executable version of the compiler is not commonly used, it is not included in the typical distribution packages but is available on request—although the Windows version is included with APN. Contact MicroSabio for more information. 

## **See Also** 

- COMPIL.LIT 

## **History** 

- 2018 October, A Shell 6.5.1650: Add switches -z and -zt. 

A-Shell Reference 

Page 419 

## **POLYSHELL** 

## **pshell {-a ashell cmd}{-hp}{-j jobname}{-l}{-l2}{-t}{-u}{-x}{-f optionfile}{-1} {other ashell args}** 

Note that PolyShell is an extra-cost option available for A-Shell running in non-Windows environments. 

PolyShell is a multi-tasking "shell" that allows a user to run and switch between multiple instances of A-Shell on a single workstation. It does not currently support running anything other than A-Shell. This can be considered both a limitation and an advantage. It is almost certainly too limiting for power users and system operators who may prefer a multi-tasking mechanism, such as multiple X windows, or the multi-screen console, that allows anything to be executed in any of the windows. On the other hand, it may be just perfect for users who are only interested in running an application under the control of A-Shell, since it effectively forces each _window_ to run just that application. 

One other advantage of PolyShell over more "powerful" multitasking mechanisms is the low amount of processing overhead. Since A-Shell already tracks the screen contents, there is no additional overhead required for maintaining and restoring screen contents. In fact, when a process is in background, its output is simply sent to /dev/null (i.e. thrown away) since it has already passed through the A-Shell/TRACKER screen mapping system anyway. This is considerably more efficient that installing a pseudo-terminal and directing output through a "reverse terminal driver" to maintain a logical map of the screen's contents. 

Furthermore, by using the "job control" signal mechanism built into most versions of Unix (it is contained in the POSIX.1 and FIPS 151-1 standards) there is no additional overhead for filtering of keyboard characters to watch for the hot key(s). However, one disadvantage of this approach is that you cannot run PolyShell under the control of a Unix shell that traps job control signals, because such shells interfere with PolyShell's ability to trap those signals. The standard Bourne shell (sh) does not trap job control signals, while the Korn (ksh) does but may be turned off using set +o monitor. The C shell (csh) may or may not, depending on the version. Consult your shell documentation or local Unix guru for information on how to disable the job control signal handler in shells that support it. 

The bash shell under Unix does not appear to allow you to turn off trapping of job control signals. So we recommend using the Korn shell instead. 

One additional advantage of PolyShell in an application environment is that it permits certain A-Shell utilities, such as SEND.LIT and CHAT.LIT to be more effective by automatically routing the messages to the job that is in foreground. (In contrast, if you wanted to SEND a message to another user who had multiple telnet sessions running, you would have no way of knowing which one of those was actually occupying the foreground context for that user.) Messages sent via SEND.LIT to a user running under 

A-Shell Reference 

Page 420 

PolyShell are intercepted by PolyShell; the current process is switched into background (where it can continue to run unbothered by the message), and the user is switched to menu mode where the message is displayed. This way the recipient cannot fail to see the message, and yet it does not interfere in any way with a running process. 

Operationally, PolyShell is more or less self-explanatory. The menu options are limited to opening, closing, switching among, and displaying the status of the child instances. The only non-obvious operation is the hot key used to switch back to the menu or between instances. This is defined via the POLYKEY and SWAPKEY settings in miame.ini. 

## **Subtopics** 

- PolyShell Command Line Switches 

A-Shell Reference 

Page 421 

## **POLYSHELL COMMAND LINE SWITCHES** 

Since PolyShell is responsible for launching the individual instances of A-Shell, you can pass all of the normal A-Shell command line switches and arguments to PolyShell. In addition, the following arguments have special meaning to PolyShell. 

|**Switch**|**Action**|
|---|---|
|a|Define executable<br>to launch A-Shell with|
|f|Read command line arguments<br> from a file|
|h (or ?)|Display help message|
|l|Auto-launch first instance|
|l2|Auto-launch first two instances|
|j|Define base job name<br> to use for A-Shell instances|
|t|Validate Terminal Type|
|x|Reverse Poly and Swap Key|
|1|Limit to one child|



A-Shell Reference 

Page 422 

## **DEFINE EXECUTABLE** 

## **a <ashell executable name>** 

The **-a** switch allows you to define an alternate executable name (besides ashell) for launching the instances of A-Shell. This is only useful when for some strange reason you have one or more custom versions of A-Shell with custom names. Note that although it is technically possible to plug any executable file name in with this option, PolyShell will not work correctly except with A-Shell. 

A-Shell Reference 

Page 423 

## **READ COMMAND LINE ARGUMENTS** 

## **f <optionfile>** 

The **-f** switch forces PolyShell to read its command line arguments from the first line of specified file. For example: 

```
pshell –f /vm/miame/pshell.cfg
```

If the specified file (/vm/miame/pshell.cfg in this example) contained the following: 

- `-x –l2 –t menu` 

then the first command would have the same effect as if it were: 

```
pshell –x –l2 –t menu
```

The point of such a redirection, which may not be obvious at first, is twofold. First, it allows you to change the parameters on a global basis by modifying just one file, rather than by modifying each user’s startup profile. Second, even though you could accomplish nearly the same effect by launching pshell from within a script, this method is more efficient since it eliminates the need for a copy of the shell to be launched and then maintained in memory while it waits for the pshell command to exit. This would take up about 60K-100K per user on average, which is perhaps not that significant but is still a complete waste. By using the –f switch as shown above, you get all the benefits of central administration of the pshell startup switches without any of the extra overhead of using a script. 

A-Shell Reference 

Page 424 

## **DISPLAY HELP MESSAGE** 

The **-?** switch (or alternatively, the **-h** switch when it is the only switch) causes PolyShell to display a brief help message documenting the command line options. This help message consists of all the lines codes as category #4 in the SYS:PSHMSG.<lan>, allowing you to customize it if desired. 

A-Shell Reference 

Page 425 

## **- AUTO LAUNCH FIRST INSTANCE** 

The **-l** switch (that’s the letter _ell_ , for _launch_ , not the numeral _one_ ) forces PolyShell to automatically launch the first instance of A-Shell, so that launching PolyShell has the same effect (for an unknowing user) as launching A-Shell. Otherwise, PolyShell starts at its own command menu, from which you can then launch instances of A-Shell. This switch also has the effect of automatically shutting down PolyShell when the last A-Shell child instance is closed. (Otherwise, closing the last A-Shell child instance just returns you to the PolyShell menu, where you can then issue a command to exit entirely or to open up an new child instance.) 

A-Shell Reference 

Page 426 

## **- AUTO LAUNCH FIRST TWO INSTANCES** 

The **-l2** switch is identical to the **-l** switch, except that the first time the user hits the "swap" key from within the first child, a second child is automatically launched (using the same command that was used to launch the first instance.) This is useful in environments where it is "normal" for users to have two "windows", since it saves the user from having to manually open up either of the windows, but also defers the overhead of opening the second window until it is actually going to be used. Additional windows can still be opened by using the "menu" key to bring up the PolyShell menu and then using the normal "open" command. 

A-Shell Reference 

Page 427 

## **DEFINE BASE JOB NAME** 

## **j <jobname base>** 

The **-j jobname** switch forces A-Shell to use the specified job name (assuming it is available.) When passed to PolyShell, it works similarly except that PolyShell appends a numeric digit to the end to distinguish each of the child instances from each other. For example, PSH -J FRED will generate child instances with job names of FRED1, FRED2, etc. Otherwise, the generated job names will be of the form PSHxxx. (See the discussion of the TRMDEFstatements in miame.ini for information on another way to force the use of predefined jobnames.) 

The –j switch understands the special macro \$USER, interpreting it as the login user name. The preceding backslash is required to prevent the shell from pre-processing the $USER macro before PolyShell sees it. (Typically, shells interpret $USER to be the _effective_ user name, not the _login_ user name.) 

A-Shell Reference 

Page 428 

## **VALIDATE TERMINAL TYPE** 

The **-t** switch causes PolyShell to present the user with the option of changing terminal types before proceeding with the session. It does this by first displaying the license banner and then asking the user to either confirm that it looks ok, or to specify a new terminal type. If a new type is specified, PolyShell changes the TERM environment variable to the new type, and then repeats the process until the user accepts the result. This can be a handy way to allow many users to share the same logon profile even though they have different terminal types. 

Note that it is not possible to increase the length of your **TERM** environment variable definition. Thus, you can change it from " **am62a** " to " **vt420** ", but not from " **am62a** " to " **wyse50** ". Therefore, if you are using the **–t** switch, you should always start with a **TERM** setting whose length is at least a long as any of the other possibilities you are interested in. As a convenience along these lines, A-Shell will support " **am62aa** " as an alias to " **am62a** ", and the standard **am62a.tis** TERMINFO definition we supply will as well. 

A-Shell Reference 

Page 429 

## **REVERSE POLY AND SWAP KEYS** 

The **-x** reverses the action of the "Poly Key" and the "Swap Key." 

PolyShell uses two special keys which are defined in miame.ini by the POLYKEY and SWAPKEY directives. The key defined by POLYKEY is "hot", meaning that it will work regardless of what the application is doing (provided it hasn’t shelled out.) The default action of the POLYKEY is to bring up the PolyShell menu, which seems reasonable since you can do any of the other PolyShell operations from there. The other key, defined via the SWAPKEY directive, is only active when the application is waiting for input, and its default action is to switch directly to another instance of A-Shell. 

Some people feel that we should have made the "hot" key do the direct swap option rather than bring up the menu. For them, we have the **–x** switch, which switches the action taken by the two keys. Even with **–x** , the POLYKEY is still the only hot key, but now it will swap directly to the next session rather than to the PolyShell command menu. 

A-Shell Reference 

Page 430 

## **LIMIT TO ONE CHILD** 

The **-1** switch (that’s the numeral _one_ , not the letter _ell_ ) effectively cancels out most of the point of PolyShell by limiting the number of child sessions to one. Why would anyone want to do such a silly thing? One not-too-farfetched reason might be that you like the way PolyShell intercepts SEND.LIT messages without overwriting the current screen comments, but you don’t want certain single-tasking users to get confused by launching more than one session. 

A-Shell Reference 

Page 431 

## **VUE EDITOR** 

## **vue {-r} {-t} {-w} {-y} filename** 

The **vue** command is a reasonably complete implementation of a powerful text editor with a similar look and feel to VUE version 3.0. It is available in standalone versions for Unix, as a convenience to those old-timers who prefer it over more popular native editors. Its operation is identical to that of the A-Shell command program, with the exception that the search path for ini.vue is expanded to include /etc/ini.vue (with priority over any other copy of ini.vue.) The available switches are as follows: 

## **Switches** 

## _r:_ read only mode 

The _-r_ switch invokes read only mode. All functions work normally except you cannot save the file. 

## _t_ :   trace ini file processing 

The _-t_ switch causes certain details relating to the locating and processing of the ini.vue file to be displayed on the terminal. This can be useful when trying to figure out why your ini.vue parameters do not seem to be working properly. 

_w:_ start in wide (132 column) mode 

The _-w_ switch will cause vue to switch immediately to 132 column mode (if the terminal supports it.) You can also switch between 80 and 132 column display from the vue command mode using the WIDE and NARROW commands. 

## _y:_ create file if not already existing 

The _-y_ switch will cause the file to be automatically created if it doesn’t already exist. Otherwise, vue will ask you if you want the file created. 

## **Comments** 

It is not necessary for the MIAME environment variable to be set in order to use AshellVUE. Function keys, however, will not work unless the vux file can be located in DSK0:[7,0], which does require that the MIAME environment be set up. Similarly, the help files are expected to be found in the directory corresponding to DSK0:[7,1]. The typical way to take care of this in standalone Unix implementations is to store all of the VUE-related files in /usr/lib/ashellvue, either add that to the PATH or 

A-Shell Reference 

Page 432 

define the MIAME environment variable to point to that directory, and then create a miame.ini (in the same directory) which contains the following lines: 

```
LANGUAGE=/usr/lib/ashellvue/englsh.ldf  ; LDF file
```

```
DEVICE=DSK0:[7,0]  /usr/lib/ashellvue/  ; location of VUX files
DEVICE=DSK0:[7,1]  /usr/lib/ashellvue/  ; location of HLV files
```

Under Unix, you can establish VUE as your standard editor by setting the EDITOR environment variable. 

Under Unix, file names are typically lowercase, and thus VUE will fold a specified filename to lower case if it doesn’t already exist in upper case. A simple way to force it to use upper case is to prepend a relative or absolute directory specifier such as "./" to the filename (e.g. $ vue ./README.TXT) 

If you would like a Windows standalone version of VUE, the best approach is to create a DO file (call it avue.do) that logs you in and executes "VUE $0 $1 $2 $3 $4". You can then associate particular file extensions (e.g. LST, TXT, etc.) using the Windows explorer with an A-Shell command line that might look something like: `c:\vm\miame\bin\ashw32.exe –e –i c:` 

`\vm\miame\miame.ini "%1"` . Then when you double-clicked on a file with the proper extension, Windows would launch an A- Shell session and bring up the file in VUE. Alternately you could create a BAT file to launch A-Shell with the specified argument. 

A-Shell Reference 

Page 433 

## **- A SHELL EXPLORER** 

_Added February 2019_ 

ASHEXPLORER is included in A-Shell/Windows and ATE release packages. This standalone utility is similar to a cross between the File Open dialog—see MX_GETOFD—and Windows Explorer. It is useful within an application when you want to allow the user to browse, preview, and possibly use the default open operation on selected files, but without necessarily waiting on the user, and without giving the user too much flexibility to go wandering as would otherwise be the case with Windows Explorer. Launch via XCALL HOSTEX or XCALL MX_SHELLEX, with zero or more of the switches noted in the table below. 

## **ASHEXPLORER.EXE {switches}** 

|**Switch**|**Description**|
|---|---|
|/START,<br>folder-or-fspec|Specifies the starting folder, and optionally the file to select for preview. Default is current directory.|
|/FILTER|`/FILTER,"descr | wildcardlist {| descr | wildcardlist}..."`<br>Provides a filter specification to limit the files shown, using the same syntax as inMX_GETOFD<br>. Each wildcard list is a<br>semi-colon delimited list of filename wildcards, e.g. *.jpg;*.png; XX*.bmp. Quoting the entire argument is<br>recommended; do not include spaces within any wildcard list. For example:<br>`/FILTER,"Images | *.jpg;*.png | Docs | AB*.pdf;XY*.docx"`|
|/TITLE,title|Specifies the title for the dialog box that appears. String must be quoted if it contains spaces.|
|/CANCEL,label|Specifies the label for the cancel/exit button (default="Exit").|
|/MAX{IMIZE}|Maximize the dialog.|



A-Shell Reference 

Page 434 

|**Switch**|**Description**|
|---|---|
|/MAXBTN|Add a Min/Max/Normal button to the dialog caption bar.|
|/NOADDRESS|Remove the address (aka URL) line from the dialog. Useful when you want to confine the user to a single directory<br>and/or there is no reason to reveal the address of the directory being viewed.|
|/NOCHANGEDIR|Don't allow browsing outside of the initial directory.|
|/NOFILEPROMPT|Remove the "File name: " prompt and edit box that otherwise appears beneath the list of files, where the user could<br>type the name the file to select.|



## **History** 

- 2018 July, A Shell 6.5.1639: Add feature to A-Shell 

A-Shell Reference 

Page 435 

## **SWITCHING BETWEEN SESSIONS** 

If you are running A-Shell/Windows or ATE, and you are using multiple instances of ATE or A-Shell, you may use the keyboard combination CTRL+TAB to toggle between those sessions. 

In the event that you are using A-Shell with PolyShell (an A-Shell add-on that you don't need to know about unless you are using it) _and_ your miame.ini file contains the phrase `POLYKEY=` (grave)` , then you may also switch between ATE sessions by use of the grave key. This option has been thoughtfully added for those dexterity-challenged users who can't master the multifinger coordination necessary for CTRL+TAB, or who might be used to and prefer to use the typical Polyshell hot key. 

Note also: 

- Minimized windows are re-displayed by CTRL+TAB, and skipped by **`** (grave). 

- The grave key is activated only by the server for ATE; for local Windows sessions, it depends on `POLYKEY=`` in the local 

- miame.ini. 

A-Shell Reference 

Page 436 

## **SCROLLBACK** 

A-Shell includes a handy and useful feature called _scrollback_ which enables the viewing of lines that have scrolled off the top of the screen. If you perform a DIR command, for example, and A-Shell outputs 50 or 100 lines, only the last 24 lines are visible; the others have scrolled off the top of the display. In the absence of scrollback, those lines are lost to you. With scrollback, however, you simply move the screen "backwards" or "up" to reveal the missing lines. 

Rather than being a fixed, 24-line display, in other words, your screen can be a "scrolling window" on everything that has recently been written to it. 

To turn scrolling on/off: 

- Use CTRL+SHIFT+UP-ARROW. 

- Go to _Settings_ on the menu bar and click on _Scrollback._ 

Once it is turned on, you can scroll up and down by: 

- holding down the CTRL key while using the UP-ARROW and DOWN-ARROW keys 

- holding down the CTRL key while rolling up/down with the mouse wheel 

- using the vertical scroll bar on the right edge of the window 

Also note the following: 

- The scrollback buffer holds approximately eight screens (200 lines) of text. 

- The scrollback buffer is always on. The actual scrollback of the buffer may be turned off and on, but the buffer itself is always 

- active. This means that when you first turn it on, the existing scrollback buffer text (i.e., the last 200 lines of screen output) can immediately be displayed. 

- There is no disadvantage to leaving scrollback on. So it makes sense to turn it on the first time you need it, and then just 

- leave it on for the rest of your session. 

## **See Also:** 

A-Shell Reference 

Page 437 

- The system command PAGE may also be used as a means of managing the output of commands like TYPE and DIR which 

- might otherwise scroll off the screen. 

## **History** 

- 2017 July, A Shell 6.5.1610: Add _Scrollback_ to _Settings_ menu to toggle visibility of the vertical scroll bar. 

A-Shell Reference 

Page 438 

## **MENUS** 

This section briefly discusses the various menu selections that appear in the standard A-Shell/Windows environment. 

Note that it is possible that some or even all of these menu selections have been disabled or removed by your application software, and that many others have been added or substituted in their place. You would need to consult the application documentation for details in such a case. 

The menu-bar options are set according to the LANGUAGE option in miame.ini. 

As with other Windows programs, A-Shell menus can be selected either by the mouse, or by holding down the ALT key while typing the underline letter in the menu item name. This will cause the associated drop-down menu to appear, at which point you can again select the menu item with the mouse or by typing the underlined letter, or by using the UP-ARROW and DOWN-ARROW keys to move the selection bar and hitting ENTER to select the item. The only deviation here between A-Shell and some other Windows programs is that A-Shell does not support the Control key shortcuts that you might be familiar with. For example, CTRL+V works as a shortcut in many windows programs to select the Paste option on the Edit menu. A-Shell doesn’t support these shortcuts because by convention, virtually all of the Control key sequences have been assigned to another purpose, typically editing operations within the current input context. (CTRL+V, for example, was the traditional command to delete a word from the current input line.) 

## **Subtopics** 

- File Menu 

- Edit Menu 

- Settings Menu 

- Help Menu 

A-Shell Reference 

Page 439 

## **FILE MENU** 

The File menu contains options to control the loading and saving of A-Shell configuration settings. These settings are normally kept in a file called default.ash, and mainly relate to options configurable on the various Settings menus (colors, fonts, etc.) In addition, it also stores the size and position of the A-Shell window (to be used as the default on the next launch.) Note that if a configuration file other than default.ash is to be used, it must be specified on the command line used to launch A-Shell. See the Settings File switch in Launching A-Shell. 

|**Menu**|**Description**|
|---|---|
|Load Settings|Allows you to load a new configuration file.|
|Save Settings|Saves the current settings to the current configuration file.|
|Save Settings As|Saves the current settings to a configuration file, which you can name. This is useful when individual users want to have<br>their own configuration settings independent of other users. In that case, you would need to use the –o command line<br>switch to specify the configuration file when you launch A-Shell.|
|Default Settings|Causes the current settings to revert to the defaults.|
|Print Screen|Provides a means to graphically capture anything being displayed inside the A-Shell window.|
|Exit|This is only active when you are at the A-Shell command prompt. In that case, clicking Exit will force the command<br>HOSTinto the keyboard buffer, which in turn will cause the A-Shell session to terminate.|



A-Shell Reference 

Page 440 

## **PRINT SCREEN** 

Selecting the print screen option from the file menu will display a large dialog box similar to the one below. Within the gray background is a preview of the image being saved. Select the options and choices you wish, and then save, print or email the results. 

Note the following special or unusual aspects of Print Screen's operations. If you have used other print screen utilities, these features may seem a little odd. 

• Saving the image file: A file, the name of which is specified in the "Image File" field on the screen and which may be changed, is created (a) when you first enter the program, and (b) when you change any of the "Source" or "Image Attributes" values. You do not need to manually save the image, since a new copy is saved with every change. If you do not change the name of the output file, each new image will be written over the top of the old one. 

- The image attributes "Negative" and "Ink Saver" are not available unless "Grayscale" is enabled. 

- The "Ink Saver" option may save so much in that text is too light too see. 

Note also that your settings are saved at the end of each Print Screen session, and will be active the next time you use Print Screen. 

A-Shell Reference 

Page 441 

## **CONFIGURING PRINT SCREEN** 

Although Print Screen is customizable (and easily removed), a default behavior and place on the menu is set to reduce the confusion that has historically surrounded the print screen function. 

The behavior of the print screen utility is determined by a configuration file, bas:aprntscrn.cfg; see the following topic Sample APRNTSCRN.CFG. 

That sample aprntscrn.cfg configuration file is included in the installation/update packages, but will not overwrite an existing copy. 

The APRNTSCRN.SBX file (and its source, aprntscrn.bp) will be supplied (and overwritten) during installation/update. So if you want to modify the default print screen behavior, you should supply your own SBX and plug its name into the Command= line of the aprntscrn.cfg file. 

To remove the item from menu, just comment out (or remove) the Command= line from the aprntscrn.cfg file. To accomplish this for many ATE clients in one step, you can use ATSYNC.LIT in a startup command file to update the individual copies of aprntscrn.cfg from the server. Or, even simpler, just send a command to delete the aprntscrn.cfg file, e.g. 

```
? TAB(-10,AG_WINEXEC);"$DEL %MIAME%\DSK0\007006\APRTNSCRN.CFG";chr(127);
```

or, using AGCMD.LIT: 

```
.AGCMD WINEXEC $DEL %MIAME%\DSK0\007006\APRNTSCRN.CFG
```

As an alternative to calling an SBX to perform the print screen function, you can specify an arbitrary Windows command line (removing the "SBX:"), e.g.: 

## `[MENU]` 

```
Command=super-print-screen.exe -arg1 -arg2 -arg3
```

A-Shell Reference 

Page 442 

Note that the aprntscrn.cfg file is only processed by the menu subsystem the first time you click on the menu bar. So removing it or changing the Command= line after the menu has already been accessed will have no further effect until you close and relaunch the session. 

- 2011 May, A Shell 6.0.1215: Print screen function added to A-Shell. 

A-Shell Reference 

Page 443 

## **SAMPLE APRNTSCRN.CFG** 

```
;A-Shell Print Screen utility configuration
```

```
[MENU]
```

```
Command=SBX:APRNTSCRN
```

```
;Command=$ASHELL -zi -e RUN APRNTSCRNR
```

```
;Sample winexec command line:
```

```
;Command="C:\Program Files (x86)\TechSmith\Snagit 10\snagit32.exe"
```

```
[IMAGE]
```

```
FilePrefix=img
;capture directory
SaveDir=%miame%\captures
;image type (png,bmp,jpg,pcx,tif)
ImageType=png
Comp=0
```

```
ConvertToGray=0
InkSaver=0
Negate=0
```

```
;SourceWindow is same as IMGOP_CAPTURE winid param
```

```
SourceWindow=-2
```

```
ClientOnly=0
```

A-Shell Reference 

Page 444 

```
[OUTPUT]
```

```
Printer=
```

```
Orientation=Portrait
```

```
Title=A-Shell Print Capture
EmailTo=support@microsabio.com
```

```
;following will stifle attachment of ashlog.log
```

```
EmailLog=
```

```
;Use notes for email subject? (else use Title)
UseNotesForSubj=1
```

```
;Following identifies a non-standard ashlog.log (to attach to email)
```

```
;EmailLog=%miame%\dsk0\001002\mylog.log
```

```
;Following stifles the attachment of any log file (comment out for default ashlog.log)
EmailLog=
```

```
[UI]
```

```
;User interface (1/0)
```

```
UI=1
```

```
DlgTitle=A-Shell Screen Capture
```

A-Shell Reference 

Page 445 

## **EMAILING LOG FILE** 

_Added July 2014_ 

Print Screen includes the ability to email a copy of the ashlog.log (or other log file) along with the screen capture. The feature is active by default, provided that the ashlog.log file is in /vm/miame/ashlog.log (on the ATE server) or %miame%\ashlog.log (for local Windows). In the case of ATE, the print screen utility will attempt to FTP the ashlog.log file from the server. 

If your ashlog.log file does not match the default location, you must add the following item to your bas:aprntscrn.cfg file to enable/configure it: 

```
[OUTPUT]
```

```
EmailLog=<log spec>
```

where <log spec is the fully qualified file spec for the log file (on the server for ATE, or local for local Windows). Note that this doesn't have to be ashlog.log; you could use this feature for your own application log file. 

To disable the feature set the <logspec> to blank. 

Note that since the aprntscrn.cfg file exists on every client PC, updating it requires either transmitting entire new copies to each PC (perhaps with ATSYNC), or you can update just that one field using: 

- `? TAB(-10,AG_XFUNC2);"INIX,BAS:APRNTSCRN.CFG,1,OUTPUT,EmailLog,";logspec$;chr(27);` 

## **History** 

- 2014 July, A Shell 1387: Feature added to A-Shell 

A-Shell Reference 

Page 446 

## **EDIT MENU** 

The Edit menu contains options related to the mouse and the clipboard. Also see Mouse Operations for further notes on using the mouse. 

## **Subtopics** 

## · AutoMouse 

- Copy and Paste 

A-Shell Reference 

Page 447 

## **AUTOMOUSE** 

The AutoMouse selection on the Edit menu allows you to enable or disable the "AutoMouse" feature of A-Shell. When active, a check mark will display next to the menu selection. 

AutoMouse is a feature—similar to ZTERM’s "Smart Mouse"—which allows the mouse to be used for some kinds of inputs, in applications that otherwise have no particular support for the mouse. When active, AutoMouse gives you the following mouse capabilities: 

• Double-left-clicking on a "token" anywhere on the screen will generally cause the text of that token to be transmitted into the input buffer. A "token" is a string of characters delimited on either side by a space or punctuation character. If you have the Beveling option set to Automatic, or ON via program control, then the token will be briefly "buttonized". The rectangle surrounding the token will have the appearance of being depressed and then released. 

- Double-left-clicking on any empty area of the screen will simulate the ENTER key. 

- In data entry fields which are managed by INFLD, which is usually the case, single-left-clicking immediately to the left of the 

- field will transmit a BACKSPACE character. This is often interpreted by applications as a command to back up to the previous field or screen. 

The above built-in AutoMouse functions may be supplemented by an application defining its own special "tokens". For example, an application may allow you to click on the word "Help" to transmit some kind of command that brings up a help screen. Consult your application documentation to see if any such thing is supported. 

AutoMouse will be automatically disabled by certain applications, like INMEMO (memo editing) or VUE (text file editing) in which the potential for harm is greater than the likely benefit. Also, it will be disabled whenever an application requests "Cursor Reporting", which is a lower level protocol in which all cursor actions are reported to the application via coded data bytes. 

You can also disable AutoMouse explicitly using the subroutine MX_AMOUSEXLT, opcode 4. See that topic for more details and information on related AutoMouse configuration options. 

A-Shell Reference 

Page 448 

## **COPY AND PASTE** 

Like most other Windows applications, the Copy menu item becomes enabled whenever text has been marked for selection on the screen. The selected text is copied to the clipboard when the Copy menu item is clicked. Under A-Shell, you can select text on the screen via the usual technique of holding down the left mouse button while dragging it (down and/or to the right) over a rectangle. Once you have selected such a rectangle, you can also copy it to the clipboard by hitting ENTER or CTRL+C (a common shortcut supported by many other Windows applications.) 

As with most other Windows applications, the Paste menu item becomes active when there is text available on the clipboard (whether from the current A-Shell application or any other Windows application.) Clicking on the Paste menu item will force the clipboard text into the keyboard buffer. Exactly how that will be interpreted depends on the state of the application. (In general, pasting a multi-line selection only makes sense in a context that understands multi-line input, such as the memo or text editor.) 

A-Shell Reference 

Page 449 

## **SETTINGS MENU** 

The Settings menu allows you to view and change many of the configuration settings for your A-Shell session. These may then be saved or recalled via options on the File menu. 

## **Subtopics** 

- Scheduling 

- Beveling 

- Colors Menu 

- Font 

- Misc Settings 

- Dialog Sizing 

- Preview Preferences 

- Status Lines 

A-Shell Reference 

Page 450 

## **SCHEDULING** 

_Reviewed July 2020_ 

The Scheduling menu brings up a small dialog that allows you to tinker with the way A-Shell shares the CPU with other applications on your PC. The default foreground and background priority is "13", which is measure of how long A-Shell will "hog" the CPU before intentionally yielding to another application. In general this is only of historic interest and can be safely ignored, since modern Windows scheduling and multi-core CPUs will assert their own control over how CPU resources are shared between processes. 

A-Shell Reference 

Page 451 

## **BEVELING** 

Beveling refers to the shading of graphic lines (typically used as borders) to give them a three dimensional (or "beveled") appearance. This can be classified as nothing more than visual "gingerbread", but it can also make certain applications more pleasing to the eye (and thus perhaps more enjoyable to work with). The menu selection brings up a dialog box, which has beveling options of "disable", "automatic", or "program control". Predictably, the first one disables the effect while the second option causes it to be turned on automatically. The last option allows applications the option of turning it on or off at their own discretion. 

The SET.LIT command line SET TERM BEVEL <option> can be used to change the beveling setting within an CMD or DO file. Available <option> choices are OFF, AUTO, PROGRAM-ON, and PROGRAM-OFF. 

A-Shell Reference 

Page 452 

## **COLORS MENU** 

The Colors menu and associated dialog box allows you to redefine A-Shell’s color palette. By default, A-Shell uses the same 16color palette used by AMOS, as shown in the table below: 

|**Color #**|**Color Name**||**Color #**|**Color Name**|
|---|---|---|---|---|
|0|Black||8|Dim Black (Dark Gray)|
|1|White||9|Dim White (Light Gray)|
|2|Blue||10|Dim Blue|
|3|Magenta||11|Dim Magenta|
|4|Red||12|Dim Red|
|5|Yellow||13|Dim Yellow|
|6|Green||14|Dim Green|
|7|Cyan||15|Dim Cyan|



As the table suggests, the color numbers 8 thru 15 are normally just dim versions of the corresponding colors 0 thru 7, and in fact, are normally not specified directly. Instead, an application typically selects dim or bright (via TCRT commands 11 and 12) and a pair of foreground and background colors from the range of 0 thru 7. (The foreground color is used for displaying text and other non-space characters, while the background color applies to the space behind and between the characters.) Setting dim mode is effectively equivalent to adding 8 to the color numbers. 

When an application outputs to the screen, A-Shell responds to, and stores, the color palette index numbers rather than the colors themselves. It translates the numbers into colors using the current palette definition. Therefore, there are two ways to change the colors used in an application. One is to change the color numbers themselves that are used by the application and the other is to change what the numbers mean (i.e. change the palette definition which associates actual colors with the color numbers.) 

A-Shell Reference 

Page 453 

There are several ways to change the color numbers used by an application, including SET.LIT, INI.CLR, and Tab(-2,x) and Tab(-3,x) commands within ASB programs. In contrast, this menu/dialog allows you to change the just the meaning of the color numbers. 

The dialog expresses the color palette in terms of three sets of eight colors: one for normal intensity (aka bright) foreground colors, one for reduced intensity (aka dim) and one for background colors. To change any of these, just click on the button next to the number, and choose a new color. The subsequent dialog box presents a selection 48 "stock" colors, plus a button allowing you to define a custom color. 

The official names associated with the color palette numbers will not change. Thus, you can redefine color 2, which is normally "Blue", to something more like lavender, but the button next to color 2 will continue to read "Blue". 

After you choose a new color, the effect will be immediate when you return to normal A-Shell/Windows run mode. However, you will only notice a change if parts of the current screen are using the color number(s) which you redefined. Consider, for example, a typical "green screen" monochrome application, which uses color 6 (green) for foreground text and 0 (black) for the background. If you redefine color 2 to be lavender, you will not see any change in the application display because it wasn’t using color 2. If, however, you redefined color 0 to be maroon instead of black, then the application display will immediately change from green on black to green on maroon. 

After changing the color definitions, the effect will only last for the duration of the current A-Shell session, unless you use the File..Save or Save As menu selections to save them. Note that unless you want your color definitions to affect all other users, you may want to save them in a private settings file and adjust your icon shortcut to reference that private settings file. (See the –o switch in the A-Shell command line reference for further information.) 

Because of the multiple techniques available for customizing colors, it would probably be a good idea not to overboard in redefining colors on the Colors menu/dialog. For example, you might want to go for a more sophisticated look by choosing more pastel versions of the standard colors. But if you redefine color 2 (normally blue) to yellow (normally 5), and color 6 (normally green) to magenta (normally 3), the resulting confusion will likely hamper any efforts to use any of the other color configuration techniques. 

To achieve the most "Windows-like" look, we recommend using the SET TERM SYSBCOLOR 1 command to associate background color 1 (normally white) with the current default Windows dialog box color (typically gray). If you then arrange for the application to select background color 1 (perhaps via a SET TERM BCOLOR 1 command in a command file or by changing the SCNCLR parameter of the INI.CLR configuration file) and a suitably contrasting dark foreground color (such as 0 or 2), even a legacy "green screen) application can take on a more Windows-like look. As an added bonus, by tying the background color to 

A-Shell Reference 

Page 454 

the standard Windows colors, it will adjust automatically to a change in the Windows desktop palette (accomplished via the Control Panel.) 

It is also possible to redefine the colors associated with the color palette numbers using AG_PALETTE, Define or Query Color Palette. 

## **See Also** 

- Color Customization 

A-Shell Reference 

Page 455 

## **FONT** 

The Font menu item actually has three subitems, each allowing you to define a default font for a particular aspect of A-Shell: 

Although font selection is familiar to most Windows users, the following comments may help clarify the particulars. 

**System (Fixed Pitch):** This is the font that A-Shell uses for its "normal" text-mode display. The font size that you choose in the dialog is meaningless, since A-Shell computes the font size based on the window size and the defined number of rows and columns (which is typically 24 x 80). As you resize the window, the fonts are automatically resized accordingly. Note that you must select a fixed-pitch font for display compatibility with most legacy applications, since they often use spaces for positioning and assuming that a space is the same size as any other character. 

SP For more information on fixed pitch fonts, see FONT . 

**Control (GUI):** This option only applies to applications that use the Graphic User Interface (GUI) display mechanism (i.e. look more like "typical Windows" programs.) And it only determines the default GUI font. (The application may well ignore this setting since every bit of text output can theoretically have its own font specification.) The default GUI font is equivalent to the font that Windows uses in its dialogs - something called MS Shell Dlg, which is similar to Arial or Helvetica. 

**Grid:** This option only applies to the A-Shell grid control (aka "XTREE"), and as with the GUI font above, only determines the default font. Each individual grid, and indeed the cells within the grid, and have their own custom fonts, according to the application's desires. The default grid font is the same as the default GUI font (MS Shell Dlg), which works reasonably well, except that it doesn't scale particularly well. If you like to use the XTREE font scaling feature, you may want to change your grid default font to something like Tahoma, which scales better. 

As with the Color settings, you must use the File..Save (or Save As) option to save your font selections for subsequent A-Shell sessions. 

A-Shell Reference 

Page 456 

## **MISC SETTINGS** 

These settings all relate to adjustments to the screen layout and appearance. Also see the related Dialog Sizing options. Scroll over regions of the image below and click on them for links to the indicated topics. 

## **Subtopics** 

- External Font Leading 

- Background Fill Color 

- Proportional Font Scaling 

- Minimum Margin When Maximized 

- Use Fixed Pitch in Edit Boxes 

- Force Standard Colors in Edit Boxes 

- Set Active Background Color 

- Allow Edit Boxes to Use Leading Space 

- Force Edit Boxes to Match Combo Height 

A-Shell Reference 

Page 457 

## **EXTERNAL FONT LEADING** 

The term "leading" (pronounced "ledding") is a carryover from the old manual typesetting days when lead (as in the metallic element Pb) wafers were used to insert space between lines of text. Thus line spacing became known as "leading". There are two types of leading: internal and external. Internal leading is the space between the visible bottom of a character and the bottom of the character cell. (Characters with descenders, like "j", have less internal leading than those without them.) External leading is the space between the bottom of the character cells in one row and the top of the character cells in the next row. Typically, whether on a dumb terminal, a terminal emulator, or A-Shell/Windows, the screen is divided up into character cells with no external leading between the rows. (The apparent space between the rows is due to the internal leading within each cell.) 

The motivation for increasing the external leading is that most Windows applications tend to have a lot more vertical space between fields than text applications do. (It is quite normal for a text application to have data entry fields on each line, whereas you will rarely see a Windows form in which the edit boxes are so close together.) To help achieve a more spacious look without modifying the program to actually skip rows, you can just add leading. The more leading you add, the shorter the fonts become for a given screen size. 

The effect of changing the leading is immediate, so it is easy to experiment with. It is saved along with other settings by the File..Save or File..Save As menu options, and loaded automatically when A-Shell is launched. 

A-Shell Reference 

Page 458 

## **BACKGROUND FILL COLOR** 

When lines of text are output to the screen, if the leading is non-zero, there will be space between the lines that is not filled in by the background color associated with that PRINT statement. This is generally not a problem if your application doesn’t use reverse video or different text background colors for more than one line at a time, but if so, you may need to adjust the Background Fill Color option. The choices are: 

- A fixed background color number (0-15): This is the simplest and cleanest, but requires that your application stick with a 

- fixed background color and doesn’t create multi-row blocks of highlighted text using reverse video or a different background color. 

- Automatic fill (-1): In this case, the space below each line of text output is filled with the background color of the text. The 

- left and right margins of the screen are filled with the background color which seems to be most predominate on the screen. 

- Passive fill (-2): The space below each line of text output is left alone, only being updated during screen clearing operations, 

- such as TAB(-1,0) or TAB(-1,10). 

A-Shell Reference 

Page 459 

## **PROPORTIONAL FONT SCALING** 

This controls how proportional fonts are scaled, and only applies to GUI extensions (buttons, edit boxes, checkboxes, static text controls, etc.) which may or may not be present in your application. (As of build 974, it also only applies to GUI font objects on the main window; those inside of dialogs are controlled by a corresponding option on the Dialog Sizing dialog.) The standard fixed pitch fonts are always scaled according to the window size, but this is not necessarily desirable with the proportional GUI fonts. It is actually quite rare for Windows applications to change the size of the fonts according to the size of the window. In fact, it is rare for Windows applications to even adjust the spacing of controls when changing the window size. In the case of A- Shell, in order to keep GUI objects (including static text controls) synchronized with the fixed pitch character grid, we always adjust the spacing of objects when the window is resized. But the question is whether to adjust the font sizes as well. 

For the most Windows-like effect, set the scaling to 0. This will result in the standard Windows control font (a sans serif font similar to Arial or Helvetica, which is called MSDialog in WindowsXP and Segoe UI under Vista and later). Since its size will not change with the window size (if the scaling factor set to 0), while the size of fixed pitch text and certain container objects, such as buttons and edit boxes will change, you will probably want to adjust your Window size until the fonts seem to fit best. (The larger the window becomes, the more space the fonts will have to fit into their containers, but at the same time, the difference between the size of the proportional fonts and any fixed pitch fonts will increase. Once you determine the most desirable window size, save your settings (File..Save). 

If you want to be able to make the fonts bigger on demand simply by maximizing the Window, then set the scaling factor to something in the range of 80 to 100. This will cause the proportional fonts to scale up and down according to the window size. Note, however, that font scaling is not totally linear, so you may find that with large window sizes, you need a smaller scale factor, say 80 to make things fit, than you do at smaller window sizes. (Again, the idea is tinker with the scale factor and window size until you get a pleasing combination, then save it.) 

A-Shell Reference 

Page 460 

## **MINIMUM MARGIN WHEN MAXIMIZED** 

(WINDOWS/ATE) This resolves the conflicts relating to adjusting the sizing of maximized windows. The normal, default setting is 0, which means that if the number of columns divides evenly into the screen width, when maximized there will be no left or right margin at all. (This happens, for example with 800x600 and 1280x1204 at 80 columns.) On some PC's however, this may cause the first and last column(s) to be clipped (due to over scan). Previously, we just subtracted a fudge factor from the screen width to prevent this problem, but now you can just set the minimum margin parameter. The margin units are pixels, but in most cases, setting the minimum margin to just 1 pixel will actually result in a considerably larger margin since font widths generally come only in integer pixel widths. For example, in the 800x600 case, the font width would be 10 pixels at 80 columns. But if you introduce a 1 pixel margin, the font width will have to be reduced to 9, which means that 80 columns only occupies 720 pixels (leaving a margin of 40 on either side). 

Note that in the Windows and ATE environments, you can increase the number of columns in the window grid to put some of the margin space to work. For example, in the 800x600 case, if the font width is going to be 9 pixels, you could increase the number of columns from 80 to 88 and still a 4 pixel margin on either side. 

The margin is ignored in non-maximized mode, because in that case, first of all, over scan is not likely to be a problem, and secondly, if it were, you could just adjust the window width with the mouse. 

A-Shell Reference 

Page 461 

## **USE FIXED PITCH IN EDIT BOXES** 

This applies only if your application uses Windows-style edit boxes for editing data fields. If so, they will normally use the standard Windows proportional font for the data characters. Some people don’t like the fact that this makes it difficult to see what is the maximum number of characters for a field. (With fixed pitch characters, the field size relates exactly to the number of characters allowed, but with proportional fonts, it depends on the widths of the individual characters.) One way to minimize (but not totally eliminate) that confusion is to set this option, which will force the edit boxes to use a fixed pitch font. The actual font will be scaled so that the maximum number of characters allowed will approximately fill the field space, but due to the idiosyncrasies of font scaling, it will never be quite as exact as it is with fixed pitch. (You may be able to set a switch in your application to get it to use the old-fashioned text-oriented input style rather than Windows-style; "Neo-Luddites" should contact their application developer for details.) 

A-Shell Reference 

Page 462 

## **FORCE STANDARD COLORS IN EDIT BOXES** 

_Reviewed July 2020_ 

This option overrides the application’s color parameters for edit boxes. Some applications will assign various fancy color schemes to editing, for example, using one color while editing, another for display, a third for redisplay of updated fields, etc. These enhancements can be quite effective in a text environment, but may not work so well in a GUI environment. Setting this option will cause A-Shell to ignore the application’s color specifications and just use the standard Windows ones for any edit boxes. This is essentially mandatory when Windows Themes are in effect. 

A-Shell Reference 

Page 463 

## **SET ACTIVE BACKGROUND COLOR** 

This option is used to define a special background color to be applied to INFLD edit controls when they are active. The theory is that by defining a light color that is nonetheless distinguishable from the standard white, it will be easier for users to detect which edit field is active. Note that the effect only works for INFLD controls that are based on the standard Windows edit control (i.e. includes combo boxes and up-down controls, but not check boxes, radio buttons, or date/time controls.) Note that the button and feature is not active unless the Force Standard Colors in Edit Boxes option is checked. 

A-Shell Reference 

Page 464 

## **ALLOW EDIT BOXES TO USE LEADING SPACE** 

This only applies if the External Leading option (above) is non-zero. If so, it allows edit boxes to extend approximately half way into the leading area below the current row. This is often useful to allow sufficient space for the characters to fit within the box. (Depending on your scaling options, window size, etc., you may find that your edit boxes are clipping off the bottoms of the characters. If so, this is one way to deal with it.) 

A-Shell Reference 

Page 465 

## **FORCE EDIT BOXES TO MATCH COMBO HEIGHT** 

This option deserves an award for being especially cryptic. It can be safely ignored if your application does not use drop-down combo boxes, date pickers, or any other field editing control which includes a little down arrow button on the right side which opens the field up. If it does, then there is a potential problem in that Windows, in its infinite wisdom, does not allow those edit boxes to be scaled, while normal edit boxes can be. Thus, if you have a mixture of the two types of edit boxes and you adjust the window size, the edit boxes will change in height, but the combo boxes will not. If this effect bothers you, then set this option, which will force the edit boxes to remain at the same height as the combo boxes. (That, however, overrides the previous option, as well as undermines the ability to adjust the ratio of font sizes to their containers by adjusting the window size.) So, like so many other factors in the GUI environment, it’s a tradeoff. 

A-Shell Reference 

Page 466 

## **DIALOG SIZING** 

This dialog contains options which control the sizing of dialogs created at runtime by A-Shell applications, rather than embedded into A-Shell, as is this dialog itself. 

## **Subtopics** 

- Dialog Grid Units 

- Font Scaling % 

- Grid Unit % Adjustment 

- Include Caption in Dialog Height 

A-Shell Reference 

Page 467 

## **DIALOG GRID UNITS** 

The three radio button choices allow you to choose which of the two dialog grid systems (described below) you want to use. The first two choices force all dialogs to use the specified grid. The last choice (choice left to program) allows the applications to determine it on a dialog-by-dialog basis (by whether or not the MBF_ALTPOS flag is specified; see AUI_CONTROL for programming details.) 

The Dialog Grid Units setting allows the user to control what kind of metric units (or grid units) to use for defining the size of dialogs and the positioning of objects within them. The two choices are as follows: 

## **Main window grid size** 

This is equivalent to the grid used in the main A-Shell window—e.g., the 24x80 grid. The size of this grid unit is exactly the size of a single fixed-pitch character, plus the external leading, and it will vary based on the physical size of the window and the currently defined number of rows and columns. Note that this grid system is always used for main windows. The main problem with this grid system is that it makes your dialog sizing dependent on the size of the main window at the time the dialog was created. Thus, if a user likes to have several applications running at the same time, and makes the main window relatively small, your dialogs may be too small. Meanwhile, another user may like to maximize the main window, causing your dialogs to be huge. (This is very unlike the way a typical Windows application sizes its dialogs.) A related problem is that because there may be such a huge discrepancy between the main window grid size and the typical GUI font used in dialogs, the row/column units used to position and size controls in the dialog may be nearly meaningless, making it hard to visualize the dialog while programming. A third problem is that when the dialog is created, the coordinates specified are for the total size, including the caption. Because the caption height may be more or less than one logical row, depending on the size of the main window, this makes it hard to know exactly how many usable rows are inside the dialog. For these reasons, the traditional grid is not recommended. 

## **Windows desktop font size grid** 

This is based on the standard Windows desktop font (i.e. the font used for the text beneath desktop shortcut icons). This is also the same font that is used for the standard menu bar options in Windows programs, and for the text in most standard Windows dialogs. This grid system solves the problems discussed above. First, it is independent of the size of the main window. Second, since it is based on the standard Windows GUI font size, it adjusts automatically to changes in the Windows desktop settings (i.e. the resolution and font DPI). In other words, if the user doesn't like the typical tiny Windows font and adjusts the font DPI to make everything in the Windows environment bigger, your A-Shell dialogs will get bigger right along with everything else. Third, since the units are based on the same standard GUI font that is the standard in dialogs, the units are more meaningful in the 

A-Shell Reference 

Page 468 

sense that they relate more closely to the amount of text you can display. (Obviously, it is impossible to have a one column equals one character ratio with proportional fonts like you have with fixed pitch fonts, but the grid unit width is based on the "average" character width, with a little extra to allow for text that may consist of above-average widths.) 

A-Shell Reference 

Page 469 

## **FONT SCALING %** 

The Font Scaling parameter in the Dialog Sizing dialog is equivalent to the Proportional Font Scaling option on the Misc Settings dialog, except that the form applies only to dialogs, whereas the latter applies only to the main window. Also, the scaling basis is somewhat different between the two. In both cases, 0 indicates the standard Windows font size (i.e. no scaling). Any other percent value for the Font Scaling factor in the Dialog Sizing dialog is relative to that same standard Windows default font size. So 100% in this case is equivalent to 0; 125% would give you fonts that are 25% larger than the standard Windows default font. (In contrast, the font scaling factor on the Misc. Settings dialog is relative to the size of the main window grid.) 

For dialogs using the Windows desktop font size grid, increasing the font scale factor also increases the size of the grid units and thus increases the size of the dialog and all the controls within it. The overall effect is similar to what happens when you change your Windows desktop font DPI, except that here the effect is only limited to A-Shell dialogs. In contrast, for dialogs using the A- Shell main window grid, changing the font scaling factor does not affect the size of the dialog; it only affects the size of the text, and the height of combo box controls. (If the Misc Settings option to force edit box height to match the combo box height is set, then changing the font scale factor also changes the edit box height.) 

A-Shell Reference 

Page 470 

## **GRID UNIT % ADJUSTMENT** 

These two options apply only to dialogs using the Windows desktop font size grid, allow you to adjust the height and width of the grid unit without affecting the font size. This is a somewhat exotic technique, but might be handy if you find that your dialogs are either too spacious (in which case you specify numbers less than 100%), or two crowded (causing some of the text inside controls to be clipped), in which case you can increase the percentages. Or, a third situation would be that you feel that all your dialogs are either too tall and skinny or too short and fat, in which case you can adjust the percentages to get the desired aspect ratio. Note however that these adjustments are global (i.e. they affect all dialogs using the Windows desktop font size grid), so are of no use in adjusting just a couple of dialogs. (For that you need to modify the dialog design itself.) 

A-Shell Reference 

Page 471 

## **INCLUDE CAPTION IN DIALOG HEIGHT** 

This rather obscure option only applies to dialogs that were forced to use the Windows desktop font size grid because of the radio button options at the top of the dialog. (In other words, dialogs that were designed to use that grid will not be affected.) The option is probably only useful as a visualization tool, to be used temporarily, when considering the choice to migrate from the traditional main window grid to the newer Windows desktop grid. Since the height of dialogs created using the desktop font size grid does not include the caption (title bar) height, switching from the traditional grid to the desktop font size grid has the effect of making your dialogs taller, which initially makes them look "funny". Although the real solution is to adjust the internal layout of the dialog, this option can be a useful expedient. 

A-Shell Reference 

Page 472 

## **PREVIEW PREFERENCES** 

These settings control the behavior of A-Shell's print preview system, which is a quasi-independent module called "APEX." APEX is an extra-cost option with A-Shell, and it may therefore not be available for your use. See the section of this document on APEX for information on Preview Preferences. 

A-Shell Reference 

Page 473 

## **STATUS LINES** 

Use these options to turn on/off the top, bottom and session status lines. Note that turning on status lines does not cause information to appear on the lines, nor does it provide any additional space for normal terminal operations. Status lines are accessible only by program control, and are optionally used by programmers for, well, status information. 

The session status line, added in A-Shell 1213 of April 2011, displays a session clock (how long this session has been active) and, during host-client file transfers, a progress indicator. 

A-Shell Reference 

Page 474 

## **HELP MENU** 

The contents of the Help menu are sometimes modified by the application, and by the doc\ashelp.mdf configuration file. So it is quite possible that your menu will look different than  the one shown here. If the menu has not been modified, it will look like this: 

|**Menu Item**|**Description**|
|---|---|
|About A-Shell|The About box displays information about A-Shell in general (copyright), this running copy (version, memory usage,<br>font, etc.), and this particular license (nodes, serial number, etc.).|
|Check for Updates|This option checks to see if there are any A-Shell updates available. It will display the latest version along with your<br>current version and give you choices to view the release notes and/or perform the update. Note that if you are running<br>ATE, the update referred to will be for your instance of ATE only; it will not affect other ATE instances or the instance<br>of A-Shell running on the server. Otherwise, it will be for A-Shell/Windows, which, depending on your network<br>configuration, may be just for your workstation or a copy shared by other users. In the latter case, you will need to<br>get the other users off the system before performing the update.|
|Doc Links|Among the document links, you will usually have a link to this document (A-Shell Reference), plus a link to the<br>documentation page on the MicroSabio website. You may also have links to additional local documentation resources<br>for both A-Shell and your application. SeeHelp Menu Links<br> in the_Configuration_section of this document for notes on<br>customizing these items.|



A-Shell Reference 

Page 475 

## **MOUSE OPERATIONS** 

Although many A-Shell applications were originally developed for dumb terminals (without mice), A-Shell/Windows does support a number of mouse capabilities. 

## **Copy and Paste** 

You can copy text from the A-Shell display to the clipboard, and paste it from the clipboard into the current application’s input context, more or less as you would with any Windows application. See Copy and Paste on the Edit menu for further details. 

## **Double Click To Transmit** 

Double-clicking on a token of text (such as a numbered menu item) will cause it to be transmitted as if it had been typed, followed by the ENTER key. See AutoMouse. 

## **Mouse Wheel** 

In most contexts, the mouse wheel will behave as a series of up-arrow or down-arrow keys, typically causing scrolling or stepping through fields. See NOWHEEL to disable. 

## **See Also** 

- Using the Mouse 

A-Shell Reference 

Page 476 

## **- - PRINT TO EMAIL** 

Aside from the various developer-level options for outputting to email (see the Email discussion), there is also a user level-option which only requires that a logical printer be set up whose ini file contains the statement COMMAND=SBX:EMAILP. (See Printer Configuration for further instructions on setting that up.) The only other requirement is that your application software provides a way to choose a printer. (See the EZSPL configuration notes in Printer Configuration for information on how to add printer selection to an application that uses hard-coded printer names.) Once you have the ability to select a printer, you can then print any ordinary (text only) report to email, using the MAPI interface that is included with most versions of Windows. When such a printer is selected, it will launch your email client (e.g. Outlook, Eudora, etc.) with the printed document embedded into the body of the text message, and allow you to address it as you would any other email message. 

A-Shell Reference 

Page 477 

## **PRINT PREVIEW** 

_Reorganized and revised, January 2023_ 

There are various methods you may use to have reports that were created in A-Shell displayed on the screen before (or perhaps instead of) printing them. 

• Perhaps the easiest and best method for simultaneously managing both (a) the display of reports and (b) the printing options after display, is the A-Shell add-on product APEX. APEX is an extra-cost option, but it is specifically designed for A-Shell and is therefore perhaps the most well integrated. It is also a true Windows preview, supporting fonts, graphics, colors, etc. Follow the link to the documentation for additional details. 

- A-Shell's built in print spooler EZSPL includes a preview option described here: EZSPL Print Preview. Note that EZSPL is a 

- text-only viewer. 

- The browser method uses only components which come free with Windows or with A-Shell, and which works well as long as 

- your report file consists only of plain text, is to view it in a browser. You can create a pseudo-printer, which will wrap the report file with the necessary HTML codes for fixed-pitch display and launch the browser to display it, by setting up the following printer ini file: 

## `COMMAND=SBX:HTMLP` 

Compile into an SBX the source file HTMLP.BP in SOSLIB:[907,29], then copy it to BAS: to use it. See Printer Configuration for further details on the COMMAND statement and on printer configuration in general. 

- If you wish to view the report and then send it on to other people, generating a PDF may be the best option. You simply send 

- the report to a PDF "printer," which is not an actual printer but which acts like one from the perspective of A-Shell or any other program, and a PDF is created and possibly displayed. This method works with any kind of report, including ones with embedded graphics and/or GDI directives. You can use the original Acrobat PDF Writer from Adobe, the free PDF printer from Microsoft, or A-Shell's own (and recommended) PDF generator PDFX. 

A-Shell Reference 

Page 478 

## **SEARCH PATHS** 

For better or worse, A-Shell uses fixed search paths to locate files to be opened or executed. The ability to define and map logical devices and PPNs on to host operating system directories eliminates most of the benefit of user-customizable search paths, and the fixed paths provide a reasonable compromise between simplicity and flexibility. The specific search path logic depends on the context and type of file (command, program, subroutine, data), as detailed in the sections below. 

## **Command Search Path** 

## **Subroutine Search Path** 

The search path for the subroutine referenced by < `XCALL name>` or < `VXCALL expr` > is as follows: 

- embedded subroutines 

- name.sbx in user memory (see SBX Loading and Cacheing) 

- dev:name.sbx[p,pn] 

- dev:name.sbx[p,0] (replace dev: and [p,pn] with current .RUN file location if SBX_RUNDIR set) 

- dsk0:name.sbx[7,6] 

- WEBCACHE:name.sbx 

Note that an ALTSBXEXTSP directive may be specified to add an additional extension that will act as an alternative to SBX. If defined, the alternate extension will be searched for prior to SBX for each of the separate directories in the search path above. Note also that although it is not possible to specify an extension in the XCALL statement, it is possible with VXCALL, in which 

A-Shell Reference 

Page 479 

case the search would only look for that extension. 

## **See Also** 

- LOAD system command 

- COMPRGEXT (define executable extensions) 

- TRACE FOPENS (traces subroutine search/open) 

## **RUN Search Path** 

The default path for a RUN file, in the context of a RUN command or CHAIN statement, is listed below. It is modified or shortened as appropriate if the filespec contains an explicit device, PPN, and/or extension. 

- prog.run in user memory (see LOAD) 

- current dev:prog.run[p,pn] 

- current dev:prog.run[p,0] 

- dsk0:prog.run[7,6] 

- WEBCACHE:prog.run 

The file extension (ext) is RUN. In addition, an ALTRUNEXTSP directive may be specified to add an additional extension that will act as an alternative to RUN. If defined, the alternate extension will be searched for prior to RUN for each of the separate directories in the search path above. However, if the filespec in the RUN or CHAIN statement contains an explicit extension, then the search will be limited to just that extension (and any extension would be allowed). 

## **See Also** 

- TRACE FOPENS (traces RUN file search/open) 

A-Shell Reference 

Page 480 

## **Data File Search Path** 

When opening a data file (see File I/O), A-Shell will search for the file in the following locations: 

- If the AUTO_MEMOPEN option has been defined, file.ext in user memory. This overrides an explicit dev: and/or PPN in 

- the OPEN statement. 

- current dev:file.ext[p,pn] 

- current dev:file.ext[p,0] 

- WEBCACHE:prog.ext 

The default file extension is DAT, except in the case of ISAM or ISAMA files, where the default extension is IDX and the corresponding data file is opened implicitly from the same directory location. 

## **See Also** 

- TRACE FOPENS (traces file opens) 

- LOAD system command 

- MMAPLIST system parameter 

A-Shell Reference 

Page 481 

## **COLOR CUSTOMIZATION** 

There are at least three ways to configure the color settings for an A-Shell application without modifying the application itself: First, you can edit the INI.CLR file (see Configuration for details.) Second, you can use the SET TERM FCOLOR # and SET TERM BCOLOR # commands within a startup command file to set the initial foreground and background colors. (For applications that are not "color-aware", either of these first two techniques will be effective.) The last method is to change the definition of the color palette itself (i.e. what actual colors are associated with the color numbers used at the application level.) Under A-Shell/Windows, this can be done via the Edit..Settings menu (which see, above.) Under A-Shell/Unix, you would have to do it within your terminal emulation software. (ZTERM, for example, has a color redefinition capability similar to A-Shell’s.) 

In September 2016, a user asked: "Why are A-Shell / ATE screen colors NOT set to the "natural defaults" shown in the colors settings?" And the answer is: 

The .ash file is overriding the "natural defaults", which aren't so much "natural" as "original," dating back to the first color terminals used with AM systems. 

The original scheme makes sense for programs and people still based in that 80's era. Trying to use a black background in programs with any GUI content at all—where the default text color is black—is a disaster. The gray is a kind of compromise for mixed GUI/text environments. 

For better or worse, there is so much flexibility in the system, and so many parts, that I doubt anyone really understands it, even Herman, who has probably tried harder than anyone. We have the .ash file, which contains the RGB definitions of the color numbers, i.e. what you see in the Settings > Colors dialog; we have the TAB(-2,x) and TAB(-3,x) commands for changing the default fg/bg color index; we have the LIB:INI.CLR file which contains sets of color indices for various contexts like INFLD, VUE, etc.; we have the AG_COLOR command allowing you to redefine the RGB values programmatically; we have MX_WINSETTINGS allowing you to save/load .ash files; and we have the FGC/BGC fields in AUI_CONTROL.) It's great if you understand it all and know exactly what you want; otherwise it's a nearly impenetrable mess, begging for some kind of overall "scheme" choices ("Midnight", "Navajo", "Valentine", etc.) and an easy way for users to just choose one. But that's pretty much what selecting a new .ash file does. 

So the "net advice" on the subject is this: if you have one or more color scheme you like, and a preferred default, use File > Save As to save it/them to an .ash file and then load and use them as desired. 

## **See Also** 

A-Shell Reference 

Page 482 

- Colors Menu 

A-Shell Reference 

Page 483 

## **INTERFACING TO THE OUTSIDE WORLD** 

Although A-Shell is running on a Windows or Linux host computer, interfacing with the programs and data in those operating systems still require the efforts of a programmer or integrator to work out the details. So the following topics are covered less in the spirit of "how to" and more in the spirit of "what you can do," with suggestions on where to go for further "how to" details. 

## **Email** 

Emailing from A-Shell is possible using several different approaches. To send email directly, without any interactive human intervention, the best approach is to use the EMAILX utility, which is available for a modest license fee. You can also use the built-in subroutine TCPX to interface directly to your mail server. For additional information on email processes and options, see: 

- PDFX, the A-Shell PDF generation module that provides various email options 

- MX_MAPI 

- EMAILX 

- EMAILP 

## **Web Pages** 

Making content available via web pages can be handled in at least two different ways. At the simplest level, you can add a couple of HTML statements to the start and end of any report and then view it via any browser, either by manually typing in the FILE://<filename> URL into the browser, or by launching it via the MX_SHELLEX function (under A-Shell/Windows or ATE), or via a terminal-emulator-specific escape sequence (under A-Shell/Unix). 

The minimum set of HTML statements needed at the start of a report file is the string " `<HTML><BODY><PRE>` " and the corresponding trailing command would be " `</PRE></BODY></HTML>` ". You could accomplish this without any program modification by using the PREFIX and SUFFIX options in the printer ini files (which see in this document), but you would then have to launch the browser manually. An even simpler solution (under A-Shell/Windows) is to print to a printer whose ini file contains `COMMAND=SBX:HTMLP` . This will apply the HTML statements above and automatically launch the browser to view the file. 

The approach above is only useful for local or directly connected users. To make content available via web pages to ordinary web browser users who have no other connection to your server, you can modify one or more programs to support a CGI interface. 

A-Shell Reference 

Page 484 

## **SQL / ODBC** 

If your data is stored in ISAM PLUS files, you can purchase a third party ODBC driver from Easysoft Limited that allows you to query, read, and write your data using popular client data analysis tools (spreadsheets, report writers, etc.). 

The Easysoft ODBC driver can also access non ISAM PLUS files, but you lose the ability of using indexes. (That is, you have to scan one file at a time, from start to finish.) In either case, you’ll need a the map layout of your data records in order to create a schema definition. If you didn’t write the application, contact your application supplier for assistance before purchasing an Easysoft license. 

## **CSV (Comma Separated Values)** 

In many cases, the simplest way to make your data available for analysis by popular PC tools is to output it in CSV format. Although this is a programming task, it is a very simple one. To make it even simpler, ASB includes statements—primarily WRITECD—that further simplify the task of outputting comma delimited files. Such files can be transferred to a PC, if necessary, and then read directly by many popular PC data-analysis utilities such as Excel. 

Many people instinctively shy away from this suggestion, either out of the belief that converting data files to CSV format is complex or that it would take a long time to run the conversion. Both of these beliefs are misguided. In all but the most extreme cases, a utility to create a CSV version of an existing data file should take only a short time to write and only a few seconds to run. It often takes longer for the utility program—such as Access or Excel—to launch than it does to create the CSV data. 

## **See Also** 

- AXL:  Input/output for spreadsheet files 

- HTTP:  Interfacing with web services 

- XMPP:  Jabber messaging 

- TCPX:  Interfacing via TCP connections, 

- FTP2:  Interfacing via FTP/SFTP file transfers 

A-Shell Reference 

Page 485 

## **SCREEN PICTURES** 

Although Windows offers a variety of ways to capture a picture of the screen, A-shell includes an integrated screen picture utility, which is available at most input prompts, and which is often much faster and more efficient to use. The pictures are text-only, but this has the advantage of making them small, quick to print, and easy to edit or import into other contexts. It is also possible to create a log of screen snapshots and refer back to them at will, with or without printing them. 

To take a screen picture, from most application contexts, just press CTRL+P. Unless your application is in a context where it is not able to process the CTRL+P command, this pop up a dialog box that looks something like this: 

```
Display Screen Buffer?
```

```
Printer to Print Capture To:
```

```
Delete Capture File after Printing?
```

```
Comment:
```

You can abort from this dialog by hitting the ESC key. 

The **Display Screen Buffer** first prompt gives you the option of examining the accumulated screen picture log. (Whether or not there are more than one snapshot available will depend on whether you used the Delete after Printing option at the time of the previous screen snapshot.) 

The **Printer** prompt allows you to specify a printer. Note that you can put in a non-existent printer if you don’t want to really print it. Under A-Shell/Windows, you can also use the pseudo-printer PROMPT, which will present the Windows select-printer dialog, from which you could always cancel. 

The **Delete after Printing** option is self-explanatory. If you answer negatively, your next screen snapshot will be appended to the current snapshot file, allowing you to accumulate as many as you like. (This can be handy for documenting sessions for training, documentation, or other review purposes.) 

The **Comment** option allows you to add a comment to the bottom of the screen snapshot. This can be very helpful to the person later looking at the snapshot, wondering why you took it. 

## **Notes** 

A-Shell Reference 

Page 486 

If the PRINTER setting in miame.ini specifies a second printer name (e.g. PRINTER=P1,P2) then that printer (p2 in this example) will be automatically used as the printer for the screen snapshot, and the pop-up dialog above will skip over the first two questions. If it also specifies the "NODLG" option (e.g. PRINTER=p1,p2,NODLG) then the snapshot will be sent to the printer without the dialog above even appearing. Either of these options is useful when you want to simplify and/or standardize handling of screen snapshots, for example, using them strictly for reporting problems. (In that case, the ideal would be to have your snapshot printer actually email the snapshot to your support provider.) 

The CTRL+P command is actually only processed by the INFLD (aka INPUT) subroutine. This routine is used internally by the vast majority of input routines (including the dot prompt, memos, and field-level data entry) but there may be applications or application situations that do not use it. To obtain screen pictures in such situations, either consult your application provider or use one of the Windows-based methods (assuming you are using a Windows workstation.) 

The screen picture file will be named <jobname>.buf and will be stored in the special directory MEM0:[1,1] if it exists, else the current login directory. You might want to erase these files nightly to avoid the situation where someone wants to print just a single screen picture but instead gets many pages of pictures taken during prior days that were printed without the delete option. 

## **See Also** 

- MX_SCRNPIC 

A-Shell Reference 

Page 487 

## **FUNCTION KEY PROGRAMMING** 

A-Shell supports the same function key programming (aka translation) methods most popular under AMOS. For those unfamiliar with function key translations, here is a brief overview, followed by specific instructions on how to do it yourself. If applicable, see the following topic Standard IFX Translations. 

Nearly all terminal keyboards, whether PC-based or not, include a number of special keys which send more than just a simple ASCII byte. When a key sends more than one byte (i.e. a "multibyte sequence"), it usually starts with one of a small group of bytes recognized as "lead-in" characters (ASCII 27 or ESCAPE, and ASCII 1 or CTRL+A, being the most common). Typical keys that send such multi-byte sequences are those across the top marked F1 thru F12 (or higher), plus a collection of keys over to the right with names like PAGE-UP, PAGE-DOWN, etc. In addition, using the SHIFT, CONTROL, and/or ALT keys in conjunction with certain other keys may produce a multi-byte sequence, e.g. SHIFT+TAB. 

The terminal driver (a module embedded within A-Shell that understands your terminal hardware) recognizes these multi-byte sequences by a combination of their lead-in characters and by the fact that the remaining bytes arrive too fast to have been manually typed. Since these multi-byte sequences typically vary greatly among hardware terminal types, they are difficult for applications to use directly. To overcome this difficulty, the terminal driver condenses the sequence into a single integer value, which then serves as an index into a translation table, which can be easily modified by the user or developer. 

Function key translation tables are stored in files, which use one of two naming conventions. The first convention is for the name of the file to match the terminal driver name, with an extension that indicates the context in which the translations should be used. The most common of these is .ifx (for most input contexts) and .vux (for VUE). These are stored in DSK0:[7,0] (aka the LIB: ersatz directory.) For example, under A-Shell/Windows, the most common terminal driver name is PCTDVG, so the corresponding translation files are lib:pctdvg.ifx and lib:pctdvg.vux. Under Unix, the most common terminal drivers are AM62A, AM62C, AM65, AM75, WYSE50, and thus the corresponding translation files are lib:am62a.ifx, etc. These .ifx and .vux files are automatically loaded into memory as needed. 

Under A-Shell/Windows, your terminal driver name is determined by the CONSOLE statement in miame.ini. Under A-Shell/Unix, it might be determined by a TRMDEF statement in miame.ini, or simply by setting your terminal emulator to a particular emulation and letting the operating system figure it out. Unix will set the TERM environment variable to indicate the terminal type, and then A-Shell will consult this variable to set the terminal driver. You can examine the TERM environment variable from the Unix shell prompt by typing the command: `ECHO $TERM` . You can reset it with the command: **TERM=xxxxxx; export TERM** (where xxxxx is the desired terminal type). From the A-Shell dot prompt, you can check your terminal driver setting with the command **SET TERM** . If it shows "GENERC", then your TERM environment variable setting was not recognized, and it is using a 

A-Shell Reference 

Page 488 

generic driver (which will not support function key translation.) Otherwise, it will indicate your terminal driver name, such as AM62A. 

The second naming convention is for the filename to be anything you like, with an extension of PFK. For example, a user named Jack may create a set of his own special function key translations called jack.pfk. Or, perhaps a user or developer will set up some special function key translations for a particular application, such as invoicing, and call it invoic.pfk. These PFK translation files must be manually loaded into user memory (using the LOAD command) in order to be recognized, and once loaded, they override the previously mentioned type of translation file. 

Under AMOS, these two naming conventions corresponded to different file formats, and required different commands to edit them; FIXTRN for the former and SET PFK for the latter. Under A-Shell, they are actually the same format and are both maintained by the FIXTRN utility. See "Notes" for other differences between AMOS and A-Shell relating to the function keys. 

To create or edit either style of function key translation table, use one of the following command forms: 

```
FIXTRN
```

```
FIXTRN <extension>
```

```
FIXTRN <name>.PFK
```

The first form will create or edit lib:xxxxx.ifx (where xxxxx is your current terminal driver name.) 

The second form will create or edit lib:xxxxx.<extension> where <extension> would normally be either ifx or vux (but could be something else if your application was going to specifically request usage of another extension.) 

The last form will create or edit the specified PFK-style function key translation file, loading it from memory or from the current PPN if it exists. 

From that point, the FIXTRN utility works the same way in all cases. It first prompts for a special key to be used as a delimiter, then prompts you to enter a function key, after which it displays the existing translation (if any) and allows you to enter a new one. You can repeat that process for as many special function keys as you like. At the end, it writes out the new translation table and offers to update it in memory as well. 

## **Notes** 

A-Shell Reference 

Page 489 

There is no particular limit to the length of a translation. The output of the translation is buffered and fed into successive input requests until it is all used up, after which the next real input character (or next translation) will be used. 

See FIXTRN.LIT and LOAD.LIT for further details. 

If your application does not use all of the function keys, and you want to program the unused ones to act as typing shortcuts, the recommended procedure would be to copy the standard IFX file to another name, using a PFK extension (e.g. `COPY MYFUNC.PFK=AM62A.IFX` ). Then use FIXTRN to modify the desired function key translations. Finally, load and lock the PFK module into user memory at the start of your A-Shell session (e.g. `LOAD MYFUNC.PFK /LOCK` ). The alternative would be to simply modify the standard IFX file, but that runs the risk of it being overwritten during a subsequent update. 

Unlike the case under AMOS, PFK translations do not deactivate all IFX translations. Instead, the PFK and IFX translation tables are additive, assuming both are loaded into memory. The PFK takes precedence, but if a key is not defined to the PFK, then the IFX translation will still be active. The idea here is to allow you to add your own function key translation customizations or extensions, but still be able to take advantage of any updates to the IFX tables for those keys which you have not customized. 

A-Shell Reference 

Page 490 

## **STANDARD IFX TRANSLATIONS** 

The "standard" IFX file maps the function keys to sequences starting with CTRL+G (^G) and followed by CTRL+A for F1, CTRL+B for F2, etc, as shown in the table below (which should be used as a guide when setting up or verifying an IFX file): 

|**Key**|**Translation**|**Key**|**Translation**|
|---|---|---|---|
|F1|^G^A|Shift F1|^G^Q|
|F2|^G^B|Shift F2|^G^R|
|F3|^G^C|Shift F3|^G^S|
|F4|^G^D|Shift F4|^G^T|
|F5|^G^E|Shift F5|^G^U|
|F6|^G^F|Shift F6|^G^V|
|F7|^G^G|Shift F7|^G^W|
|F8|^G^H|Shift F8|^G^X|
|F9|^G^I|Shift F9|^G^Y|
|F10|^G^J|Shift F10|^G^Z|
|F11|^G^K|Shift F11|^G^[|
|F12|^G^L|Shift F12|^G^\|
|F13|^G^M|Shift F13|^G^]|
|F14|^G^N|Shift F14|^G^^ (Ctrl+G, caret)|
|F15|^G^O|Shift F15|^G^_ (Ctrl+G, underline)|
|F16|^G^P|Shift F16|^G (Ctrl+G, space)|
|Page Up|^R|Shift TAB|^G#|
|Page Down|^T|Shift Left Arrow|^G$|
|Insert|^F|Shift Up Arrow|^G%|



A-Shell Reference 

Page 491 

|**Key**|**Translation**|**Key**|**Translation**|
|---|---|---|---|
|Delete|^D|Shift Right Arrow|^G&|
|Home|^^ (Ctrl+caret)|Shift Down Arrow|^G' (Ctrl+G, apostrophe)|



INFLD (the input routine which uses the IFX translation file) uses these sequences to identify the function key, and then will return a code to the calling application allowing it to decide on the proper action to be taken. (Applications often reuse function keys for different purposes in different contexts.) 

Note that most PC keyboards do not have F keys going beyond F12. However, most terminal emulation software packages provide an alternate key sequence to simulate the missing keys. Consult your terminal emulation documentation for details. 

A-Shell Reference 

Page 492 

## **INPUT LINE EDITING** 

A-Shell supports two similar but distinct input modes, known as "line mode", and "image mode". In line mode, the operating system is in charge of the details of keyboard entry, passing an entire line to the application after the user hits the line termination key (typically ENTER). In image mode, the application is fully in charge of input, processing each character as it is typed. 

In the Unix world, line mode is typically known as "canonical" (or "cooked") mode, and "image mode" is known as "raw" mode. So much for terminology standardization. 

As a technical aside, in actuality all input within A-Shell is in image (or raw) mode, from the operating system’s perspective. A- Shell itself then simulates line mode based on the application context. 

Although line mode and image mode are not easy to distinguish from the user’s point of view, the important distinction is that in line mode, you have the ability to recall prior lines of input using CTRL+R (sometimes mapped to the PAGE-UP key). This is particularly useful when working at the dot prompt, since it is common to have a typo in a complicated command cause the command to be rejected. Rather than re-typing the entire command line, you can hit CTRL+R (or the PAGE-UP key), and then use the line editing keys to correct the mistake. You can also hit CTRL+T (or PAGE-DOWN) to cycle forwards through the last several command lines entered. 

See the following topic for the full list of Line Editing Commands. 

A-Shell Reference 

Page 493 

## **LINE EDITING COMMANDS** 

The following line editing commands work in almost every input context (line mode or image mode). The only exceptions would be in certain custom image input routines. Since image mode puts the burden of processing these line editing commands on the application itself, unless the application is using the INFLD routine internally, it is possible that it hasn’t implemented these commands. 

|**Command**|**Action**|
|---|---|
|Rt Arrow or Ctrl+L|Move the cursor one character to the right|
|Lf Arrow or Ctrl+H|Move the cursor one character to the left|
|Down Arrow or Ctrl+J|May terminate the current field and move to the previous field. (This is highly application dependent.)|
|Up Arrow or Ctrl+K|May terminate the current field and move to the next field. (This is highly application dependent.)|
|Ctrl+A|Move the cursor to the start of the previous word|
|Ctrl+B|In a multi-line editing context, this will break the current line at the cursor, moving the remainder of the line to the<br>next line (and shifting everything else down one line.) At the start of a line, this would simply insert a blank line.<br>(Heavily application dependent.)|
|Ctrl+D or Delete|Delete the character under the cursor|
|Ctrl+E|In some programs, this will abort the current entry operation or mode|
|Ctrl+F or Insert|Insert a space at the cursor (shift rest of field to the right)|



A-Shell Reference 

Page 494 

|**Command**|**Action**|
|---|---|
|||
|Ctrl+G|Start of pseudo function key sequence. In most programs, Ctrl+G followed by 1 will simulate the F1 key; Ctrl+G<br>followed by 2 will simulate the F2 key, etc., thru F9. Ctrl+G followed by A will simulate F10, Ctrl+G followed by T<br>will simulate F20, etc.|
|Ctrl+I or TAB|TAB may terminate the current field and move the cursor to the next field. (This is highly application dependent.)|
|Ctrl+M|Same as Enter.|
|Ctrl+N|Move cursor to end of field.|
|Ctrl+O|In a multi-line editing context, this would be the opposite of Ctrl+B. It concatenate the next line to the end of the<br>current line, bringing all the other lines up by one. (Heavily application dependent.)|
|Ctrl+P|Take a picture of the current screen. Depending on the configuration of the PRINTER statement in miame.ini, this<br>may display a pop-up dialog box with options or just send the picture to the designated printer.|
|Ctrl+Q|Toggle insert/replace mode.|
|Ctrl+Ror Page Up|In line mode, this will recall the previously entered line. In image mode, it may do nothing, or it may terminate the<br>current field, sending a message to the application that you want to go back to a previous screen. (Heavily<br>application dependent.)|
|Ctrl+T or Page Down|In line mode, this will recall the subsequently entered line (after having used Ctrl+R one or more times). In image|



A-Shell Reference 

Page 495 

|**Command**|**Action**|
|---|---|
||mode, it may do nothing, or it may terminate the current field, sending a message to the application that you want<br>to go forward to the next screen. (Heavily application dependent.)|
|Ctrl+U|Move the cursor to the beginning of the current line or field.|
|Ctrl+V|Delete the word starting from the cursor.|
|Ctrl+W|Move the cursor to the next word.|
|Ctrl+X|Toggle capitalization of the current word (or may have an alternate, application-defined meaning).|
|Ctrl+Y|Erase from the cursor to the end of the current field or line.|
|Ctrl+Z|Erase the current field or line. In a multi-line context, this would delete the current line, moving the subsequent<br>lines up.|
|Ctrl+[ or ESC|Typically aborts the current input operation. (Very application dependent.)|
|Ctrl+\|Displays the INFLD TYPE codes and other "about" info on the bottom line.|
|Ctrl+Shift-Underline|May recall the original value of the current field (after mistakenly editing it.)|



A-Shell Reference 

Page 496 

## **ERROR MESSAGES** 

This section contains an alphabetic list of the most common error conditions and messages that can occur, or be displayed by A- Shell, along with explanations and possible causes. Note that most of these messages are stored within sys:errmsg.<lan> and thus are subject to change, particularly if <lan> is not "USA." Also see the troubleshooting topic in Printer Configuration for printer-related troubleshooting tips. 

## **- - A Shell ? node license already in use** 

A-Shell when used on PC networks or Unix is licensed on a per-node basis. The number of simultaneous users allowed is dependent on the security key used to install A-Shell. This error will be displayed if a new node attempts to start an A-Shell session and all node licenses are already in use. Contact your dealer or MicroSabio to purchase additional licenses. 

In some cases, node licenses can be used up by jobs that no longer exist, but which failed to exit gracefully. The first step in diagnosing this problem is to use SYSTAT to display the list of jobs logged into A-Shell. Under Unix, SYSTAT will identify and flag "phantoms" and "zombies". (Phantoms are jobs that are logged into A-Shell but which no longer exist at the OS level. Zombies still exist at the OS level, but they are in a nether state between life and death, and need to be helped into the digital afterworld.) `SYSTAT/K/Z` will automatically remove them, freeing up the node licenses used by them. 

Under Windows, it is more difficult to identify jobs which no longer exist. If you can't recognize them directly, one technique would be to use the JSTAT command. If the job is not responding, it will display [time out] on its status line while querying the job. JSTAT.LIT also reports what the job was last doing, whether it is executing any commands, keyboard operations, etc., all of which can help you identify jobs that are no longer running. 

You can remotely abort a job that is stuck in some kind of an unresponsive state using the KILL command with the /K switch. If that doesn't work, or if it doesn't succeed in freeing all of the resources left by the job, you can use the QUTL command ("ZAP" option). 

The ABOUT command will display information about the number of jobs in use and node licenses used up, which can help you evaluate if you are making any progress with the above techniques. 

In small systems, or if all else fails, the simplest approach may be to just ask everyone to exit from A-Shell, and then manually erase the jobtbl.sys and qflock.sys files which are found in the same directory where miame.ini file is (typically /vm/miame or C:\VM\MIAME). These files are automatically removed by the last user to exit (provided no one crashed without exiting 

A-Shell Reference 

Page 497 

properly), and they are automatically re-created as needed. Some sites insert an erase command for these files into the boot process for the server, so that you can be sure of having a clean job table after a hard reboot. 

## **- A Shell out of memory** 

This error is displayed on entering A-Shell, and is distinct from the ASB-type ?OUT OF MEMORY error. A-Shell was unable to allocate a partition of the size requested by the MEMORY parameter in the A-Shell configuration file from the available operating system memory. This partition is used as A-Shell’s workspace, but unlike under AMOS, it is not used to load programs. (Programs are loaded in dynamically allocated memory.) Under Windows and Unix, it is unlikely that you will ever see this message. If you do, then the chances are that the machine really does require more physical memory—or that your MEMORY command is crazy. Note that you can dynamically change the size of your memory partition with the MEMORY.LIT command. 

## **- A Shell partition too small for file buffers** 

In order to keep track of open files, A-Shell maintains a number of internal buffers, and additional buffer space for ISAM 1.x files. The number of these is specified with the FILES command in the A-Shell configuration file, and they are allocated within the A- Shell memory partition. The size of the A-Shell memory partition is given by the MEMORY parameter in the system configuration file miame.ini. If this error appears, either increase the size of the memory partition, or reduce the number of data and ISAM buffers required. 

## **Access Denied** 

If you get this error during an attempt to write to a file (and/or your program aborts with Error 24), then see "Write protected **.** " . If you get an "Access Denied" pop-up error message when printing to a Window shared printer, you may need to create a local port which points to the network device. To do this, use the Add Printer wizard, select Local Printer (not network), then choose the option to add a local port, and enter the printer’s network share name (e.g. \\server\printer). 

In general, this error indicates (rather obviously) that you do not have sufficient privileges to perform the specified action. Both Unix and Windows (under the NTFS file system) have mechanisms for assigning access privileges to files, programs, directories - and other resources. Consult your operating system documentation, and also A Shell Installation for further details. 

## **Cannot create instance** 

This error indicates that A-Shell is not able to add a record to the jobtbl.sys file, which is normally created and managed in parallel to the qflock.sys file, whose location is specified in the QUEUE parameter of miame.ini. The most likely problem is that 

A-Shell Reference 

Page 498 

you don’t have sufficient user privileges to write to the file (or to create the file by writing to the directory), or that the file has become inaccessible due to some network problem. If you can’t fix the privilege problem directly, then the best solution may be to ask everyone to exit A-Shell, and then erase both jobtbl.sys and qflock.sys. They will be recreated automatically by the next user to launch A-Shell. 

## **- Cannot open A Shell queue system** 

The queue file specified in the QUEUE line of the A-Shell configuration file could not be opened. Full read/write access permission is required by all users of A-Shell both to the directory in which this file resides, and to the file once it is created. Note that in addition to the queue file (normally qflock.sys) there is also a file called jobtbl.sys which is created and managed in parallel with . See notes for **Cannot create instance** above. qflock.sys 

## **Compiler reports an absurd number of syntax errors** 

There are two common causes of this. The first is that you are using COMPIL or COMPLP on a program that contains ISAM 1.x statements. Since these two variations of the compiler assume by default that the only ISAM is ISAMPlus, they will complain about every ISAM statement. You can solve that problem by either using OCMPIL, or adding the /I switch to COMPIL or COMPLP. Note that all three of these LIT files are identical, but work differently by looking at their own name. Thus, renaming OCMPIL to COMPIL does not work. However, if you prefer to use the command COMPIL but have it act like OCMPIL, the trick is to erase COMPIL.LIT and instead make a compil.do[2,2] that executes OCMPIL. 

## **Compiler reports many errors; how do I stop display?** 

Since the operation of ^S and ^Q is dependent on various operating system settings and thus may not be operational within A- Shell, the best way to stop the compiler (or any other scrolling display) is to use the PAGE utility. For example: 

```
.PAGE COMPIL MYPROG
```

This will cause the display to stop and wait for you to hit RETURN (or Q to quit) after each screen full. 

## **Cannot open company name file** 

The company name file specified in the CONAME line of the A-Shell configuration file could not be opened. If A-Shell is being run for the first time, then it will be attempting to create the file, so ensure that you have file write access to the directory. If A-Shell is not being run for the first time, then check that the file exists and that you have file read access to it. 

A-Shell Reference 

Page 499 

## **Configuration file not found** 

The A-Shell configuration file (usually miame.ini) could not be found. Ensure that the environment variable **MIAME** has been set correctly, or that the correct path has been specified with the **-i** switch to A-Shell. 

## **Ctrl+S and Ctrl+Q do not work (to stop scrolling)** 

See Compiler reports too many errors to see (above). 

## **Disk is full; what can I erase?** 

The first file to check is opr:spool.log), which contains a log of every print request made (since the file was last erased) and which can grow rather large rather quickly on systems that do a lot of spooling. You should arrange for a daily or weekly procedure to erase that file. (As of the 4.7 release, the spool.log file will be automatically archived when it reaches 3MB. Up to 4 archived copies – spool.001 thru spool.004 will be kept, with the oldest erased to make room for the newest.) Another A-Shell log file which can be erased (assuming of course that you don’t care about the contents) is ashlog.log which will be found (assuming it exists) in the same directory where miame.ini resides. (This location may be overridden by the LOGDIR statement in miame.ini.) (It also gets archived up to 4 times as just described for spool.log. Beyond that, obviously you need to look at the temporary files created by your application. If you are running under Unix, you can get a quick overview of how full the filesystems are with the **df –v** command (e.g. .HOST DF –V), although SYSTAT will also show how many blocks are available in the filesystems used by your logical devices. (Note that running out of disk space in the root filesystem of a Unix machine is something you want to avoid at all cost, thus it is very wise to put your application in a separate filesystem so that at least it will never cause the OS to crash just because your program goes crazy producing output.) If **df –v** indicates a full filesystem but you can’t figure out which files are responsible, try using the Unix **du** utility to list the size of each directory. (Since there are many, you may want to pipe that to a file and then sort it so you can narrow down your search.) 

## **Ersatz definition file not found** 

This is displayed on entering A-Shell if the subject of an ERSATZ command could not be found. Check that the file exists and that you have file read permission in order to access it. 

## **Ersatz device specification is not formatted properly** 

An ERSATZ definition line in one of the files specified by an ERSATZ command is not in the correct format. The correct form is: 

A-Shell Reference 

Page 500 

```
OPR:=DSK0:[1,2]
```

or 

```
OPR2:=DSK0:
```

The usual cause is that one or both colons have been omitted. Note that the CPU number field for networked computers is not supported. 

## **Form feed problems (too many or too few) while printing** 

Under Unix, these are generally caused by printer filters that have their own inscrutable logic for form feed generation. When all else fails, you can take matters into your own hands by configuring the printer to use a filter that outputs absolutely NO trailing formfeeds under any circumstances. For SCO, we supply one on our web site called ‘ **dumbnoff** ’ which you can copy to your printer interfaces directory (/lp/spool/lp/model). Then, add AUTOFF=ON to your A-Shell printer ini file. This will cause A-Shell to take over the job of adding a trailing formfeed when required by your spooler switches. Refer to the discussion on Printer Configuration for more details. 

## **File specification error** 

This error can be generated by any A-Shell **.LIT** command program if a file specification was given on the command line that does not conform either to the DevPPN file specification format or to the host machine pathname format. See Printer Configuration and its subtopics for information on specifications for files and directories, etc. 

## **Illegal command in MIAME.INI** 

The A-Shell configuration file contained an unknown command. Check the spelling of all commands, and that the commands themselves (to the left of the equal sign) are given in upper case. 

## **Incompatible version of qflock; remove after all users exit** 

Occasionally a change is made to the queue system record layout to accommodate new information. When this happens, the queue version number is updated. Whenever an instance of A-Shell is launched, it checks its own latest queue version number against that version number of the qflock.sys and jobtbl.sys files which are actually in use, and if they differ, you get this message. As the current users exit, the last one out will erase the qflock.sys and jobtbl.sys files, assuming there are no phantom or corrupted records in it. If they do not go away even after you are sure all users are out, you can erase them manually. 

A-Shell Reference 

Page 501 

If you want to test a new version of A-Shell without interfering with people running an older version, then you can always specify a different miame.ini on the A-Shell startup command line; see Specify Ini File. Within that miame.ini you can specify a different name in the **QFLOCK** parameter. 

## **- Infinite loop corruption in A Shell queue system** 

In theory, this error should never be displayed. However, it is possible for A-Shell to be fooled into thinking this is the problem when in fact the problem is insufficient privileges to write to the queue file. Check the privileges of the qflock.sys file (whose location is specified in the miame.ini QUEUE statement.) One scenario where the privileges prevent you from writing to it would be if the superuser created the file (i.e. was the first A-Shell user). If you cannot fix the privileges for the existing qflock.sys file, have everyone exit A-Shell, then manually remove the qflock.sys and jobtbl.sys files and then relaunch A-Shell. 

## **Invalid # terminal rows or columns to initialize TRACKER** 

This may happen under Unix when the terminal type—as determined by the TERM environment variable—is not one of the builtin types. For normal terminal sessions, the problem may require you to adjust your terminal emulator to use a different emulation. This would mainly be an issue for non-ATE terminal emulators. In the case of a background session, perhaps launched by cron, the solution is probably to use the command line switch **-td dumb** . Also see Selecting a Terminal Emulation and Background Jobs. 

## **Language definition file not found** 

This is displayed on entering A-Shell if the language file (usually with .LDF extension) could not be opened. Check that the file exists and that you have file read permission to be able to access it. 

## **License does not match operating system version** 

A-Shell licenses are specific to a particular operating system. You would get this error if, for example, you tried to use an A- Shell/Windows license to run A-Shell/Unix. If you wish to migrate to another operating system, contact your dealer or MicroSabio to have your license converted. (There is a nominal charge for this.) 

## **JOBTBL Full! (Increase MAXJOBS setting in miame.ini.)** 

The job table is a file called jobtbl.sys which is automatically generated whenever A-Shell is launched and the file is not already in existence. Its size is computed to allow for some reasonable multiple of the number of licensed nodes, but if you run a lot of 

A-Shell Reference 

Page 502 

jobs that do not count against the license (such as background jobs or PolyShell jobs), then the computed number may be insufficient. In that case, you can add a MAXJOBS statement to miame.ini to specify a larger size. It is not normally necessary to get everyone out of A-Shell to make this effective – the next time A-Shell is launched it should detect the new size and expand the file. 

## **Msg #,# (sys:<filename>)** 

This occurs when the message number (#,#) is not found in the message file whose name is in the (parentheses.) Usually this is because you updated the A-Shell executable but not the message files, and the new version of A-Shell is trying to use a new message that wasn’t previously there. In that case, just download the latest A-Shell release to get the latest message files. Another possibility is that the message file has become corrupted. To check, just VUE it and then resave it. A third possibility is that your language definition file is not right, and so A-Shell is trying to use a non-existent message file extension. If the 

<filename> mentioned in the message does not exist, check your LANGUAGE statement in miame.ini to make sure that it references a valid language definition file. If it is simply a matter of you using a language file that we don’t provide a set of messages for, copy one of the others (with the same filename and different extension) to the desired extension, and then you will at least have messages (although perhaps not in the desired language.) Feel free then to use VUE to edit the message file and translate the messages. 

## **Operating in demonstration mode** 

This warning is displayed on entering A-Shell if demonstration mode is enabled. Thereafter a license warning banner will be displayed periodically explaining that you are breaking software licensing agreements and guilty of software theft if this copy of A-Shell is being used for any purpose other than demonstration or evaluation. Demonstration mode is enabled either if serial number of **0000** was entered during installation, if the wrong serial number/security key was entered, or if the contents of the company name licensee file specified with the CONAME command in the A-Shell configuration file has been changed. See LICENS for information on entering a valid security key. 

## **Out of memory** 

This is a standard ASB-type error (ASB error 3), and is distinct from the **?A-Shell out of memory** error. It occurs when attempting to run a program which runs out of memory in the job's memory partition, the size of which is established by the MEMORY parameter in the A-Shell configuration file. You can also change the memory partition size dynamically with MEMORY.LIT or with the MX_MEMORY subroutine. 

A-Shell Reference 

Page 503 

The memory partition is used for a variety of purposes, including storing program variables, command files during execution, expression and function parameter stacks, and string manipulation. Since the RUN program itself is loaded into dynamically allocated memory, a large RUN file would not be directly responsible for out of memory. However, large RUN programs tend to have large numbers of variables, which will take up memory partition space. 

Expressions involving manipulation of large string variables can consume a lot of memory and are a common cause of ?STACK OVERFLOW (ASB error 33) or ?STRING OVERFLOW (ASB error 54). 

Dynamic Arrays (DIMX)  operations do not use the memory partition. If you receive an out of memory error in a DIMX statement, it is because the operating system is unable to provide the requested amount of memory at that point in time; increasing your memory partition size will not help—and may make it worse by effectively taking that memory out of the system pool. 

You use the MEM(0) function within a running program to monitor the amount of memory available in the memory partition. 

## **Out of queue blocks** 

"Queue blocks" (which are actually records in a shared file called qflock.sys) are used primarily by XCALL LOCK and XCALL XLOCK, and some developer-specific variations of them, as a scheme of keeping track of, or controlling access to, shared resources (e.g. record and file locks). If you are running out of them, either the qflock.sys file is too small, or your application is not freeing up the queue blocks that it uses. 

The size and location of the file is defined by the QUEUE statement in miame.ini. The file is automatically created when the first A-Shell user starts up, and automatically deleted when the last user logs out. That system can be foiled by "phantom" jobs that never log out. If such is the case, and particularly if one of those phantom jobs has allocated queue blocks and never released them, you need to either remove the phantom jobs, manually clear the locks from the qflock.sys, or get all the real users out and then erase both qflock.sys and jobtbl.sys (which will be in the same directory). 

Comments and debugging suggestions: 

- ABOUT will show you which miame.ini file you are using. 

- VUE %MIAMEFILE% will allow you see and edit the current miame.ini file (to determine where the qflock.sys file is, and 

- possibly to increase its size). Note however, that any changes to the QUEUE statement will not take effect until all users have exited and the existing qflock.sys is deleted. 

A-Shell Reference 

Page 504 

- QUTL has options to display the queue block usage, both in the form of summary totals, and in detailed lists of the locks by 

- type and by user. It also has an option to "zap" a user (remove the user from the system and release the locks held by it). This is one way to get rid of "phantom" jobs. 

- `SYSTAT/W` will display how long each job has been logged in. This is useful for identifying jobs that have been abandoned (i.e. 

- anything over 24 hours might be suspect, at least for a normal, non-background job). 

- See the subroutines XLOCK and FLOCK and the LIT programs ABOUT, SYSTAT, and QUTL. 

- If you suspect that an application is not freeing the locks that it requests, one way to study it would be to activate the 

- subroutine trace (with `SET TRACE XCALL ON` or by opening the System Messages window and using the properties dialog). This will trace all of the subroutine statements, which would allow you to see just what an application is actually doing in terms of requesting and releasing locks. 

## **Printing problems under Linux** 

Linux systems are often configured by default to use the "ghostscript" printer filter, which is often too smart for its (or our) own good. Some things that can throw it into a spin are print files whose final line does not have an LF on the end, or files with embedded escape sequences. The best way to solve these problems is to change your printer configuration (under Linux) to use a null (or text or raw) driver. 

## **Print spooling with PREFIX, SUFFIX or AUTOFF doesn’t work** 

One possibility is that you do not have sufficient privileges to write to the directory where miame.ini resides. The above spooling options cause temporary files to be created in that directory, and if the directory cannot be written to, the operation will fail. Other suggestions are to use the .SET TRACE LP ON command to display detailed information about the various steps involved in printing (possibly clarifying where it is failing) and to look at the opr:spool.log) file to see if it contains any useful error messages. 

## **RUN file format bad or incompatible** 

2011 August, A-Shell 5.1.1228: Improved handling of "RUN file format bad or incompatible" error: the first time this error occurs, the module is re-loaded from disk. If it happens again, then the error is reported. This helps eliminate rare situations where an updated SBX gets loaded before it is full written to disk, or where some other mishap has caused the copy of a program in memory to become corrupted even though the one on disk is good. Such events are always logged though. 

A-Shell Reference 

Page 505 

## **Security key is invalid** 

The security key is stored on the first line of miame.ini. The format of the line is: 

```
SERIAL=####kkkk-kkkk-kkk-kkkkkk-kkkkkkkk   ;comment
```

#### is your serial number and the kkk… represents your security (or license) key. 

The most likely cause of this error is that the line has become corrupted, due to either manual editing or some other mishap. It is also possible that the coname.dat file (referenced by the CONAME statement in miame.ini) has changed, since its contents are tied to the security key. If you have your original license key written down, you can re-enter it (from the dot prompt) using LICENS. Note that if your miame.ini appears corrupted, you may need to first manually clean it up before it can be properly updated. To do this, use your favorite text file editor and set the first line to: 

```
SERIAL=0999NXXXXXXXXXXXXXXXABCD          ; license key
```

Make sure to include several spaces between the ABCD and the semicolon. 

## **Specified job name <job> already exists** 

This could occur for one of three reasons. The first is that you are specifying a job name via the **-j** switch to A-Shell (or PolyShell). The second is that you are using TRMDEF statements in miame.ini to assign job names, and A-Shell is not generating "unique enough" device identifiers (possibly due to an incorrect CONSOLE statement.) The third is that the specified job has partially crashed but still exists in the job table. Under Unix, A-Shell will prompt you directly to see if you want to kill the conflicting job, which usually takes care of the problem. Alternately, you can have another user (who is already in A-Shell and can get to the dot prompt) execute `SYSTAT/K/Z` to clear any zombies or phantoms. Under Windows, this is not possible, but you can still have another user remove the dead job with QUTL. Or, you can just specify the **-j** switch with a known-unique job name. 

Under Windows, as of A-shell 7.0.1773, jobs are now automatically removed from the job table when the session is aborted by an event such as a system reboot, shutdown, or logoff operation. Two new entries will appear in the ashlog under these events: 

```
QueryEndSession (xxxxx) eventname
```

```
EndSession (n,xxxxx)
```

A-Shell Reference 

Page 506 

The first message occurs when the shutdown event is requested. The eventname will be "CloseApp", "Critical", or "Logoff". (Apps can potentially try to block the shutdown at this point, but A-Shell does not.) 

The second message indicates whether the session is actually ending. The n value will be 1 if so, or 0 if the shutdown operation was aborted. 

The xxxxxx flags will indicate the following: 

```
0x00000001 - indicates that the process has a file open that needs to be replaced during the shutdown (not
likely for A-Shell)
```

- `0x40000000 - indicates the shutdown is being forced` 

```
0x80000000 - indicates users is logging off
```

## **Stack Overflow** 

This is equivalent to ASB Error 33, and is a special case of the more general Out of memory error. 

The A-Shell stack occupies the free memory space within the user partition, and is used for local variables (within functions and procedures) as well as for working copies of variables involved in expression evaluation. The error is typically caused by one of the following three conditions: 

· The memory partition is simply too small to accommodate the program. In this case, it is equivalent to the Out of memory error; in fact, the same situation might result in either error, depending on whether the lack of memory is noticed at the start of an ASB instruction or in the middle of it. 

- You've exceeded the number of open files defined by the FILESSP statement. 

- The program has an infinite recursive loop (such as a function that calls itself). The only solution for this is to fix the logic 

- error. 

## **String Overflow** 

A-Shell Reference 

Page 507 

String overflow (ASB error 54) is similar to Stack Overflow and occurs when there is insufficient memory in the job's memory partition to handle an expression or operation involving large strings. See the discussion of the more general Out of memory error for further information. 

## **- This update of A Shell not covered under your license** 

This error will occur if you update your copy of A-Shell with a version that was released after the maintenance expiration embedded in your license key. To check your maintenance expiration before downloading an update, you can use ABOUT from the A-Shell command prompt, or in the case of Windows, you can also display the _Help...About_ dialog box. The release date of the update will be displayed on the web page along with the update file. 

Note that the maintenance expiration does not limit you from running your currently licensed version of A-Shell. It only prevents you from running a new version generated after the maintenance expiration. To avoid this problem and gain access to all updates, at all times, contact your dealer or MicroSabio to renew the maintenance on your license annually. 

## **Too many sessions originating from same source address!** 

This message may occur with ATS (A-Shell Telnet Server) and indicates that you have too many open sessions originating from the same device, or sharing the same IP address. ATS is somewhat more flexible that other A-Shell versions in allowing multiple sessions to share a single node license if they originate from the same device, but since this could be abused by running many terminals through a single terminal server or other proxy service, there is a limit (typically about the same as the number of licensed nodes.) 

## **Unable to load <name> control** 

A-Shell loads a number of DLLs dynamically as needed to implement certain control types (XTEXT[XS] and XTREE[XS] being two examples). The search path for such DLLs starts in the directory where ashw32.exe was loaded from (typically c: 

\vm\miame\bin), and this is where we keep all of the DLLs released with A-Shell (so as to avoid conflicts with other applications which may be using different versions of the same DLLs). When A-Shell encounters an error loading one of its DLLs, it will make a second try to load it from an alternate location: 

```
C:\Program Files (x86)\Common Files\A-Shell\        (64 bit systems)
```

or 

```
C:\Program Files\Common Files\A-Shell\              (32 bit systems)
```

A-Shell Reference 

Page 508 

This directory does not normally exist, so the second try will not have any effect unless you set it up. The only reason why you would do such a thing is if you are experiencing the rare error condition where it reports that the DLL cannot be loaded because it is in use. Most likely the cause would be some antivirus software, or backup software or something else on the system that is gaining exclusive use to the library long enough to block other users. But if the cause cannot be resolved directly, you can work around it by creating the alternate directory above and putting a second copy of the affected DLLs into it. 

## **History** 

- 2012 December, A Shell 6.1.1326:  Added alternate paths to search sequence 

## **Unable to initialize ODBC environment** 

This error only applies to A-Shell for Windows when it has been linked with the ISAM Plus to ODBC interface. The ODBC manager has not been installed correctly on the workstation. In order to install ODBC, use Microsoft’s ODBC administration programs, odbcadm.exe, or odbcadm32.exe. Test access to the SQL data source using Microsoft Query. 

## **Warning: instance already exists for [??????] - over-writing** 

A-Shell stores user information for each session or instance of A-Shell in the jobtbl.sys file. This warning means that an entry already exists in the queue file with the same unique identifier as the one now being used. The most common cause of this is that your last session of A-Shell ended in an unclean manner, for example if the PC crashed or hung in a network situation. In these cases, the message is for information only, and can be ignored. If the warning persists, or recurs regularly when all sessions end cleanly, then the unique identifiers need to be checked. Under Unix, check the CONSOLE and TRMDEF parameters for correctness. In a PC network situation, check that _unique_ names have been assigned to each workstation. Also, attempting to use a standalone, 1-node license version of A-Shell in a networked environment will cause this error, and A-Shell will fail. 

## **Warning: maximum no. aliases exceeded** 

This is displayed on entering A-Shell if too many subroutine aliases have been defined in miame.ini with the ALIASSP command. Aliases up to the offending one will function correctly. The number of aliases will have to be reduced, or some of the routines recoded in C. 

## **Warning: maximum no. ERSATZes exceeded** 

A-Shell Reference 

Page 509 

This is displayed on entering A-Shell if too many ERSATZ devices have been defined. ERSATZ entries up to the offending one will function correctly. Remove some ERSATZ file references completely from the configuration file, or try to create some cut-down ERSATZ files which contain only the devices really needed. This should be a very rare error, since A-Shell supports 1000 ersatz devices for both Windows and Unix. 

## **Warning: nested include statements not permitted** 

This is displayed on entering A-Shell if a file which is the subject of an **INCLUDE** statement itself attempts to include another file. Restructure the files so that only one level of inclusion is used. 

## **Warning: standalone mode for network license disables locking** 

This is displayed on entering A-Shell purely as a reminder. The copy of A-Shell has been installed with a multi-node network license, but has been forced to run in standalone mode with the -s command line switch. This will disable multi-user functions such as locking, but temporarily disables the need to set a computer name. 

## **Windows printer [ptrname] not defined to this workstation** 

This can mean one of two things. Either the application attempted to print a file to the explicitly named printer [ptrname], and no printer ini file (either or sys:ptrname.ini or ashcfg:ptrname.pqi) was found, or the printer ini file was found, but the DEVICE name it specifies does not match any of the printers known to Windows on this workstation. Note that the reason these two cases report the same error message is that if the printer ini file is not found, A-Shell auto-defines one on the fly, with DEVICE=[ptrname]. (This feature eliminates the need for printer ini files in many cases.) If unclear why the printer [ptrname] does not match any of the defined printers on this workstation, refer to Troubleshooting Techniques in the Printer Configuration section. 

## **Window instance exceeds the limit defined in your config file** 

This would occur if the number of A-Shell sessions you have running on your PC exceeds the limit specified by the MAXINST statement in miame.ini. Try increasing that, or closing some of you’re A-Shell windows. 

## **Write protected error (ASB Error 24)** 

This error (or a variation of it, such as "Access Denied") will occur if you do not have write permission for the file or directory you are trying to write to. One cause of this is copying files from a CD. (Files on a CD often have the read-only attribute set, and 

A-Shell Reference 

Page 510 

some methods of copying files under Windows may not clear that bit.) If there are just a few files affected, then you can fix them (under Windows) by locating them in Explorer, right clicking, and clearing the read-only check mark. This is not convenient if you have many files with the problem. In that case, open a Command Prompt (aka "DOS") window, use the CD command to change to the proper directory, and use the ATTRIB –R command. (This will clear the read-only flag on all the files and subdirectories within the current directory.) Repeat this for all the affected directories. 

If the problem occurs under Unix, then login in as root (or use the **su** command), **cd** to the relevant directory, then use **chmod –R +w *** (or some variation of the **chmod** command, such as **chmod 666** to reset the privileges for one or all of the affected files. Refer to File Ownership and Privileges for further information. 

## **- Your job queue has been zapped; exit A Shell now** 

## **Short version** 

This occurs when someone deletes the qflock.sys and/or jobtbl.sys files (or at least clobbers your entry within the latter, perhaps with the QUTL command) while you are running. A-Shell does not notice the problem until it has reason to update the queue (such as when chaining between programs or logging to a new PPN.) If this problem happens every time you launch a second session, then the problem is most likely that A-Shell is not able to generate a unique device identifier due to a problem in your CONSOLE statement in miame.ini. 

## **Long version** 

The message indicates that another job has overwritten the current job's job-control-record. (Each job has a record in the jobtbl.sys file where it stores a variety of current status information about the job; this is the primary source of information used by SYSTAT, JSTAT, and most subroutines that request information about a job.) 

When a new instance is started, A-Shell generates a (hopefully) unique ID for the instance, then scans the JOBTBL to see if there is already a record for it (which happens when a workstation crashes or is rebooted without exiting A-Shell), if so, displays a brief warning message on the screen and in the log, and then re-uses the record. 

You can see the instance identifiers using `SYSTAT/C` (3rd column). Generally they consist of 2 parts separated by a colon: an identifier of the workstation (like a machine name or possibly an IP address), plus an instance number (01, 02, etc.) to separate the instances of A-Shell coming from the same workstation. 

For example: 

A-Shell Reference 

Page 511 

```
.systat/n/c
```

```
Status of A-Shell/32 7.0.1772.1 on Saturday, July 26, 2025 11:05:39
TSKAAA TSKAAA  JACKT400:01        DSK0:1,4       RN  SYSTAT    2912  986K bytes
TSKAAB TSKAAB  JACKT400:03        DSK0:150,277   RN  MYDOC     5464  939K bytes
TSKAAE TSKAAE  JACKT400:05        DSK0:150,277   ^C  VUE       6892 1502K bytes
```

This shows 3 instances, all coming from the machine whose name is "JACKT400", and each with a separate instance # (01, 03, and 05). 

In some particular environments, such as Terminal Server, or CGI, or when launching A-Shell sessions from another application, it may be necessary to ask A-Shell to add a numeric suffix (-###) to the machine name (and prior to the instance number) in order to prevent duplicates. There are two ways to accomplish this: add OPTIONS=NTTS to miame.ini, or add the **-awts** switch to the A-Shell launch command line. 

Besides `SYSTAT/C` , the best tool for analyzing this problem is the ashlog.log file, provided you add TRACE=INOUT,SIGHUP,BASERR to miame.ini (which is recommended as standard procedure.) This will cause A-Shell to log an entry for each session started and ended, along with the ID name, job number, user login, and license utilization information. 

A-Shell Reference 

Page 512 

## **APEX** 

**A** -Shell **P** review and **EX** tensions ("APEX") is a built-in component of A-Shell for Windows and ATE. At the user’s option or under program control, APEX receives a print file and re-directs it into a preview window. That window displays an image of the report and provides the user with various viewing options such as zoom, show multiple pages or single page, etc. After previewing the report, the user may then print the report as it was originally intended to be printed (i.e., to the originally-specified printer), print it under user control (different printer, say, or landscape instead of portrait), or discard it. The purpose of the viewer, as with all such print preview functions, is to make sure that you are printing what you think you are printing—and to save time, energy, money and paper in the process. In some cases, viewing the report may eliminate the need for printing entirely. 

APEX offers a variety of controls and options to facilitate viewing the report. Most of these items and how to use them are fairly obvious. 

APEX also includes an _Extensions_ element, through which plug-in functions—included with A-Shell or supplied by a developer using the published interface—can be added to the APEX toolbar to perform various kinds of report post-processing. The most popular of these, included in the standard distribution of A-Shell, are Export to XLS, which converts a report into a spreadsheet, and Email Report. 

Some of the tools and options of APEX are briefly described below below. 

## **Title Bar and Tool Bar** 

The APEX title bar displays information about the report: original filename ("tstz" in this example), a sequence number (-1), printing this session, temporary extension (.APF for "A-Shell print file"), the number of pages in the report, Windows printer for which this report is intended, and the printer properties being used for printing. The toolbar provides options (in order from left) to set zoom percentage (10% to 999%); zoom in; zoom out; single page; multi-page grid (drop-down menu); page number / back / forward; print setup; print; help; close; print per application; find text (search); open another report; APEX preferences; export to XLS; export preferences; email report; email preferences. 

## **- Multi Page Grid** 

A-Shell Reference 

Page 513 

Clicking on the multi-page grid option (see toolbar above) offers choices for the layout of multiple pages. You can (barely) see the grid choices below near the top left. The full screen shows the report in the 4 (across) by 2 (down) grid. 

## **Find Text (Search)** 

Clicking the find text tool and entering a word into the "Find" dialog box ("exitcode" in this case) causes all the occurrences of "exitcode" on the current (first, in this case) page to be highlighted. Clicking "Find Next" displays the highlighted words on the next applicable page, etc. 

A-Shell Reference 

Page 514 

## **PREFERENCES** 

Several things about how the preview function behaves are under user control, configurable in _Preferences_ dialog. This dialog is accessible from both the menu bar in A-Shell/ATE ( _Settings...Preview Preferences_ ) and from the Preferences button on the preview toolbar. The following screen shot, while not necessarily identical to the one shown in your version of the program, illustrates some of the user-controlled options. 

Preferences toolbar button: 

## **Preview on Print** 

Normal report printing consists of a report being created by a program, and then being sent to the PC for printing. The "Preview On Print" option allows you, the user, to control the circumstances under which those reports from the host, received for printing, are instead displayed on your screen. The "Always" and "Never" options should be fairly clear. The two "Application Control" options allow you to let the program that created the report determine whether the report is previewed--and gives you the option to say what happens when the report program doesn't specify anything. 

There is no right or wrong, or best or worst, setting for this option. It is strictly determined by (a) your needs and objectives, and (b) those of your work environment. 

The default value for this setting is "Application Control, Default=Off", which means that (a) APEX is expecting to receive a launch or don't launch command from the program that generated the report, and (b) if it does not get such a command, it will NOT launch. 

## **On Exit from Preview** 

What do you want to happen when you exit the preview window (which, by the way, you can do by clicking on the "X" in the top right corner of the preview window, or by hitting the Escape key)? As you make your choice, keep in mind that all reports viewed with APEX are saved to disk; you can come back and view them again later if you wish. 

## **Preview Window State** 

A-Shell Reference 

Page 515 

It is not possible for the program that launched the preview, or the programmer who wrote the program, to know how the user wants to deal with the preview: display the preview windows right now, or continue working and view the report later? The _Preview Window State_ allows the user to set her preference for what happens when a report is sent to the preview window. "Visible (Foreground)" means that the preview window is shown right now. "Minimized (Background)" means that the preview window is created right now but then minimized; it appears in the task bar, which you need to click in order to view the report. 

## **Preview File Retention** 

When a file is viewed using APEX, it is possible that the user may want to view this file again later. So as soon as a report is viewed, a copy of it is written to a file in the APEX folder. If the original file name being viewed is "report.xxx," then the file that is written into the APEX folder is called "report.apf" (apf = A-Shell Print File). These files remain in the APEX folder, and can be opened by the _Open another report file_ button on the toolbar. 

How long do they remain in the APEX folder? This is controlled by a setting on the Preferences called "Preview File Retention (hours)." The default value is 96 hours (four days), but you can set it to whatever you wish. 

From an environmental perspective, the fact that you can view the report again later should make it easier to forego actual printing of every document (after previewing), merely out of fear that you might need it reference it in a few hours or days. The default setting of 96 insures that your disk won't get clogged up with more than four days worth of report files. 

A-Shell Reference 

Page 516 

## **OPERATIONS** 

Most of the operations of APEX are obvious or fairly easy to figure out. **Keystokes and Mouse Clicks** lists short-cut navigation tools for viewing the report, and the toolbar icons are briefly described below. 

The **Zoom Percentage** controls shows various steps of zoom. When you use the magnifying glass buttons to zoom in or zoom out, the steps by which you zoom are those shown in the zoom percentage control. You may manually set (by typing it in) the zoom percentage to any value between 10 and 1000. Note that when you are selecting a value for the zoom percentage control, and it has the focus, using the PageUp and Down key, as well as the up and down arrows, apply to the zoom percentage and not to the report being displayed. In other words, you can cycle through the zoom percentages by using those directional keys. 

**Print as Intended by Application** is an unusual operation, so please see the documentation for an explanation. 

The **Find Text** button on the toolbar will be grayed out (inactive) if the report being previewed does not contain any text—i.e., is all images and/or graphics. To initiate a text search, click on this button and enter the text to be found in the resulting dialog box. 

**Open Another Report File** opens a file selection dialog in the APEX folder. 

**Preview Preferences** provides control of basic preview operations. 

**Export to XLS** produces a spreadsheet from the displayed report, and the adjacent icon provides configuration options. 

**Email Report** is pretty clear, and the adjacent icon provides configuration options. 

A-Shell Reference 

Page 517 

## **KEYSTROKES AND MOUSE CLICKS** 

|**Keystroke**|**Action**|
|---|---|
||**Multi-page Mode**|
|Home|Positions to the first group of pages, starting at the first page. The first page becomes the current page.<br>testing.|
|End|Positions to the last group of pages, ending at the last page. The first page of the displayed pages<br>becomes the current page.|
|Control+Home|Same as the Home key.|
|Control+End|Same as the End key.|
|Left-Arrow|Moves to the previous page. The displayed group of pages is adjusted if necessary.|
|Right-Arrow|Advances to the next page. The displayed group of pages is adjusted if necessary.|
|Up-Arrow|Moves the first page of the displayed group of pages to the previous page (or sheet in duplex mode). The<br>current page is adjusted if necessary.|
|Down-Arrow|Advances the first page of the displayed group of pages to the next page (or sheet in duplex mode). The<br>current page is adjusted if necessary.|



A-Shell Reference 

Page 518 

|ell Reference||
|---|---|
|Page-Up|Displays the previous group of pages. The current page is adjusted if necessary.|
|Page-Down|Displays the next group of pages. The current page is adjusted if necessary.|
|Plus on NP|Zoom in. ("NP" refers to the numeric keypad.)|
|Left click|Display page clicked in single-page view at scaling of last single-page view.|
|1 (numeric)|Switches from multi-page mode to single page mode.|
||**Single Page Mode**|
|Home|Positions to the top of the current page.|
|End|Positions to the end of the current page.|
|Control+Home|Positions to the top of the first page.|
|Control+End|Positions to the end of the last page.|
|Left-Arrow|Horizontally scrolls left on the current page.|
|Right-Arrow|Horizontally scrolls right on the current page.|



A-Shell Reference 

Page 519 

|ell Reference||
|---|---|
|Up-Arrow|Vertically scrolls up on the current page.|
|Down-Arrow|Vertically scrolls down on the current page.|
|Page-Up|Vertically scrolls up on the current page. At the top of the current page, move to the bottom of the<br>previous page.|
|Page-Down|Vertically scrolls down on the current page. At the end of the current page, advance to the top of the next<br>page.|
|Plus on NP|Zooms in . ("NP" refers to the numeric keypad.)|
|Minus on NP|Zooms out. ("NP" refers to the numeric keypad.)|
|Escape|Close|
|Left click|Zoom in. Same as "plus zoom" button.|
|Right click|Zoom out. Same as "minus zoom" button.|
|Ctrl+PlusKey|Zooms in 5%.|
|Ctrl+MinuKey|Zooms out 5%.|
|2 (numeric)|Switches from single page mode to multi-page mode.|



A-Shell Reference 

Page 520 

|ell Reference||
|---|---|
|||
||**Both Modes**|
|Escape|Close|
|Ctrl+P|Print|
|Alt+Ctrl+P|Toggles between main window (A-Shell or ATE) and Preview.|
|Ctrl+Enter|Toggles between multi-page and single page modes.|
|Ctrl+Alt+|Toggles between maximized and normal windows.|
|Ctrl+G|Go to page number control.|
|Ctrl+Z|Go to zoom control.|
|F1|Help|
|F3|Find|



A-Shell Reference 

Page 521 

## **PRINT AS INTENDED BY APPLICATION** 

This is rather an odd function to see in a Windows program, so a bit of explanation is in order. 

Reports that are generated by A-Shell programs frequently are sent—by the report program—directly to a PC printer. In addition to the report, those print instructions include information for the printer, such as the name of the printer, number of copies, etc. However, APEX intercepts the report and (a) stops it from going directly to the printer, and (b) allows the user to now print the report using different parameters than the report program specified. Which is fine, and of course the user can print as he/she wishes. 

But she might decide what she really wants, after looking at the report, is for it to be printed how the report program originally intended. Unfortunately she doesn't know what the report program intended; perhaps it was going to print six copies on a network printer called "Laser45." 

By using this oddly-named button and function, the user can make sure that the report is handled and/or processed and/or printed as the original instructions intended. 

If you do not need this function, just use the regular print operation. 

A-Shell Reference 

Page 522 

## **OPEN ANOTHER REPORT FILE** 

See _Preview File Retention_ in Preferences for information on what files may be opened and how they got here. 

When you click this button, you will see a standard Windows file open dialog. Unfortunately, the list of file names that you see is probably not enough information to figure out what report it is you want to see. On the file open toolbar, you should see an icon near the top of the dialog box called _Views_ , and one of its options is "details." If you click on the _details_ icon, you should be able to see a little more information about the files. You may click on the column headers to sort by those columns in any effort to fine the report you're looking for. Unfortunately, not much information is available to you here, so you will just have to open as many reports as it takes to find the one you're after. 

A-Shell Reference 

Page 523 

## **EXTENSIONS** 

You can add your own extensions to APEX, which are accessed as buttons on the toolbar and which call your own ASB code, by defining them in the APEX configuration file, ashcfg:apex.cfg. The configuration file, if present, is scanned for commands of the following form: 

## **BUTTON=prog, iconspec, tooltip {,msgno, inifile}** 

## _prog_ 

indicates the subroutine which implements the extension. In theory it wouldn't have to be an SBX, but currently that is the only format supported, so _prog_ must be in the form of "SBX:name", e.g. "SBX:PRTXLS". The corresponding subroutine (e.g. PRTXLS.SBX) must be in the BAS: directory (e.g. c:\ate\dsk0\007006\prtxls.sbx). See Comments, below. 

## _iconspec_ 

specifies the icon to display in the button that will be added to the toolbar. Supports the same syntax as for AUI_CONTROL icon buttons. 

## _tooltip_ 

is a short tooltip to display when the mouse hovers over the button. 

## _msgno_ (optional) 

may specify a message number in the file <inifile.lng>, where lng is the current language extension, e.g. USA, to supply the tooltip text. If present, it overrides the tooltip parameter above. Note that within the specified <inifile.lng> message file, the specified _msgno_ value is assumed to be in the 000,### message group. In other words, if _msgno_ = 001, then it will look for the line starting with 000,001,... Some message files, like PRTXLS.USA, may contain multiple groups of messages. 

## _inifile_ (optional) 

may specify an initialization file used by the extension, although the details of how is is used are up to the custom code in _prog_ . Note that because commas are used as a delimiter in the BUTTON directive, the inifile parameter cannot contain a [p,pn] component. Use an ersatz instead, e.g. bas:prtxls.ini. 

The file may also contain any number of comment lines, each beginning with a semicolon in the first position. For example: 

A-Shell Reference 

Page 524 

```
;APEX customization
```

```
;BUTTON=prog,icon,tip{,msgno,ini}
```

```
;If msgno>0, is expected to be msg 002,### in inifile.lng
```

```
BUTTON=SBX:PRTXLS,ashico1::document_out,Export to Excel,38,BAS:PRTXLS.INI
```

```
BUTTON=SBX:PXLCFG,ashico1::preferences,Configuration Options For Export,0,BAS:PRTXLS.INI
```

There are no particular limitations on what the subroutine (prog) may do, other than that it cannot delete or replace the file being previewed, and must eventually return so that APEX can resume control. 

## **Comments** 

In order for an SBX subroutine to work as an APEX custom extension, it must be written according to the A-Shell print filter interface requirements; see the printer initialization command line COMMAND=SBX... for details. In addition to the mandatory parameters passed to all print filters, APEX will always pass two additional arguments, _inifile_ and _xeflags_ , i.e. the entire interface is: 

```
xcall <sbxname>, sts, fspec, printer, switches, copies, form, {inifile, xeflags}
```

where _inifile_ will be the _inifile_ specified in the apex.cfg BUTTON command line, and _xeflags_ will contain zero or more of the following bits: 

|**Value**|**Description**|
|---|---|
|&h0080|routine was called by APEX|
|&h0100|print debug flag was set|



**History** 

A-Shell Reference 

Page 525 

2017 August, A-Shell 6.5.1612:  Custom buttons can now use PNG format. 

A-Shell Reference 

Page 526 

## **EXPORT TO XLS** 

_Updated June 2022; see History_ 

One of the standard export/extension modules included with APEX is a routine that converts reports to XLS spreadsheet. The function is accessible via toolbar buttons—one to perform the export, another to configure it. Following is a guide to understanding and troubleshooting the APEX export process. 

- The _Export to XLS_ button is enabled if and only if the A-Shell subroutine PRTXLS.SBX is present and available. It should be 

- located in the BAS: directory, normally DSK0:[7.6]. If the _Export to XLS_ button is inactive (grayed out), it is because this essential file is missing. 

- When the _Export to XLS_ button is clicked, A-Shell/ATE calls PRTXLS.SBX which analyzes the report and creates a 

- corresponding XLS document. 

- PRTXLS reads the export configuration file prtxls.ini which also resides in the BAS: directory. Some of the export options may 

- be accessed via the _Configure XLS Export_ button, next to the _Export XLS_ button on the toolbar. 

- PRTXLS uses the LibXL function library to write the exported data into the new format. The LibXL library is contained in the 

- file libxl.dll, which resides in the A-Shell \bin directory. It must be version 3.7.2 or later. 

- PRTXLS creates a new file called <sourcefilename>{-suffix}.xls. The -suffix is used to create unique filenames to avoid 

- overwriting existing files and is based on an option in the configuration file. 

- The DATA tab contains the rows of the report that appear to be the primary data lines. 

- The REMNANTS tab contains the lines in the original report which were NOT considered data lines (headers and other 

- adornments.) 

- The ORIGINAL tab contains the complete original report. 

The idea is that this file will allow the user to quickly and easily compare the exported data to the original data and detect any errors. The file <sourcefilename>.xls is placed in the c:\apex folder unless another folder has been specified in the ini file. 

## **History** 

A-Shell Reference 

Page 527 

- 2022 June, A Shell 6.5.1717.5, PRTXLS 2.1(218): Made improvements to the column separation logic. Columns with only one space of separation are now more reliably separated. Also close a crash loophole. 

- 2017 July, A Shell 1610, PRTXLS.SBX 2.0(101): The basic XLS engine was changed from a Perl script, which required a Perl server, to the LibXL function library. The Perl configuration is no longer supported, and the export function is now fully contained within A-Shell and its associated libraries. 

## **Subtopics** 

- Export to XLS Example 

- Report Format Considerations 

- PRTXLS Config File 

A-Shell Reference 

Page 528 

## **EXPORT TO XLS EXAMPLE** 

The report that displayed in the APEX preview window like this... 

...produced a spreadsheet that looked like this: 

A-Shell Reference 

Page 529 

## **REPORT FORMAT CONSIDERATIONS** 

_Added August 2017_ 

PRTXLS can process any kind of report, but it can only generate spreadsheets consisting of relatively uniform set of rows and columns. In order to accomplish that, it needs to start with a report that reasonably fits that description—i.e., one in which: 

- The data lines are reasonably distinguishable from the non-data lines. 

- The data lines have a consistent set of non-overlapping columns. 

In some cases, particularly those where the column data is sparse, or not very consistent, or very crowded, PRTXLS may fail to correctly identify the column divisions. This will result in lumping two columns from the report into a single column in the spreadsheet, or vice versa. If you have such a report and are willing to make minor changes to your report layout to improve the conversion to XLS, the easiest thing to do is to create a separator line between the column headings and the column data, consisting of dashes, with a space at the end of each column. For example: 

```
ItemNo Description        QtyOnH Unit  LastOrderDate    YTDSales
```

```
------ ------------------ ------ ----  -------------  ----------
```

When PRTXLS sees this kind of header, it will assume that the breaks in the dashes mark the breaks in the columns. Otherwise, it will use a variety of heuristics for deciding how the columns are to be divided. Since alphanumeric data may contain spaces, and since it is not unusual for the same data to appear in many consecutive rows, PRTXLS will generally refrain from dividing columns that are separated by only a single blank space, especially if there are preceding columns that have multiple spaces of separation between them. So another simple adjustment you can make to a report layout so that it converts better would be to either allow at least two blank spaces between each column, or if you have to pack the columns closer, use one space consistently. 

To assist in troubleshooting, A-Shell's debug function may be helpful. To turn it on, check the "Debug" option on ATE's _Connection Properties...Printer...General Options_ menu. If you are using A-Shell rather than ATE, get to the prompt and enter `SET DEBUG` . 

A-Shell Reference 

Page 530 

## **PRTXLS CONFIG FILE** 

_Modified August 2017_ 

Various operations and options in the Export to XLS process are controlled by settings in the export initialization file, prtxls.ini. If this file is missing or an individual lines/statement is missing, APEX will use the value shown as "Default" in the table below. The ini file is normally stored in the [7,6] directory or equivalent, although when PRTXLS.SBX is invoked from the COMMAND statement of a printer ini file, the ini file specification may be passed as an argument (e.g. `COMMAND=SBX:PRTXLS,dsk7:xls123.ini[40,30]` ). 

Note that each of the statements below must reside within the section indicated. Within a section, the order or presence/absence of a given statement is not relevant. The section names are in upper case, are enclosed in square brackets, and are preceded by a blank line. See the sample ini file section. 

As with many ini files, lines beginning with semi-colons are comments and are ignored by the file processor. Comments can only occur on their own lines--i.e., cannot be appended to the ends of command lines. 

|**Statement**|**Section**|**Values**|**Default**|**Description**|
|---|---|---|---|---|
|IncludeTotals|DATA|0,1,2,3|0|Determines how lines that appear to be subtotals or totals are<br>handled. 0-omit; 1=treat as data; 2=move to separate columns;<br>3=convert to formulas.|
|IncludeBlankLines|REMNANTS|0,1|0|If set, blank lines are included in Remnants worksheet.|
|IncludeDupLines|REMNANTS|0,1|1|If set, duplicate lines are included in Remnants worksheet. (Otherwise<br>only one line per set of duplicates is included.) For example, if set,<br>the Remnants page may have many identical lines containing column<br>headers.)|
|SortBy|REMNANTS|0,1|0|If set, Remnants lines are sorted by their contents.|



A-Shell Reference 

Page 531 

|BGcolor|ORIG|See sample ini file|Silver|Background color of "Original" worksheet.|
|---|---|---|---|---|
|AppendSeqNo|POST|0,1|1|If set, a sequence number is appended to the XLS filename to make it<br>unique.|
|SaveToDir|POST|Path specification||Directory where the XLS file is saved.|
|SendToPC|POST|0,1|1|(Unix only) If set, causes the exported XLS file to be transferred to<br>the PC using ATE/ZTERM FTP protocol.|
|Launch|POST|0,1|1|If set, the spreadsheet program (typically Excel) is launched to view<br>the spreadsheet.|
|**The following statements applied only to the Perl implementation of PRTXLS.SBX and are no longer applicable.**|||||
|RemoteServer|POST|IP address: port|n/a|Specifies the location of a service to generate the XLS file. (Local<br>generation requires that Perl be available and the WriteExcel add-on<br>library be installed.)|
|IgnoreLocalServer|POST|0,1|0|Set to force use of RemoteServer even if local generation is available.|
|ServerErrorURL|MISC|URL||URL of page to display when an error related to the RemoteServer<br>occurs.|



**Example** 

A-Shell Reference 

Page 532 

```
;PRTXLS.INI - Config file for PRTXLS.SBX
```

```
[DATA]
```

```
IncludeTotals=1
```

```
[REMNANTS]
```

```
IncludeBlankLines=1
```

```
IncludeDupLines=1
```

```
SortBy=1
```

## `[ORIG]` 

```
;BGcolor options: silver,white,red,lime,blue,yellow,magenta,cyan,brown,green,navy,purple,gray,orange
BGcolor=silver
```

```
[POST]
```

```
AppendSeqno=1
```

```
SaveToDir=c:\vm\miame\dsk0\150502
```

```
SendToPC=1
```

```
Launch=1
```

A-Shell Reference 

Page 533 

## **EMAIL REPORT** 

_Added July 2017_ 

This APEX extension module provides a simple way to send the report via email. In the following dialog, the blue arrow shows the Email Report button, the green arrows show the configure button. 

To add this extension to your APEX toolbar, add the following to the apex.cfg[1,7] file: 

```
BUTTON=SBX:PRTMAPI,mail_into_i22b.png,Email Report,0,BAS:PRTMAPI.INI
```

```
BUTTON=SBX:APXTEDIT,control_panel2_i22b.png,Email Options,0,BAS:PRTMAPI.INI
```

Note that the PRTMAPI.SBX and APXTEDIT.SBX modules and the corresponding prtmapi.ini configuration file must be in [7,6], (i.e. %MIAME%\dsk0\007006\). The PNG files shown above are for the standard icons, as illustrated, but can be changed to others according to your preference. Also note that the APXTEDIT.SBX module can be used to edit any ini file, and may therefore be reused for configuring other extensions. 

Provided the local PC has a configured email client, clicking the Email Report button will open up a compose window in that client, with the current report either embedded in, or attached to, the message. The user just has to fill in the address, possibly add a short intro message, and click send, for example: 

Note that in the case where the report is embedded in the message body as shown above, it will be rendered in fixed pitch HTML format (so that the columns remain aligned.) 

## **History** 

- July 2017, A Shell 1612: Function added to A-Shell. 

## **Subtopics** 

- PRTMAPI Config File 

A-Shell Reference 

Page 534 

## **PRTMAPI CONFIG FILE** 

Configurable options for this function may be accessed from the icon to the right of the envelope icon (supposed to be a control panel). This pops up an editing window for the very simple prtmapi.ini file: 

The options are as follows: 

```
AttachFile=#     ; 0 to embed (default), else 1 to attach file
Receipt=0         ; 1 to request receipt
FixedPitch=1     ; 0 for proportional, 1 for fixed pitch (default)
SmallType=0     ; 0 for normal (default), 1 for smaller fixed pitch
To=                  ; optional default To address to plug into email editor
Text=               ; optional text to insert at top of message
```

A-Shell Reference 

Page 535 

## **OTHER TOPICS** 

Following is a collection of APEX miscellaneous topics that are interesting or important, but don't seem to fit elsewhere in the documentation. 

## **Licensing** 

The programs and files needed by APEX are automatically installed on the PC with the underlying software (A-Shell for Windows or ATE). Starting from the date it is installed, APEX will work in unrestricted mode for approximately 30 days. After that free-trial period, APEX reverts to demo mode, which means that it will work so you can see its functionality, but with a rather annoying message saying that it is in demo mode. To enable full APEX operation on your PC, you will need to obtain an APEX license. 

## **Debugging APEX** 

In case of a problem launching the preview from ATE, use the System Message Window to help clarify what is happening. Call up the _A-Shell Developer Control Operations_ dialog with control+shift+double-right-click, then select _System Message Window_ . When the debugging/trace window comes up, repeat the print attempt. It will log the command string that is actually being used, which might then be helpful to test independently, such as from Start..Run, or at least useful in identifying the problem 

## **Settings** 

In ATE, changes to _Preferences_ are immediately stored with the connection profile in the Windows Registry. This means that they are both implemented immediately, and saved for future use; all subsequent operations of the preview window, whether in this session or new sessions, will reflect the latest settings. 

In A-Shell/Windows, changes to _Preferences_ are part of the overall A-Shell settings set which, along with the other options on the various Settings menu dialogs, are stored in the A-Shell settings (.ash) file. However, as with all other settings, changes made in the dialogs are _not_ automatically written to the file. Thus, they only affect the current session. To make them permanent, you must save them via the _File...Save_ option. 

## **Files and Folders** 

When you call up the _Preferences_ menu, the actual words you see are taken from the file sys:sbrmsg.usa. If you see odd codes in place of intelligible options, then your sbrmsg file is not being found. 

Any temporary work files required by APEX are created in the APEX folder. 

A-Shell Reference 

Page 536 

The default location of the APEX folder is This PC\documents\apex (c:\users\<username>\documents\apex), and this folder will be created the first time it is needed. If you don't like this location and/or want it to be placed somewhere else, you may create an environment variable called "APEX" and point it wherever you wish. 

Most of the print preview and display-related aspects of APEX are performed by a program module called 

sftprintpreview_###.dll where "###" is platform and version information. This file lives in the main A-Shell or ATE folder on your PC. 

## **Margins** 

In A-Shell 6.5.1679 of April 2020, there was a significant change to how APEX displays reports that are being sent to virtual printers. In short, we removed the automatic setting of XORIGIN/YORIGIN to 360 twips (1/4 inch) for virtual printers, such as PDF writers, that do not report a built-in physical margin. Adding the margin looks better in the case where you are thinking in terms of what the report would look like on a real printer, but it's misleading in the case of virtual printers like PDFX. Such virtual printers have no inherent margins, but may add them when viewing in the PDF viewer, or when printing. Note that while this is a change in behavior, it only occurs when APEX is being used to preview output of a virtual printer, which is of questionable utility in the first place; in any case the change doesn't affect the actual printed output. 

Unfortunately, this change would cause reports to display differently than the did previously. They may be more correct, but they're also different that what APEX users we're used to. So the behavior was modified again such that that the settings of //XORIGIN,360 and //YORIGIN,360 were added when none was specified—unless the //SETOPTION,NO-AUTO-MARGINS directive specified. This avoids a subtle but possibly unwanted behavior change when updating. Going forward, though, the NO-AUTOMARGINS option is recommended. 

A-Shell Reference 

Page 537 

## **SYSTEM COMMANDS** 

Below is a table listing A-Shell's system commands, with links to extended descriptions for most of them. For information on how the commands are processed, search paths, wildcards and various related topics, see the following Introduction topic. 

## Note that: 

- An asterisk in the "Class" column indicates that the command will accept wildcards. 

- The system commands are all .LIT files which can be found in the SYS: account. 

- Most of the commands will display usage information if invoked with a **/?** switch. 

|**Command**|**Class**|**Function**|
|---|---|---|
|ABOUT|A-Shell|Display information about the current license and environment|
|ADB|A-Shell|Provides a means to debug code running on a target job.|
|AGCMD|A-Shell|Sends aAG_XXXfunction from the dot prompt or a command file|
|APN|A-Shell|Launches APN session.|
|APPEND|AMOS|Appends file together|
|ASHLPD|A-Shell|Invokes A-Shell line printer daemon|
|ASHUPDATE|A-Shell|Retrieves A-Shell updates via the A-Shell menu_Help ... Check for Updates_|



A-Shell Reference 

Page 538 

|**Command**|**Class**|**Function**|
|---|---|---|
|ASTAT|Utility|Abbreviated dynamic job display|
|ATECFG|JB Tech|Configure A-Shell Terminal Emulator (Windows only)|
|ATECTL|A-Shell|Connect ATE "reverse channel" socket|
|ATEUPDATE|A-Shell|Initiates an ATE update|
|ATSYNC|A-Shell|Synchronize host directory with ATE's cache on PC|
|C, CLS|Utility|Clears the screen and resets a few video attributes: exit reduced intensity, disable protected<br>fields, end reverse blinking, turn cursor on.|
|CHAT|A-Shell|(Unix only) Full screen dialog between two users|
|COMPIL|AMOS|ASB 1.4 compiler|
|COMPLP|A-Shell|BASIC_plus_compiler; seeCOMPIL|
|COPY|AMOS *|Copy files|
|CSV2XL|A-Shell|Alternative toPRINT.LITfor generating spreadsheets from CSV input|



A-Shell Reference 

Page 539 

|**Command**|**Class**|**Function**|
|---|---|---|
|CREATE|AMOS|Allocate random data file|
|DATE|AMOS|Display system date|
|DEL|AMOS|Deletes modules from user memory|
|DEVTBL|AMOS|List virtual AMOS devices|
|DIFF|Unix|(Unix only) Compare two source files|
|DING|AMOS|Ring bell|
|DIR|AMOS *|Produce directory of files|
|DO|AMOS|Force command file execution|
|DUMP|AMOS *|Dump file contents in octal or hex|
|ECHO|AMOS|Echoes <text> to screen|
|EL, EP|A-Shell|Deprecated. Was used to launch old A-Shell Editor. UseAPN<br>instead|



A-Shell Reference 

Page 540 

|**Command**|**Class**|**Function**|
|---|---|---|
|ELSE|AMOS|Conditional flow in command file|
|ENDIF|AMOS|Conditional flow in command file|
|ERASE|AMOS *|Erase files|
|ERSATZ|AMOS|Display defined ERSATZ devices|
|EXIT|AMOS|Exit command or DO file|
|EXPLORE|A-Shell|Launches Windows file explorer|
|EZPRT|A-Shell|Print file, using EZ-SPOOL configured menu of printers|
|EZTYP|A-Shell|Display text file with full paging control|
|FLIT||Used internally by A-Shell|
|FIXTRN|AMOS|Function key translation table editing utility|
|FORCE|AMOS|Force keystrokes into another job’s input|



A-Shell Reference 

Page 541 

|**Command**|**Class**|**Function**|
|---|---|---|
|FREE|AMOS|Display amount of free space on specified device|
|FUNCIDX|A-Shell|Generates an XTREE index of functions within a set of files|
|GETENV|A-Shell|Retrieves value of environment variable; use<br>`getenv {var}`|
|GETATEREG|A-Shell|Retrieve ATE configuration settings from the server|
|GOTO|AMOS|Jump to label within command file; seeDO File Statements|
|HEAD|A-Shell *|Display (or copy) first N lines of a text file|
|HOST|A-Shell *|Return to host machine command level|
|IF|AMOS|Conditional flow in command file|
|IMGDSX|A-Shell|Image display utility|
|ISMBLD|AMOS|Build ISAM 1.x file|
|ISMDMP|AMOS|Dump ISAM 1.x file|



A-Shell Reference 

Page 542 

|**Command**|**Class**|**Function**|
|---|---|---|
|ISMUTL|AMOS|Dump/build/examine ISAM-A file|
|JOBALC|AMOS|Display current job name|
|JSTAT|A-Shell|Monitor another job|
|KILL|AMOS|Terminate another process|
|LICENS|A-Shell|Update license information|
|LOAD|AMOS|Load file into memory|
|LOG|AMOS|Change current login account|
|LOGROLL|A-Shell|Rolls over log files|
|LOGON|AMOS|WithMUSER<br>, simulates the logon scheme used under AMOS|
|LOGOFF|AMOS|Log off|
|LOKUTL|A-Shell|Display information about file locks in use|



A-Shell Reference 

Page 543 

|**Command**|**Class**|**Function**|
|---|---|---|
|LOOKUP|AMOS|Test for existence of file; seeDO File Statements|
|MAKE|AMOS|Create a blank sequential file. Will create a file ending in "." if so directed|
|MAP|AMOS|Display user memory|
|MDFUPD|A-Shell|Internal use only: convert help menu to new format during update.|
|MDO|A-Shell|Internal use only: variation ofDO.LIT.|
|MEMORY|AMOS|Change user partition size|
|MMAP|A-Shell *|Display or load list of files to be memory mapped|
|MOVE|A-Shell *|Move a file (Unix only)|
|MUSER|AMOS|With LOGON, simulates the logon scheme used under AMOS|
|OCMPIL|AMOS|AlphaBASIC 1.3 compiler; seeCOMPIL|
|OPRE|Debug plc|AlphaBASIC 1.3 pre-compiler|



A-Shell Reference 

Page 544 

|**Command**|**Class**|**Function**|
|---|---|---|
|ORUN|AMOS|Run AlphaBASIC 1.3 or 1.4 program (same as RUN)|
|PAGE|Debug plc|Page command output|
|PPN|AMOS|Display PPNs on a given device|
|PRE|Debug plc|AlphaBASIC 1.4 pre-compiler|
|PRINT|AMOS *|Sends files (wildcard spec) to a spooler|
|PWD|A-Shell|Display current login directory in native O/S format|
|QUIT|A-Shell|Same asHOST<br>, but terminates PolyShell parent and all siblings|
|QUTL|Debug plc|Queue/XLOCK/FLOCK display utility|
|RENAME|AMOS *|Rename files|
|RUN|AMOS|Run ASB 1.3 or 1.4 program|
|RUNPROF|A-Shell|Generate a run profile log|



A-Shell Reference 

Page 545 

|**Command**|**Class**|**Function**|
|---|---|---|
|SAVE|AMOS|Save module from memory to disk|
|SBCSCH|SBC Inc.|Custom search routine written by Gary Guilbert; see usage with<br>`SBCSCH/?`|
|SEND|AMOS|Send text message to another user|
|SET|AMOS|Set miscellaneous system and job parameters|
|SETATEREG|A-Shell|Set ATE configuration settings|
|SETENV|A-Shell|Sets environment variable; use<br>`SETENV var = value`|
|SHLEXC|A-Shell|Execute/open specified file in Windows|
|SIZE|AMOS|Display size of specified file, in bytes|
|SLEEP|AMOS|Sleep specified number of seconds or fractions of a second|
|SLEEPR|AMOS|Sleep until specified time|
|SORT|AMOS|Sort sequential data file|



A-Shell Reference 

Page 546 

|**Command**|**Class**|**Function**|
|---|---|---|
|SRCCOM|AMOS|Compare two source files|
|SUBMIT|AMOS *|Submit a background task|
|SUBMIT2|A-Shell|Special version ofSUBMIT.LITfor use with Docker|
|SYSACT|AMOS|Maintain PPNs and passwords|
|SYSTAT|AMOS|Display jobs and devices|
|TAIL|A-Shell *|Display (or copy) last N lines of a text file|
|TELNET|JB Tech|Launch A-Shell Terminal Emulator; seeATECFG|
|TELSER|A-Shell|Turn current session into telnet server|
|TIME|AMOS|Display system time|
|TYPE|AMOS|Type sequential text file on screen|
|U|AMOS|Store a command line for later recall|



A-Shell Reference 

Page 547 

|**Command**|**Class**|**Function**|
|---|---|---|
|UPDCUR|A-Shell|Updates current directory from online repository|
|VER|AMOS|Display current A-Shell version|
|VERIFY|AMOS *|Verify files against a DIR file|
|VERSYS|A-Shell|Display detailed version information about a program|
|VIEWASHLOG|A-Shell|Provides a simple way to view ashlog.log|
|VUE|AMOS|Full screen-based text editor|
|WEBRUN|A-Shell *|Runs A-Shell's WEBCACHE system for named program|
|WSET|Debug plc|InstallTRACKER<br>2.0|
|XY|AMOS|ExecuteTCRT<br>code|
|ZTXFER|MS|ZTERM file transfer|
|ZXPWIN|A-Shell|(ZTERM utility) Transfer file to PC and launch app|



A-Shell Reference 

Page 548 

## **INTRODUCTION** 

_Rewritten July 2022_ 

As its name suggests, A-Shell is a _shell_ program: an environment for running programs which sits above the native operating system and provides additional services to facilitate application development and portability. Like other shell programs, A-Shell presents the user with a prompt, frequently referred to herein as the "dot prompt" since the default prompt consists of a period. At this prompt the user can enter commands for standard operations such as changing directories, execute high-level file operations like DIR, COPY, ERASE, PRINT, etc., set parameters for and retrieve information about the environment, track other processes, and of course run, compile and edit programs. Generically these kinds of commands are known as "shell commands;" but to avoid confusion with other levels and types of shell commands, such as Linux or Windows shell commands, they are referred to in this documentation as "A-Shell System Commands" or just "System Commands". 

A-Shell System Commands are actually written in ASB and thus are nearly the same as regular programs except: 

- The file extension is LIT instead of RUN. 

- The default location—i.e., search path—is the SYS: directory, DSK0:[1,4]. 

- Although they can be interactive, they typically accept parameters via command line arguments and switches. 

- They are executed by name without the need for the RUN, e.g. "DIR" instead of "RUN DIR". 

Additional points: 

- Binary Compatibility 

While A-Shell’s system commands are binary compatible across A-Shell platforms, they are not binary compatible with the AMOS LIT commands. In fact, as previously mentioned, A-Shell’s LIT commands are simply ASB programs that have been renamed from .RUN to .LIT, and which have appropriate startup logic to process command line arguments. You can create your own system commands by doing the same thing. 

- Host Command Execution 

While A-Shell's set of System Commands is sufficient for most tasks, and has the advantage of being portable, you can also 

A-Shell Reference 

Page 549 

invoke host operating system (or host shell) commands without leaving A-Shell. This is accomplished via the HOST or SHLEXC commands. For example: 

```
.HOST grep ABCD /vm/logs/a* > alogs.lst &    ; (Unix) execute grep in background
```

```
.host explore      ; (Windows) launch explorer
```

```
.shlexc schedule.xlsx    ; (Windows) launch app registered for xlsx files
```

- Command Scripting 

As with most other shells, A-Shell supports a scripting mechanism to allow command sequences to be combined and stored in files to be executed as a set. See Command Files for more details. 

See the following topics for more details and a complete list of System Commands. 

## **Subtopics** 

- Syntax 

- Wildcards 

- Command Search Path 

- Command Line Editing and Recall 

A-Shell Reference 

Page 550 

## **SYNTAX** 

The general syntax of an A-Shell system command line is: 

## **<command-name> {switches} {arguments} {switches}** 

or, in the case of many commands that operate on files, and/or which accept wildcard filespecs: 

## **<command-name> {<outfile>=} {wildcard list} {switches}** 

<Angular brackets> are used in these syntax examples to indicate a token that _must_ be replaced, while {curly brackets} indicate items that _may_ be replaced (i.e., are optional). So in the example above, {<outfile>=} indicates an optional term; if specified, _<outfile>_ must be replaced with an actual argument, such as myfile.txt. 

The command name (e.g. COPY) is never case sensitive, and is generally given as just the name, without the extension or the directory location. Specifying more than just the name may alter the search path (for which see next topic). If the command takes arguments, they are usually not case sensitive, but this could be up to the discretion of the command implementation. 

Switches are always preceded by a forward slash, and are virtually never case sensitive. In most cases, the switch may be abbreviated to the minimum number of unique characters for that command. For example, many commands support the switch _/query_ , which can usually be abbreviated to _/q_ . In some cases switches may precede the arguments, but the most common position is at the end. 

Most commands support the switch /? to display help for the command. 

The _<outfile=>_ syntax element in the second example above indicates that the output of the command will be sent to that file, rather than to the screen. This is roughly the AMOS equivalent of the Unix technique of redirecting _stdout_ to a file. 

For some commands, like COPY and APPEND, _<outfile=>_ is mandatory. 

Also note that unlike Windows and Unix, output (destination) arguments precede the input (source) file arguments, i.e. they are reversed and require the equal sign as in a program assignment statement. For example: `COPY DEST.LST = SRC.TXT.` 

Command lines are tokenized using both spaces and commas, plus other punctuation characters. For example, the command name itself may be terminated by a space, slash, equal sign, or new line. Arguments for system commands are typically separated by commas, while arguments for DO commands must be separated by spaces. 

A-Shell Reference 

Page 551 

The semicolon marks the beginning of a comment, as in this example: 

```
DIR/V MYAPP.LST=A.RUN,B.RUN,C.RUN ;this is a comment
```

This would create the file myapp.lst containing the directory information including version (/V) of the three specified files. 

Most commands, including all wildcard commands, accept both DevPPN and native filespecs, but the native filespecs must be enclosed in double quotes, for example: 

```
COPY ASHLOG.TXT = "/vm/miame
```

```
TAIL "C:\TEMP\SYSTEM.LOG" /L:5
```

Note that wildcards are not allowed in conjunction with native filespecs. 

A-Shell Reference 

Page 552 

## **WILDCARDS** 

Unlike the Unix shells (Bourne, bash, etc.) which expand command lines containing wildcards into command lines listing all of the matching files before executing the command program, A-Shell leaves wildcard processing to the commands themselves. The main commands that support wildcards are those that potentially operate on multiple files (eg. DIR, COPY, ERASE, RENAME, etc.). They are identified with an asterisk in the "Class" column of the System Commands List. Commands which support wildcards will also accept a comma-delimited list of filespecs, each of which may contain wildcards. Supported wildcards are: 

|**Wildcard **|**Meaning**|
|---|---|
|*|Matches any full or partial token in the specified position. For example, *.RUN matches any filename with a<br>RUN extension. Or AB*.DAT[1,*] would match any filename beginning with AB that has a DAT extension and is<br>in the Project 1. When a portion of a filespec is omitted, it may act like the * wildcard. For example,<br>`DIR ABC`<br>is equivalent to<br>`DIR ABC.*`(rather than<br>`DIR ABC*.*`).|
|?|Matches one character. If multiple ?? are used together, then the combination will match between 1 and the<br>specified number of question mark characters. For example, A?BC.?? Would match any file any file starting<br>with A, followed by any character, followed by BC, and with any one or two character extension. May also be<br>used with the [P,PN], e.g. *.BAS[150,27?]|
|ALL:|Special wildcard that matches all devices. For example, ALL:*.BAS[7,6] would match all files with extension<br>BAS in [7,6] on any device.|
|[]|Matches any PPN. For example, ALL:[]. You may also omit one of the two parts of the PPN, such as [,0]<br>(equivalent to [*,0]).|



## **Examples** 

|**Entered**|**Result**|
|---|---|
|DIR DSK0:*.RUN[]|Look for all programs in DSK0: with a RUN extension, in any PPN|
|.DIR ALL:*.1?[100,*]|Look in all devices, for all programs with an extension of 1, or 1 plus any character, in|



A-Shell Reference 

Page 553 

|**Entered**|**Result**|
|---|---|
||the PPNs made up of 100 with any programmer number|
|COPY ARC:*.SAV = CUST*.DAT|Copy all .DAT files from current directory with names matching CUST* to the ARC:<br>device, preserving the original filename but changing the extension to .SAV|



A-Shell Reference 

Page 554 

## **COMMAND SEARCH PATH** 

When you type anything onto the A-Shell command line, such as "xxxxx," A-Shell searches (a) for "xxxxx" with various extensions, and (b) in various locations. Following is the location and filename extension for which A-Shell searches, and the order in which it does so. 

|**Search Target**|**Results and Comments**|
|---|---|
|xxxxx.ext|Applies only if an explicit extension included on the command line|
|sysdev:xxxxx.LIT[1,4]|Special mounted system directory defined by -mntsys switch (if<br>applicable)|
|DSK0:xxxxx.LIT[1,4]|LIT command in the standard system directory (aka SYS:)|
|xxxxx.LIT[p,pn]|LIT command in current directory [p,pn]|
|xxxxx.LIT[p,0]|LIT command in library directory associated with current directory|
|sysdev:xxxxx.CMD[2,2]|Special mounted command directory defined by -mntsys switch (if<br>applicable)|
|DSK0:xxxxx.CMD[2,2]|CMD file in standard command file location (aka CMD:)|
|xxxxx.CMD[p,pn]|CMD file in current directory|
|xxxxx.CMD[p,0]|CMD file in library directory associated with current cirectory|



A-Shell Reference 

Page 555 

|**Search Target**|**Results and Comments**|
|---|---|
|||
|sysdev:xxxxx.DO[2,2]|Special mounted command directory defined by -mntsys switch (if<br>applicable)|
|DSK0:xxxxx.DO[2,2]|DO file in standard command file location (aka CMD:)|
|xxxxx.DO[p,pn]|DO file in current directory|
|xxxxx.DO[p,0]|DO file in library directory associated with current directory|



A-Shell Reference 

Page 556 

## **COMMAND LINE EDITING AND RECALL** 

Given the syntactic complexity and advanced typing skills involved with some of these command lines, you are likely to commit syntax errors or simply tire of retyping commands that you already typed just a few moments previously. At that point you will appreciate the ability to recall previous command lines and edit them. To cycle backwards through the last 25 command lines, hit CTRL+R (typically the same as the PAGE-UP key). To cycle forwards through them, hit CTRL+T (PAGE-DOWN). Once you find the previously-typed command line, you can re-execute it just by hitting ENTER. If instead of just re-executing it as is, you prefer to edit it first, you can do so using the following keystrokes: 

|**Primary **|**Alternate**|**Editing Action**|
|---|---|---|
|ctrl+a||Move cursor to previous word|
|ctrl+c||Abort the current line (start a new one).|
|ctrl+d|delete|Delete the character under the cursor|
|ctrl+f|insert|Insert a space under the cursor|
|ctrl+h|LeftArrow|Move cursor to the left|
|ctrl+l|RightArrow|Move cursor to the right|
|ctrl+n||Move cursor to the end of the line|
|ctrl+q||Toggle insert/replace mode|
|ctrl+r|PageUp|Cycle through the previously typed ten command lines.|
|ctrl+t|PageDown|Cycle forward through the previously typed ten command lines after<br>having usedCTRL+Rto go backwards.|
|ctrl+u||Move cursor to start of command line|
|ctrl+w||Move cursor to next word|
|ctrl+y||Delete line to the right of the cursor|



**See Also** 

A-Shell Reference 

Page 557 

• **U** (system command) 

A-Shell Reference 

Page 558 

## **ABOUT** 

## **ABOUT {switches}** 

ABOUT displays information about your A-Shell software license and environment. 

## **Switches** 

|**Switch **|**Function**|
|---|---|
|/L|Causes the output to written to the file about.lst instead of the screen.|
|/R|Forces a rebuild/recount of jobtbl.sys before displaying the information.|
|/?|Writes switch listing and usage info to the screen.|



## **Notes** 

- Details about the software license are also available from, and may be changed with, the LICENS command. For 

- A-Shell/Windows, similar information is available for viewing (but not changing) from the _Help...About_ menu. 

- If you enter new license data and then immediately run ABOUT, it is possible that ABOUT will return incorrect license 

- information—i.e., info that doesn't agree with the license you just entered. To correct, simply exit A-Shell, reload, and rerun ABOUT. 

## **Example** 

```
A-Shell Version:           7.0.1772.1/32
```

```
  Release Date:            07-May-25
```

A-Shell Reference 

Page 559 

```
Licensed to:               Smith Electronics
  Serial #                 4348
  A-Shell Key:             TLWSPPR-RWKL8E-XUAJBD-F7JLB47
  Nodes Licensed:          20
  Nodes / Jobs in Use:     1 / 1
  License Options:         ATE ATS PDFX APEX AXL ASQL
  Maintenance Expiration:  06-Jan-27
INI File:                  c:\ashell\latest\miame.ini
ATE Licensing:             Server
Host Operating System:     Win10/64
  Release:                 26100
  Product:                 HOME_PREMIUM (&h03)
  Locale:                  en-US
JOBTBL.SYS:                C:\Ashell\Latest\jobtbl.sys
  Created:                 09-May-25 09:44 (50 Records)
```

## **Comments** 

For ATE, the ABOUT display clarifies that the version it is displaying at the top of the About box applies to ATE and not to A-Shell on the server. The latter version shows in the lower part of the box. The display also indicates which ASHNET library is being used, when applicable. 

## **History** 

## 2024 February: Minor adjustments to screen output info and format 

A-Shell Reference 

Page 560 

- 2023 September, A Shell 1742, ABOUT.LIT 2.2(111): ABOUT now displays  a few details about the OS, including the locale. 

A-Shell Reference 

Page 561 

## **ADB** 

_Written August 2025_ 

## **ADB {parameters} {switches}** 

ADB, the A-Shell DeBugger, provides a means to interactively debug compiled programs, including dynamically setting breakpoints, single stepping, querying variables, etc.. 

## **Parameters** 

_prog.ext_ 

Optional name and extension of program to debug. This is typically a RUN file, it could be an SBX or LIT. 

## **Switches** 

/LSX{DIR}=directory 

Specifies the directory (DevPPN or ersatz notation) where LSX files matching the program(s) to be debugged can be found. 

/TARGET{JOB}=jobnam 

If specified, identifies an existing target job where the code to be debugged is running, or will be run. If not specified, a slave job (named ADB### where ### is the current job #) will be launched. Under Windows, the slave job will appear on the toolbar and can be made visible in the normal way. Under UNIX, it runs in background and remains invisible. 

## **Operation** 

On startup, ADB performs the following steps: 

- Unless the /TARGETJOB switch is specified, a slave process is launched and logged in to the same directory that ADB is 

- running from. 

· If prog.ext is specified, the corresponding LSX file is loaded from the directory specified by the /LSX switch. If not specified or the file isn't found, you will be prompted for an alternate location. Note that for full functionality, the LSX file should be created using the /SYM switch to add the symbol table. 

A-Shell Reference 

Page 562 

- A listening socket is opened for the target job to connect to. 

- An inter-job communication (IJC) command is sent to the target job informing it of our listening socket and asking it to 

- connect back to us to permit debugging. 

- ADB then waits for the target job to respond. This may take a few seconds and requires that the target job be running at 

- least A-Shell version 7.0.1778. 

- Once communication is established, ADB goes into interactive mode 

In interactive mode, ADB displays a prompt ("ADB >") and waits for and processes a variety of keyboard commands. While waiting, it may receive messages from the remote job, displaying them spontaneously. Initially, it will looking something like this: 

```
ADB version 1.0(106) A-Shell DeBugger
Launching task ADB1 ...
Message sent to ADB1 on job 2  (JACKX1:2B)
Waiting for ACK .... [ACK]
Waiting for target to connect [^C to abort] ...
Connection Accepted!
    Cmd/Rep: INIT/ACK                  Status: MON TIW / Running
    Msg:     Init Debugging
Debugging
```

```
ADB >
```

Use HELP {command} to display the list of available commands, or details on a specific command. See the following walkthroughs to get a better sense of how to use them. 

A-Shell Reference 

Page 563 

## **Comments** 

ADB borrows liberally from aspects of the GNU command line debugger gdb, including naming convention, command structure, etc. Obviously that is only helpful to those already familiar with it in the Linux environment. However, unlike gdb and most other debuggers, ADB does not rely on symbols (source code and variable information) being embedded in the target program via a special debug compilation. Instead, it relies on local access to the external symbol files (LSX) created by `COMPIL /LF /SYM` to navigate the object code being debugged. That may seem like a difference without a distinction since in both cases special compiler features need to be employed, but the advantage of the ADB approach is that the symbol files, although needing to be stored and accessible to ADB, are not part of and do not have any effect on the RUN code. This eliminates (a) potential issues arising from differences between the debug-mode and release-mode code, and (b) the hassle of having to toggle between debug and release versions of the object code. 

A second significant difference, at least compared to the command line text mode implementation of gdb is that ADB operates in a separate foreground process from the process being debugged, eliminating complications that otherwise arise when both the debugger and the target process being debugged share the same display. Although this typically requires that you have two sessions (two windows or two ATE connections) open and accessible at your workstation, it offers several advantages, including: 

- The ability to debug a process that you can’t see and don’t otherwise have physical control over or access to, provided that it 

- is connected to the same server and hasn’t blocked TCP connections or signals. 

- The ability to initiate debugging on a target that is already mid-program. This is potentially useful for debugging processes 

- that have gotten stuck in an unknown state that you don’t know how to reproduce. 

- The ability to terminate debugging and detach from the target process, allowing it to continue unaffected by the operation. 

- This assumes use of the /TARGETJOB switch to debug an existing process; otherwise the target process launched by ADB is shut down automatically when ADB exits. 

- Elimination of all display conflicts between the two processes. In fact, the target can include multiple GUI windows even 

- though ADB itself runs in text mode. 

Here’s a simple schematic of how the pieces fit together: 

The following "walkthrough" topics provide extended examples of ADB in action: 

A-Shell Reference 

Page 564 

- #1: Target Already Running 

- #2: Target at Command Level 

- #3: Debugging an SBX 

## **See Also** 

- COMPIL switches /LF and /SYM 

## **History** 

- 2025 August, A Shell 7.0.1778:  ADB added to A-Shell. 

A-Shell Reference 

Page 565 

## **ADB INTERACTIVE COMMANDS** 

Once started, an ADB debugging session is controlled interactively by means of the commands listed below. See the following _Walkthrough_ topics for more detailed information and contextual examples of their usage. 

|**Command**|**Description**|
|---|---|
|**Breakpoint Commands**||
|B{REAK} {program.ext}{:location}|set breakpoint|
|I{NFO} BREAK|list breakpoints|
|D(ELETE) #|selete breakpoint #|
|**Run Commands**||
|R{UN} {cmdlin}|force debuggee to run cmdlin (at dot prompt only)|
|F{ORCE} text|force text (+CR) into target input buffer|
|C{ONT}|continue (run) to next breakpoint|
|S{TEP}|execute one ASB instruction (step into calls)|
|N(EXT}|execute one ASB instruction (step over calls)|



A-Shell Reference 

Page 566 

|**Command**|**Description**|
|---|---|
|||
|A(BORT)|send ^C to debuggee|
|**Information/Display Commands**||
|L{IST} {program.ext}{:location}|list source code|
|P{RINT} variable|display value of variable|
|I{NFO}|display status of debuggee|
|B{ACKTRACE} or BT|show call stack (at breakpoint)|
|**Miscellaneous Commands**||
|WIDTH ###|change display width to ### columns|
|QUIT|quit debugging (debuggee continues running)|
|<Enter> by itself|will typically default to prior command (useful for<br>repetitive commands like STEP, NEXT and LIST +)|



A-Shell Reference 

Page 567 

A-Shell Reference 

Page 568 

## **ADB WALKTHROUGH #1** 

_Written August 2025_ 

Following is a walkthrough of a debugging session, hopefully providing a feel for how it works while also pointing out several tips and other details that might otherwise go unnoticed in the help references. 

We’ll start the debugging session with a target job TSKAAC, specifying the ersatz location ADDS: for the LSX directory: 

```
.ADB /TARGETJOB=TSKAAC/LSXDIR=ADDS:
```

The target job in this case is running the program EXLIB:ADDSVUE[908,81], currently sitting at an input prompt. Assuming the target job is not blocking signals and/or TCP connections and is at least 7.0.1778, it should acknowledge the debugging request within a few seconds, after which we’ll see the following: 

```
ADB version 1.0(106) Remote debugger
```

```
Message sent to TSKAAC on job 3  (JACKX1:3E)
Waiting for ACK .... [ACK]
Waiting for target to connect [^C to abort] ...
Connection Accepted!
```

```
     Cmd/Rep: INIT/ACK            Status: TIW / Running
     Loc:     ADDSVUE.RUN:009c33    Level: 0
     Msg:     Init Debugging
Debugging
```

```
ADB >
```

The indented block, similar to what we can request at any time with the INFO command, provides basic information about the state of the target job, including the name of the program it is running (ADDSVUE.RUN). 

A-Shell Reference 

Page 569 

At this point, the debugging session consists of commands entered at the ADB prompt. You can display the available commands using the HELP command as shown here: 

```
ADB > HELP
```

```
Breakpoint commands:
```

```
    B{REAK} {program.ext}{:location} - set breakpoint
```

```
    I{NFO} BREAK - list breakpoints
```

```
    D(ELETE) # - delete breakpoint #
```

```
Run commands:
```

```
    R{UN} cmdlin - force debuggee to run cmdlin (at dot prompt only
```

```
    F{ORCE} text - force text (+CR) into target input buffer
```

```
    C{ONT} - continue (run) to next breakpoint
```

```
    S{TEP} - execute one ASB instruction (step into calls)
```

```
    N(EXT} - execute one ASB instruction (step over calls)
```

```
    A(BORT) - send ^C to debuggee
```

```
Information/Display commands:
```

```
    L{IST} {program.ext}{:location} - list source code
```

```
    P{RINT} variable - display value of variable
```

```
    I{NFO} - display status of debuggee
```

```
    B{ACKTRACE} - show call stack (at breakpoint)
```

```
    BT - same as BACKTRACE
```

```
Misc commands:
```

A-Shell Reference 

Page 570 

```
    WIDTH ### - change display width
```

```
    QUIT - quit debugging (debuggee continues running)
```

ENTER by itself will typically default to prior command; this is useful for repetitive commands like STEP, NEXT and LIST +. 

Typically, you would start with the LIST command to look at the source code in the vicinity of where the program counter is: `ADB >` **`LIST`** 

```
Loading LSX info ...  522 labels
Loading SYM info ...  2239 variables
Resolving local variable scope ...  807
ADDSVUE.RUN ...
```

```
009b9e      endif
009b9e
009b9e      totwidth = Fn'ADDS'Setup'Display'Record(ds, fnformatter$="Fn'<type>'
UnPack$")
009bbe
009bbe      if not dlgview then                     ! [119] silence output in dl
gview mode
009bc5          ? "Total width of all display fields: ";totwidth
009bf7      endif
009bf7
009bf7      if Interactive then     ! [113]
```

A-Shell Reference 

Page 571 

```
009bfd          a = 0
009c04          input "Enter 1 to display structure info ... ",a
009c34          if a then
009c3a              call Fn'ADDS'View'Structures(ds)
009c41          endif
009c41      endif
009c41
009c41      xcall SIZE, fspec'data$, filebytes
009c4d      if filebytes < 1 then
ADB >
```

Note the messages at the top about loading the LSX / SYM info. This will happen whenever a command requires symbol information and the target program has changed. Multiple LSX / SYM files can be loaded during a single debugging session, as needed when debugging both a program and SBX modules it calls, or a series of programs chained to. Also note that the current location will be highlighted (009c04 above) if included in the list. 

At this point we could hit ENTER to page forward, or LIST a specific location, such as the function referenced at location 009c3a above, e.g. LIST Fn’ADDS’View’Structures(). 

Aside from specifying explicit locations to LIST, you can also use the minus key ( **–** ) to page backwards and the plus key ( **+** ) to page forwards. And as with most ADB commands, just hitting ENTER will repeat the prior command, so you can continue in either direction by just hitting ENTER. 

Note that labels, functions and variables are all case sensitive and that functions/procedures should be specified with a pair of empty parens (), although they will be assumed to be labels if starting with Fn. 

To minimize the amount of line wrapping, consider using the WIDTH command to increase the number of characters displayed per line. 

A-Shell Reference 

Page 572 

We could also just set a breakpoint at the start of that function, like this: 

## `ADB >` **`BREAK Fn’ADDS’View’Structures()`** 

```
Breakpoint set - use INFO BREAK to list breakpoints
```

Now, since the target program is at an INPUT statement, we can either switch to that session (if we have access), or we can force a response of “1” (to view the structure) using the FORCE command: 

## `ADB >` **`FORCE 1`** 

That should cause the target program to call the Fn’ADDS’View’Structures() function and run into our breakpoint, at which point we’ll see: 

```
Breakpoint @ ADDSVUE.RUN:003db4
003db4      Fields = fn'adds'get'layout(ds)
```

```
ADB >
```

```
     Cmd/Rep: INFO/ACK                  Status: RUN / At Break
     Loc:     ADDSVUE.RUN:003db4        Level: 2
```

```
ADB >
```

```
Breakpoint @ ADDSVUE.RUN:0039ab
0039ab          map2 flddef'hdr$,s, 80, " F#  Struct or Field Name      Type   Size  Subs   :”
```

```
     Cmd/Rep: INFO/ACK            Status: RUN / At Break
     Loc:     ADDSVUE.RUN:0039ab    Level: 2
```

```
ADB >
```

A-Shell Reference 

Page 573 

When a breakpoint is hit, the target will report its location, allowing ADB to display the source line. For a function, that will typically be the first executable statement within the function. To get a better sense of where we are, we can use the LIST command again: 

```
ADB > LIST 3DB4
ADDSVUE.RUN ...
003c2b          map2 rspec$,s,100
003c2b          map2 rch,b,2
003c2b          map2 flddef'hdr$,s, 80, " F#  Struct or Field Name      Type   S
ize  Subs     Pos  Deftype"
003c72          map2 flddef'mask$,s,80, "###. \----------Name------------\ \\  #
###  \-----\ ####  \-------------------\"
003cc7          map2 dspflddef'hdr$,s, 130,"D#   F# Struct or Field Name
      Formatter                     DspWid  SQL-Flags   Decs  SQL Type"   ! [108
```

```
]
003d37          map2 dspflddef'mask$,s,130,"##. ### \----------Name-------------
---\  \----------------------------\  ####  \--------\  ####  \-----------------
--\"  ! [108]
003db4          map2 fno,i,2
003db4          map2 dfno,i,2
003db4          map2 fldname$,S,64
003db4
```

A-Shell Reference 

Page 574 

```
003db4      Fields = fn'adds'get'layout(ds)
003dc0      if Fields < 0 then
003dcb          .fn = "Error retrieving layout of record struct"
003dfa          exitfunction
```

It may be hard to get your bearings from the limited amount of code that can display in one full screen, particularly when lines are wrapped as in the above example. The WIDTH command may help address that issue. Ideally you would have the LSX file open in an editor in another window, but you can also reposition the window into the code using some combination of LIST +, LIST -, or LIST xxxx, in this case to confirm that we really are at the start of the target function Fn'ADDS'View'Structures()... 

```
ADB > LIST 3CC7
ADDSVUE.RUN ...
003c0d
003c0d  Function Fn'ADDS'View'Structures(ds as DYNSTRUCT:inputonly) as i4
003c2b
003c2b      map1 locals
003c2b          map2 rspec$,s,100
003c2b          map2 rch,b,2
...
```

Note that while not theoretically necessary, in some cases a LIST command with no location specified may be ambiguous, in which case adding the location counter eliminates all confusion. 

A-Shell Reference 

Page 575 

Also note that it is easy to get confused or out of sync given the semi-independence of the target program from ADB (with a mixture of synchronous and asynchronous communication between the two processes). A good go-to is to use the INFO command to re-sync and clarify the state of the target. 

## At this point you may want to single-step through the function: 

## `ADB > STEP` 

```
00433b      dsname$ = Fn'Dynst'Name'From'Instance$(ds)
```

The STEP command executes one instruction and then displays the next source line. In the above case, it executed the call to fn'adds'get'layout(ds) at location 3db4, stopping at the first instruction inside that function, which is another function call. Since we are now nested inside one or more functions, we might want to use the BACKTRACE (or BT) command to get a sense of our call stack: 

```
ADB > BT
```

```
[Call stack:]
```

```
[1] 00e315              call Fn'ADDS'View'Structures(ds)
```

```
[2] 003db4      Fields = fn'adds'get'layout(ds)
[3] 00433b      dsname$ = Fn'Dynst'Name'From'Instance$(ds)
```

```
[End of stack trace]
```

The above stack trace shows that from the top level we called the function Fn’ADDS’View’Structures(), which then called fn’adds’get’layout(), which is about to call Fn’Dynst’Nsme’From’Instance$(). If we aren’t interested in stepping into that function, we can use the NEXT command in place of STEP to proceed to the next instruction in the function we are currently in: 

## `ADB >` **`NEXT`** 

```
004094      debug.print (99,"adds") "layout",dsname$,DynName$
```

```
ADB >
```

A-Shell Reference 

Page 576 

```
0040ee      if dsname$ # DynName$ then
```

```
ADB >
```

The NEXT command executed the function call and then stopped at the next line in the current function, at location 004094. We then hit ENTER (repeating another NEXT command), stopping at 0040ee. At this point, let’s check the values of those two variables: 

## **`ADB > PRINT dsname$`** 

```
  Cmd/Rep: PRINT/ACK
```

```
  Vartyp:  S,LOCAL (&h002101)
  Size:     64
  Value:   STQ_BXHI
```

## **`ADB > PRINT DynName$`** 

```
  Cmd/Rep: PRINT/ACK
```

```
  Vartyp:  S,STATIC (&h002201)
  Size:     64
  Value:   STQ_BXHI
```

They both have the same value (STQ_BXHI) , so the body of the IF statement will be skipped. 

Assuming that’s all we’re interested in as far as this function is concerned, we can use the CONT command to proceed to the next breakpoint: 

```
ADB > CONT
```

```
    Cmd/Rep: CONT/ACK            Status: TIW / Running
```

A-Shell Reference 

Page 577 

```
    Loc:     ADDSVUE.RUN:003e59    Level: 2
ADB > LIST
003e4b      close #rch
003e4f      xcall EZTYP, rspec$
003e59
003e59  EndFunction
...
```

Note that the job status reported back from the NEXT command is “TIW / Running” (Terminal Input Wait), indicating that the program stopped at an input prompt before hitting a breakpoint (so it is technically "running", as opposed to waiting on ADB). And the LIST command shows us that the last instruction executed was a call to EZTYP. So the target is currently waiting for the user to exit from the EZTYP display. Some things we might do at this point: 

- If we have keyboard access to the target session, we could just ESC and proceed. 

- `>` **`FORCE ^[`** to force an ESC to the target to make it exit from EZTYP. 

- `>` **`INFO BREAK`** to display the breakpoints 

```
[Breakpoint list:]
```

```
    1) ADDSVUE.RUN:003db4
```

```
[End of breakpoint list]
```

- `>` **`DELETE 1`** to delete breakpoint #1 

```
Cmd/Rep: CLEAR/ACK           Status: TIW / Running
```

```
    Loc:     ADDSVUE.RUN:00e750    Level: 1
```

A-Shell Reference 

Page 578 

```
    Msg:     1 breakpoint(s) deleted
```

Or we can just terminate the debugging session with the QUIT command: 

```
ADB > QUIT
     Cmd/Rep: QUIT/ACK              Status: TIW / Running
     Loc:     ADDSVUE.RUN:00e750    Level: 1
```

```
Decoupling from debug session
```

Since the target job was already running when we launched ADB with the /TARGETJOB switch to connect to it, the QUIT command will completely disengage, leaving it running unaffected by the debugging activities. Although ADB can interrupt the target program flow, it can't change variables or execution logic, so shouldn't have any effect on the program outcome. 

A-Shell Reference 

Page 579 

## **ADB WALKTHROUGH #2** 

_Written August 2025_ 

Walkthrough #1 involved a target program that was already running before the debug session was started. In some cases that might not be practical; for example, if the issue you want to debug occurs before the program stops for user input. Or you just want to debug a program without having to manually launch a separate task to run it first. 

The context for this walkthrough then is that we want to debug the program EXLIB:FOREACH[908,53] starting from the command prompt. 

```
.LOG EXLIB:908,53
```

```
.ADB FOREACH.RUN
```

```
ADB version 1.0(106) A-Shell DeBugger
```

```
Launching task ADB2 ...
```

```
Message sent to ADB2 on job 3  (JACKX1:3C)
Waiting for ACK .... [ACK]
Waiting for target to connect [^C to abort] ...
```

```
Connection Accepted!
```

```
     Cmd/Rep: INIT/ACK                  Status: MON TIW / Running
     Msg:     Init Debugging
Loading LSX info ...  14 labels
Loading SYM info ...  32 variables
Resolving local variable scope ...  11
```

A-Shell Reference 

Page 580 

```
Debugging
```

```
ADB >
```

Note that we started the session by logging to the location where the both the RUN and LSX files were and thus there was no need for an explicit directory for the RUN file or an /LSXDIR switch. Other things to note about the above which differ from Walkthough #1 are that because there was no /TARGETJOB specified, ADB launched its own slave job ("ADB2" in this example) and logged in into our current directory. The FOREACH.LSX file has been loaded, providing a context for subsequent commands, but FOREACH.RUN is not yet running. 

We can tell it is not yet running a program as there is no Location (Loc) information in the indented status. We can still set a breakpoint in the desired target program by specifying its name explicitly as shown below.The Status "MON" indicates "monitor level", aka "at the command prompt", and "Running" indicates that it is currently running in the sense that it has not been stopped by ADB via a breakpoint. 

## `ADB >` **`BREAK`** 

```
Set Breakpoint at next instruction: FOREACH.RUN:000024
```

```
Breakpoint set - use INFO BREAK to list breakpoints
```

## `ADB >` **`INFO BREAK`** 

```
[Breakpoint list:]
```

```
      1) FOREACH.RUN:000024
```

```
[End of breakpoint list]
```

```
ADB >
```

Note that the BREAK command with no arguments defaults to the currently loaded program (FOREACH.RUN, even though it's not actually running yet), and to the next instruction after the current position. If we really wanted to set a breakpoint at the very first instruction, we'd need to use `BREAK 0` .) 

A-Shell Reference 

Page 581 

We can use the LIST command (again, without any arguments for the current location) to see just where our breakpoint is: 

```
ADB > LIST
```

```
FOREACH.RUN ...
```

```
000000
```

```
000000      ++include ashinc:ashell.def
```

```
! SOS70:ASHELL.DEF[907,16] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< <1_1>
```

```
000000
```

```
000000
```

```
000000  ++ifnmap VERSYS_ASHELL_DEF
```

```
000000
```

```
000000  map1 VERSYS_ASHELL_DEF,s,40,">>@VERSYS(1)->>ashell.def[317]"
```

```
000024
000024  map1 CR_LF$,s,2,chr(13)+chr(10)     ! [251]
000031
000031      define FS_DRV = 1       ! MX_FSPEC flags (1)
```

```
ADB >
```

A-Shell Reference 

Page 582 

Note that LIST normally shows the statement at the current location—i.e. the next statement to execute, in bold. But in a case where there are multiple source lines for the same location, they all show bold as seen above. 

Now we can start the program running using the RUN command: 

```
ADB > RUN
```

```
Breakpoint @ FOREACH.RUN:000024
000024  map1 CR_LF$,s,2,chr(13)+chr(10)     ! [251]
```

```
ADB >
     Cmd/Rep: INFO/ACK                  Status: RUN / At Break
     Loc:     FOREACH.RUN:000024        Level: 1
```

```
ADB >
```

Note that RUN assumes we are talking about the currently loaded program (FOREACH.RUN). If you wanted to start with a different program, perhaps one that would eventually CHAIN to or XCALL the program we are debugging, we would use FORCE with an explicit command line. You can however add command line arguments to the RUN command if applicable (e.g. `RUN ARG1 /SWITCH2` ). 

The response to the RUN command shows that we've hit the breakpoint, displaying the next instruction. MAP statements with initializers are effectively a combination of a variable definition and an assignment statement. We can then use a series of NEXT commands (first one explicit, the others implicit, i.e. just hitting ENTER) to step through the MAP statements and ++INCLUDE'd functions until we get to a point of interest: 

## `ADB >` **`NEXT`** 

```
000031  map1 AG_TERM,S,1,chr(127)         ! [201] terminator
```

A-Shell Reference 

Page 583 

```
ADB >
```

```
000039  private dimx test(5), x, 1
```

## `ADB >` 

```
000045  private dimx $capitals,ordmap(varstr;varstr)
```

```
ADB >
```

```
000051  Procedure Init'Module'Scope'Collection()
```

## `ADB >` 

```
0001b4  Procedure Test'Module'Scope'Collection()
```

## `ADB >` 

```
0002cd  Procedure Test'Static'Local'Collection(country$ as s0,cap$ as s0)
```

```
ADB >
```

```
000529  Procedure Clear'Module'Scope'Collection()
```

## `ADB >` 

```
0006bc      ? tab(-1,0);"Test iteration and scope for collections"
```

```
ADB >
```

```
...
```

```
ADB >
```

```
0008af      dimx $capitals,ordmap(varstr;varstr)
```

## `ADB >` 

```
0008bb      $capitals("California")  = "Sacramento"
```

```
ADB >
```

A-Shell Reference 

Page 584 

Note that when stepping through MAP statements, the only ones that you’ll see are those that have some kind of runtime action such as an initial value. DIMX statements will also show up because there is a runtime action, initializing the array or collection. Procedure and Function definitions will also show up, since the runtime interpreter has to acknowledge and skip over them when they appear in-line. 

The complications in locating the logical start of the program could all have been bypassed if there was a standard label (e.g. START: or BEGIN: or MAIN: ) marking the logical beginning of the main program, in which case we could have specified that in the BREAK command (e.g. BREAK FORACH.RUN,MAIN: ).. 

Now that the target program is running and under ADB control, we can proceed as we would in the case covered in the first walkthrough. To wrap this example up, let’s illustrate another PRINT command: 

```
ADB > PRINT $capitals("California")
```

```
  Cmd/Rep: PRINT/ACK
```

```
  Vartyp:  S(),DIMX-AUTOEX (&h00a0e1)
```

```
  Size:     10
```

```
  Value:   Sacramento
```

The PRINT command works for simple scalar variables as well as arrays and collections, but only if the subscripts are literal. So PRINT ARY(3) works, but PRINT ARY(var) would not. Variables with multiple instances (i.e. local variables) will be selected based on the current location. Some complex variables, like iterators ($$i) or MLIST tokens are not supported by the PRINT. 

When done debugging, use the QUIT command to terminate the session. Unlike the case in Walkthough #1 where the target job was already running before we started debugging, in this case, since the target slave job was launched by ADB, it will be shut down by the QUIT command. 

A-Shell Reference 

Page 585 

_Written August 2025_ 

## **ADB WALKTHOUGH #3** 

In this walkthrough we’ll debug the subroutine INIX.SBX as called by a test program TSTINX. Both modules, along with their respective LSX files are in SOSLIB:[907,26]. As in the second walkthrough, we’ll start by logging to the location where the target program will be run from and launch the target session directly within ADB rather than connecting to an existing session, as in the first walkthrough. Note however that the program we specify on the ADB command line is actually an SBX that resides in BAS:, not in this directory. What matters for debugging is that the corresponding LSX can be found by ADB, and that the SBX can be found by the normal runtime search. 

## `.ADB` **`INIX.SBX`** 

```
ADB version 1.0(106) A-Shell debugger
```

```
Launching task ADB1 ...
```

```
Message sent to ADB1 on job 2  (JACKX1:2D)
```

```
Waiting for ACK .... [ACK]
Waiting for target to connect [^C to abort] ...
```

```
Connection Accepted!
```

```
     Cmd/Rep: INIT/ACK                  Status: MON TIW / Running
     Msg:     Init Debugging
```

```
Loading LSX info ...  94 labels
Loading SYM info ...  301 variables
Resolving local variable scope ...  110
```

```
Debugging
```

```
ADB >
```

A-Shell Reference 

Page 586 

In this case we’ll assume that INIX.SBX does have a convenient SBXMAIN: label at the logical start of its main body, so we can set a breakpoint there without having to do a lot of single-stepping or hunting around in the LSX to find it… 

## `ADB >` **`BREAK SBXMAIN:`** 

```
Breakpoint set - use INFO BREAK to list breakpoints
```

```
ADB > INFO BREAK
```

```
[Breakpoint list:]
```

```
      1) INIX.SBX:000417
```

```
[End of breakpoint list]
```

```
ADB >
```

Note that, as in the prior walkthrough, we’re setting a breakpoint in a module that isn’t yet running. 

Now we can start the test program (TSTINX) running. But since ADB has no idea about TSTINX yet, we’ll use the FORCE command instead of the RUN command to allow us to force an arbitrary command line. Furthermore, from experience we know that TSTINX prompts the user for a couple of questions before it calls INIX.SBX. Here’s what it looks like if we RUN TSTINX directly… 

```
TSTINX.BAS - Test INIX.SBX
```

```
Choose data source: 1) Small File, 2) Large (you specify): 1
```

```
Mode: 1)Create TEST.INI, 2)Read, 3)Del Item, 4)Del Sect, 5)Add Item : 2
```

```
Reading TEST.INI...
```

So we want to force the responses (1<CR>,2<CR>) to the program to get it to XCALL INIX so we can debug it… 

A-Shell Reference 

Page 587 

```
ADB > FORCE RUN TSTINX
```

```
     Cmd/Rep: INFO/ACK                  Status: TIW / Running
     Loc:     TSTINX.RUN:0000b9         Level: 1
```

```
ADB > FORCE 1^M2
Breakpoint @ INIX.SBX:000417
000417          on error goto TRAP
ADB >
     Cmd/Rep: INFO/ACK                  Status: RUN / At Break
     Loc:     INIX.SBX:000417           Level: 3
ADB >
```

The breakpoint message indicates the location of the breakpoint and displays the next source line. We can use the BACKTRACE (BT) command will show us how we got here… 

```
ADB > BT
[Call stack:]
Loading LSX info ...  6 labels
Loading SYM info ...  323 variables
Resolving local variable scope ...  110
[1] 00023f      on TMODE call TCREATE,TREAD,TDELITEM,TDELSECT,TADDITEM
[2] 00047b          xcall INIX,INIFILE,0,SECTION(I),ITEM(I),TVALUE
[3] 000417      on error GOTO TRAP
[End of stack trace]
```

The stack trace above doesn’t indicate the modules for each location; it’s assumed you can figure that out by some knowledge of the context. In this case, the session was initiated by RUN TSTINX, so we can assume that the first entries, up until the XCALL INIX, are all locations in TSTINX. From that point on, they must be in INIX.SBX since that’s where we hit the breakpoint. We could confirm that using the LIST command with an explicit location, e.g. LIST TSTINX.RUN:23F 

Now that we’ve hit our breakpoint, let’s use LIST (no arguments for current context) to get our bearings… 

A-Shell Reference 

Page 588 

```
ADB > LIST
INIX.SBX ...
000417          MAP2 VALUEX,S,2000
000417          MAP2 DEFAULTX,S,2000
000417
000417  MAP1 MISC
000417      MAP2 RC,B,1
000417      MAP2 AGPARMS,S,3000       ! [511]
000417
000417
000417  SBXMAIN:
000417          on error GOTO TRAP
00041a
00041a      xgetargs INIFILE,TYPEX,SECTION,IDENT,VALUEX,DEFAULTX
000429
000429      IF TYPEX and 32 THEN
000433          IF Fn'Sync'SBX'to'ATE("INIX.SBX") < 0 THEN
00044c              VALUEX = "-1"
000454              xputarg @VALUEX     ! [522] 5, VALUEX
00045c              return(VALUEX)
000460              end
000461          ENDIF
ADB >
```

Single step past the XGETARGS and then query the IDENT parameter, the fourth parameter passed in the XCALL INIX statement: 

```
ADB > STEP
```

```
00041a      xgetargs INIFILE,TYPEX,SECTION,IDENT,VALUEX,DEFAULTX
ADB > PRINT IDENT
  Cmd/Rep: PRINT/ACK
  Vartyp:  S (&h002001)
  Size:     60
  Value:   Manufacturer
```

Assuming that our concern relates to whether this SBX is returning the expected values, we might want to set another breakpoint back in the main program just after XCALL INIX so we can test the return variables. We know (from the backtrace) that the XCALL INIX takes place at location 00047b in TSTINX.RUN, but we don’t know what the next convenient breakpoint location is, so let’s use LIST to scout it out… 

```
ADB > LIST TSTINX.RUN,47B
TSTINX.RUN ...
```

A-Shell Reference 

Page 589 

```
0003d5      return
0003d6
0003d6  TREAD:
0003d6      if lookup(INIFILE) = 0 ? INIFILE;" not found" : END
0003fb      ? "Reading ";INIFILE;"..."
000419      T1 = TIME
00041f      for I = 1 to COUNT
000446          ? "Reading ";SECTION(I);",";ITEM(I);"...";tab(-1,254);
00047b
00047b          xcall INIX,INIFILE,0,SECTION(I),ITEM(I),TVALUE
000496          ? TVALUE;
```

Set our breakpoint at TSTINX.RUN:496 (the next instruction) and then use CONT to let the target run to it: 

## `ADB >` **`BREAK TSTINX.RUN:496`** 

```
Breakpoint set - use INFO BREAK to list breakpoints
ADB > INFO BREAK
[Breakpoint list:]
      1) INIX.SBX:000417
      2) TSTINX.RUN:000496
[End of breakpoint list]
ADB > CONT
     Cmd/Rep: CONT/ACK            Status: RUN / At Break
     Loc:     INIX.SBX:000429    Level: 3
ADB >
Breakpoint @ TSTINX.RUN:000496
000496          ? TVALUE;
```

Although the target program will print the value of TVALUE on its screen, we can also see it on our ADB display using PRINT: 

## `ADB >` **`PRINT TVALUE`** 

```
  Cmd/Rep: PRINT/ACK
  Vartyp:  S (&h002001)
  Size:     60
  Value:   Gutenberg
```

## And exit: 

```
ADB > QUIT
     Cmd/Rep: QUIT/ACK            Status: RUN / At Break
     Loc:     TSTINX.RUN:000496    Level: 2
```

A-Shell Reference 

Page 590 

```
Decoupling from debug session
```

A-Shell Reference 

Page 591 

## **AGCMD** 

## **AGCMD {switches} <cmd> <parms>** 

AGCMD is used to send an AG_xxx function from the system prompt or from within a command file, thereby avoiding the need to write and compile a program. It is useful for experimentation and for inserting simple ATE or other GUI configuration functions in startup command files. 

## **Switches** 

|**Switch **|**Function**|
|---|---|
|/K#|Assign result to DO file variable $KBD#|
|/S|Silent (don't display the command response)|
|/N|No wait (don't wait for any response)|
|/W:#|Wait # seconds for response (overriding default)|
|/?|Writes switch listing and usage info to the screen.|



## **Parameters** 

## _cmd_ 

the symbolic AG_xxx name—case insensitive, with or without the AG_ prefix—or numeric value of the AG command to execute. 

## _parms_ 

A-Shell Reference 

Page 592 

the parameter list as it would be passed in the AG_xxx statement, except without the trailing chr(127). 

## **Examples** 

```
AGCMD WINEXEC,$DEL %ATE%\dsk0\001004\ftpdlx.log
```

```
AGCMD WINTITLE,This is the new and improved title
```

```
AGCMD SHOWWINDOW 3
```

```
AGCMD STATUSLINES,1,0
```

```
AGCMD/S 24,cmd.exe,option,"/c ipconfig > ipcfg.lst",,0,1
```

```
AGCMD/N PALETTE,3,0,123,207,242
```

```
AGCMD/S/K1 BROWSEFOLDER
```

```
.AGCMD GETENV %TEMP%
```

```
Response = C:\Users\joaqu\AppData\Local\Temp
```

## **Comments** 

If neither of the /N or /W:# switches are specified, AGCMD will use the "normal" wait value based on the function itself, ranging from no wait (for functions with no response, e.g. AG_STATUSLINES), to a few seconds (for functions with an immediate response, e.g. AG_GETENV), to unlimited (for functions which require a user response, e.g. AG_WINPTR). 

Some functions have a variable response (or lack of), depending on the function parameters. For example, AG_PALETTE has no response when used to set a color, but has a "standard wait time" response when used to retrieve palette info. For these functions, AGCMD defaults to the "standard wait time" of a few seconds. To avoid waiting for a response that won't be coming, use the /N switch as in the example above. 

## **History** 

A-Shell Reference 

Page 593 

2023 August, A-Shell 6.5.1740, AGCMD.LIT 1.0(108):  Enhanced to support AG_FILETIMES, AG_GETDPI, AG_DPM, AG_DIRCLEAN. 

2017 July, A-Shell 6.5.1610, AGCMD.LIT 1.0(105): Enhanced to support AG_SCROLLBACK: 

- .AGCMD AG_SCROLLBACK 1         ; toggle 

.AGCMD AG_SCROLLBACK 1          ; show/enable 

.AGCMD AG_SCROLLBACK 0          ; hide/disable 

- 2011 May, A-Shell 5.1.1215:  Added function to A Shell 

A-Shell Reference 

Page 594 

## **APPEND** 

## **APPEND {switches} <target>=<source1>,<source2>{,...}** 

APPEND creates a file consisting of two or more input files concatenated together. 

## **Switches** 

|**Switch **|**Meaning**|
|---|---|
|/I|Causes nonexistent input files to be ignored. If the I switch is not present, a<br>missing file will cause the operation to abort.|
|/Z|Strips EOF (^Z) characters from the source files. Some Windows files end with a<br>^Z used as an end-of-file marker, which can cause all kinds of havoc in<br>programs not prepared to filter these out.|
|/?|Writes switch listing and usage info to the screen.|



## **Comments** 

If the outfile already exists, it will be overwritten. You may specify the same file as both the target and one of the source files. 

APPEND handles long native filenames containing spaces. For example, the following is legal: 

```
.APPEND TEST.LST=TEST.LST,"%TEMP%\THIS IS A LONG FILE.LST"
```

APPEND supports the case where the destination and one of the source files is the same file, and neither exists, provided the /I{gnore} switch is specified, e.g.: 

```
.APPEND /I A.A=A.A,B.B
```

In older versions of A-Shell, this would have aborted with an error if A.A didn't exist. Now, the above command is logically equivalent to `COPY A.A=B.B.` 

A-Shell Reference 

Page 595 

## **APN** 

_Added November 2014_ 

## **APN {file{.ext}} {switches}** 

APN launches an A-Shell Programmer's Notepad (APN) editing session for the specified file. 

## **Switches** 

|**Switch **|**Meaning**|
|---|---|
|/R|Launches file in read-only mode|
|/T|Traces the search for the default extension list. Default<br>extension list: bas,bp,txt,cmd,do,bsi|
|/Y|Creates file if non-existent (else asks)|
|/?|Writes switch listing and usage info to the screen.|



If the extension is omitted, it searches for an ini.vue file using the same path as VUE does (current [p,pn], [p,0], dsk0:[7,0]) 

and then uses the DEFAULT statement in the ini.vue for the list of extensions to search. If the ini.vue is not found, it uses a built-in default list of: 

.BAS, .BP, .CMD, .DO, .BSI, .BPI, .CPY. .UTL, .INI 

## **Comments** 

If APN is not already running, it will then be launched. If the specified file.ext is not already being edited in one of the APN windows, a new window (TAB panel) will be opened containing the file. The focus will then be switched APN to facilitate editing. If the file was already open within APN, the only action will be to set the focus on the specified window. 

## **See Also** 

- There is a fair amount of worthwhile information about APN on the APN page of MicroSabio's web site 

A-Shell Reference 

Page 596 

## **History** 

- 2014 November, A Shell 6.1.1397:  Added function to A-Shell. 

A-Shell Reference 

Page 597 

## **ASTAT** 

## **ASTAT {switches}** 

ASTAT displays a dynamically updated list of jobs currently running along with the current program name. The list is formatted into two columns to fit more jobs on the screen, making it useful on large systems. You may condense the list further by putting the names of programs that are not of interest in the file bas:ignore.prg (one per line). Thus, if you want to quickly size up if it is safe to do a shutdown or backup, you may want to list those programs that are safe to interrupt (such as the main menu, application logon, etc.) so that only the jobs which are doing something worthy of attention will be shown. 

## **Switches** 

|**Switch **|**Function**|
|---|---|
|/#|(#=1-9) Sets the sleep interval (time between screen updates) in seconds. The default is one<br>second. Note that the shorter the interval, the more load this program will place on the<br>system, particularly on a large system.|
|/C|Causes the console or tty name to be displayed for each job instead of the user name.|
|/S|Sorts the entries by job name.|
|/SU|Sorts the entries by user name.|
|/SP|Sorts the entries by program name.|
|/?|Writes switch listing and usage info to the screen.|



ASTAT was actually developed and then contributed to the A-Shell community by Carl Staff of Diversified Data Systems. Thanks, Carl! 

## **History** 

- 2011 September, A Shell 5.1.1235:  Add support for new job table layout and ten character program name. 

A-Shell Reference 

Page 598 

## **ATECFG** 

(Windows only) ATECFG is a wrapper for the Windows program, ATECFG.EXE, which is installed along with A-Shell/Windows and which allows you to add or edit ATE configurations. ATE (A-Shell Terminal Emulator) is a facility that allows you to turn your A- Shell/Windows session into a client connected to another machine, connected via an SSH or telnet link. It is invoked via TELNET.LIT. 

In order to use TELNET to make a connection to another machine, you must first define a configuration, which is a collection of parameters describing the connection. Such configurations are stored in the local Windows Registry. The parameters are reasonably self-explanatory to anyone familiar with telnet and serial connections. See the discussion on TELNET for more information about ATE. 

A-Shell Reference 

Page 599 

## **ATECTL** 

## **ATECTL switch** 

ATECTL allows you to connect, disconnect, or query the status of the ATE "reverse channel." 

## **Switches** 

|**Switch**|**Function**|
|---|---|
|/C|Connect|
|/D|Disconnect|
|/S|Query|



The "reverse channel" is an optional second socket connection between the ATE client and the server used for the purpose of sending response information from the client to the server. The "reverse channel" generally speeds up communication between the server and client, and minimizes conflicts between keyboard activity and the other control information sent between the two machines. 

When connected, all non-keyboard communication from the ATE client to the server is sent via the socket, rather than sharing the _stdin_ data stream with the keyboard. The objective is to eliminate interference between keyboard data (especially in the form of type ahead) and control data (such as result codes from INFLD and GUI operations). 

There are two steps to activating the connection. The first is to check the option "Accept Connection From Server" on the Misc tab of the ATE configuration dialog and enter an available port number that is visible by the server to the client. A highnumbered port, above 20000, is recommended. 

The second step is to execute `ATECTL/C` from the dot prompt of the server after connecting. 

Note that if there is a firewall between the server and client (or you are running a software firewall in the ATE client), you will need to open up the port you choose to connect on. 

A-Shell Reference 

Page 600 

Also note that use of this connection is optional, and can even be turned on and off during a session. When the connection is not available, ATE will revert to using the keyboard channel for passing control. 

A-Shell Reference 

Page 601 

## **ATEUPDATE** 

_Documentation added January 2024_ 

## **ATEUPDATE {switches}** 

(Used only from ATE)  ATEUPDATE initiates an ATE update. It is normally invoked internally by _Help > Check For Updates_ on the ATE toolbar, but can also be invoked directly for various update-support purposes. 

## **Switches** 

|**Switch **|**Function**|
|---|---|
|/A|admin mode (required if not running from ATE session)|
|/F|force update (even if already current)|
|/L|launch update program if applicable (else download only)|
|/Q|quiet mode|
|/S|sync local update cfg file with ATE client (only)|
|/S+|same as /S but continue with normal processing afterward|
|/W|force A-Shell update instead of ATE (same asASHUPDATE)|
|/?|Writes switch listing and usage info to the screen.|



A-Shell Reference 

Page 602 

**Switch Function** 

## **See Also** 

- "Updating" topic in the ATE Reference 

A-Shell Reference 

Page 603 

## **ATSYNC** 

_Revised August 2023; see History_ 

## **ATSYNC {hostdir} {,pcdir} {switches}** 

(Used only from ATE)  ATSYNC does a one-way synchronization of the contents of a directory or a set of files, from the server to the ATE client. This is particularly useful for resources—images, icons, auxiliary files—that are distributed with an application— i.e., on the server—but which need to be present on each individual client. 

## **Parameters** 

## _hostdir_ 

specifies the source of the files to be transferred. It can be either a directory on the host, in DevPPN or native format, or a file containing a list of files to transfer; see /F switch below. If _hostdir_ is not specified—i.e. the command line starts with a comma or a switch or is blank—it uses the current directory. If _hostdir_ contains forward slashes, enclose it in quotes. 

## _pcdir_ 

specifies the target directory on the PC, using native Windows directory syntax, with optional embedded environment variables using the %envvar% syntax. If not present, the default is %ATEPERMCACHE%. In the case of the /F switch, _pcdir_ just sets the default directory for entries in the list file that do not contain explicit target directories. 

## **Switches** 

|**Switch**|**Function**|
|---|---|
|/A{UX}|Use the ATE aux port transfer protocol as an alternative to FTP. The switch is set automatically in the<br>ATSD environment, where FTP is usually not configured.|
|/C{ONT}|Continue trying even after a transfer error.|
|/D{DELETE}|Delete files from PC target directory not in host source directory.|



A-Shell Reference 

Page 604 

|**Switch**|**Function**|
|---|---|
|/F{ILES}|Replaces the HostDir parameter with a file containing the list of files to transfer. See Comments, plus<br>History note for 6.1.1366.|
|/L{IST}{:file}|Output to file rather than screen. If filename ("f") is not specified, output file is atsync.lst.|
|/NOERR|Don't display FTP errors, just return status.|
|/NOHASH|Don't use file hash to determine if updated needed. This may speed up the process slightly for large<br>files.|
|/NOTIME|Disable any use of the timestamp to decide whether the file needs to be transferred. This is a moot<br>point, except when the /NOHASH switch is also used, in which case the determination will be based<br>solely on the file size. The /NOTIME switch will be ignored for ATE versions prior to 6.1.1368.1.|
|/P{RGDLG}|Display progress dialog.|
|/U{PDATE}|Transfer file only if source newer than destination.|
|/V2|Requests the new FTP implementation inASHNET<br>1.6.138. Note that if the switch is specified, it will still<br>use the old (FTPDLX) implementation if theASHNET<br>is not version 138+. This switch should significantly<br>reduce the amount of time it takes to synchronize many files. /V2 is the default value.|
|/?|Writes switch listing and usage info to the screen.|



A-Shell Reference 

Page 605 

## **Comments** 

ATSYNC only replicates files from the server to the client; it is not a general purpose two-way synchronization utility. 

Files are transferred if they are different and the modification timestamp on the server is newer than that on the client. To ignore the timestamp, use the /NOTIME switch. 

Unless the server and client copies of a file are identical, based on hash, modification time, and/or file size (see /NOHASH and /NOTIME switches), ATSYNC transfers the server's copy of the file to the client, even if the timestamp on the client copy of the file is newer than that on the server copy. 

ATSYNC relies on FTP (or SFTP) as configured on the ATE client. The FTP root directory must agree with the root directory as seen by A-Shell on the server. See FTP Debugging. 

The ATSYNC protocol is optimized to minimize latency time, especially if the /V2 switch is used, and to eliminate unnecessary transfers. It is therefore much more efficient than simply doing a wildcard transfer from the server to the client. 

## The /F{ILES} switch uses ATEAPX which must be present in the BAS: directory. 

## **See Also** 

- Discussion on the ATE environment variable. 

## - 2023 August, A Shell 6.5.1470, ATSYNC 1.3(123):  /V2is now the default. 1.3(123) 

## - 2015 September, A Shell 6.1.1417: AG_FTPSYNC (ATSYNC) fixes and refinements: 

- Client will now accept a timestamp from the server which it uses to fine-tune the test for whether the source file is newer or 

- older than the destination. This is useful in situations where the system clock and/or time zone is different enough between the server and client to create confusion as to which version is actually newer. 

- Now, when the hashes are different (unless /NOHASH specified) or when the file sizes are different, the file is only transferred 

- if the source timestamp is newer. Disable that logic with /NOTIME to force a transfer unless the hashes and sizes are the same. Previously it was always transferring files if the sizes were different. 

A-Shell Reference 

Page 606 

- New version of ATSYNC adapts to the behavior of the client (based on whether it is before 6.1.1417.0 or not). This fixes an 

- issue in which the /NOHASH switch was previously being misinterpreted by the client, causing the sync operation to not take place even if needed. 

- Setting DEBUG mode was causing the final FTP operation to fail. 

- Clean up the ambiguity in the atsync.lst file relating to the client transfer log which is normally appended to the end. In cases 

- where no files needed to be transferred, a previous copy of the client transfer log was being included. 

- Clean up several other minor user interface issues. 

Note that the updated ATE client will resolve these issues regardless of whether the copy of ATSYNC.LIT on the server is updated. 

- 2014 June, A Shell 6.1.1387:  /D now explicitly ignored with /F mode. The delete option doesn't really make much sense when not syncing an entire directory; attempting it could have had strange side effects. 

- 2013 December, A Shell 6.1.1368, 1369, 1370: 

- In SBX mode, the normal /L message ("See ...") is eliminated, allowing for totally silent operation. For all other cases, it now 

- reports the total time of the transfer operation, making it easier to see how much faster sync operations are with the /V2 switch. 

- Add /V2 switch. 

- Zero-byte files are now transferred just like any other files. Previously they were flagged to be transferred but then skipped 

- by the actual transfer routine. 

- Add /NOTIME switch. 

- 2013 November, A Shell 6.1.1366, ATSYNC.LIT 1.3(114): Now includes the switch /F{ILES} allows you to replace the HostDir parameter with a file containing the list of files to transfer: 

```
.ATSYNC HostDir{,PCdir}/FILES
```

The layout of the HostDir file should be a series of lines in the following format: 

```
hostfile{,pcfile}
```

A-Shell Reference 

Page 607 

Each hostfile specification may be in either DevPPN or native format and may be partially or fully qualified. The pcfile specification can be omitted, in which case the files will be transferred to the directory specified by the PCdir parameter on the ATSYNC command line. To override that, provide a fully qualified PC filespec in the pcfile parameter. 

You may insert a ";" at the start of the line to comment it out. 

ATE will create a log file called %atecache%\ateftp.log for each file transfer, using the format: 

```
status,hostfile,pcfile
```

Where status will be 0 for a successful transfer, else an error code. Hostfile and pcfile will be the fully qualified host and PC file specifications for the transfer. 

If you specify the ATSYNC /L switch, the ateftp.log file contents will be appended to the list file. Otherwise, you can retrieve it manually using AG_FTP or some other method. 

- 2013 August, A Shell 6.1.1359, ATSYNC 1.2(112):  Now works both as a LIT and as a subroutine; just copy the LIT to SBX. The XCALL syntax consists of just one parameter containing the command line otherwise passed to the LIT, i.e. 

```
CMD$  = "MYICONS:,%ATE%\myicons /P/L"
```

```
xcall ATSYNC, CMD$
```

to retrieve the exit status, you can call it via XFUNC(), i.e.: 

```
STATUS = XFUNC("ATSYNC", CMD$)
```

## STATUS values: 

|**Value**|**Meaning**|
|---|---|
|0|Ok|
|1 - 200|ASB error except for "1" and "3," which see see below|



A-Shell Reference 

Page 608 

|**Value**|**Meaning**|
|---|---|
|< -7|SeeASHNET Error Codes|
|=> 30000|SeeFTPDLX error codes|
|1|Login failure or ^C interrupt|
|3|Invalid SFTP port, or invalid local directory, or unable to link to FTPDLX,<br>or unable to create temp file|
|-2|Command line syntax error (missing comma?), or out of memory|
|-3|Unable to open temp file|
|-4|File sync disabled by ATE|
|-5|Can't link to ashnet library, or opcode sequence error|
|-6|Temp file error or opcode sequence error|
|-7|No hostdir (not specified and not logged in)|



If you'd like to customize the display, contact us for the source code. 

A-Shell Reference 

Page 609 

## - 2013 May, A Shell 6.1.1353, ATSYNC:  Add /A{UX} switch. 

- 2009 January, A Shell 5.1.1177:  The ATSYNC mechanism can now be disabled by creating a registry item DisableFileSync (DWORD) within the current ATE profile (HKCU\Software\MicroSabio\JBCT\ATE\Hosts\profile-name\DisableFileSync) and setting it to 1. The motivation behind this odd feature is to accommodate certain "power users" (presumably developers or tech support staff) who have to connect remotely to multiple sites (running different versions of the application) and who don't necessarily want to have icons, bitmaps, subroutines, etc. synchronised to the PC each time. You are on your own to create and set this registry value, but once set, ATSYNC will abort immediately with error -4. 

- 2008 December, A Shell 5.1.1131, ATSYNC.LIT 1.0(107): Now supports hash codes as a way of making sure whether files are different or not. Also, it now works from within a CMD or DO file. Previously, the CMD file interfered with the input of status responses coming from the ATE client, causing it to act as if no files needed transferring. 

A-Shell Reference 

Page 610 

## **CHAT** 

## **CHAT <target name>** 

(Unix only) CHAT allows two users to enter into a dialog in which they can type messages back and forth to each other; this is similar to PTCHAT.LIT under PolyTRACK. While in the dialog, their previous instance of A-Shell is put into the background, and automatically restored to the foreground when the dialog is over. 

_Target name_ may be either the job name or the login user name of the person you want to chat with; you can use the SYSTAT command to help you determine this information.) The target user will then get a pop-up message on his screen asking him if he wants to engage you in dialog. If not, or if he does not respond within fifteen seconds, the dialog does not take place. While this is happening, the originating user will have been returned to the dot prompt and can go on running another program. If the target user does engage, at that point, a similar phenomenon will happen with the originating user. (A pop-up dialog appears on the screen, suspending the previous process.) Once the dialog begins, it continues until either user exits by hitting the ESCAPE key. At that point, the dialog is closed on both screens and both users go back to the process that was previously running. 

Note that because of Unix security rules, it is impossible for one user to send signals to another unless the first user has superuser privileges, or unless they are both sharing the same effective user ID. Refer to File Ownership and Privileges for instructions on achieving this. 

A-Shell Reference 

Page 611 

## **COMPIL** 

_Updated August 2018; see History_ 

## **COMPIL srcfile {switches}** 

COMPIL and its aliases COMPLP and OCMPIL each process an ASB source file, creating a compiled RUN file which can be executed by RUN.LIT. The line above shows the syntax for all three variations. For example: 

```
COMPIL MYPROG.BAS /X:2/LF/M/C:APP_VER=9
```

## _srcfile_ 

specifies the program source file (with an assumed extension of .BAS or .BP). If omitted, COMPIL will display the internal compiler version number. 

## _switches_ 

COMPIL has an extensive list of switches. Refer to the link above for a listing and links to extended descriptions if needed. 

## **Comments** 

The three LIT commands are just wrappers which process parameters and then call the internal compiler module embedded inside the A-Shell executable (via MX_COMPIL). In fact, they are all the same, but they act slightly differently—mostly in terms of default switches—based on looking at their own name at runtime. 

- OCMPIL, which is equivalent to COMPIL with /13 switch, is designed to emulate the AlphaBASIC 1.3 compiler of the same 

- name. 

- COMPIL emulates the AlphaBASIC 1.4 compiler. 

- COMPLP is equivalent to `COMPIL/X:1` and is designed to emulate the BASIC _plus_ compiler of the same name. 

Note that the OCMPIL nearly always produces the exact same output (RUN file) as the AMOS equivalent, and thus is the best choice when cross-platform compatibility is important. On the other hand, it lacks several features, such as support for ISAM-A, 

A-Shell Reference 

Page 612 

structure loops, SWITCH, user-defined functions and procedures, etc., and thus is the worst choice when developing for the A- Shell platform exclusively. 

In addition to the three LIT wrappers, there are two standalone (native executable) implementations of the compiler, which do not depend in any way on the presence of A-Shell: 

```
compil.exe  (Windows)
```

```
compil      (Unix)
```

For the standalone implementations, the switches are the same, but the syntax is slightly different. The switches must precede srcfile, use the lead-in character "-" (rather than "/"), and are case sensitive (must be lower case). For example: 

```
c:\compil.exe -a -b -m -x:2 prog.bas)
```

There is also another front-end, RECOMX in EXLIB:[908,73], which compiles all of the BAS and BP source files in the current account. The source code of RECOMX is provided so that the switch settings can be customized for individual developers. 

- See A Shell Extensions for additional details of the compiler and related language features, and Compiler Edit History for information on changes to the compiler. 

## **History** 

- 2025 October, A Shell 7.0.1780, COMPIL.LIT 1.1(138): support new /SYM switch to include variable/symbol table information in the LSX file; needed by ADB.LIT. 

- 2019 March, A Shell 6.5.1657, COMPIL.LIT 1.1(136): add /F1 switch. 

- 2018 August, A Shell 6.5.1639, COMPIL.LIT 1.1(135):  add /NOTRC switch. 

- 2017 July, A Shell 6.5.1610, COMPIL.LIT 1.1(134): makes the scroll bar visible if the environment supports it (A-Shell/Windows and ATE version 6.5.1610 or later) and the output of the command causes the screen to scroll. 

2016 May, COMPIL.LIT(132):  /PX extends pre-pass to eliminated unused functions 

2016 October, COMPIL.LIT(133):  Add support for /IGOO 

2015 September, COMPIL.LIT(131): /XTAGS generates CTAGS output 

A-Shell Reference 

Page 613 

2015 August, COMPIL.LIT (130): /CTAGS generates a list of includes 

A-Shell Reference 

Page 614 

## **SWITCHES** 

## Following are the switches used with COMPIL. 

|**Switch**|**Function**|
|---|---|
|/13|OCMPILmode (AlphaBASIC 1.3 compatibility)|
|/A|Increase size of offsets used for program addresses from 16 to 24 bits. This fixes "transfer<br>address out of range" compiler errors. Beginning withCOMPILversion 1.0(112), /A is invoked<br>automatically (as needed).|
|/AV|Additional Variables<br>: Extends the allowable number of variables.|
|/B|Background: Send errors messages to <sourcefile>.lst.|
|/C|(C:symbol=value) Provides for passingCompiler Symbol Definitions<br>.|
|/CI|Enables case insensitive compilation. Note that this applies to labels and function/procedure<br>names as well as variables and symbols.|
|/CTAGS|Outputs just a list of++INCLUDEfiles to <source>.lst. Mainly for internal use byAPN.|
|/D|Enables use of certain d/BASIC statements.|
|/DEBUG|Activate conditional debug code by compiling the variable DEBUG as 1.|
|/F1|Disables the header signature which otherwise would be used if the program contains any<br>features introduced in 6.5.|
|/I|Allow the use of ISAM 1.0 statements (not relevant forOCMPILor /13)|
|/IGOO|Treats all++INCLUDEs as++INCLUDE'ONCE; "IGOO" = Include Global Once Only.|
|/IEEE|Assume F,8 instead of F,6 if variable size is not specified.|
|/LF|Creates a consolidatedList File<br>showing all of the source with location offsets.|
|/LI|Local Include<br> causes the directory information on any++INCLUDEstatement to be ignored.|
|/LSM|Create .LSM file containing metadata used byAPN.|



A-Shell Reference 

Page 615 

|**Switch**|**Function**|
|---|---|
|/M|Mapped variable required: causes compiler error for any unmapped variables.|
|/MX|Unmapped Variable List: Reports every line in which an unmapped variable appears.|
|/N|Turns off the display of compiler statistics.|
|/NOTRC|Ignore all trace related statements during compilation (++pragma TRACE_xxx, TRACE.xxx,<br>DEBUG.xxx).|
|/O|Removes the internal line number references from the compiled object code, making it smaller<br>and faster, but eliminating the capability for error handling routines to display the line number of<br>the error.|
|/P|Enables support forNamed Parameters<br>.|
|/PX|Superset of /P, which is implied; enables automatic removal of un-referenced functions and<br>procedures from the compiled output. The removed routines are also marked as such in the /LF<br>List File.|
|/RC|Run Compatible<br>: Preserves runtime compatibility for AMOS.|
|/S|Silent: Turns off the display of++INCLUDEfile names.|
|/SYM|Adds a symbol table section to the LSX file. SYM is useful only in conjunction withADB.LIT<br>.|
|/T|Trace: Display source code as it is being processed.|
|/V:1|Attempts to duplicateAMOS 1.4<br> and higher.|
|/VC|(VC:pattern)Version Copy<br> causes the compiler to make a backup copy of every source module<br>encountered according to the specified pattern.|
|/XTAGS|Outputs a "tag" file to <source>.TAGS. Mainly for internal use byAPN.|
|/X:1|Enables use of certain BASIC_plus_syntax elements. These are clarified in more detail in the<br>section on BASIC_plus_extensions.|
|/X:2|Enables the use of certain A-Shell language extensions. SeeA-Shell Extensions<br>.|
|/X:3|Same as X:2, but creates an SBX file instead of RUN.|



A-Shell Reference 

Page 616 

|**Switch**|**Function**|
|---|---|
|/?|Writes switch listing to the screen.|
|**Definition File:** compil.def||



A-Shell Reference 

Page 617 

## **COMPILER SYMBOL DEFINITIONS** 

The following command line switch supports passing symbol definitions into the compiler. Syntax: 

## **/C:symbol {=value}** 

## **Example** 

```
COMPIL MYPROG/RC/C:APPVER=2/C:GUI="VISTA"
```

This specifies the /RC switch, plus two instances of /C to define two symbols, APPVER=2 and GUI="VISTA". These definitions are treated exactly as if the following had been inserted at the top of the MYPROG source code: 

```
define APPVER=2
```

```
define GUI="VISTA"
```

Note the need for quotes when defining a string symbol per the normal rules of the DEFINE statement. 

If the =value clause not specified, it is treated as = 0, i.e. the symbol is defined (responds to ++IFDEF <symbol> but it has a null value. 

## **Example** 

## COMPILER_VERSION Macro 

A-Shell Reference 

Page 618 

## **LSX FILES** 

_Updated February 2022_ 

The List File compiler option— **/LF** for COMPIL.LIT, **-lf** for the standalone compiler—generates a consolidated list file showing all of the source code, with all of the ++INCLUDE files merged in. Add the /SYM or -sym switch to include a symbol table for use with ADB.LIT. The list file is known as the LSX File, is named <prog>.LSX, and is normally created in the same directory as the main program source, subject to the LSX_FSPEC pragma. Some of its attributes and uses are detailed in the comments below. 

The LSX header includes details indicating how the program was compiled, and stats allowing you to be sure of a match between a particular pair of LSX and RUN files.The new header looks like this: 

```
LSX >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
```

```
Main Source : C:\VM\MIAME\DSK2\205170\apvch.bp
```

```
  Stats     : 442-203-632-231  25-Feb-22 14:33:35  259890 bytes
Object      : C:\VM\MIAME\DSK2\205170\apvch.run
  Stats     : 247-540-225-666  26-Feb-22 16:25:18  208514 bytes
Compiler    : 6.5(965)
  Switches  : /av /i /x:2 /lf /px /m
```

```
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
```

The top two lines provide the filespec, hash, last modification time and size of the main source module. The next two lines provide the same details for the object of the compilation (RUN, SBX, LIT). The last two lines are the same as in previous LSX versions, identifying the compiler version and switches. 

Note that the compiler edit number is independent of both the A-Shell edit number and the version of COMPIL.LIT. To display the compiler edit number of the compiler embedded in A-Shell, enter `COMPIL` at the dot prompt without and arguments. For the standalone compiler, execute `compil -about` . 

A-Shell Reference 

Page 619 

Since the LSX file contains all of the source code merged in from all the ++INCLUDE statements, it effectively captures the entire state of the source code at the time it was compiled, and thus provides an easy way to archive the source corresponding to a particular RUN or SBX module released. The top of the LSX file indicates the compiler version and switches, which you can use to regenerate the compiled output directly from the LSX file. For example, we can recompile the LSX with above header as follows: 

```
.compil apvch.bp/av/i/x:2/px/m
```

Note that we don't need the /lf switch, but if it was included, a new list file will be created with a .LSY extension. 

Also note that you can make minor edits to the LSX file and recompile it, perhaps to fix a minor bug in an older version of a program which has since undergone many changes that you don't want to introduce along with the bug fix. The only trick here is that the compiler expects every line of source code to be prefixed with the six digit location counter (see below) followed by two spaces, which you will need to manually add to any lines you add. However, this is just a syntactic formality; the compiler does not care about the value of the location counters in the LSX file, so you can just set them all to a dummy value like 000000 or 999999. 

++INCLUDE files are inserted into the consolidated LSX file with a header and footer to help you navigate the code. The header looks like this... 

- `00f245  ++include'once bas:harvestdb.bsi` 

- `! DSK0:HARVESTDB.BSI[7,6] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< <77_6>` 

The <##_#> suffix at the end of the header indicates sequential file number and the nesting level. So in the above example, this is the 77th file opened so far (1 main and 76 include files), and we are now nested 6 levels deep. 

At the end of the include file, a footer is inserted like this... 

- `! >>>>>>>>>>>>>>>>> (harvestdb'bsi) ^> c:\vm\miame\dsk0\007006\prdlmt.bsi <75_5>` 

A-Shell Reference 

Page 620 

The name of the include file that we are returning from is in parentheses, followed by the full native spec of the file we are returning to (i.e. the one that contained the ++INCLUDE that we just processed), followed by the <file#_level> indicator. 

When a file include directive is skipped (e.g. ++INCLUDE'ONCE was specified and the file was already included), instead of the normal ++INCLUDE file expansion, the LSX contains only a note as in the following: 

```
00f245  ++include'once sql:sql.def
```

```
! Skipping sql.def (already included)
```

The LSX file contains the location counter for each line of the source code, providing a way to located the source corresponding to ASB errors. Traditionally programmers used line numbers for this purpose, but line numbers are cumbersome to deal with, cluttering up the source code, requiring renumbering utilities and management schemes to avoid duplicating line numbers in + +INCLUDE modules, making the RUN modules larger and adding to the execution overhead. In ASB they have mostly been deprecated in favor of location counters, which require no additional overhead or effort, other than to keep a copy of the LSX files corresponding to the compiled programs for cross-reference purposes. 

The standard ASB error messages contain the location counter automatically, but if you are trapping errors yourself, you can retrieve the location counter using the ERR(8) function. You can also use the .LOCATION Dot Variable to retrieve the current location file, independent of error processing; see History notes below. Because it takes effort on the part of the user to write down and report error messages faithfully, and/or effort by the programmer to programmatically track them, you may want to take advantage of the built-in BASERR TRACE—by adding TRACE=BASERR to miame.ini—which results in all ASB errors, whether trapped or not, being logged to the ashlog.log file along with their location counters. 

Note that by convention, location counter values are displayed in hex within internal error messages, log messages, LSX file, etc. But since the PRINT statement only outputs in decimal, you will need to use a function such as MX_OCVT or the function Fn'Dec2Hex$() in SOSLIB:[907,11] to convert the ERR(8) or .LOCATION values to hex, e.g. `PRINT Fn'Dec2Hex$(ERR(8))` . 

Also note that because the LSX file only shows the location counter at the start of each source line, while an error might occur at a location in the middle of a source line, the location counter reported for an error may not necessarily match any location counter shown in the LSX file. For example, consider the following LSX excerpt: 

Page 621 

## A-Shell Reference 

```
003337       ELSEIF (dlg'ashdevinf_cntlsup_ary(x).gen'type = 5) THEN
00334f           menucntl = dlg'ashdevinf_cntl_ary(x)
00335b           IF (ABS(menucntl.clickcode) = ABS(click)) THEN
003369               fn'dlg'ashdevinf_clickcode2pointer = x
003371               EXIT
003375           ENDIF
003375
003375 !     comment bla bla bla
003375       ENDIF
003375   NEXT x
```

If the value of (x) in the second line generates a subscript out of range error (ASB error 8), the location counter reported for the error will probably be somewhere between the location given for the start of the line (334f) and the location for the start of the next line (335b). So to locate the error, you will just have to scroll through the LSX to find the pair of lines that bracket the error location. 

The above example also illustrates the fact that many source lines do not increase the location counter at all, since they don't generate any executable code. The last 5 lines shown all have the same location counter, 3375. 

If you don't use the /M switch, which reports un-mapped variables as errors, the compiler will automatically generate MAP statements for any such variables, and these will be listed near the bottom of the LSX file as follows: 

```
MAP1 AUTO'MAPPED'VARS
```

```
    MAP2 COMMON'RKEY,F,6
```

A-Shell Reference 

Page 622 

```
    MAP2 COL'X,F,6
```

```
    MAP2 COPIES,F,6
```

This explicit listing provides a relatively easy way for you to come in from the figurative cold—of living with the subtle errors introduced by inevitable typos—to take advantage of the compiler's ability to point out those typos to you before they become bugs. Just copy the AUTO'MAPPED'VARS MAP statements from the LSX file back to the original source and then you can compile with /M. That won't help resolve issues related to typos you've already introduced—although perhaps in seeing the AUTO'MAPPED'VARS all together, you might spot some suspicious ones—but it will allow you to benefit going forward. 

When the /LF switch is used to create an LSX list file, unreferenced variables are listed at the end, as a convenience for those interested in clearing dead weight out of program. Note, however, that these are not errors, and in many cases, it isn't even desirable to remove them. For example, it is common to group misc variables under a heading, e.g. 

```
MAP1 WORK'VARS
```

```
MAP2 X,F
```

```
etc.
```

Typically in the above case, there would probably be no explicit reference to WORK'VARS, but you couldn't just delete it without elevating the MAP2 variables beneath it to MAP1. So the new feature is only to be used a guide or ignored as you see fit. 

Note: see Compiler Edit History, edits 452 and 500, for additional info on the List File option. 

When compiling with /P or /PX, a section will be added to the bottom of the LSX file listing all the procedures and functions defined in the program, along with the reference count—i.e., the number of times the routine is called. For example: 

A-Shell Reference 

Page 623 

```
Procedures, Functions [reference count]
```

```
======================================================
```

```
Fn'NextCh(ch) [2]
```

```
Fn'XMList'Load'Doc($xml,xmldoc$) [1]
```

```
Fn'XMList'Save'Doc($xml,xmldoc$,level,och) [0]
```

```
Fn'XMList'Get'Subtree'Callback($xml,item$,parent$,flags,$response) [1]
```

In the above example, we can see that there are several functions which are defined but are never used. These don't hurt anything, other than making the RUN modules larger than they need to be, so we might want to remove them. Fortunately, the /PX switch will do this for us automatically, showing a "<nc>" (for Never Called) next to any function that gets removed by this "tree-shaking" feature, e.g. 

```
Procedures, Functions [reference count]
```

```
======================================================
Fn'NextCh(ch) [2]
```

```
Fn'Load'Doc($xml,xmldoc$) [1]
```

```
Fn'Save'Doc($xml,xmldoc$,level,och) [0] <nc>
```

```
Fn'Get'Subtree'Callback($xml,item$,parent$,flags,$response) [1] <nc>
```

```
Fn'Walk($xml,@fn'callback=.NULL,level=0 ,parent$=.null ) [0] <nc>
```

The above shows that the last three functions were removed from the RUN module, because they were never called. Note that this can occur even when the reference count is non-zero, as in the Fn'Get'Subtree'Callback example above, which was apparently referenced once, but still marked <nc>. This occurs when the only references to the target routine occur within other routines which themselves are never called. In the above case, it may be that the function Fn'Walk() references 

A-Shell Reference 

Page 624 

Fn'Get'Subtree'Callback(), but since Fn'Walk() is itself not referenced anywhere and thus never called, then by extension, Fn'Get'Subtree'Callback() is never called, and can thus be removed. 

Note that routines that are removed by the /PX switch still show up in the LSX file, but the location counter will not increment. The routines removed this way are essentially treated by the compiler as if removed by conditional compilation logic. 

## **See Also** 

- The compiler /LSM switch which generates another kind of list file containing program metadata which is mostly used by APN 

- but which is somewhat related to the metadata contained in the LSX file. 

- LSX_FSPEC 

- ADB.LIT 

## **History** 

- 2024 April, A Shell 7.0.1757, edit 1046:  Add some performance statistics to the end of the LSX file. 

- 2022 February, A Shell 6.5.1711, edit 967:  LSX file ++include indicators now show a <##_#> suffix indicating the sequential file number and the nesting level. 

- 2019 February, A Shell 6.5.1656, edit 893:  Expand LSX header. 

- 2016 June, A Shell 6.3.1514, edit 762:  /PX switch added to the compiler. 

- 2014 March, A Shell 6.1.1382, edit 663:  Function list with reference count added to LSX 

- 2014 January, A Shell 6.1.1373, edit 652: /P switch added to compiler 

Note that the above feature introductions were subject to various subsequent fixes and enhancements; for details see the Compiler Edit History and search for "LSX." 

A-Shell Reference 

Page 625 

## **LOCAL INCLUDE** 

When the Local Include ( **LI** ) switch is specified, the directory information on any ++INCLUDE statement is ignored; the file is loaded from the current directory. This might be useful in situations where, for reasons of portability or archival, you might consolidate all of the ++INCLUDE modules associated with a single program into a single directory. Compiling with /LI would then eliminate the need to edit all of the ++INCLUDE statements to remove the directory specifications. 

For example, you might use the switch /VC:c:\archive\%f.%e to make a copy of all the source modules associated with a program into the directory c:\archive. To compile to copy made in that directory, you could then log into that directory and use the /LI switch. 

Note that a related feature is always activated: when the compiler is unable to locate the specified ++INCLUDE file in the specified directory, or in the BAS: account, it will look in the location where the main source file was loaded from. (In comparison, the /LI switch ignores the specified and BAS: locations and only looks in the current directory.) 

Note that when using the compil.exe version of the compiler, if you are compiling from a difference directory than where the source files are, you may need to specify the -l switch in order to establish the current directory context from which the -li switch will be processed. 

A-Shell Reference 

Page 626 

## **RUNTIME COMPATIBLE** 

The Run Compatible ( **RC** ) switch enables the use of several compiler and source code enhancements without breaking backwards Runtime Compatibility with AMOS. To be effective, you must use with COMPIL.LIT / OCMPIL.LIT 1.0(117)+ (not COMPLP) and without any of the /X:# switches. The idea is to accommodate people who want to compile under A-Shell and use as many A- Shell features as possible, but still retain the option of copying the RUN files to AMOS for execution there. 

The features which /RC adds to COMPIL or OCMPIL can be divided into fully and partially supported categories, as shown below. 

## Fully Supported: 

|upported:||
|---|---|
|DEFINE|.SIZEOF()|
|DEFSTRUCT / ENDSTRUCT|Use of underline in identifiers|
|Hex, Octal, ASCII Literal Values (&h10FC,<br>&o1777, 'a')|Max source line length of 3070 instead of 512|
|IF / ELSE / ELSEIF / ENDIF|++INCLUD nested 13 levels deep|
|DO / WHILE ... UNTIL / LOOP|++PRAGMA (all)|
|BABIC_plus_-style FOR/NEXT<br>semantics (test before loop)|Comment may follow an & on a continuation line|
|EXIT / REPEAT|++ERROR, ++MESSAGE|
|SWITCH / ENDSWITCH|Conditional compilation (++IF, ++IFDEF, ++IFNDEF, +<br>+IFMAP, ++IFNMAP, ++ELSE, ++ELIF, ++ENDIF)|
|Shortcut Operators (var += <expr>, etc.)||



## Partially Supported: 

|3D TAB(x,y,z): z value ignored|DPRINT / EPRINT / TPRINT: compiled as if PRINT|
|---|---|
|TRACE.xxxx / DEBUG.xxxx: compiled as|DIMX: compilation only, and only if OPTIONS=RC_DIMX.|



A-Shell Reference 

Page 627 

XCALL EVTWIN 

- See the discussion on A Shell Extensions for more information on all of the above statements and features. 

A-Shell Reference 

Page 628 

## **SINGLE CODE BASE** 

Here are some strategies for managing a single code base for deployment under AMOS and A-Shell. 

If you are willing to maintain a single source code base, but generate separate RUN modules for each run-time environment, then you can take advantage of conditional compilation directives to separate out the code that isn't cross-compatible. For example: 

```
++if RUN_VER = "ASHELL"
```

```
    INPUT CSV #CH, name$, addr1$, addr2$, comments$
```

```
++else
```

```
    <some alternative logic not relying on A-Shell specific features like INPUT CSV>
```

```
++endif
```

In this case, for the A-Shell compilation, you can, for example use `COMPIL /X:2/C:RUN_VER="ASHELL"` to compile the A-Shellspecific sections and ignore the AMOS-specific sections. For the AMOS version, use `COMPIL /RC` (optionally with `/C:RUN_VER="AMOS"` in place you plan to test for that condition explicitly). If you accidentally include some non-AMOS compatible code outside your `++if RUN_VER = "ASHELL"` condition blocks, the compiler will flag these as errors in the version of the compilation without /X:2. 

you will be able to distinguish the different RUN versions using the VERSYS utility. 

If, on the other hand, if you would rather maintain just a single set of RUN modules which work in all environments, then you pretty much have to limit yourself to only those features that are supported by /RC (which leaves out, for example, user-defined functions and procedures). The only alternative would be to compile with /X:2, but make sure that you separate out your A- Shell-only or AMOS-only code via run-time IF statements. For example: 

```
<runtime logic to set RUNVER$ to "ASHELL" or "AMOS" - perhaps using GETJTB>
```

```
if RUNVER$ = "ASHELL" then
```

A-Shell Reference 

Page 629 

```
    INPUT CSV #CH, name$, addr1$, addr2$, comments$
```

```
else
```

```
    <some alternative logic not relying on A-Shell specific features like INPUT CSV>
```

```
endif
```

The above technique also requires one further trick in order for AMOS to accept the RUN modules created by the A-Shell compiler when using /X:2: you will need to manually modify the RUN header. The 11th and 12th bytes of the RUN file contain a series of flags which indicate to the run-time system certain attributes of the RUN module, such as whether it was compiled with OCMPIL or COMPIL, /A or not, etc. This allows the run-time interpreter to properly interpret the RUN code, and also to identify RUN modules that are incompatible. Trying to run an invalid RUN module will most likely result in "illegal syntax code" errors (error #34). 

To modify the RUN header to make it appear to be AMOS-compatible, write an ASB program to treat the RUN file as a RANDOM file with a record size of 1, allowing you to manipulate the 11th and 12th bytes. To determine what they should be, use VERSYS to look at similar RUN modules compiled under AMOS. In particular, be careful about /A (and /AV), since if the associated header flag bits are not correct, the program will crash. For this reason, you may want to use /A explicitly on all compilations, whether needed or not, so that you can use a fixed RUN header. Otherwise, the A-Shell compiler will invoke /A (and /AV) automatically as needed and your utility to patch the header will have to leave the /A and /AV bits alone. 

## **Subtopics** 

· 

A-Shell Reference 

Page 630 

## **VARIABLE INDEX AREA** 

The **AV** switch allows the "variable index area" to exceed 64K. Furthermore, like with the /A switch (which is implied by /AV), unless OPTIONS=STRICT, the compiler will automatically restart the compilation using /AV if the program would exceed the 64K variable index limit. Normal variables require ten bytes of indexing space each (array variables take more), so this limited programs to something less than 6400 variables. With /AV, the limit becomes 256 times greater. /AV is independent of other compiler switches (except /A), so you don't need to go to BASIC _plus_ mode, but any RUN file thus compiled will not be compatible with AMOS, nor with any version of A-Shell prior to 4.9(857). You will get the error "RUN file is in an incompatible format" if you try to run such a program under AMOS or an earlier A-Shell. 

A-Shell Reference 

Page 631 

## **VERSION COPY** 

The Version Copy ( **VC** ) switch causes the compiler to make a backup copy of every source module encountered (the main program and any ++INCLUDE files) according to the pattern. The idea is to provide a simple way to archive source code, which is sensitive to program versions. 

The pattern is made up of literal characters, plus any of the following: 

|**Symbol**|**Meaning**|
|---|---|
|%d|directory of the original file (e.g. c:\vm\miame\dsk0\150100\)|
|%f|filename of the original file, minus extension (e.g. myprog)|
|%e|extension of the original file (e.g. bas)|
|%v|vedit value of the file. For the main file, this comes from the program statement, e.g. "PROGRAM name,M.ms(eee)"<br>where M=VMAJOR, m=VMINOR, s=VSUB and ###=VEDIT. For included files, it comes from a comment found<br>anywhere in the file, having the following form:<br>`!VEDIT = ###`<br>Spaces around the "=" are optional, and the ### may be one to five digits long. Following the last digit, to the<br>remainder of the line, no characters are allowed except spaces and "!". These restrictions are to avoid confusing an<br>occurrence of "VEDIT" in, say, an assignment statement, with a declaration of the version number of the source file.|



Note that VUE uses the same rules to identify the VEDIT statement, used in two special commands related to using the VEDIT value: 

|**Comma**<br>**nd**|**Result**|
|---|---|
|^_E|increments the VEDIT value and inserts a partially filled in dated edit history line at the cursor location|
|^SE|inserts a "[###]" at the cursor location (### = the current VEDIT value)|



A-Shell Reference 

Page 632 

If no VEDIT value is defined for the current file, it is treated as 0. 

For example, consider an original program file (after conversion to local syntax) of c:\vm\miame\dsk0\909060\sqltest4.bp : 

```
/vc:%d%f-%v.%e        ==> c:\vm\miame\dsk0\909060\sqltest4-104.bp
```

```
/vc:c:\backup\%f.%e   ==> c:\backup\sqltest4.bp
```

```
/vc:%dalpha-%v-%f.bak ==> c:\vm\miame\dsk0\909060\alpha-104-sqltlest4.bak
```

The pattern may also be quoted, which is necessary in order for it to contain spaces or slashes, i.e., under Unix we might have: 

```
/vc:"%dback up/%f.%e"  ==> /vm/miame/dsk0/909060/back up/sqltest4.bp
```

Without the quotes, the pattern will be terminated at the first space or forward slash. 

Note that if the %d (directory) directive is omitted from the pattern, the copied file will be placed in the current directory. This would be one easy way to get all of the ++INCLUDEd modules used by a program into one directory. See the following topic on the /LI switch for a related feature. 

A-Shell Reference 

Page 633 

## **VERSION 1.4 COMPATIBLE** 

The **V:1** switch attempts to match new features and quirks of the AMOS version of COMPIL.LIT 1.4(309) and higher (released with AMOS 2.3A). Unfortunately, although this version of COMPIL shares the same major and minor version number (1.4) with preceding versions, it introduces some new features and generates RUN modules with various differences, causing them to be incompatible with earlier versions of RUN.LIT. This is true under both AMOS and A-Shell. The main reason for using this switch would be if you are using a source code feature that was not previously supported. Note that even with the /V:1 switch, the A- Shell compiler does not support all of the AlphaBASIC 1.4 changes and may not generate the same hash as the AMOS version. Also note that /X:1 and /X:2 both implicitly give you /V:1 features. Features that are activated by /V:1 include: 

- LOOKUP returns 0.5 for a zero block file 

- READ’ONLY option on OPEN statements 

- READ’READ’ONLY statement 

- ALLOCATE’INDEXED supports the Device param. 

A-Shell Reference 

Page 634 

## **COMPILER EDIT HISTORY** 

The following list, extracted from the A-Shell Development notes, shows all compiler edits, including fixes and minor changes. Missing descriptions indicate that the edit in question was a purely internal matter that would not be of interest to A-Shell developers. 

|**Compile**<br>**r**<br>**Edit #**|**A-Shell**<br>**Version**|**Release**<br>**Date**|**Description**|
|---|---|---|---|
|1081|1785|07 Apr 2026|Compiler edit 1081:  ++PRAGMA FORCE_FSPEC in conjunction with/L and without ++PRAGMA<br>LSX_FSPEC was causing the LSX file to overwrite the compiled output. Bug introduced in compiler<br>1080 with 7.0.1785.3.|
|1080|1785|02 Apr 2026|++PRAGMA FORCE_FSPEC now also sets the default base name for the LSX if there is no explicit +<br>+PRAGMA LSX_FSPEC.<br>Resolve an issue with both pragmas in which literal quotes were getting in the way of concatenating<br>a literal or defined symbol with the %s argument, e.g. ++PRAGMA FORCE_FSPEC MYSYM%s.|
|1079|1784|10 Mar 2026|The /ci (case insensitive) switch was not affecting collection variables (e.g. ordmaps).|
|1078|1783|02 Feb 2026|Compiling a program whose name was greater than 32 characters was causing the compiler to<br>abort. New limit is 72.|
|1077|1780|23 Oct 2025|ASHELL is now recognized as a control statement equivalent to the pre-existing AMOS control<br>statement, i.e. as an alternate to Xcall ASHELL (or Xcall AMOS). This is part of a long-term effort to<br>gradually replace archaic references to "AMOS" which may be confusing to A-Shell programmers<br>who didn't come from the AMOS environment.|



A-Shell Reference 

Page 635 

|1076||28 Aug 2025|Relocate the symbol table information created by /SYM to the LSX file.  Previously it was a separate<br>file.|
|---|---|---|---|
|1075|1775|11 Aug 2025|Support implicit CALL statement when first token on line is function, e.g. the following statements<br>are now equivalent:<br>call fn'foo()<br>fn'foo()|
|1072|1775|11 Aug 2025|Fix spurious unmapped variable error when compiling LSX.|
|1073|1775|11 Aug 2025|Support ++PRAGMA LIT (equivalent to FORCE_EXT "LIT" but more  of a natural sibling to the<br>existing ++PRAGMA SBX).|
|1072|1775|11 Aug 2025|Support new /SYM (or -sym) switch to create a SYM file. Used for debugging.|
|1071|1775|11 Aug 2025|Support new PYCALL(mod,func,args...) function to call an external Python function. Arguments:<br>_mod_is the filespec containing the python code (e.g. mycode.py)<br>_func_is the name of the python function with the specified module<br>_args_are the arguments to the function<br>The interface is preliminary state, with more details to follow.|
|1070|1772|13 May 2025|Fix problem where automatic %x loop variables in FOR/NEXT loops were being incorrectly treated as<br>global regardless of the context. This wouldn't matter, except when the same %x variable was<br>accessed at multiple levels within recursion.|



A-Shell Reference 

Page 636 

|1069|1772|08 May 2025|Fix spurious illegal default value errors on output-only parameters caused by leading spaces.|
|---|---|---|---|
|1068|1771|10 Apr 2025|Add new dot variable .PID.|
|1067|1771|10 Apr 2025|Add new new dot variable .ASFLAGS.|
|1066|1770.3|14 Mar 2025|Several dot functions were generating spurious syntax errors. Problem introduced in edit 1065.|
|1065|1770.2|14 Mar 2025|Further refinements to the behavior of various .ARGxxx functions.|
|1064|1770.1|09 Mar 2025|The :OUTPUTONLY qualifier on a DYNSTRUCT parameter no longer defeats the autobinding when the<br>caller passes a DEFSTRUCT to it.|
|1063|1770.0|27 Feb 2025|Treat updates to ordmaps during iteration as errors.|
|1062|1770.0|27 Feb 2025|Add new dot function .ISBOUND.|
|1061|1768.7|03 Feb 2025|Extend edit 1060 (below) to treat a single "@" as a comment indicator if it is the first statement<br>token on the line—i.e. preceded by nothing other than white space and possibly a line number.|
|1060|1768.6|03 Feb 2025|Treat "@@@" as equivalent to REM or !, i.e. start of a comment. This was apparently a feature of<br>some early versions of AlphaBASIC.|
|1059|1768.3|24 Jan 2025|The minimum run version in the RUN header was still being unnecessarily set to 1767 in many cases<br>where DEFSTRUCTs were defined but not embedded.|



A-Shell Reference 

Page 637 

|1058|1768.1|21 Jan 2025|Function parameters with default values set to actual variables (e.g. arg1=GTOTAL as f6) were not<br>being compiled correctly, resulting in an illegal syntax error (#34) at runtime. Note that this is<br>somewhat rare and exotic technique, requiring that the variable in question be declared PRIVATE to<br>the module (and thus global to the functions in the module). As part of the fix, attempting to declare<br>a default value that is actually a function (e.g. arg1=fn'foo() as f6) is now tagged as illegal by the<br>compiler. (Previously the compiler let it slip through, triggering another illegal syntax error when<br>called.)|
|---|---|---|---|
|1057|1768.0|14 Jan 2025|Compiler edit 1057:-<br>•<br>Prior edit 1052 was incorrectly setting the RUN minimum version to 1767 regardless of<br>whether there were any embedded defstructs.<br>•<br>Support added for a new special symbol definition: /C:_NO_MIN_1767=1. When defined (to<br>anything), it doesn't set the RUN minimum version to 1767 even if there are embedded defstructs.<br>This is safe as long as you compile and RUN under the same architecture.|
|1056|1767.1|7 Jan 2025|Fix LSX generation bug introduced in edit 1050 resulting in LSX compilation failure.|
|1055|1767.0|6 Jan 2025|Back out edit 1049—i.e. allow any default value on OUTPUTONLY parameters. Based on feedback<br>from the field, it was determined that the behavior was only useful in a one-time scan of old code to<br>look for potential problems. And for that, the standalone compiler version 1049 thru 1054 could be<br>used.|
|1054|1767.0|6 Jan 2025|New ++PRAGMA OVERRIDE_OUTPUTONLY causes parameters with the :OUTPUTONLY qualifier and a<br>default value to revert to input/output. This is intended to be transitional feature to support<br>programs that were counting on the behavior prior to compiler edit 1047 (7.0.1765.6) until they can<br>be corrected. After that edit, and without this pragma, the :OUTPUTONLY qualifier was taken<br>seriously, meaning that any value passed in to that parameter would be ignored, and as of compiler<br>edit 1049, attempting to set a default value for an :OUTPUTONLY parameter (other than 0 or "")<br>generates an error.|



A-Shell Reference 

Page 638 

||||Note that this option can also be set by passing the new COMPIL_OOO flag (&h400000000, defined<br>in compil.def) to the MX_COMPIL function.|
|---|---|---|---|
|1053|1767.0|6 Jan 2025|You may now override the minimum runtime version field in the RUN file header by defining the<br>symbol _MIN_RUN_VER = ####, where #### is the desired minimum version. This can be done<br>either with a DEFINE statement in the source code, or by passing the /C: switch to the compiler.<br>Background: normally the compiler will automatically plug in the minimum run version value based<br>on the language features used in the program. The RUN interpreter will compare that value to the<br>current runtime version, and if not sufficient, will abort with an explicit complaint -- "Program<br>requires minimum A-Shell level ####". This is deemed preferable to getting some cryptic error,<br>such as #34 (Invalid Syntax Code) when the intepreter encounters the unrecognized code. However,<br>there may be times where you know better than the compiler. For example, your program may<br>check the version at runtime and avoid code that requires a later version, in which case you might<br>want to override the minimum version in the header to allow it to run on earlier versions anyway.<br>Or, in the case of embedded defstructs (see compiler bug fix 1052 above), if you distribute RUN<br>programs across older 64 bit A-Shell versions, you may want to force the minimum run version to<br>1767, to avoid wasting time later trying to figure out why embedded defstructs aren't working.|
|1052|1767.0|6 Jan 2025|Programs with embedded defstructs are now compatible across 32 and 64 bit architectures.<br>Previously the structures embedded with the RUN were different depending on which platform it was<br>compiled on, breaking the ability to distribute the same set of RUN files across platforms. Starting<br>with this update, embedded defstructs are compiled as they were in the 32 bit environment,<br>maintaining backwards compatibility there. However, any program with embedded defstructs that<br>gets recompiled in the 64 bit environment will generate an error when attempting to use the<br>embedded defstruct if run on an earlier version of A-Shell in the 64 bit environment.|
|1051|1767.0|6 Jan 2025|Language enhancements, compiler edit 1051:<br>•<br>.ARGTYP_READONLY(@argname) or .ARGTYP_READONLY(argno) returns .TRUE if the<br>argument was passed as a literal or stack expression rather than a variable.<br>•<br>.ARG_PASSED(@argname) or .ARG_PASSED(argno) returns .TRUE if the argument was|



A-Shell Reference 

Page 639 

||||actually passed by the caller, rather than auto-set via the default value specification in the function<br>declaration. Note that although this function is fully resolved by the compiler, making it at least<br>nominally backwards compatible, on runtime versions prior to 7.0.1767, it acts as the inverse<br>of .ARGTYP_READONLY(). For example...<br>call fn'foo(arg=9)<br>...<br>function fn'foo(arg=1 as b2)<br>? .ARGTYP_READONLY(@arg)  ! .TRUE in all cases<br>? .ARG_PASSED(@arg)    ! .TRUE if > 7.0.1766, else FALSE<br>endfunction<br>The argument is readonly because it was passed as a literal value. The function could try to update<br>it using<br>`XPUTARG(@arg1)`but it would have no effect, since the value is on the stack.<br>But readonly or not, it was actually passed, which might be meaningful to the called function.<br>However, prior to 7.0.1767, the runtime is unable to determine that, so it will the readonly status<br>instead. From 1767 forward, the two flags are independent.|
|---|---|---|---|
|1050|1767.0|6 Jan 2025|Skip over the body of functions when there is an error in the function declaration. This eliminates a<br>domino effect that often generates an avalanche of errors that are all secondary to the one error in<br>the declaration.|
|1049|1767.0|6 Jan 2025|Setting an OUTPUTONLY function parameter default to anything other than 0, "", or .NULL now<br>generates an error. Although in theory that should be legal, allowing it runs too high of a risk of it|



A-Shell Reference 

Page 640 

||||not behaving as the programmer might have expected due to changes in the way OUTPUTONLY<br>parameters have been handled historically.|
|---|---|---|---|
|1048|1765.9|05 Dec 2024|Fix: structure-type function parameters with default values were triggering spurious compiler syntax<br>errors.|
|1047|1765.6|24 Nov 2024|Fixes:<br>•   Specifying a default value for a parameter in a function declaration was effectively overriding the<br>outputonly clause.<br>•   The :outputonly attribute was making it impossible to specify that parameter by name in a<br>DYNFUNC() call.|
|1046|1757.5|29 Apr 2024|Add some performance statistics to the end of the LSX file.|
|1045|1757.5|29 Apr 2024|++IFDEF <structname> was not working properly during the /px pre-scan, resulting in spurious<br>"function not defined" errors if the target function was dependent on such a conditional.|
|1044|1756.1|01 Mar 2024|With the /X:2 switch, an OPEN statement whose RECNO variable was the last variable MAPped was<br>generating a spurious illegal variable size error.|
|1043|1756.0|20 Feb 2024|Add new ASB control statementEXITPROGRAM<br>.|
|1042|1752.5|13 Dec 2023|1. Extend the 1041 edit to treat all case variations of a variable named DATN (datn, DatN, etc.) in a<br>MAPstatement, whether scalar or array, as entirely disabling recognition of the double-arctangent<br>function—i.e. reverting entirely to the behavior before that function was introduced.<br>2. Compiler now complains about INPUT statements targeting an array or a gridmap that are|



A-Shell Reference 

Page 641 

||||missing the CSV token.|
|---|---|---|---|
|1041|1752.2|04 Dec 2023|DATN is no longer treated as a keyword (double arctangent function) if it appears in aMAP<br>statement first.|
|1040|1751.4|04 Nov 2023|Internal cleanup of potential 64 bit overflow issues.|
|1039||||
|1038|1750.3|08 Oct 2023|Eliminate bogus runtime error 74 when passing a collection via DYNFUNC.|
|1037|1742.0|25 Sept 2023|PRIVATE blocks in a main program module were not getting initialized by the first function call. This<br>would have been a problem if the block contained DIMX statements or actual code that needed to be<br>executed.|
|1036|1742.0|25 Sept 2023|WRITECD ARY() statement now supports numeric array types as well as gridmaps.|
|1035||||
|1034|1739.4|15 Aug 2023|Add new convenience operator to assign elements to an array in a single operation from a CSV-<br>formatted string:|
|1033|1735.2|02 Aug 2023|Transclude fix: Eliminate spurious errors when the TCF spec in a ++include statement contained a<br>device prefix.|
|1032|1735.2|02 Aug 2023|Transclude fix: Private variables in transcluded modules weren't getting initialized.|



A-Shell Reference 

Page 642 

|||||
|---|---|---|---|
|1031|1735.2|28 July 2023|Transclude fix: Eliminate spurious errors when the TCF spec in a ++include statement contained a<br>device prefix.|
|1030|1735.1|27 July 2023|Transclude fixes:<br>•   Failure to specify a TCF section in the ++include line was causing the operation to ignore the TCF<br>file contents.<br>•   PRIVATE module variables now work as expected in transcluded modules. Previously, the<br>compiler was complaining of duplicate variables.|
|1029|1735.0|23 July 2023|Transclude fix: ++include with [p,pn] was getting confused with the new transclude syntax.|
|1028|1735.0|23 July 2023|Correct problem with spurious errors caused by appearance of keywords in DEFXCALL parameter<br>lists. Problem was introduced in edit 1020.|
|1027|1734.4|07 July 2023|Transclude statement was treating spaces after the second comma (separating the TCF spec from<br>the section name) as significant, almost certainly causing it to abort with a section not found error.|
|1026|1733.0.3|19 June 2023|Provide support for storing a label reference in a numeric variable and then using it as the target of<br>a GOTO, CALL or GOSUB statement.|
|1025|1732.0.4|12 June 2023|Add support for "transclude" variation of ++include directives.|
|1024|1731.2|06 June 2023|Correct another variation of the bug partially fixed in edit 1023.|



A-Shell Reference 

Page 643 

|1023|1731.1|06 June 2023|Correct an issue introduced in compiler edit 1022 resulting in bogus compiler errors for certain<br>combinations of ordered map parameter passing.|
|---|---|---|---|
|1022|1731.0.1|29 May 2023|Compiler now complains about mismatched collection arrays passed by reference to functions.|
|1021|1730.5.3|23 May 2023|++IFDEF directive now recognizes DEFXCALL.|
|1020|1730.5.2|23 May 2023|DEFXCALL now allows subroutine names that are also keywords—e.g. Xcall Ashell. Standard include<br>file ashinc:xcall.def updated accordingly.|
|1019|1728.2|25 Mar 2023|RUN header was getting corrupted if program had more than 8K of DATA statement values and a<br>minimum run version requirement. VERSYS would report the bad header but the runtime system<br>would most likely crash if program was run.|
|1018|1728.1.2|25 Mar 2023|Remove a spurious syntax error when the READ'ONLY option was included on a file opened in<br>RANDOM mode.|
|1017|1728.1.1|25 Mar 2023|Compiler edit 1017: ORDMAPM assignments were not being compiled correctly, resulting in null<br>values being assigned. Introduced in compiler edit 1016.|
|1016||||
|1015|1727.0.2|11 Mar 2023|An ordered map copy of the form $map1() = $map2() may have triggered a spurious syntax error in<br>the subsequent statement.|
|1014|1725.0.1|14 Feb 2023|Add support fortrigonometric DATN function<br>.|



A-Shell Reference 

Page 644 

|1013|1724.0.4|06 Feb 2023|DIMX arrays of type B, F and I may now be passed by reference to functions.|
|---|---|---|---|
|1012|1724.0.3|06 Feb 2023|DIMX arrays of type S may now be passed by reference to functions. Previously, only type X was<br>allowed.|
|1011|1724.0.2|06 Feb 2023|Resolve a conflict between the GLOBAL_BEGIN pragma and dynamic structure compilation that was<br>causing spurious compiler errors.|
|1010|1724.0.1|06 Feb 2023|Minor internal adjustments to improve code portability and robustness.|
|1009|1721.7.1|09 Nov 2022|DATA statements longer than 512 bytes were overflowing an internal statement buffer without<br>triggering a proper compiler error, in some cases causing the compiler to crash. The limit has been<br>increased to 1024. However, note that multi-term DATA statements can always be broken up into<br>multiple DATA statements; the limit will therefore only be an obstacle in cases where the length of a<br>single DATA term exceeds it.|
|1008|1721.3.1|05 Oct 2022|The embeddedDEFSTRUCT<br>index wasn't being terminated properly, leading to<br>DEFSTRUCT/DYNSTRUCT binding errors under certain sequences.|
|1007|1721.1|28 Sept 2022|DEFSTRUCT members with initial values or overlays were not being compiled correctly, typically<br>either leading to bogus compiler error messages or invalid syntax or out of memory errors when<br>using DIMX to create an array of structure elements.|
|1006|1721.1.4|25 Sept 2022|Close a loophole in which certain array variable references nested within with function parameter<br>lists were triggering bogus unmapped variable compiler errors.|
|1005|1721.1.3|25 Sept 2022|Auto-binding of a DEFSTRUCT to a DYNSTRUCT when passing parameters to a function was not|



A-Shell Reference 

Page 645 

||||working for function parameters defined with default values.|
|---|---|---|---|
|1004|1721.1.2|25 Sept 2022|DEFSTRUCTs embedded in the RUN file were missing DEFTYPE information—i.e. any DEFTYPEs in the<br>DEFSTRUCT were converted to the native types.|
|1003|1720.7.1|14 Sept 2022|/F1 switch wasn't eliminating all minimum run versions from the header.|
|1002|1720.4|07 Sept 2022|A label named SET'RECNO or XOPEN was incorrectly setting the minimum runtime version in the<br>RUN header to 1684, as if it had seen the statements by those names.|
|1001|1720.0.8|31 Aug 2022|Language enhancement, compiler edit 1001: The CALL statement can now be used to invoke a<br>dynamic function. For example:<br>CALL DYNFUNC(func$,args...)<br>CALL DYNFUNC$(func$,args...)<br>This is analogous to using the CALL statement with static function, and is more natural than a<br>dummy assignment when you don't care about the return value of the function. Requires A-Shell<br>6.5.1720+.|
|1000|1720.0.5|31 Aug 2022|Language enhancement: named parameters can now be used with DYNFUNC, e.g.<br>DYNFUNC(fname$, argx=valuex, argy=value1)<br>Note that this affects both the compiler and runtime, so the use of named parameters in a DYNFUNC<br>expression will now set the minimum runtime level to 6.5.1720.|



A-Shell Reference 

Page 646 

||1720.0.7|31 Aug 2022|/CI support now extended to dynamic functions, both the function names and argument names.|
|---|---|---|---|
|999|1720.0.6|31 Aug 2022|Language enhancement: default parameter values are now supported in dynamic functions.<br>Previously the compiler didn't complain, since functions declared dynamic can still be called<br>statically.<br>Note that in the case of dynamic functions, default values are limited to constant expressions,<br>whereas for static functions, they could involve variables.<br>Use of default values in a dynamic function definition now sets the minimum runtime level to 1720,<br>so programs that ran under earlier runtimes (whether or not the default values were respected) will<br>now require the 6.5.1720+ runtime.|
|998|1717.14.14|03 Aug 2022|• The /CI (case insensitive) option was affecting DEFINEd literal strings. This bug was introduced in<br>edit 994).<br>• Symbol definitions passed in via the /C: switch were being lost if the program was too big for the<br>specified options, leading to an automatic compilation restart with the /A or /AV switches activated.|
|997|1717.13.2|02 Aug 2022|Internal compiler code refinements.|
|996|1717.12.1|27 July 2022|Fix crash related to embedded defstructs.|
|995|1717.4.2|9 June 2022|the existence of a ++ directived within the text following a ++MESSAGE or ++ERROR directive was<br>in some cases confusing the compiler as to conditional compilation state.|
|994|1717.4.1|9 June 2022|Refinements toDEFALIAS<br>:<br>•  ++IFLBL / ++IFNLBL now recognize DEFALIAS'd function and procedure labels, acting based on|



A-Shell Reference 

Page 647 

||||the existence of the target function / procedure (and not the existence of the DEFALIAS definition).<br>•  ++IFDEF / ++IFNDEF now treat DEFALIAS definitions as they would symbols defined via DEFINE<br>statements.<br>•  UNDEF now works on DEFALIAS definitions.|
|---|---|---|---|
|993|1716.6.2|26 May 2022|fix several issues related to .SUBLIST and .SPLICE: (1) passing a .SUBLIST to a function expecting a<br>list was causing a spurious array vs. scalar mismatch compilation error; (2) in some statements<br>a .SUBLIST was being treated as scalar variable, possibly leading to a spurious compilation error or<br>real runtime error; (3) a FOREACH statement iterating through a .SUBLIST may have thrown a<br>spurious compilation error; (4) the 3-argument version of .SPLICE was being compiled incorrectly,<br>leading to possible stack corruption at runtime.|
|992|1716.6.1|26 May 2022|attempting a private instantiation of a DEFSTRUCT containing overlaid variables was resulting in a<br>spurious compiler error.|
|991||||
|990|1716.3.1|19 May 2022|close a loophole in which function call parameter lists containing literals might trigger a spurious<br>syntax error or fail to compile correctly. Also syntax error messages now display a suffix "-->><br>xxx ..." where xxx indicates the part of the line where the syntax error was detected. This is mainly<br>helpful in very long source lines where it is sometimes difficult to find the missing or misplaced<br>character.|
|989|1715.12.2|13 May 2022|close a loophole introduced in edit 984 resulting in the corruption of some function calls and XCALLs,<br>primarily in the CentOS environment.|
|988|1715.12.1|13 May 2022|minor refinements to the LSX file structure to ensure that the LSX compilation is fully independent of|



A-Shell Reference 

Page 648 

||||the environment in which it was created.|
|---|---|---|---|
|987|1715.11.2|13 May 2022|fix problem with ++INCLUDE'IF'EXISTS when compiling an LSX file in a different environment than<br>where the LSX file was originally created. If the existence at the time the LSX was created didn't<br>agree with the existence when compiling the LSX, the ++include nesting levels would get out of<br>sync with the original, possibly leading to bogus compilation errors.|
|986|1715.10|06 May 2022|the first unmapped variable, if numeric, was failing to finalize the definition of last mapped variable,<br>causing it to behave in certain expressions as if it had the default size for its type. Problem was<br>introduced in one of the early 6.5 versions.|
|985|1715.9.1|03 May 2022|DEFTYPEs associated with structure members were not being saved or retrieved by the<br>MX_DYNSTRUCT operations. The native type,size info was still correct, but applications relying on on<br>the DEFTYPEs were out of luck. Bug was introduced in 6.5.1711.|
|984|1715.8.1|01 May 2022|tighten the syntax checking on named parameter lists (both XCALL and function/procedure) to<br>require that scalar parameters are passed scalar values and array (byref) arguments are passed<br>array (byref) values.|
|983|1715.7.1|23 Apr 2022|further refinement to edit 982 to eliminate spurious complaint about XCALL array parameters with<br>spaces within the parentheses, e.g. XCALL MYSBX, ARY( 1 ), ...|
|982|1715.6.1|22 Apr 2022|replacement for edit 981 (which was recalled).|
|981|1715.5.1|21 Apr 2022|extend the fix in edit 978 to apply to XCALL named parameters (defined with DEFXCALL).|
|980|1714.3.1|21 Apr 2022|fix for spurious error "cannot input from output-only parameter) on XGETARG when the specified<br>argument number was one beyond the number of parameters formally declared. Apply range|



A-Shell Reference 

Page 649 

||||checking on the XGETARG argument number to make sure > 0 and < 1024 (max).|
|---|---|---|---|
|979|1714.2.1|12 Apr 2022|RND2 / SRND2 were failing to set the minimum runtime version to 1517.|
|978|1714.1.1|08 Apr 2022|fix problem introduced in edit 975 causing spurious undefined parameter errors with function<br>parameter definitions of the form $ary()=.NULL as ordmap(...).|
|977|1713.0.1|08 Apr 2022|new system function TRIM(strexp), or TRIM$(strexp). This removes the leading and trailing blanks<br>from the string expression argument, equivalent to the combination of STRIP$(strexp) and LSTRIP$ (strexp).|
|976|1712.4.3|21 Mar 2022|MX_DYNSTRUCT DYNOP_DEF calls referencing file-based DEFSTRUCTs were incorrectly handling<br>array members of the structure if the file contained a ++PRAGMA PRIVATE section prior to the<br>DEFSTRUCT.|
|975|1712.4.2|20 Mar 2022|named parameter references to arrays (byref) were incorrectly accepting scalar parameter name<br>syntax.|
|974|1712.4.1|20 Mar 2022|various minor improvements to the clarity of certain error messages.|
|973|1712.3.1|20 Mar 2022|the ++PRAGMA GLOBAL_xxx was causing symbol definitions passed in to the compiler on the<br>command line (via /C:symbol=definition) to be lost.|
|972|1712.0.3|08 Mar 2022|clean up minor issues relating to spurious errors appearing after real prior errors.|
|971|1712.2.1|27 Feb 2022|new system function LSTRIP(strexp), or LSTRIP$(strexp), strips leading blanks from the specified|



A-Shell Reference 

Page 650 

||||string expression.|
|---|---|---|---|
|970|1712.0.1|28 Feb 2022|remove all special adjustments to the operator precedence rules in shortcut operator statements.<br>This is an extension / cleanup of the change in 6.5.1708.1 (compiler edit 958) which restored the<br>normal precedence rules for trailing USING operators.|
|969|1711.4.1|27 Feb 2022|fix bug causing a bogus syntax error on an expression involving a nested USING clause in a shortcut<br>operator assignment. Bug was introduced in 6.5.1708.1 (compiler edit 958).|
|968|1711.3.1|23 Feb 2022|improve clarity of error messages relating to argument lists. Also close loophole allowing illegal<br>parameter sizes to fail to trigger an error.|
|967|1711.2.1|22 Feb 2022|LSX file ++include indicators now show a <##_#> suffix indicating the sequential file # and the<br>nesting level.|
|966|1711.1.3|17 Feb 2022|close window of opportunity for GPF associated with errors related to embedded DEFSTRUCTs.|
|965|1711.1.15|16 Feb 2022|include features mentioned elsewhere.|
|964||14 Feb 2022||
|963|1711.0.8||fix bug introduced in compiler edit 892 to support dynamic structures.|
|962||14 Feb 2022||



A-Shell Reference 

Page 651 

|961||||
|---|---|---|---|
|960||||
|959|1708.1.2||new auto-defined macro ABC_SCALE is set to the current SCALE value (0 if no SCALE statement yet<br>encountered).|
|958|1708.1.1|27 Oct 2021|USING expressions on the right side ofShortcut Operators<br>are now evaluated after the completed<br>expansion of the shortcut operator statement.|
|957|1708.1.6|27 Oct 2021|DEFALIAS<br>now updates the effective type (string or numeric) of the function, making it possible to<br>alias a numeric function call to a string function or vice versa.|
|956|1708.0.5|21 Oct 2021|close a loophole that resulted in a bogus syntax error following an instance of an array base<br>reference in an XCALL parameter list.|
|955|1707.3.1|21 Oct 2021|use of an automapped %m variable in the global context was resulting in a memory error at<br>runtime.|
|954|1707.2.1|07 Oct 2021|close two loopholes related to the use of %x auto-mapped variables (see 1707.0 below) which were<br>resulting in spurious compiler error messages.|
|953|1707.1.1|06 Oct 2021|MX_DYNSTRUCT DYNOP_DEF was not supporting.SIZEOF()<br>, resulting in a spurious error.|
|952|1707.0.2|04 Oct 2021|MX_DYNSTRUCT<br>support: the default amount of work area memory allocated when defining<br>(compiling) a dynamic structure has been increased from 128K to 2M.|



A-Shell Reference 

Page 652 

|951|1707.0.1|03 Oct 2021|auto-mapped variables are now confined to local contexts.|
|---|---|---|---|
|950|1706.3.1|03 Oct 2021|eliminate bogus "ambiguous relop" errors in nested control statements involving DYNSTRUCT<br>references.|
|949|1706.0.2|28 Sep 2021|supports automapped %var variables.|
|948|1705.9.1|24 Sep 2021|automapped for/next loop variables (see 6.5.1704.0) were generating bogus compiler errors if there<br>was a ++extern statement in the same function.|
|947|1704.1.1|05 Sep 2021|all standard string functions now support the optional $ suffix on the name (e.g. STR(x) or STR$(x).)|
|946|1704.0.1|10 Jun 2021|auto-mapped for/next loop variables. You may now create a new variable on the fly to act as the<br>loop counter in a for/next loop by preceding the variable name with a %. SeeFOR … NEXT<br>Control<br>Structures.|
|945|1703.0.3|05 Jun 2021|eliminate spurious error complaining about the type or size of the record number parameter in a file<br>OPEN statement if the parameter is part of a DIMX array.|
|944|1702.2.1|18 May 2021|generate error if non-F6 var specified in OPEN statement.|
|943||08 May 2021||
|942|1697.1.1||references in PRINT statements to entire arrays, such as PRINT .EXTENT(ARY()), were resulting in<br>spurious syntax  errors.|



A-Shell Reference 

Page 653 

|941|1697.0.1|27 Jan 2021|WRITECD of an entire array.|
|---|---|---|---|
|940|1696.1.1|22 Jan 2021|close a loophole resulting in spurious "attempt to input from output only parameter" (or vice versa)<br>errors in  SBXs.|
|939|1695.0.1|18 Jan 2021|new feature: "Implicit function return value capture". That's a mouthful to describe what is really a<br>kind of "syntactic sugar" to  simplify referencing the result of a previously called function without<br>having to map a variable and explicitly assign the value to it.|
|938|1690.3.1|10 Jan 2021|support a ++ifdef ... ++endif statement on a single source line.|
|937|1689.2.1|08 Oct 2020|arrays/collections may now be passed to DYNFUNC(), as they can in normal function references.<br>Previously only  array elements were supported.|
|936||10 Sep 2020||
|935|1687.0.1||new dot variables:  .MILLITIME returns number of milliseconds since midnight, and .MICROTIME<br>returns number of microseconds since midnight. a missing closing parenthesis on the end of a<br>function parameter list wasn't always being flagged as a  syntax error. It was compiling as if the<br>closing parenthesis had been there.|
|934|1686.0.1|17 Jul 2020|new unambiguous shortcut  operators:  #+= and $+=. These are equivalent to the existing shortcut<br>operator += except that they unambiguously specify either addition or concatenation, respectively,<br>regardless of the destination type.|
|933|1685.0.1|02 Jul 2020|new dot variables: SBXNAME, SBXVERSION, CCYYMMDD, MMDDYY, DDMMYY, RECSIZ.|



A-Shell Reference 

Page 654 

|932|1684.0.4|01 Jul 2020|XOPEN now supports RANDOM and ISAM 1.x files. Also, XOPEN supports the option of expressing<br>the flags argument as an expression rather than as a binary variable.|
|---|---|---|---|
|931|1684.0.2|12 Jun 2020|in programs compiled without the /X:2 or /RC switches, the memory storage assigned to the last<br>explicitly mapped  variable was overlapping the first unmapped variables (assuming no /M). Problem<br>was introduced in compiler edit 894 (A-Shell 6.5.1656.1)|
|930|1684.0.1|12 Jun 2020|the new SET'RECNO statement was causing a syntax error on a subsequent statement in certain<br>contexts.|
|929|1683.0.5|12 Jun 2020|new ++PRAGMA FORCE_F1_HDR "<boolean>" may be used to toggle the /F1 switch. Use of<br>the .ISNULL() function now sets the minimum runtime version to 1414.|
|928|1683.0.4|08 Jun 2020|updated to support various language enhancements.|
|927|1679.2.1|08 Jun 2020|STRSIZ 0 was causing spurious errors in some function declarations.|
|926|1676.1.1|14 Apr 2020|in programs compiled without the /M  (require all variables to be mapped) option, a reference to a<br>non-existent  structure member (ST.MEMBER) within an otherwise defined structure (ST) was<br>resulting in the structure name getting auto-mapped as a F,6 variable.|
|925|1673.2.1|06 Feb 2020|some variations of invalid DEFTYPE  statements were crashing the compiler.|
|924|1672.2|02 Jan 2020|revises edit 923 so that all ++ conditional compilation directives within functions and procedures are<br>included in the LSX, even if within a function that has been shaken out by the /PX switch. Such<br>conditionals may still be be relevant to how the rest of the file is compiled, and this resolves<br>problems with conditionals that span the start or end of a routine.|



A-Shell Reference 

Page 655 

|923|1672.1|13 Dec 2019|incorrect minimum run version was written into object header in some cases. LSX file may have<br>ended up with mismatched ++IF/++ENDIF if a conditional block straddled the function definition<br>and the function was shaken out by the /PX switch.|
|---|---|---|---|
|922|1671.4.5|13 Dec 2019|attempting to use the .ISNULL() function with a non-string argument now generates an illegal<br>expression error.|
|921|1671.0.5|05 Dec 2019|optimizes the runtime code generated by trace statements of the forms DEBUG.PRINT <args> and<br>TRACE.PRINT (level,tags) <args>|
|920|1670.0.5|05 Dec 2019|the Minimum Run Version stored in the program header now distinguishes between two variations of<br>the .CLEAR statement.|
|919||01 Nov 2019||
|918|1668.0.2||the Shortcut Operators<br>+= and -= now work with collections.|
|917|1665.4|19 Sep 2019|eliminate spurious "exceeded 512K limit" error on DATA statements when used in conjunction with<br>some newer features.|
|916|1665.3.2||static functions which were called only by dynamic functions were getting shaken out of the tree by<br>the /PX algorithm.|
|915|1665.2|30 Aug 2019|the presence of a single Dynamic function was disabling the /PX removal of un-called functions. It<br>now only ensures that no Dynamic functions are removed, since we can't be sure if they are called<br>dynamically.|



A-Shell Reference 

Page 656 

|914|1665.1.2|30 Aug 2019|add comment marker (!) to "{shaken out by /PX}" notations in the LSX file for ease of recompiling<br>from the LSX.|
|---|---|---|---|
|913|1664.4.1|30 Aug 2019|TRACE.xxx statements were not allowing additional statements on the same line (using colon<br>separators). Not that we'd like to encourage the anachronistic practice of jamming several<br>statements together on a single line (presumably for the purpose of sharing a single THEN or ELSE<br>clause), when it is much cleaner to use the multi-line IF/ENDIF construction. But technically it should<br>be legal.|
|912|1664.3.2|11 Aug 2019|the /PX switch was causing .GLBI (and previously CMPGLOBAL.TMP) temporary files to be left<br>behind.|
|911|1664.2.1|11 Aug 2019|the temporary file used to hold a GLOBAL_BEGIN/END block now uses a source-file-specific name<br><source>.glbi instead of the fixed name cmpglobals.inc. This resolves a conflict with running<br>multiple simultaneous compilations in the same directory.|
|910|1663.0.1|11 Aug 2019|new ++pragma provides a way to assign a name to the LSX file that includes the vedit field of the<br>program version: ++PRAGMA LSX_FSPEC "filespec" where "filespec" can be an A-Shell-style or<br>native filespec, optionally including the following special macros:|
|909|1662.2.2|22 Jul 2019|compiler was failing to recognize the new LSX headers, causing total failure to be able to recompile<br>LSX files.|
|908|1662.0.6|14 Jul 2019|fix failure to allow IFE() and IFE$() functions within relative expressions, e.g. IF IFE$(A$,B$) =<br>C$ ...|
|907|1661.2|24 Jun 2019|.sizeof(var) was generating spurious variable not found errors for defstruct references in isolated<br>cases. Introduced in compiler edit 902.|



A-Shell Reference 

Page 657 

|906|1661.1|06 Jun 2019|.sizeof(var) was generating spurious variable not found errors under a certain situations. Introduced<br>in compiler edit 902.|
|---|---|---|---|
|905|1661.0.7|06 Jun 2019|new functional directive EXTERN().|
|904|1661.0.5|06 Jun 2019|resolve an issue with MX_DYNSTRUCT in which source files with multiple DEFSTRUCTS containing<br>MAP1 statements may have led to corrupted extents of array members of the target structure.|
|903|1661.0.3|06 Jun 2019|.SIZEOF() now supports DEFTYPE names, e.g. .SIZEOF(BOOLEAN).|
|902|1660.7.1|06 Jun 2019|.SIZEOF(VAR) was not respecting scope, (i.e. was finding global VAR when it shouldn't.)|
|901|1660.4.5|08 May 2019|IFELSE(relexpr,expr1,expr2), along with the IFELSE$() string version, were both treating the relexpr<br>as being purely numeric, which after edit 890 was resulting in any string operands within the relexpr<br>being converted to numeric prior to evaluation. This rendered string comparisons, e.g. A$ > B$ as<br>being equivalent to VAL(A$) > VAL(B$), which had only about a 50% chance of giving the expected<br>result.|
|900|1660.4.4|08 May 2019|in /X:1 or /X:2 mode, a FOR/NEXT loop was incorrectly starting from one STEP unit after the correct<br>starting value if the initial expression ended with an operator with lower precedence than addition.<br>For example, FOR I = X MAX Y TO Z was starting at (X MAX Y) + 1 rather than (X MAX Y) because<br>MAX has lower precedence than the implicit addition or subtraction of the step value. The problem<br>didn't affect theOCMPILimplementation of FOR/NEXT, and didn't occur if the 'from' expression was<br>parenthesized. Same patch as 6.4.xxxx.|
|899|1660.4.3|08 May 2019|++PRAGMA GLOBAL_BEGIN wasn't working when the source file spec was longer than 50 characters<br>—i.e. when using native filespec notation for the program source.|



A-Shell Reference 

Page 658 

|898|1660.0.2|08 May 2019|MX_DYNSTRUCT now allows DEFTYPE aliases for implicitly sized X variables. There were previously<br>allowed, but the DEFTYPE name was lost during the runtime compilation.|
|---|---|---|---|
|897|1659|08 May 2019|fix for IFE() and IFE$() functions; original implementation didn't hold up when nested within other<br>types of expressions, in particular IFELSE(). Note that the fix involves both the compiler and<br>runtime.|
|896|1657.0.2|26 Mar 2019|compiler now embeds into the object header an indication of the minimum acceptable A-Shell<br>runtime version, when certain newer language features are present. Runtime versions prior to<br>6.5.1657 will not recognize the new header signature and will treat the RUN as invalid (i.e. will<br>refuse to run it). From this version on, the runtime system will recognize the minimum version<br>header and will give a more precise error. Program requires minimum A-Shell level ####.|
|895|1657.0.1|03 Mar 2019|new functions IFE() and IFE$().|
|894|1656.1.a|03 Mar 2019|close loophole in the ++PRAGMA TRACE_BEGIN logic that was resulting in spurious variable-not-<br>defined errors in certain kinds of IF <expr> GOTO <label> statements where the <expr> involved a<br>function call.|
|893|1656.0.2|27 Feb 2019|LSX Header now includes more detail.|
|892|1656.0.1|27 Feb 2019|add Explicit Comparison Operators<br>.|
|891|1655.0.2|27 Feb 2019|new pragma ++PRAGMA AUTO_LARGE_CONSTANTS.|
|890|1655.0.1|14 Feb 2019|new operators and casting functions NUMEXPR, STREXPR, #+, $+ to eliminate the ambiguity in the<br>+ operator.|



A-Shell Reference 

Page 659 

|889|1651.8|14 Feb 2019|unmapped struct.member errors now display the full struct.member name. Previously it was only<br>noting the structure name.|
|---|---|---|---|
|888|1650.0.1|18 Dec 2018|high level operations to Copy, Add, Subtract Collections (i.e. ORDMAP, ORDMAPM and MLIST<br>structures) to/from each other.|
|887|1650.0.2|08 Nov 2018|++PRAGMA TRACE was generating spurious unmapped variable errors when encountering named<br>parameter references inside function argument lists within certain kinds of statements (such as IF).|
|886|1649.0.4|08 Nov 2018|the ++IFMAP and ++IFNMAP conditional directives were always operating relative to the GLOBAL<br>scope, rather than the scope (and extern rules) that would apply to the a variable in that context.<br>For example, ++IFNMAP FOO within a function now checks for the existence of a variable FOO in the<br>same way that a regular reference to FOO in that context would, i.e. considering a locally defined<br>FOO, then a module private FOO, and then—if auto_extern or or ++extern FOO had been specified—<br>a global FOO.|
|885|1648.1.1|22 Oct 2018|the first dynamic function compiled was missing the type,size attributes in the dynamic function<br>index.|
|884|1647.4.1|04 Oct 2018|close memory corruption loopholes in the DYNSTRUCT compilation routines.|
|883|1647.2|30 Sep 2018|dynamic functions were unable to be located within RUN modules that were automatically<br>recompiled with /A or /AV by the compiler due to the size. The .fn alias for the current function<br>name was not working with private functions.|
|882|1647.0.4|30 Sep 2018|the Dynfunc mechanism now allows for retrieval of function return type information; see<br>MX_DYNFUNC. TRACE.PRINT statements with the (level) and/or (level,tags) option were throwing<br>bogus syntax errors for variations that weren't errors.|



A-Shell Reference 

Page 660 

|881|1647.0.3|30 Sep 2018|support .fn (case INsensitive) within a function as an alias for the function name variable. For<br>example...|
|---|---|---|---|
|880|1647.0.2|30 Sep 2018|use of Ellipsis (...) in argument lists to facilitate passing arguments through a wrapper function.|
|879|1647.0.1|30 Sep 2018|language extension: Dynamic Function Calls.|
|878|1646.6.1|30 Sep 2018|revise compilation of ds.field(x) and ds.@fname$(x) to allow for better runtime error detection and<br>handling. Incorrect use of ds.@fname$(x) in place of ds.@fname$(x)(y) can now be trapped at<br>runtime with error 71, undefined dynstruct member. Any programs using DYNSTRUCT must be<br>recompiled! Improve robustness of file-based MX_DYNSTRUCT DYNOP_DEF. Disable the auto-tracing<br>—activated by ++PRAGMA TRACE_BEGIN—ofMAP Statements<br>with initializers, as this was leading<br>to spurious errors. Fix spurious compiler error on IF <expr> RESUME <label>. Fix problem with +<br>+PRAGMA TRACE_BEGIN appearing to have no effect after a previous ++PRAGMA TRACE_BEGIN at<br>the same nesting level.|
|877|1646.1|15 Sep 2018|change syntax for indirect deferred dynstruct references from ".." to ".@" : ds.@fname  ! fname<br>contains name of member (was ds..fname); ds.fname   ! fname is name of member (same as<br>before)|
|876|1646.0.1|15 Sep 2018|the DYNOP_DEF operation in MX_DYNSTRUCT now supports reading the structure definition from<br>ASB source files in addition to strings.|
|875||15 Sep 2018||
|874|1645.0.2||fix problem with CASE SYMBOL1...SYMBOL2 introduced in edit 870; Report any dynamic (S,0 or X,0)<br>variable within a DEFSTRUCT as an error; Reset default trace level to 0, was 99 as of edit 871.|



A-Shell Reference 

Page 661 

|873|1645.0.1|29 Aug 2018|add dynamic structures.|
|---|---|---|---|
|872|1644.1|29 Aug 2018|the overall length of a ++PRAGMA statement was being incorrectly limited to 50 characters, which<br>was mainly affecting TRACE_BEGIN. The new limit is 600 characters, with a max of 512 for the<br>TRACE_BEGIN token-list—the fourth argument).|
|871||23 Aug 2018||
|870|1642.2.3||eliminate the ambiguity surrounding a defined symbol XXX when .XXX is an internally defined<br>symbol—e.g. .TRUE. The problem was that the XXX was getting translated independently of the dot,<br>resulting in unexpected results. For example assuming DEFINE TRUE = 1, a subsequent reference to<br>.TRUE was returning .1 (substituting TRUE for 1 independent of the dot) rather than -1 (the built-in<br>definition of .TRUE). Attempts to define symbols with leading dots are now considered errors, and<br>references to symbols with leading dots consider only the dot version.|
|869|1642.2.2|15 Aug 2018|internal refinement to support the possibility of dynamically compiling defstructs at runtime.|
|868|1641.0.1|15 Aug 2018|PRIVATE variables and ++PRAGMA PRIVATE_BEGIN / _END blocks may now be used in the main<br>source module to limit the scope of those variables to just that source file. Note that this<br>enhancement entirely handled by the compiler; there is no issue with backwards or forwards<br>runtime compatibility, even under AMOS.|
|867||03 Aug 2018||
|866|1639.3.4||fix some minor aesthetic problems with the auto tracing mechanism.|
|865|1639.3.3|16 Jul 2018|add private functions to the tags file for the benefit ofAPN.LITand the Go To Definition script.|



A-Shell Reference 

Page 662 

|864|1639.3.2|16 Jul 2018|a DIMX array defined locally to a routine and then passed by reference to another routine was<br>incorrectly getting deallocated return from the lower routine.|
|---|---|---|---|
|863|1639.2.2|16 Jul 2018|trace statements involving more than one comma-delimited term, of which at least one was a<br>quoted string constant, where being formatted in a confusing way.|
|862|1639.0.7|16 Jul 2018|support the /NOTRC option (or -notrc when using the standalone compiler executable).|
|861|1639.0.5|16 Jul 2018|new ++PRAGMAs to support enhanced tracing ++PRAGMA TRACE_BEGIN   {optionlist}, ++PRAGMA<br>TRACE.END     {optionlist}, ++PRAGMA TRACE.OPTIONS {optionlist}|
|860|1637.3.2|16 Jul 2018|compiler was failing to flag a syntax error for WRITECD and WRITETD statements lacking a comma<br>or semicolon between each field.|
|859|1636.0.4|12 Jun 2018|the starting key in a FOREACH statement may now be any kind of expression.|
|858|1633.0.2|26 May 2018|very long FOR statements were potentially failing to compile correctly due to an overflow, without<br>triggering a compiler error.|
|857|1631.1.2|15 Apr 2018|the /PX logic was failing to recognize a call to a function that was specified as the initializer to a<br>MAPstatement, thus opening up the possibility that the function would be removed, leading to a<br>function-not-found error.|
|856|1631.0.5|06 Mar 2018|close a loophole that was allowing the compiler to go into an infinite loop in certain obscure cases<br>involving unterminated literal strings with conditional compilation blocks.|
|855|1630.1.2|06 Mar 2018|SCALE: XPUTARG literal argument numbers and literal .EXTENT index numbers were not being|



A-Shell Reference 

Page 663 

||||scaled in the RUN file. The updated run-time system will now handle it either way.|
|---|---|---|---|
|854|1629|22 Feb 2018|add language feature: INPUT CSV into a Dynamic Array.|
|853|1628.1.2|15 Feb 2018|(a) XPUTARG @PARAM was not working properly with SCALE; (b) compiler now properly complains<br>about a dangling comma at the end of a function/procedure parameter list. Previously such<br>superfluous commas were ignored, but introduced doubt as to what the compiler was thinking.|
|852|1628.0.2|13 Feb 2018|increase maximum length of a single line of source code, including continuations, from 3K to 16K.<br>Also increase the limit on the number of xcall / function / procedure parameters from 128 to 1024.|
|851|1628.0.3|13 Feb 2018|(a) /PX was not properly handling ENDFUNCTION statement with line numbers; (b) /P and /PX were<br>not properly handling UNDEF statements; (c) built-in macros ABC_CURRENT_MODULE$ and<br>ABC_CURRENT_ROUTINE$ were in some case returning garbage.|
|850|1626.0.4|13 Feb 2018|the patch in edit 848 for ++IFMAP and /PX now works for /P as well as /PX.|
|849|1625.1|30 Jan 2018|default function and procedure parameter values were not being respected in calls where no named<br>parameters were specified. Problem was introduced in compiler edit 847.|
|848|1625.0.2|25 Jan 2018|(1) Passing a named lblref reference to a function without prefixing the name with @ was compiling<br>but failing to actually pass the parameter. (2) ++IFMAP and ++IFNMAP now work as expected<br>with /PX. Previously, since ++IF conditionals are processed during the initial pass butMAP<br>Statements<br> are not, a function that was only referenced within a block of code conditioned on a<br>seemingly true ++IFMAP would get shaken out out of the tree, resulting in a function-not-defined<br>error. This is now resolved. Note that ++IFMAP <var> only applies to global variables, not local or<br>private variables.|



A-Shell Reference 

Page 664 

|847|1624.3.1|25 Jan 2018|fixes related to indirect/lblref functions:|
|---|---|---|---|
|846|1624.0.2|23 Jan 2018|.CLEAR enhancement: .CLEAR ARY() now supported for all types of arrays; previously it only applied<br>to collections. The details of the clearing operation depend on the nature of the array being clear,<br>described in further detail below.|
|845|1624.0.1|23 Jan 2018|STRSIZ-related refinements.|
|844|1623.0.1|23 Jan 2018|collections passing: Collections can now be passed by reference in an XCALL to an SBX|
|843||22 Dec 2017||
|842|1621.3.2||when using the /LF switch without /M, certain ++EXTERN ARRAY() statements for DIMX and<br>ORDMAP arrays were generating spurious errors: unmapped variable or mismatched type/size.|
|841|1621.2.2|30 Nov 2017|the standalone Unix compiler was failing to process the -b and -l switches correctly. It was also<br>failing to fold++INCLUDEfilenames to lower case if the compiler wasn't running from a directory<br>mapped to a MIAMEDEVICE<br>.|
|840|1621.2.1|30 Nov 2017|certain references to a collection indexed by an array of structures, e.g. $coll(struct(i).member),<br>within a FOREACH loop, were resulting in a spurious error on the NEXT $$i statement at the bottom<br>of the loop.|
|839|1620.0.2|30 Nov 2017|symbol definitions passed on the command line using /C:sym=value were being ignored during the<br>first pass of the /P and /PX processing. Also, the compiler macros ABC_CURRENT_ROUTINE$ and<br>ABC_CURRENT_MACRO$ were in some cases creating an additional spurious macro "A" which might<br>have caused a spurious syntax error for a variable "A".|



A-Shell Reference 

Page 665 

|838|1620.0.1|07 Nov 2017|add ASB StatementDEFALIAS<br>.|
|---|---|---|---|
|837||07 Nov 2017||
|836||||
|835||||
|834|1616.0.2||support .ARGTYP(@arg) and .ARGSIZ(@arg). Concept is similar to that used for XPUTARG @arg (i.e.<br>@arg is treated essentially as a macro for the argument number corresponding to the argument arg<br>as defined in the function/procedure definition or as retrieved in an SBX using XGETARG(S).) No<br>change to the runtime system required.|
|833||07 Sep 2017||
|832||||
|831|1613||relax limitations on XPUTARG @VAR to allow the same parameter number to be associated with<br>multiple variables, provided that the VAR the XPUTARG @VAR statement is never associated with<br>more than a single parameter #.|
|830||||
|829||||
|828|1608.0.1||expand XPUTARG @argname mechanism (see 1607.0) to work for SBXs.|



A-Shell Reference 

Page 666 

|||||
|---|---|---|---|
|827|1607.4.3|29 Jun 2017|compiling with /P or /PX was resulting in spurious "undefined argument" errors in some cases when<br>using the new XPUTARG @arg syntax. See 6.5.1607.0. When compiling with /PX and /LF,<br>unreferenced functions and procedures ending with a two-part 'END' token—e.g. "End Function" or<br>"END PROCEDURE"—were only writing the "END" to the LSX file, causing problems if the LSX was<br>later compiled. The "{shaken out by /px}" line in the body of such routines in the LSX file is now<br>properly commented out, allowing the LSX to be re-compiled without the /PX switch.|
|826|1607.0.2|21 Jun 2017|the maximum source code length of a function declaration was incorrectly set at about 512 instead<br>of 3072 like all other source lines.|
|825|1607.0.1|21 Jun 2017|XPUTARG now supports the ability to reference the parameter to be returned by its name rather<br>than by its number, using the following syntax:|
|824|1606|21 Jun 2017|certain DEFSTRUCT arrangements were generating absurd numbers of bogus syntax errors.|
|823|1605.1||the DEFSTRUCT/MAP1 enhancement added in compiler edit 821 was generally not working for +<br>+include files; an illegal dot within a MAP or DEFSTRUCT variable name wasn't being reported.|
|822|1605|03 Jun 2017|language enhancement adds newShortcut Operators<br>VAR |= expr and VAR &= expr|
|821|1603|29 May 2017|DEFSTRUCT may now include a MAP1 statement as the first member of the structure.|



A-Shell Reference 

Page 667 

The last entry in the table above, compiler edit 821 and A-Shell 1603, marked the beginning of the A-Shell 6.4 development cycle. At present, that marks the end of these notes. The list may be extended farther back in time at some point in the future. See the following topic for a second listing of compiler edits; it excludes bug fixes and overlaps somewhat with the list above, but - it also goes back in time to 2013. For older notes on compiler changes and all A-Shell changes, you can also consult the A Shell Development History documentation. 

A-Shell Reference 

Page 668 

## **COMPILER EDIT HISTORY II** 

This is an older version of the compiler edit history, which differs from the main version in that it omits minor changes and bug fixes. It extends back to compiler edit 624 and A-Shell version 6.1.1339 of March 2013. 

## **- A Shell 6.3/6.4 below here** 

- 2017 March, A Shell 6.4.1547, edit 803:  The line marking the end of a ++INCLUDE now also indicates the module that we are returning to. 

- 2017 March, A Shell 6.4.1546, edit 797:  Maximum nesting levels for ++INCLUDE and ++IF conditions increased from 20 to 40. Improve messaging/recovery for the overflow condition. 

- 2016 November, A Shell 6.3.1538, edit 792:  Add new Dot Functions .LINENO and .LOCATION. 

- 2016 October, A Shell 6.3.1534, edit 790:  Use of .ARGCNT within a PRIVATE_BEGIN / PRIVATE_END block now generates a compile error. Although the expression wouldn't technically be illegal, because the PRIVATE block is essentially called for initialization by whatever function or procedure in the module gets called first, there is really no good way to predict in advance what the .ARGCNT value will represent, and thus it is almost certain to create a discrepancy between the expected and actual behavior. 

- 2016 September, A Shell 6.3.1528, edit 779: Add pragma  ++pragma INCLUDE_GLOBAL_ONCE_ONLY <boolean> . When enabled, ++INCLUDE is treated as ++INCLUDE'ONCE, except when it occurs inside a function or procedure. In such cases, it is likely that you are intentionally including an extra copy of some map statements. 

2016 September, A-Shell 6.3.1528, edit 778: Add auto-defined macros `ABC_CURRENT_ROUTINE$` and `ABC_CURRENT_MODULE$` . 

These equate to the current function/procedure name (or "" if none), and the current module filename (file.ext). Both may be useful in standardized error reporting. 

- 2016 September, A Shell 6.3.1528, edit 777: Add three pragmas: +PRAGMA ASHELL_EXTENSIONS <boolean>, ++PRAGMA PRE_PROCESS <boolean>, and ++PRAGMA EXTENDED_PRE_PROCESS <boolean> 

- 2016 September, A Shell 6.3.1528, edit 776: Add indirect function calls. 

- 2016 September, A Shell 6.3.1527, edit 774: Add .INSTRR function 

- 2016 September, A Shell 6.3.1526, edit 773: Add IFELSE functions 

A-Shell Reference 

Page 669 

- 2016 August, A Shell 6.3.1523, edit 770:  Add Private Attribute for Functions and Procedures 

- 2016 July, A Shell 6.3.1517, edit 764:  Enhancement to recognize the new random generator functions RND() and SRND() in /X:2 mode. 

- 2016 April, A Shell 6.3.1508, edit 761:  Optimization of PRIVATE_BEGIN/END logic so that the initialization is effectively "lazy", i.e. delayed until code within the module is executed. This eliminates unnecessary initializations that would otherwise occur if the ++INCLUDE for the module is placed near the top of the parent program. 

## **- - A Shell 6.1/6.2 below here, A Shell 6.3/6.4 above** 

- 2015 October, A Shell 6.1.1420, edit 756 & 758: Compiler/APN change/refinement (edits 756 & 758): ++IF, ++IFDEF and + +IFNDEF directives are now being "obeyed". Previously, all of the ++IFxxx directives were being ignored, resulting in both the True and False sections being included in the tags. This was harmless in some cases, but in others it was resulting in duplicate tags, which interferes with the ^ALT+G command. Note however, that since neither MAPs nor labels are "compiled" by the tagger, ++IFMAP, ++IFNMAP, ++IFLBL and ++IFNLBL directives continue to be ignored—i.e. no source code is excluded by them or their associated ++ELSE and ++ELIF directives. Also, SIZEOF(var) will evaluate to zero. Hopefully this represents the sweet spot on the compromise between file loading/tagging speed and accuracy. 

- 2015 September, A Shell 6.1.1418, edit 751: Compiler now generates the tag output used by APN, eliminating the need to call the external tagger and speeding up file loads substantially. Note that this only applies to the standalone compil.exe and APN. 

- 2015 August, A Shell 6.1.1416, edit 748: MAP2+ statements are now flagged as illegal if not preceded by a finalized MAP1 statement. 

- 2015 August, A Shell 6.1.1416, edit 747: Compiler bug fix ***SERIOUS***: Referencing a variable in a MAP statement initializer was causing the side-effect of finalizing the parent MAP1 definition, which was then causing it be encoded in the RUN file with the wrong size. 

- 2015 August, A Shell 6.1.1414, edit 744: Attempting to define a local dimx byref array without the required initial subscript value of -1 is now flagged as an error. Previously, no error was generate but the pass-by-reference mechanism would not have worked correctly. 

- 2015 August, A Shell 6.1.1414, edit 743: MAP Statements with initial values, when part of a DEFSTRUCT, were generating improper assignments in the RUN file. Typically these were benign, but in some cases they were causing the program to abort with a nonsensical error code during the initialization. 

A-Shell Reference 

Page 670 

- 2015 August, A Shell 6.1.1414, edit 742: Add new Dot Function .ISNULL for use with ordered maps to test for the .NULL condition. 

- 2015 February, A Shell 6.1.1401, edit 740: DEFXCALL now allows all named parameters to be optional, i.e. to be enclosed in braces, e.g.: `DEFXCALL MYSBR {,one=1, two=2, three$="3"}` . Previously there had to be at least one mandatory parameter prior to the "{" marking the start of the optional parameters. 

- 2014 November, A Shell 6.1.1398, edit 734: When passing an entire ordmap to a subroutine, you can now use the more natural syntax with a pair of empty (), rather than having to specify a null string, e.g. (""). For example, in the CGIUTL opcode CGIOP_GETPARARY (see edit 1394 below), you can now specify the ordmap using () as in this example: `xcall CGIUTL, CGIOP_GETPARARY, status, $req() {,stdin$}` The old syntax is still supported, but is now deprecated and any existing programs using it should probably be changed after updating to this version. 

- 2014 October, A Shell 6.1.1396, edit 730: LSM files (/LSM compiler switch) no longer limited to Windows. 

- 2014 October, A Shell 6.1.1392, edit 718: You may now optionally use procedure-style syntax with the subroutine statement. In other words, instead of: `XCALL NAME,ARG1,...ARGN` , you can instead use `XCALL NAME(ARG1,...ARGN).` The advantage of the alternate syntax is perhaps mainly aesthetic, but will seem more natural to programmers coming from other language backgrounds. Another potential advantage is that it would allow APN call tips to be set up for common subroutines, since the feature is triggered by typing the "(" which normally signals the start of a procedure parameter list. 

2014 October, A-Shell 6.1.1392, edit 717: Add pragmas GLOBAL_BEGIN and _END. 

- 2014 October, A Shell 6.1.1391, edit 714: ++MESSAGE and ++ERROR output is now captured when executing in background mode—i.e. from within APN. 

- 2014 October, A Shell 6.1.1391, edit 713: ++INCLUDE files without a line terminator on the last line should no longer generate syntax errors. 

- 2014 October, A Shell 6.1.1391, edit 711: New auto-defined COMPILER_VERSION macro equates to the compiler edit. 

- 2014 October, A Shell 6.1.1391a, edit 710: New  .TRUE and .FALSE may be used as self-documenting replacements for -1 and 0. 

- 2014 October, A Shell 6.1.1391b, edit 710: New statement DEFTYPE may be used to define an alias for a data type. 

- 2014 October, A Shell 6.1.1391, edit 708: It is no longer required that function names start with fn'. 

A-Shell Reference 

Page 671 

## - 2014 July, A Shell 6.1.1387, edit 685: LSX file now shows offsets for members within instances of structures. 

- 2014 July, A Shell 6.1.1387, edit 679: ++PRAGMA ERROR_IF_NOT_MAPPED "FALSE" may now be used to override /M or a previous "TRUE". Previously it was only possible to enable the /M switch, not disable it. Note that you can now turn the option on and off multiple times within a program, allowing you to get the benefit of the for new sections of code without being forced to clean up the unmapped variables in all of your code—i.e. in all of your include modules. 

- 2014 July, A Shell 6.1.1387, edit 678: Improve error reporting on missing ++endif; now lists all of the unmatched ++if statements in the stack. 

- 2014 July, A Shell 6.1.1387, edit 675: On first $COPY, attempt to also include <prog>.VER if it exists. 

- 2014 July, A Shell 6.1.1387, edit 672, 674: Support Madics $COPY directive. Similar to ++INCLUDE but with default extension .cpy and different search paths. 

- 2014 July, A Shell 6.1.1387, edit 673: Compiler now allows a locally defined structure variable with same name as a module or global variable provided they are same type of structure. 

- - 2014 July, A Shell 6.1.1387, edit 669 671: APN-related internal adjustments. 

- 2014 June, A Shell 6.1.1387, edit 668: Compiler now flags as an error an attempt to define a local structure whose name matches an auto-externed global or private (module) structure. Although this would be technically legal, it invites confusion likely to lead to difficult-to-detect bugs, especially when the local and module/global structures aren't even the same layout. 

- 2014 June, A Shell 6.1.1387, edit 668: Added support for -so switch to output errors to _stdout_ rather than to a file or window. This makes it easier to interface with certain editors and IDEs. 

- 2014 March, A Shell 6.1.1381, edit 663: When using /P and /L, the LSX file now contains a list of all the procedures and functions, along with an indicator of how many times they were called. 

- 2014 March, A Shell 6.1.1381, edit 655: New statements ++IFLBL label, ++IFNLBL label and ++ELIFLBL label areanalogous to the existing ++IFDEF, ++IFNDEF, and ++ELIFDEF statements, as well as ++IFMAP, ++IFNMAP and ++ELIFMAP, except that instead of referring to defined symbols or mapped variables, they refer to labels—used by GOTO and GOSUB—as well as procedure and function names. Note however that when the specified label is meant to refer to a function or procedure name, it must be terminated by an empty pair of parentheses. 

A-Shell Reference 

Page 672 

- 2014 March, A Shell 6.1.1380, edit 654: The new UNDEF statement causes the specified symbol to be undefined, allowing it to be redefined or to fail a ++IFDEF symbol test. 

- 2014 February, A Shell 6.1.1373, edit 651: Two new Dot Functions, .ARGTYP(argno) and .ARGSIZ(argno), return the type and size of the specified argument passed to the current SBX, function, or procedure. If the specified argno is invalid, the return value will be -1. 

- 2014 February, A Shell 6.1.1373, edit 652/653: Subroutines, both internal and SBX, may now use named parameters for functions and procedures. Parameter passing to subroutines is nearly identical to that for procedures and functions, so the implementation details are nearly the same. The main difference is that since subroutines do not have definition statements like functions and procedures, a new statement had been introduced to allow you to define their parameter names and default values: DEFXCALL xcallname{+|,}pname{|alias}{=defval},pname{|alias}{=defval}... 

- 2013 October, A Shell 6.1.1363, edit 647: When a function or procedure definition occurs (illegally) within an extended IF or FOR statement, the compiler now reports the location of the unterminated IF or FOR statement. Otherwise, it may have occured countless lines or even modules previously, since there otherwise no limit to the size of the body of a FOR or IF statement, making it very difficult to find the problem. 

- 2013 August, A Shell 6.1.1358, edit 642: New variations of ++INCLUDE: ++INCLUDE'IF'EXISTS <filespec> and + +INCLUDE'ONCE'IF'EXISTS <filespec>. As the name implies, these operate just like ++INCLUDE and ++INCLUDE'ONCE except that if the file is not found in the normal search path, it is just skipped. 

- 2013 April, A Shell 6.1.1350, edit 633: New compile-time function .OFFSIZ$(struct.member) is a variation of the .OFFSET() function which returns the combination of the specified structure member's offset and size, as a string formatted as "offset~size". While the combination of the two values in a string may seem unusual, since the offset and size are often used together, the combined format eliminates the need to specify the struct.member name twice, which invites discrepancy, and lends itself to use in runtime functions that may parse out the two values and combine them with other information. 

Also: SIZEOF(VAR) now handles a much wider variety of VAR arguments, including structure names, DIMX structure variables, etc. Also, for symmetry with .OFFSET(), .SIZEOF() may be used interchangeablywith SIZEOF()—i.e. with or without the leading dot. 

- 2013 April, A Shell 6.1.1350, edit 632: The new compile-time function .OFFSET(struct.member) is similar to SIZEOF(var) except that it returns the offset to the specified member variable within the specified structure, starting from 1, rather than the size of the variable, and it only works on fields within structures. Also, in the case of arrays, .OFFSET only returns the offset to the base 

A-Shell Reference 

Page 673 

of the array, and doesn't actually allow the use of subscripts. The specified structure name can either be a defined structure name, or a MAP'd or DIMX'd instance of it. 

- 2013 March, A Shell 6.1.1346, edit 627: Add new conditional compilation statements ++ELIFDEF <symbol> and ++ELIFMAP <var>. ++ELIFDEF is to ++IFDEF, and ++ELIFMAP is to ++IFMAP, as ++ELIF is to ++IF. 

- 2013 March, A Shell 6.1.1339, edit 624: The new pragmas PRIVATE_BEGIN ... PRIVATE_END may be used within ++INCLUDE files to ensure that the module's private variables (MAP and DIMX) are initialized once and only once before they are used, regardless of the position of the ++INCLUDE in the main program. 

- For compiler changes prior to the release of A-Shell 6.1 and compiler edit 600, refer to the A Shell Development History documentation. 

A-Shell Reference 

Page 674 

## **COPY** 

_Updated May 2022; see History_ 

## **COPY {outspec} = inspec1 {inscopypec2, … inspectN} {switches}** 

COPY copies files from one place or name to another. 

## **Parameters** 

## _outspec_ 

specifies an output file, using either DevPPN-style (e.g. dsk1:myfile.dat[123.4]) or native operating system, in which case it must be enclosed in quotes (e.g. "c:\temp\somefile.xyz"). When dealing exclusively with DevPPN-style _inspec_ files, outspec may be omitted, in which case it acts like *.*—i.e. uses the name.ext of each _inspec_ file. 

## _inspec_ 

specifies an input file, using either DevPPN-style or native operating syntax. DevPPN-style filespecs may include the * and ? and [] wildcards (e.g. DSK2:[]*.TMP). Native filespecs must be quoted and may not contain wildcards. When the _outspec_ is blank or *.*, you may list more than one _inspec_ , provided they are all DevPPN-style filespecs. 

## **Switches** 

|**Switch**|**Function**|
|---|---|
|/D{elete}|Overwrites an existing output file.|
|/Q{uery}|Prompts for a confirmation before copying each of the input files.|
|/C{onfirm}|Similar to {/query} except that it only prompts you to confirm whenever the destination<br>already exists. Note: if you are prone to accidentally overwriting important files by loose-<br>fingered copy commands, you may want to renameCOPY.LITto something else, then|



A-Shell Reference 

Page 675 

|**Switch**|**Function**|
|---|---|
||create a copy.do file which automatically invokes the /C switch.|
|/MINDAYS:###|Ignore files changed within the last ### days.|
|/MINSECS:###|Ignore files changed within the last ### seconds.|
|/MAXDAYS:###|Ignore files not changed since at least ### days ago.|
|/MAXSECS:###|Ignore files not changed since at least ### seconds ago.|
|/NOD{elete}|Does not overwrite existing files.|
|/?|Writes switch listing and usage info to the screen.|



If all of the files on the command line (input and output) are in DevPPN-style syntax, the wildcards * and ? and [] may be used on both sides of the equals (e.g. COPY DSK1:*.X?[] = DSK2:*.D?[]). 

COPY preserves the modification time and ownership of the source file. 

COPY skips wildcarded source files that have more than one extension, and displays a warning message listing the filename. You can still copy such a files using quoted native filespecs. 

Copying from read-only devices under Windows: In general, COPY will try to preserve the attributes of the source file, such as the last-modified time stamp, archive bit, etc. One notable exception is that when copying from a read-only device (like a CD), it 

A-Shell Reference 

Page 676 

will remove the read-only attribute from the output file. (Otherwise files copied from CD would typically need manual adjustment to remove the read-only attribute.) However, this feature only works for source devices that A-Shell can detect as being naturally read-only. If this is not the case, you can force A-Shell to recognize the device as read-only by adding the ,RO flag to the DEVICE definition in miame.ini. 

COPY.LIT and MOVE.LIT are identical. Their behavior changes based on the name of the module. Both use MX_COPYFILE function to perform the operation, the only difference being that MOVE sets the CPYF_MOVE flag. 

Native filespecs may be used if they are quoted, and they may contain environment variables, e.g. "%miame%\ashlog.log" 

The following example simply makes a copy of FILE1.NEW called FILE1.OLD, overwriting an existing FILE1.OLD if necessary. 

```
.COPY FILE1.OLD=FILE1.NEW/D
```

This example copies the specified file from the SYS: directory to the current directory. 

```
.COPY=SYS:ERSATZ.INI
```

This makes copy of all of the files with BAS extensions in all of the PPNs of the current device/logical unit, plus the file dsk1:direct.lst. The copies will all be in the current PPN and will all have SAV extensions. 

```
.COPY *.SAV=*.BAS[],DSK1:DIRECT.LST
```

The following demonstrates the ability to create new directories as needed while copying files. It copies all of the files from DSK0:[50,*] to the corresponding PPN in DSK1:. Note that the ability to create new directories during the COPY operation is only available if you are currently logged into [1,2]. Furthermore, if the OPTIONS=STRICT setting is specified in miame.ini, then you may not create files during a COPY command outside of the current project. 

```
.COPY DSK1:[]=DSK0:[50,*]
```

This example copies a file from the current [p,pn] to [p,0] on the current device, illustrating the ability to default the p (or pn) part of the [p,pn] ... 

A-Shell Reference 

Page 677 

```
.COPY [,0]=PROG.RUN
```

The following two examples illustrate the use of a quoted native operating system filespec. In the second case, it also illustrates the use of %ENV% variables.  (%MIAME% is an automatically created environment variable which points to the directory where miame.ini is located.) 

```
.COPY "/tmp/backup of app.log" = OPR:APP.LOG
```

```
.COPY ASHELL.LST = "%MIAME%\ashlog.log"
```

## **History** 

- 2022 June, A Shell 6.5.1717, COPY.LIT / MOVE.LIT 3.4(147): Updated to fix a very old bug which would result in the directory listing being duplicated if there were consecutive DEVICE statements for the same device—i.e. one normal DEVICE definition and one or more PPN-specific definitions. 

- 2022 May, A Shell 6.5.1715, COPY.LIT / MOVE.LIT 3.4(146): Add /MAXDAYS:## and /MAXSECS:## switches to allow selective targeting of files changed recently. 

- 2019 June, A Shell 6.5.1662, COPY.LIT 3.4(132):  COPY has been updated to accommodate a change in maximum filename.ext size, from 10.3 to 72.8. 

A-Shell Reference 

Page 678 

## **CREATE** 

## **CREATE <file>, <blocks>** 

CREATE allocates and fills a file with the specified number of 512-byte blocks. 

Under AMOS, "random" or "contiguous" files are actually different in structure from the normal "sequential" files, and as the name implies, are allocated in contiguous space. Under Windows and Unix, there is no equivalent concept, nor is there a need for one. All data files can be accessed using either the "random" access method or the sequential method. In fact, a file allocated with CREATE could later be accessed as if it were a sequential file. Since there is no perfect way to recognize whether an existing file was created with CREATE (and thus should be treated as a "random" file) or via a sequential output process, A-Shell can only guess based on whether the file size is a perfect multiple of 512 bytes. If so, there is a very good likelihood that it was intended to be a random file. If not, then it must be a sequential file. The only significance of this decision is for the `DIR/F` operation (which indicates contiguous files with a "C"), and for the ASB LOOKUP statement, which by default returns a negative number to indicate random or contiguous files. The system parameter   setting `OPTIONS=ABSLOOKUP` eliminates that distinction, causing all files to be reported as positive numbers. 

The `OPTIONS=BRKALC` switch in miame.ini affects what the newly allocated file is pre-filled with. When set, the file is filled with brackets (]]]]). Otherwise, the contents will be whatever was previously occupying that disk space. 

A-Shell Reference 

Page 679 

## **CSV2XL** 

## **CSV2XL csvspec {,inispec}** 

CSV2XL.LIT provides an alternative to PRINT.LIT for generating spreadsheets from CSV input, eliminating the need for a printer init file that invokes the CSV2XL print filter. Note that it is still just a front-end to CSV2XL.SBX which does all the work. 

## **Parameters** 

_csvspec_ [in] 

CSV source file. .CSV extension is optional. May include //XL directives; see CSV2XL for details. 

## _inispec_ [in] 

optional init file used by CSV2XL. Default is BAS:CSV2XL.INI. 

## **History** 

- 2023 September, A Shell 1750:  Function added to A-Shell. 

A-Shell Reference 

Page 680 

## **DEL** 

_Rewritten May 2023_ 

## **DEL <spec> {switches}** 

DEL deletes a module from user memory. Modules are loaded into memory either explicitly by the LOAD command (which see for more details about user memory), or implicitly, as the result of running a program. 

## **Parameters** 

_spec_ 

specifies the name.ext of the module. Note that modules loaded into user memory do not have device or PPN attributes. The wildcard * may be used for either the name or extension; a single * by itself is equivalent to *.* 

## **Switches** 

_/unlock_ or _/force_ 

clears the lock flag (set by the LOAD /lock switch), allowing the module to be deleted 

## **Example** 

```
.LOAD BAS:CSV2XL.SBX
```

```
.LOAD DSK2:RUNSBX.SBX[200,1]
```

```
.LOAD SYS:COPY.LIT/LOCK
```

```
.MAP
PCTDVG.IFX           652    P
CSV2XL.SBX        117894    P
RUNSBX.SBX           120    P
COPY.LIT           31932    LP
```

A-Shell Reference 

Page 681 

```
Free             4290755
```

## **`.DEL`** 

```
PCTDVG.IFX
```

```
CSV2XL.SBX
```

```
RUNSBX.SBX
```

```
.DEL COPY.*/UNLOCK
```

```
COPY.LIT
```

In the above example, we used LOAD to load three modules, one of them with the /LOCK option, and then displayed them with the MAP command. The PCVTDV.IFX module was already in memory. The DEL * command deleted all but the locked module, while the second DEL command with the /UNLOCK switch deleted it. 

## **See Also:** 

- LOAD.LIT: load modules into memory 

- MAP.LIT: display memory modules and memory available 

- MEMORY.LIT: change memory size 

- MX_USRDELXS: delete memory modules from with application 

A-Shell Reference 

Page 682 

## **DIFF** 

## **DIFF {listfile=} oldfile, newfile {/w}** 

(Unix only) DIFF is an A-Shell front-end to the standard Unix **diff** utility, with is much faster and more powerful than the SRCCOM.LIT utility. Like SRCCOM, the standard version lists the lines that are different between the two specified files. The differences between DIFF and SRCCOM are: 

- DIFF ignores differences that are just white space (i.e. a TAB and three spaces is treated as no different than a single space). 

- DIFF has no switches (although you are welcome to add your own!) 

- DIFF uses the Unix-like space delimiter to separate the two filespec arguments, rather than a comma or comma space to 

- separate the files. 

- DIFF displays its output in the EZTYP viewer rather than just outputting to the screen. 

Since DIFF is simply a front-end to the Unix diff, and since source code is provided (in the SOSLIB), you can easily modify it to take advantage of other features supported in the Unix diff. 

The only switch supported is /w, which causes DIFF to ignore differences comprising white space only. 

If you create your own variation of DIFF.LIT, it is recommended that you rename it in order to avoid having it be overwritten by a subsequent A-Shell update. 

A-Shell Reference 

Page 683 

## **DING** 

## **DING <number-of-times>** 

DING rings the bell. This sophisticated technique is mainly used within CMD and DO files to get the operator’s attention, perhaps because input is required or an error has occurred. 

Under Windows and most terminal emulators, this will play the "System Default" sound. You can change the WAV file associated with that sound from the Sound applet of your Control Panel, no doubt amazing and delighting your colleagues by setting it to a shrieking woman, theme from Thus Spake Zarathustra, or a gastronomic by-function. 

If you do not have a sound card, or are using a dumb terminal, you will be at the mercy of the default hardware bell sound (and loudness, or lack thereof). 

A-Shell Reference 

Page 684 

## **DIR** 

_Updated June 2019; see History_ 

## **DIR {listspec=} {fspec1{,...fspecN}} {switches}** 

The DIR command implements most of the switches available under AMOS, plus some additional switches that are unique to A- Shell. See the following topic DIR Switches. 

Aside from the slightly different set of switches between AMOS and A-Shell, note the following differences in behavior: 

- A-Shell and therefore DIR recognize (a) traditional DevPPN names in the 6.3 format (six character name plus three character 

- extension), (b) a format of 10.3 beginning in A-Shell version 897 of August 2004, and (c) a format of 72.8 beginning in A-Shell 6.5.1662 of June 2019. See the DIR switch LONG, the LIT command SET LONGDIR, and the system parameter OPTIONS=LONGDIR to control the horizontal length of your DIR display. 

- Keep in mind that files will only be listed if you have file read permission for them. In the case of Unix, it is also required that 

- the directory, and all directories above it, have the execute bit set. (The execute privilege on a directory controls whether the directory can be traversed.) This applies equally to all wildcard commands, such as COPY and ERASE, which will effectively not see files for which you have no read permission. 

- Unlike under AMOS, where you could use DIRSEQ to sort the files in a directory, it is rather non-standard to sort an actual 

- directory under Windows and Unix. Instead, the DIR program itself is usually relied on to sort the display rather than sorting the directory itself. Consequently a set of sorting options has been added to the A-Shell version of DIR; see switches beginning with "S" in table of DIR switches. 

· Since DIR works by actually scanning the directory structures, it will find files that do not fit the DevPPN "six dot three" format, or even A-Shell's extended "ten dot three" format, and thus cannot be located by non-wildcard commands or by ASB file open statements. DIR will truncate files with names longer than "six dot three" but will use some kind of flag character, such as ">" to give you a clue that there may be more there than meets the eye. 

One particularly nasty problem of this type occurs only under Unix, which has case-sensitive filenames. Since normal files are by convention named in lower case, A-Shell translates DevPPN filespecs (which are not case sensitive) to lower case. But some file transfer programs may produce upper case filenames when transferring files from AMOS to Unix. Such files will appear in a DIR 

A-Shell Reference 

Page 685 

listing (which folds the displayed filenames to upper case to match the way AMOS DIR listings appear). But they will appear to be invisible to non-wildcard commands and ASB file option operations. To avoid this problem, make sure your file transfer program has an option to force lower case and that the option is activated. To fix the problem, see the trlcs utility which is shipped with A-Shell in the bin directory. 

· Blocks sizes for sequential files will differ between AMOS and A-Shell, due to differences in underlying block formats. AMOS uses 512 byte blocks with 2 or 4 byte links to connect the blocks in a sequential file, depending on the device format, and thus each full block contains 508 or 510 bytes of data. None of the other OS platforms that A-Shell runs on requires such links (they are implemented in the directory rather than in the disk blocks), so A-Shell treats each "block" as capable of holding up to 512 bytes of data. (Physical blocks are likely to be much larger these days, and in fact, the very idea of a "block" may be questionable - most platforms use a stream-of-bytes model instead - but 512 byte logical chunks are still widely recognized as a kind of traditional unit of size.) To compare files between AMOS and A-Shell, it is best to use SIZE.LIT to get the logical size, and/or DIR/H to check for an exact data match. 

## **See Also** 

- PAGE as an alternative to Ctrl+S and Ctrl+Q for limiting the scrolling speed of the display. 

## **History** 

- 2022 June, A Shell 6.5.1717, DIR.LIT 3.4(172):  Updated to fix a very old bug which would result in the directory listing being duplicated if there were consecutive DEVICE statements for the same device—i.e. one normal DEVICE definition and one or more PPN-specific definitions 

- 2019 June, A Shell 6.5.1662, DIR.LIT 3.4(166):  Updated to accommodate a change in maximum filename.ext size, from 10.3 to 72.8. See the DIR switch LONG. 

- 2018 November, A Shell 6.5.1651, DIR.LIT 3.3(163): Updated to avoid a read-only error related to the smart-scrollback activation feature. 

- 2017 July, A Shell 6.5.1610, DIR.LIT 3.3(162):  Now makes the scroll bar visible if the environment supports it 

(A-Shell/Windows and ATE version 6.5.1610 or later) and the output of the command causes the screen to scroll. 

- 2016 January, A Shell 6.2.1425:  Add switches /MAXSECS and /MINSECS. 

- 2013 June, A Shell 6.1.1354:  Add /1 switch. 

A-Shell Reference 

Page 686 

- 2011 June, A Shell 5.1.1221:  Remove the limit on the number of PPNs allowed per device. 

A-Shell Reference 

Page 687 

## **DIR SWITCHES** 

_Updated November 2016; see History_ 

In the list of switches below, note that you can abbreviate most switches to the minimum number of unique characters (e.g. /C for /CONTIGUOUS, etc.). 

|**Switch**|**Function**|
|---|---|
|/1|Eliminates the directory and size information from the output. When combined with the /NATIVE switch, it<br>produces just a list of filenames (file.ext), similar to the Unix ls -1 command. Added in 6.1.1354.|
|/A|Adate: displays last access date.|
|/AT|Atime: displays last access time.|
|/CDATE|Displays file "c date."|
|/CON|Displays a "C" to identify "contiguous" files. (Note that under A-Shell, this really just means the file is a<br>multiple of 512 bytes.)|
|/CTIME|Displays file "c time". Usually used with /CDATE. See notes underCDATE<br> for differences between the "c<br>date" under AMOS/Windows and Unix.|
|/D|Data: displays complete filespecs.|
|/ERSATZ|Appends the ersatz directory name (if applicable) to the the Dev:[p,pn] header for each directory group of<br>files displayed.|
|/F|Full: same as /H/CON/V|
|/H|Display hash code|



A-Shell Reference 

Page 688 

|**Switch**|**Function**|
|---|---|
|||
|/K|Kill: delete and replace listfile|
|/LONG|Changes the default display layout to filename of <72 or less>.extension of <8 or fewer> characters.|
|/LT|Sort by descending—newest to oldest—update date, in_size update fspec_format; similar to Unix ls -lt|
|/MAX:n|Display only files with n or fewer blocks|
|/MEMREQ|Memory required for program variable storage|
|/MIN:n|Display only files with n or more blocks|
|/<br>MAXDAYS:#|Omits from the display any files that have been modified more than # days ago.|
|/<br>MAXSECS:#|Omits from the display any files that have been modified more than # seconds ago.|
|/MINDAYS:#|Omits from the display any files that have been modified less than # days ago.|
|/MINSECS:#|Omits from the display any files that have been modified less than # seconds ago.|



A-Shell Reference 

Page 689 

|**Switch**|**Function**|
|---|---|
|/NA {:len}|NATIVE<br>:displays files in the native format|
|/NOFILES|Omit filenames; just output totals|
|/PAGE|Pause after each page of output|
|/Q|Query: prompt for confirmation on each input file. (Standard switch)|
|/SEXT|Sort by ascending extensions|
|/SNAME|Sort by ascending filenames|
|/SNODEV|Removes primary sort on DEVICE; seeSNOxxx<br>.|
|/SNOPPN|Removes primary sort on DEVICE; seeSNOxxx<br>.|
|/SRUDATE|Sort by descending update dates|
|/SSIZE|Sort by ascending file sizes|
|/SUDATE|Sort by ascending update dates|
|/UDATE|Display file update (last modified) dates|



A-Shell Reference 

Page 690 

|**Switch**|**Function**|
|---|---|
|/UTIME|Display file update (last modified) times|
|/V|Display file version if available. Also seeVERSYS<br>.|
|/WARN|ForcesDIRto display the message "Warning: skipping incompatible filespec" when applicable. This message<br>was displayed by default (i.e., without the /WARN switch) in versions ofDIRbefore 3.0(140).|
|/W:n|Wide: display in n columns (default n=4)|
|/?|Writes switch listing and usage info to the screen.|



A-Shell Reference 

Page 691 

## **CDATE** 

Displays file "c date." The "c date" under AMOS and Windows is the creation date, but under Unix is the date that the file’s directory entry was last changed. This occurs whenever the file ownership or privileges are changed, or when a symbolic link is created, or when the file is moved, renamed, or copied. Because of this, the "c date" can easily be more recent than the update date. 

A-Shell Reference 

Page 692 

## **LONG** 

_Updated June 2019_ 

Changes the default display layout to accommodate 10.4 format instead of 6.3 format. It also changes the default /W value from four columns to three. Filenames exceeding the maximum display length will show a ">" character following the filename. Note that the SET command LONGDIR can be used to force the 10.4 format. 

Beginning with A-Shell 6.5.1662 of June 2019, the allowable (maximum) A-Shell filename structure changed from 10.3 to 72.8. The LONG switch therefore now accepts a two-part numeric argument specifying the filename and extension lengths. The default length for extensions (with LONG) is four characters, so there is no need to specify four or fewer characters for the extension; just specify the filename length. For example: 

```
DIR /L         ; display using 10.4 format
```

```
DIR /L:30      ; display using 30.4 format
DIR /L:50.6    ; display using 50.6 format
```

## **History** 

- 2019 June, A Shell 6.5.1662:  Add numeric argument(s) 

A-Shell Reference 

Page 693 

## **MEMREQ** 

_Added November 2016_ 

The /MEMREQ switch displays the memory required for static variable storage for programs such as LIT, RUN and SBX files in place of the file size. When both /SSIZE (sort on file size) and /MEMREQ are specified, it also sorts based on the memory requirement. 

Note that the value displayed by /MEMREQ is only a total for the combined sizes of the fixed variables in the program. While this is far short of the total operating system memory used by the program, which includes dynamic variable, stack and other auxiliary memory allocations, it is a good measure of how large your job memory partition needs to be. This is particularly true since 6.3.1518 when the string stack was moved to dynamic memory. A reasonable rule of thumb would be to set your partition size to 300-500K larger than the largest /MEMREQ value for your application. Use `DIR /MEMREQ/SSIZE` to find the largest values; don't forget to also check the LIT files in SYS: since some of them may have large requirements. 

## **History** 

## - 2016 November, A Shell 6.3.1534, DIR.LIT 3.3(160):  Switch added to DIR 

A-Shell Reference 

Page 694 

## **NATIVE** 

This switch, /NA{TIVE}{:len}, displays files in the native format of the host operating system. The _len_ sub-parameter (default 24) determines the maximum display width for the filespecs. If the filename exceeds that, it is terminated with ">" just as when /NATIVE is not used. 

/NA{TIVE} causes the following other effects: 

- "Incompatible files" are treated like any other files (i.e. displayed instead of skipped). 

- File sizes are shown in bytes instead of blocks 

- File names are shown in upper and lower case as they really are. 

- When combined with /D, displays entire path for each file. Otherwise, displays just the filename + extension(s) (but for each 

- new directory, displays the directory in native format instead of the DEV:[p,pn] format.) 

- /W will default to /W:2 

A-Shell Reference 

Page 695 

## **SNOXXX** 

Normally, all sort options (/SNAME, /SEXT, /SUDATE) implicitly sort first by DEVICE+PPN. Adding /SNODEV to another sort option removes the implicit primary sort on DEVICE, and /SNOPPN removes the secondary sort on PPN. For example: 

```
.DIR ALL:[]/SNAME                  ; by DEVICE, PPN, NAME.EXT
```

```
.DIR ALL:[]/SNAME/SNOPPN           ; by DEVICE, NAME.EXT
.DIR ALL:[]/SNAME/SNODEV/SNOPPN    ; by NAME.EXT
```

Note that except for these two sort modifiers, it only makes sense to specify one sort option. (Command switches are not ordered, so there is no way to distinguish, say, /SNAME/SUDATE from /SUDATE/SNAME). Also note that adding /SNODEV or /SNOPPN changes the output format slightly. Instead of providing subtotals when the DEV+PPN changes and showing the DEV: [P,PN] just for the first file of each new group, it lists the DEV:[P,PN] on every file. 

A-Shell Reference 

Page 696 

## **DO** 

_Updated May 2022; see History_ 

## **DO <fspec> <argument list>** 

where _<argument list>_ is a list of zero or more space-delimited textual tokens which are bound to the formal DO File Arguments referenced within the file identified by _<fspec>_ . 

The DO command forces _fspec_ to be treated as a command file rather than as a system command. This is useful in situations where the _fspec_ in question exists in .CMD and/or .LIT variations as well as .DO, since otherwise, the command search path would cause the .CMD or .LIT to be found first. It is also needed to force a file with an extension other than DO to be interpreted as a DO file—although it is not clear why you want to do that. 

DO supports the command line argument _++fspec_ ; for details see DO File Arguments. 

DO.LIT is invoked automatically by the command line processor if it determines that the specified file is a command (.CMD 

or .DO) file, so it is not necessary to explicitly use "DO" except in the situations described above. DO.LIT is responsible for preprocessing the DO file to perform argument and macro substitutions. 

MDO.LIT is identical to DO.LIT, but is referenced internally under different circumstances. 

## **Comments** 

The maximum DO file size is approximately 122K. This is about the maximum size for a 430K partition, which is about the minimum partition needed for some other large system commands, such as SUBMIT. A-Shell will explicitly complain if the partition size is not sufficient. 

When DO is used within a command file to reference another command file, the command line may contain references variables - input during execution of the current command file, $KBD0 thru $KBD9 (see K0 K9 Tokens), may contain upper and lower case functions (see Input Case), and may use the concentration operator $+ (see Concatenate Parameters). 

## **History** 

A-Shell Reference 

Page 697 

- 2022 May, A Shell 6.5.1715, DO.LIT / MDO.LIT 2.1(126): special colon commands (e.g. :K) can now be indented. Previously they needed to be in column one. This may be a minor detail but can make all the difference in debugging complex DO files with many levels of nested IF / ENDIF clauses. 

- 2011 August, A Shell 5.1.1227, DO.LIT / MDO.LIT 2.1(124) and SUBMIT.LIT 3.1(150) now support file-based variable command line arguments using the ++fspec syntax. 

A-Shell Reference 

Page 698 

## **DUMP** 

_Updated May 2023; see History_ 

## **DUMP <fspec> {,starting-block #} {switches}** 

The DUMP command is an implementation of the AMOS command of the same name, for displaying the contents of files only; direct disk block dumps, UFD dumps, and MFD dumps are _not_ supported. The format of the data dump is identical to that produced by AMOS, formatted in either octal or hexadecimal depending on the current job settings (see SET). The current block number displayed under A-Shell is a sequential count of 512 byte blocks starting at one (or the specified block number). 

Since there is no difference between random and sequential files under operating systems other than AMOS, and the block linking mechanism is separated from the data itself, all 512 displayed bytes contain actual data; the first two or four will not contain link information as they do for sequential files under AMOS. This may mean that dumping a sequential file under AMOS and A-Shell (which have the same hash-total) will produce differing outputs, being shifted by two or four bytes each block. 

Note that 512 byte "blocks" do not necessarily have any physical significance outside of AMOS. Under A-Shell we simply use it as a convenient logical unit. 

## **Switches** 

|**Switch **|**Function**|
|---|---|
|/L|Causes the output to written to the file dump.lst instead of the screen.|



## **See Also** 

- The notes on PAGE for how to keep the display from scrolling too fast 

- The notes on Scrollback to see text that has scrolled off the screen 

## **History** 

A-Shell Reference 

Page 699 

- 2023 May, A Shell 6.5.1731, DUMP.LIST 1.0(108):  When a starting block number is specified, it now seeks directly to that position, rather than silently reading all the prior blocks. This is a benefit mainly with very large files. 

- 2018 November, A Shell 6.5.1651:  DUMP.LIT 1.0(108) has been updated to avoid a read-only error related to the smartscrollback activation feature. 

A-Shell Reference 

Page 700 

## **ECHO** 

## **ECHO <text>** 

ECHO functions similarly to the Unix and Windows command of the same name. It offers similar functionality to the command file ":<  ... >" mechanism, but is more flexible and powerful, supporting the full range of special $ variables (which otherwise only work within DO files) and environment variables (e.g. %MIAME%). 

## **Examples** 

```
ECHO Your job name is $NJ
```

```
ECHO The MIAME directory is %MIAME%
```

```
AGCMD/K0/S BROWSEFOLDER
```

```
ECHO You selected folder $KBD0
```

## **See Also** 

- ECHOXS 

## **History** 

- 2017 July, A Shell 6.5.1610: DUMP.LIT 1.0(107) now makes the scroll bar visible if the environment supports it (A-Shell/Windows and ATE version 6.5.1610 or later) and the output of the command causes the screen to scroll. 

- 2011 May, A Shell 5.1.1215: Added to A-Shell 

A-Shell Reference 

Page 701 

## **ELSE** 

_Revised May 2025_ 

## **IF <expr>** 

```
   <statement(s) to execute if true>
```

## **ELSE** 

```
   <statement(s) to execute if false>
```

## **ENDIF** 

IF, ELSE and ENDIF allow for the flow of control within a CMD or DO file based on various conditions that can be tested. IF takes an expression that evaluates to true or false, while ELSE and ENDIF take no arguments. See the example below and Command Files for more information. 

## **Example** 

This DO file takes a filename argument, without extension. If the filename doesn't exist (with a BAS extension), it is created by copying from another file and then loaded into VUE. If no argument is supplied, or the file already exists, it prints an error message and exits. Note that the EXIT command exits entirely out of the CMD/DO file, regardless of the depth of IF/ENDIF nesting, unlike the ASB EXIT control statement. 

```
IF "$0" = ""
```

```
    :<This command needs a filename argument>
    EXIT                      ; exit DO file
ELSE
```

```
    IF LOOKUP("$0.BAS") = 0   ; if file does not exist
        COPY $0.BAS=APPLIB:STDHDR.TXT
```

```
    ELSE
```

A-Shell Reference 

Page 702 

```
        :<$0.BAS already exists; command aborted>
```

```
        EXIT                  ; exit DO file
```

```
    ENDIF
```

```
ENDIF
```

```
VUE $0.BAS
```

A-Shell Reference 

Page 703 

## **ERASE** 

_Updated February 2026; see History_ 

## **ERASE fspec {switches}** 

ERASE not surprisingly erases files. 

## **Parameters** 

## _fspec_ 

specifies an input file, using either DevPPN-style or native operating system syntax. AMOS-style filespecs may include the * and ? and [] wildcards (e.g. DSK?:[]*.TMP). Native operating system filespecs must be individually quoted, must include at least one slash, and must not contain wildcards (e.g. ./this native file.lst or /tmp/somefile.tmp). More than one _inspec_ may be specified, in which case they must be separated by commas. 

## _switches_ 

|**Switch**|**Function**|
|---|---|
|/F{ORCE}|Forces an affirmative response to the confirmation prompt that otherwise appears<br>automatically when interactively attempting to erase multiple files via a wildcard. Note that<br>the switch is redundant but harmless in non-interactive situations, except in the case where<br>theERASEcommand is at the very end of a CMD file, where the mode transitions back to<br>interactive before the command executes.|
|/MINDAYS:#|Erase only those files that have not been modified in at least the last ### days.|
|/MINDSECS:#|Erase only those files that have not been modified in at least the last ### seconds.|
|/Q{UERY}|Prompts for a confirmation before erasing each file matching the wildcard specification.|



A-Shell Reference 

Page 704 

|**Switch**|**Function**|
|---|---|
|/S{ILENT}|Silences screen output during erase operations.|
|/T{ERSE}|Reduces the verbosity of the screen output during erase operations|
|/?|Writes switch listing and usage info to the screen.|



## **Confirmations** 

In response to developer requests, ERASE has been modified (see History) so as to minimize the chances of unintentional file deletes, which can easily occur when using wildcards. ERASE.LIT 3.4(124) and later will ask for confirmation when ALL of the following four conditions are met: 

- It is not running from within a CMD or DO file, which is determined by whether there are any characters in the command file 

- left to process. To make sure they ARE more characters to process in your command file, it would be wise to add a blank line after a final ERASE command. 

- It is not executed with the /Q switch 

- The command will result in more than one file being deleted. 

- A-Shell was not launched with the -e switch. 

For example: 

```
.erase *.bak[]
```

```
ASTAT.BAK
```

```
ATECFG.BAK
```

```
ATECTL.BAK
```

A-Shell Reference 

Page 705 

```
ATEUPDATE.BAK
```

```
ATSYNC.BAK
```

```
SBXINP.BAK[7,6]
```

```
Total of 6 files, 149 disk blocks will be deleted
```

```
Proceed with actual file deletion ? N
%No files deleted
```

```
.
.
```

```
.erase *.bak[]
```

```
ASTAT.BAK
```

```
ATECFG.BAK
ATECTL.BAK
```

```
ATEUPDATE.BAK
```

```
ATSYNC.BAK
```

```
SBXINP.BAK[7,6]
```

```
Total of 6 files, 149 disk blocks will be deleted
```

```
Proceed with actual file deletion ? Y
```

```
Total of 6 files deleted, 149 disk blocks freed
```

Note that the confirmation character is based on the current language, as is the case with the /Q confirmation; in fact, they use the same routine. The messages are all from the LITMSG.xxx file too, and will default to English if not specified in the message file. 

A-Shell Reference 

Page 706 

## **History** 

- 2026 February, A Shell 7.0.1782: Add switches /S{ILENT} and /T{ERSE}. 

- 2022 June, A Shell 6.5.1717, ERASE.LIT 3.4(137): Updated to fix a very old bug which would result in the directory listing being duplicated if there were consecutive DEVICE statements for the same device—i.e. one normal DEVICE definition and one or more PPN-specific definitions. 

- 2019 June, A Shell 6.5.1662, ERASE.LIT 3.4(134): Updated to accommodate a change in maximum filename.ext size, from 10.3 to 72.8. 

- 2016 January, A Shell 6.2.1422, ERASE.LIT 3.4(129):  Now detects when running under control of PAGE so as to not disable the warning/confirmation request when deleting multiple files by wildcard. Previously a command line like `PAGE ERASE *.BAK` was not stopping to confirm that you really want to erase all those files, because it appeared to ERASE that it was running from the command file created in memory by PAGE. 

- 2016 January, A Shell 6.2.1422:  When listing the files to be erased, ERASE now displays the file size in blocks next to each name. 

- 2015 May, A Shell 6.1.1411: Add /F switch. 

- 2013 November, A Shell 6.1.1365:  Add confirmations. 

- 2011 June, A Shell 5.1.1221:  Remove the limit on the number of PPNs allowed per device. 

A-Shell Reference 

Page 707 

## **ERSATZ** 

_Updated February 2026_ 

## **ERSATZ** 

list existing ersatz definitions 

## **ERSATZ file** 

load (or reload) definitions from _file_ 

## **ERSATZ erzname:=dev:[p,pn]** 

add or update single ersatz definition 

ERSATZ (syntax one, above) displays the list of current ersatz device definitions. These definitions are maintained within one or more text files, each of which is referenced via an ERSATZ= statement in miame.ini or was added by this command using syntax two or three. The ersatz devices may be used syntactically just like real device names. 

Syntax two and three, above, allow you to (re)load ersatz definitions, either from a file or a single definition, without needing to re-launch A-Shell. This may be useful in applications where the specific location of certain system-wide ersatz devices (e.g. REPORTS:) may need to change based on the user, menu selection, etc. 

## **See Also** 

- ERSATZSP 

- MX_SETERSATZXS 

## **History** 

- 2026 February, A Shell 7.0.1783, ERSATZ.LIT 2.1(104):  Add ability to update ERSATZ device definitions. 

A-Shell Reference 

Page 708 

## **EXIT** 

_Updated June 2021_ 

## **EXIT** 

(Used only from within CMD/DO files.)  EXIT terminates a CMD or DO file, and is only needed when you would like to terminate it somewhere other than the physical end of the file, usually in conjunction with a conditional statement involving IF. 

## **Example** 

```
if "$0" = "" then
```

```
:<Usage:
```

```
    .INFO fname
```

```
>
```

```
exit
```

```
endif
```

```
versys $0
```

```
dir/f $0
```

A-Shell Reference 

Page 709 

## **EXPLORE** 

_Added February 2015_ 

## **.EXPLORE {<directory>}** 

EXPLORE launches Windows Explorer for a specified directory location. 

If no arguments are specified, it explores the current directory. Directory format may be native Windows (relative or absolute), or AMOS-style. Examples: 

```
.EXPLORE %MIAME%
```

```
.EXPLORE SYS:
```

```
.EXPLORE DSK0:[7,6]
```

```
.EXPLORE DSK0:2,2
```

```
.EXPLORE \\SERVER\PATH
```

```
.EXPLORE ..\..\BIN
```

```
.EXPLORE
```

A-Shell Reference 

Page 710 

In the Unix/ATE environment, the directory must be PC native spec and any environment variables are evaluated relative to the ATE client. 

## **History** 

- 2015 February, A Shell 6.1.1401: Command added to A-Shell. 

A-Shell Reference 

Page 711 

## **EZTYP** 

_Updated May 2026_ 

## **EZTYP <filename>** 

EZTYP displays the specified file, using the EZ-SPOOL file viewer. Although this command was officially renamed to "EZVUE" quite some time ago, the original command name of EZTYP has been retained in the interests of backwards compatibility and ontological confusion. Refer to EZSPL configuration, and note that the colors may be affected by settings in the INI.CLR file. 

The operation of EZVUE/EZTYP is reasonably self-explanatory, particularly after a glance at the help screen, which is accessed via the **?** key. However, the following topics may help fill in some of the gaps. 

EZVUE can also be accessed via XCALL EZTYP, or simply by including the TYPE=ON parameter setting within the applicable EZSPOOL configuration file. This latter method will result in an option to preview the file being given every time your application calls XCALL SPOOL. 

The name EZVUE is essentially an alias to EZTYP and came into being to highlight the VUE-like features added to the A-Shell version of EZTYP (command mode, search capability, paging, etc.). 

LOOK is the name of a file viewer included with SuperVue and popular under AMOS, and that EZTYP is generally speaking a very suitable (and more capable) replacement for it. Applications which contain hard-coded references to LOOK might want to just create a look.do file that contains: 

```
;LOOK.DO -
```

```
$R
```

```
EZTYP $0
```

## **Wide Reports** 

EZVUE will automatically switch into 132 column mode if a cursory examination of the first several lines of the file indicates the presence of lines longer than 80 columns (unless AUTOWIDTH=OFF in the EZ-SPOOL configuration file). You can also switch 

A-Shell Reference 

Page 712 

between 80/132 columns with the left and right arrow keys. But if 132 columns is not enough, you can continue to hit RightArrow to shift the entire display window over, several columns at a time. Hitting the Left-Arrow will reverse this process, finally returning you to 80 column mode when you hit the left margin. 

## **Variable Rows** 

If your terminal supports this capability, Shift+Up-Arrow and Shift+Down-Arrow (or just T for Tall/Toggle) will toggle you between the normal 24-row display and a 42-row display. On a modern high-resolution display, viewing a large file at 42 x 132 is quite reasonable and much more efficient than at 24 x 80. 

## **See Also** 

- XCALL EZSPL TYPE command 

- XCALL EZTYP 

- VIEWASHLOG - EZTYP wrapper for filtered viewing of ashlog.log 

## **Subtopics** 

- Status Line Information 

- Printing 

A-Shell Reference 

Page 713 

## **STATUS LINE INFORMATION** 

The status line displays the _current_ line, total number of lines, current _page_ , total number of pages, and a percentage indicating how far the current page is from the start of the file to the end. This would all be very straightforward, except for some performance considerations which complicate the issue. But first, what is meant by the _current_ line? Since EZVUE was designed to work with extremely large files, it does not store the file in memory. And since it does not allow changes to the file, there is no _cursor_ . So there really is no particular _current_ line. However, for the purposes of the status line information, the current position is taken to be the end of the last line visible on the screen. 

Next, what is a _page_ ? If the file has hard page breaks, then an EZVUE _page_ is equal to a printed page. These page breaks will display as an entire line of ^^^^ characters on the screen. If the file does not have hard page breaks, then an EZVUE _page_ is simply a screen-full (typically 21 lines, since three lines are used up by the command and status prompts). 

Even after defining what a line and a page are, we still have the problem of determining just where we are in the file. This may seem strange, since EZVUE looks like an editor, and an editor obviously has to know exactly where you are in the file or you would not be able to edit it with the desired results. The problem, as mentioned above, is that since EZVUE was designed to view large report files with the maximum performance and minimum memory overhead (rather than be an editor), it does not load the file into memory. Instead, it uses the operating system’s seek facility, which is byte oriented, rather than page or line oriented, to move about the file. For this reason, it is not able (at least initially) to report the exact number of lines and pages in the file. Instead, it makes an estimate, using the average line size for the part of the file that it has had to scan in order to display it. To avoid giving a false impression of precision, it displays a question mark next to those line and page numbers which are only estimates. 

Any example may make this clear. At the start, it only reads enough lines to display one screen full. At that point, it knows exactly which line it is on, but it can only estimate the number of lines and pages in the file, so those figures will have question marks next to them. If you then use the **E** command to go directly to the end of the file, it does a direct seek to the end of the file, then backtracks just enough so that it can display the last lines of the file. At that point, it does not even know which line number or page number it is currently on, since it got to the end of the file without reading it sequentially from the beginning. However, if you request to seek directly to page 50, then it will be forced to scan from the beginning of the file, line by line, until it gets to page 50. At that point, it still does not know the total number of lines or pages, but it does know the current line number and page number, and more importantly, it knows the position of all of the pages 1-50. Thus, if you then ask to go backward four pages, it can go more or less directly to that position without having to start over again from the beginning. If you want to compute the precise number of lines and pages in the file, you can do this by requesting to go directly to a page number which is greater than the number of pages in the file (e.g. **=** 9999). After executing that command, it will have been forced to 

A-Shell Reference 

Page 714 

scan the entire file, so from that point forward, it will be able to report the precise number of lines and pages in the file, and be able to go (more or less) directly to any position. 

A-Shell Reference 

Page 715 

## **PRINTING** 

The print command ( **P** ) allows you to print an excerpt (from-to page) of the file. This much is obvious. What may not be obvious is where it gets the list of printers that you are allowed to select from. Since this was originally developed as part of EZ-SPOOL, it uses the EZ-SPOOL configuration file system for determining the names of the available printers. This system allows different sets of printers and other options to be associated with various situations, such as job name, program, account, etc. 

One potential problem with printing excerpts from a file is that the file may have contained special printer control codes (typically at the start of the file) which are lost when only an excerpt of the file is printed. There is no simple and universal solution to this problem, and you will have to use a workaround approach appropriate to your situation. For example, once you realize that the file is 132 columns wide, you can select a printer whose default configuration is set for 132 column printing. (Refer to Printer Configuration for information on how you can create a logical printer that automatically starts in a particular configuration.) If your application handles printer control codes via the PREFIX and SUFFIX options in the Printer INI, rather than by embedding them in the file itself, this problem will be minimized. (All you need is enough sense to select the appropriate printer to handle the excerpt.) If you are using a terminal emulator such as ZTERM which offers a choice of printer font sizes for "local" printing, that may be another solution. (In that case, make sure to add a "Local" printer option which uses the "AUXLOC:" pseudo printer device, which in turn will route the printout back to your terminal or emulator for local printing.) 

Another possibility for dealing with the printing difficulty just described is to use the SBR=EZPRTX parameter in miame.ini. In this case, whenever you print from within EZVUE, it will call the subroutine EZPRTX.SBX, passing it the desired page range parameters, and let it handle the print operation. The source to a generic EZPRTX.SBX is included in the release in DSK0:[7,376], with the idea that application developers can customize it to provide more sophisticated handling of partial file print requests. (For example, you can add code to deal with the printer feature codes, printer selection, etc.) 

A-Shell Reference 

Page 716 

## **FIXTRN** 

## **FIXTRN {ifx | vux | <name.pfk>} {switches}** 

The FIXTRN command performs the functions of the AMOS FIXTRN and SET PFK commands, allowing you to create and edit both types of function key translation tables. 

|**Switch**|**Function**|
|---|---|
|/D{ecimal}|Puts FIXTRN into decimal mode, facilitating the entry and display of binary translations.|
|/?|Writes switch listing and usage info to the screen.|



The "traditional" types of function key translation table (such as those used by VUE and INFLD) have names that match the terminal driver, with the extension indicating the application. Thus am62a.ifx would by the translation table for AM62A drivers when running INFLD. pctdv.vux would be for PCTDV terminal drivers when running VUE. These files are compatible between AMOS and A-Shell. The main difference is that under A-Shell, they are always loaded automatically from the LIB: account on disk, whereas under AMOS, you may need to load them explicitly into system or user memory. To create or edit a function key translation table for VUE or INFLD, use FIXTRN followed by "IFX" for the INFLD translation table or "VUX" for the VUE translation table, e.g.: 

```
.FIXTRN IFX
```

```
   Editing function key translation file: LIB:PCTDV.IFX
```

It will automatically invoke the file for the current terminal driver (PCTDV in the example above) and automatically reference the LIB: directory. 

To create or edit a PFK-style function key table (one that can be used in any application and which can be manually loaded and deleted from user memory to override any other translations), specify a filename with a .PFK extension, e.g.: 

```
.FIXTRN PILAR.PFK
```

A-Shell Reference 

Page 717 

```
   Editing function key translation file: PILAR.PFK
```

In this case, it will not put the file in the LIB: directory, since PFK files must be loaded manually, and thus can exist anywhere. 

The procedure for editing either type of file is the same (since internally, they are the same format). You start by specifying a special key to be used as the delimiter. Pick one that is not needed in any of your translations, perhaps \. For example: 

```
Enter special delimiter key (cannot be used in a translation):\
```

```
Hit a function key (or special delimiter to exit): [181]
```

```
   Current Translation: HELLO^M
```

```
   Update? [y/N] Y
```

```
   Enter new translation: LOG GL:^MRUN GLMENU^M
```

In the above example, we hit the F1 key. The program then echoes the numeric value returned by the terminal driver for that key ([181]) and displays the current translation string, if there is one. In the above example, the previous translation was "HELLO" followed by the ENTER key (CTRL+M). It then gives you the option of updating the translation. In the above example, we changed the translation to `LOG GL:` < ENTER > followed by `RUN GLMENU` < ENTER >. It then loops back to ask for a new key. When you are done examining or defining translations, hit the delimiter key one more time, which will cause it to save the file in the current directory: 

```
Hit a function key (or special delimiter to exit):
```

```
   Outputting updated PILAR.PFK...
```

```
   537 bytes output.
```

To use the translations, use LOAD to load the file into memory: 

A-Shell Reference 

Page 718 

```
.LOAD PILAR.PFK
```

Having done this, you can now hit the F1 key and it will act as if you typed the two commands `LOG GL:` and `RUN GLMENU` . 

You can use the MAP command to check if there is a PFK file currently loaded, and DEL to remove it from memory: 

```
.MAP
```

```
Loaded private function key table: PILAR.PFK
```

```
Free       694863
```

```
.DEL PILAR.PFK
```

```
PILAR.PFK deleted from memory
```

```
IFX and VUX modules reset
```

For more information on function keys and translation tables, see Function Key Translations. 

A-Shell Reference 

Page 719 

## **FORCE** 

_Update May 2015; see History_ 

## **FORCE <target> <text>** 

FORCE allows you to force keystrokes into another job’s input stream. _<target>_ may be "all" or a jobname or a user name. _<text>_ is any string of characters. 

To force control characters, precede them with ^. For example: 

## `FORCE TSKAAA RUN PROG^M` 

In the Unix environment, FORCE uses the SIGUSR1 signal, which can only be delivered between processes belonging to the same effective user or if the sender is the superuser. Refer to File Ownership and Privileges for further details on dealing with the Unix privilege issues. In the Windows environment, FORCE uses the IJC (Inter Job Communication) system, which has no privilege issues, but is subject to being turned off by the IJCFREQ command in miame.ini. Note that the ^M refered to above is composed with the literal characters ^ and M. 

FORCE.LIT supports the AMOS-style multi-line syntax:, i.e. 

```
.FORCE TSKAAB
```

```
LOG BAS:
```

```
RUN MYPROG
```

```
15
```

```
~
```

```
TIME
```

The above would force TSKAAB to execute "LOG BAS:", then "RUN MYPROG", then "15", and finally a blank line (Tilde by itself is treated as a blank line.) The blank line terminates the force operation. (The TIME command would then be executed back in the current job.) 

A-Shell Reference 

Page 720 

Note that under A-Shell/Windows, the response time for receiving forced commands may be several seconds. To avoid overrunning the target job, the sender will be forced to wait for each command to be acknowledged by the receiver. 

It also supports forcing commands to yourself. This is useful for forcing input to a program that does not normally accept input from a command file. It is usually used with the $NJ system variable in DO files to specify the current jobname, e.g.: 

```
;MYPROG.DO
```

```
:R
```

```
LOG BAS:
```

```
FORCE $NJ
```

```
RUN MYPROG
```

```
15
```

```
~
```

```
TIME
```

Note that the TIME command here will execute _before_ the forced commands, since CMD and DO input is processed first, then type ahead. Also note that there isn't much point in this exercise unless MYPROG (in this case) doesn't accept command file input. Otherwise we could just omit the FORCE command and MYPROG would run the same from the DO file as it would with the forced input. 

A-Shell still supports the non-AMOS standard single-line FORCE, in which the command is passed on the command line, e.g.: 

```
.FORCE TSKAAB LOG SYS:^M
```

Note that in this mode, you have to explicitly add a ^M to the end of the line to force a carriage return. 

Finally, note that the LITMSG.xxx message files have been updated for some new messages in FORCE. 

## **History** 

A-Shell Reference 

Page 721 

- 2015 May, A Shell 6.1.1408: Updated routine to recognize and preserve a new unique identifer field in the JOBTBL. The new version is backward compatible with earlier versions of A-Shell and has a "B" in the version number to help easily identify it. 

A-Shell Reference 

Page 722 

## **FUNCIDX** 

## **FUNCIDX <wildcard list> {switches}** 

FUNCIDX is a developer tool that generates an XTREE index of functions within a set of files as an aid to locating and using them. It is mainly intended for the SOSFUNC library of BSI files, but could be used with any set of programs. 

## **Switches** 

|**Switch**|**Function**|
|---|---|
|/XL|output to FUNCIDX.CSV (and XLSX usingCSV2XL.SBX) (automatic if GUI not available)|
|/KEYWORDS:fspec|specify alternate list of keyword (regex patterns)|



Default wildcard list is *.bsi in either the current or a specified directory. 

## **Example** 

Here's an example by keyword, showing the files and functions connected with the keyword json. Note that you use the buttons at the bottom to bring up the selected file/function in one of the specified editor/viewer programs. 

## **History** 

- 2023 September, A Shell 1750:  Function added to A-Shell. 

A-Shell Reference 

Page 723 

## **HEAD** 

## **HEAD {outspec=}{inspec1{,...inspecN}}{switches}** 

HEAD is similar to the eponymous Unix command and is used to display or copy to another file the first N lines of a specified file or wildcard list of files. 

## **Switches** 

|**Switch**|**Function**|
|---|---|
|/L{INES}:##|Lines: specifies the number of lines to copy or display. Default is 20.|
|/D{ELETE}|Delete: required when an output file is specified that already exists.|
|/Q{UERY}|Query: prompts for confirmation on each file.|
|/?|Writes switch listing and usage info to the screen.|



## **Examples** 

This example displays the first twenty lines of the specified file (more or less equivalent to using `PAGE TYPE <file>` to display one screen-full and then aborting. 

```
.HEAD SYS:ERRMSG.USA
```

This next example is similar, except it uses quotes to refer to a native host operating system file specification (note that they are case sensitive under Unix) and also uses the /L:5 switch to limit the display to the first five lines: 

```
.head "/vm/miame/miame.ini" /L:5
```

A-Shell Reference 

Page 724 

This next example creates a file called verdir.txt, which consists of the first line of each ASB source file in the current project. Assuming you adopted a standard of putting something meaningful and consistent on the first line of each source file, this could be a very useful way to compare two sets of source files (i.e. use the command below on each set of files, then sort the resulting header files and compare them using SRCCOM). 

```
.head verdir.txt=*.bas[,*]/l:1/d
```

See the notes on TAIL for the same idea only counting from the end of the file. 

## **History** 

- 2022 June, A Shell 6.5.1717, HEAD.LIT 3.4(107): Updated to fix a very old bug which would result in the directory listing being duplicated if there were consecutive DEVICE statements for the same device—i.e. one normal DEVICE definition and one or more PPN-specific definitions. 

A-Shell Reference 

Page 725 

## **HOST** 

_Rewritten April 2024_ 

## **HOST {{switches} cmd {modifier}}** 

HOST is a special command used to either exit A-Shell entirely (if no arguments specified), or to temporarily reach outside it execute a command or program in the outside world—i.e. the parent shell or native operating system environment. 

## **Parameters** 

## _switches_ 

|**Switch **|**Function**|
|---|---|
|/S|On return from the specified cmd, display its exit status code|
|/O|(Unix only) Captures the_stdout_of the command and displays it from within A-Shell. Maximum<br>size of the output text is 512K; if exceeded, a warning message will be displayed at the end of<br>the output. If /O not used, output from the cmd will not be recognized by A-Shell, causing the<br>display to become mixed up. Use<br>`XY=0`to reset it.|
|/?|Display help|



## _cmd_ 

A command or command line recognizable in the environment that A-Shell was launched from. 

## `HOST /s /o du /vm"` 

If the command itself starts with "/s" or "/o" then you must quote the first token of the command in order to avoid confusion with the switches, e.g. 

A-Shell Reference 

Page 726 

```
HOST /o "/o/mycmd" arg2 arg 2
```

_modifer_ 

An optional single character appended to the end of the command line (separated by a space) which affects the way the command is executed. See Command Modifiers. 

## **Comments** 

When HOST is used to exit A-Shell entirely (i.e. with no arguments), if the file OPR:HOST.SBX exists, it will be XCALLed prior to the session terminating. This provides a way for applications to perform cleanup, log statistics, etc. 

## **Example 1:  interactive host command** 

The following UNIX example will launch the vi editor to edit the miame.ini file : 

```
.host vi "/vm/miame/miame.ini"
```

This will take over your terminal until the vi session is exited. At that point control returns back to A-Shell, but you will need to clear the screen to get rid of the characters left behind by vi (which the A-Shell screen tracking system won't know anything about). 

## **Example 2:  redirecting host command to a file** 

This UNIX example generates a process list, filters it to just those lines executing ashell, sends the output to the file ps.lst and the uses the A-Shell EZTYP command to display it. 

```
.HOST ps -ef | grep ashell > ps.lst
```

```
.eztyp ps.lst
```

## **Example 2:  launching a command in background** 

By adding the '&' command modifier (in the UNIX environment), the specified command will run as a child in background, returning control immediately to the A-Shell session, e.g. 

A-Shell Reference 

Page 727 

```
.host "rsync -a /opt/filename.zip /tmp/" >x.lst 2>&1 &
```

## **Example 3:  launching the Windows Command Prompt** 

```
.host "cmd $"
```

In the above example, the '$' command modifier causes control to return to A-Shell immediately, even though the Windows Command Prompt remains open. This is particularly useful for launching a special Windows program that works in parallel with A-Shell (such as messaging app, stock ticker, etc.) 

## **See Also** 

- HOSTEX: Subroutine interface to HOST mechanism 

- SHLEXC.LIT: Launch Windows app registered for file type 

A-Shell Reference 

Page 728 

## **IF** 

_Revised May 2025_ 

## **IF <expr>** 

```
   <statement(s) to execute if true>
```

## **ELSE** 

```
   <statement(s) to execute if false>
```

## **ENDIF** 

IF, ELSE and ENDIF allow for the flow of control within a CMD or DO file based on various conditions that can be tested. IF takes an expression that evaluates to true or false, while ELSE and ENDIF take no arguments. See the example below and Command Files for more information. 

## **Example** 

This DO file takes a filename argument, without extension. If the filename doesn't exist (with a BAS extension), it is created by copying from another file and then loaded into VUE. If no argument is supplied, or the file already exists, it prints an error message and exits. Note that the EXIT command exits entirely out of the CMD/DO file, regardless of the depth of IF/ENDIF nesting, unlike the ASB EXIT control statement. 

```
IF "$0" = ""
```

```
    :<This command needs a filename argument>
    EXIT                      ; exit DO file
ELSE
```

```
    IF LOOKUP("$0.BAS") = 0   ; if file does not exist
        COPY $0.BAS=APPLIB:STDHDR.TXT
```

```
    ELSE
```

A-Shell Reference 

Page 729 

```
        :<$0.BAS already exists; command aborted>
```

```
        EXIT                  ; exit DO file
```

```
    ENDIF
```

```
ENDIF
```

```
VUE $0.BAS
```

A-Shell Reference 

Page 730 

## **IMGDSX** 

_Updated June 2021; see History_ 

## **IMGDSX imgspec {switches}** 

or 

## **IMGDSX @albumspec {switches}** 

IMGDSX provides simple but flexible standalone image display capabilities, either for single images or for albums (lists) of images. 

## **Parameters** 

## _imgspec_ 

The filespec of the image to display. File extension of the image file must match its type and be one of the types supported by AUI_IMAGE (JPG, BMP, PCX, TIF). Remember to quote the imgspec if it is a native filespec not compatible with the AMOS 10.3 format. 

## _@albumspec_ 

The filespec of a text file containing a list of images to display. The format of the list is: 

```
;(blank lines and those starting with a semicolon are ignored)
```

```
imgspec {,title}
```

```
imgspec {,title}
```

```
etc.
```

_switches_ 

A-Shell Reference 

Page 731 

|**Switch**|**Function**|
|---|---|
|/1|Force previous instance of IMGDSX to close before the new one appears. This applies only when<br>launching a new session to execute IMGDSX, or launching it via ATE.|
|/ALBUMFILE|File containing imagespec{,title} lines.|
|/A:hhh|Send a WM_SETFOCUS to window hhh when image has been displayed. Useful for putting focus<br>back on the window that launched IMGDSX. SeeMX_FINDWINDOW<br>for info on determining your<br>window handle.|
|/B:bmsg|Set bottom status message (else bottom status line is removed from window)|
|/C|Continuous (spec if file of specs)|
|/D:secs|Auto-advance delay when displaying an album. Default is five seconds. Note: use a high number<br>(max 65535) to effectively stop the auto-advance.|
|/E|Close instance when Escape hit or X clicked.|
|/M:msg<br>{,scale,attr,font}|Message to display in window just below image (for albums, will be overridden by image title in the<br>album file). Attribute values are the same as those used by AUI_CONTROL .|
|/P|(Albums only) Append "(n of m)" page count info to /M title|
|/S|Stretch image to fit window|



A-Shell Reference 

Page 732 

|**Switch**|**Function**|
|---|---|
|/T:title|Set title bar (else image spec is display on window title bar)|
|/W:l,t,r,b|Left, top, right, bottom window coordinates in units ranging from zero for the top or left edge to<br>10000 for the right or bottom edge. Else window size remains as is.|
|/?|Writes switch listing and usage info to the screen.|



## **History** 

## - 2021 June, A Shell 6.5.1704:  Two IMGDSX.LIT 1.0(115) refinements: 

- Quoted image specs with Unix-style directory separators are now supported. 

- Image specs are no longer folded to upper case. This was a problem for web servers running Linux since Linux is case 

- sensitive. 

A-Shell Reference 

Page 733 

## **ISMBLD** 

_Updated May 2015; see History_ 

## **ISMBLD fspec {switches}** 

ISMBLD performs fundamental file building operations for ISAM 1.x files—i.e., creating a new file, adding an index, loading data. 

## **Parameters** 

## _fspec_ 

is the name of file to create or process. You may specify a directory, but do not specify the file extension. The operation works on both the data (IDA) and index (IDX) files, so specifying an extension will just confuse matters. If the file does not exist, a new IDX and, if necessary, a new IDA will be created based on the ensuing prompts for file configuration details. Otherwise it will prompt for an existing IDA file to which a new IDX can be added. 

For an in-depth discussion on how to use the ISMBLD switches to maximize performance, see ISAM Performance. 

## _switches_ 

|**Switch**|**Function**|
|---|---|
|/A|Auto-Configure Index<br>.|
|/<br>B:###<br>#|Index block size. Allowable values are 512, 1024, 2048, 4096, 8192, 16384; the default<br>value is 512. See Note.|
|/D|Change data device of existing file.|
|/F|"Fast" load. Aassumes no duplicate keys; aborts if any are present.|
|/L:#|Index level. Allowable values are 3 to 9, the default is 3. See Note.|
|/MI|Memory map index during load operation, causing possibly faster runs.|
|/MR|Memory map only the root of the index during load. This reduces the amount of memory<br>required.|



A-Shell Reference 

Page 734 

|eference||
|---|---|
|/N|Use non-exclusive mode.|
|/V|Verbose mode. Displays progress information (percentage complete) during the build and<br>load, and the elapsed time for the load, plus messages confirming the /Mx and /F switches<br>during the load.|
|/?|Writes switch listing and usage info to the screen.|



## **See Also** 

## • ISMDMP.LIT, ISMBLD.SBX, XCALL ISMROK 

- 2026 February, A Shell 7.0.1782, ISMBLD 2.2(147):  The load from IDA option now supports files up to 536,870.911 records (up from 16,777,215) based on the theory that the second byte of each record is part of an ASCII field and thus should be >= ASCII 32 and, if not, can be assumed to be deleted. 

- 2025 November, A Shell 7.0.1781, ISMBLD 2.2(146): The load utility now supports raw data (IDA format) files as well as ISMDMP-generated sequential files. This makes it possible to rebuild a corrupted index by creating a new one and loading from the old IDA. 

- 2015 July, A Shell 6.1.1412, ISMBLD.LIT 2.1(141):  This update fixes a discrepancy between the AMOS and A-Shell behavior of the /D switch, which is used to change the IDA device. Previously, hitting ENTER to the "Enter new device name" prompt was causing an existing explicit device specification to be set to blank, meaning that the IDA is on the same device as the IDX. In contrast, the AMOS version was leaving the existing device specification alone in this case. Instead, you were expected to enter "." to remove an existing device specification. While the A-Shell version was treating "." as an invalid device. 

The updated ISMBLD.LIT 2.1(141) now matches the AMOS behavior, although the prompt has been enhanced to clarify the ENTER and "." options. 

While on the subject of the ISAM IDA device, please take note to remember why the feature existed in the first place: it was a workaround to the 32MB limitation of the original AMOS disk devices. In the modern world, it makes no sense to split the IDX and IDA across different devices. It is strongly recommended that you keep the IDX and IDA on the same device under A-Shell— i.e. leave the data file device option blank. 

A-Shell Reference 

Page 735 

- 2015 May, A Shell 6.1.1411: ISMBLD.LIT 2.1(140) no longer stores the data file device in the IDX unless it is specified explicitly on the command line (e.g. ISMBLD DSK2:MYFILE) or to the "Data file device:" prompt. This partially rolls back a change introduced in 2.1(139) which made the data device explicit in all cases. 

The explicit data device specification was causing a problem for non-AMOS-conforming devices like ARCH27: or VSK: because of limitations in the historic binary format of the IDX. It was also inviting confusion when an IDX/IDA pair was copied to another location for testing. If the data device specification was not updated using the ISMBLD /D switch, the new IDX would continue to reference the old IDA device, possibly leading to inadvertent updating of the wrong file. Note that: 

- ISMDMP displays the data file device (only if it is non-blank). 

- ISMDMP <file>/D can be used to change it. 

- If using an explicit data file device, make sure it follows the form of three alphabetic characters followed by a number 0- 

- 66635, e.g. DSK1: or XYZ999: 

- 2014 January, A Shell 6.1.1373:  ISAM 1.1 refinement: To avoid needlessly complaining about an invalid number of index levels in some IDX files created by ancient (particularly AMOS) versions of ISMBLD, and value < 3 or > 9 is now treated as 3, which was originally the only choice. A warning is logged to the ashlog.log file, along with a recommendation that it be rebuilt, but then it goes on to work as a legacy-format IDX file. Previously, A-Shell complained and returned ERF 35 (smashed index) for any invalid value except 255, which was, until recently, the only legacy/invalid value we had seen in the field. Note that if the file really was corrupt, it will surely generate an ERF 35 in short order anyway, so the only downside to attempting to treat it as a legacy IDX is that you might miss the warning which used to appear on the screen. 

- 2013 April, A Shell 6.1.1348:  ISMBLD.LIT 2.1(134) adds /A switch. 

A-Shell Reference 

Page 736 

## **- AUTO CONFIGURE INDEX** 

_Added April 2013_ 

The /A switch auto-configures the IDX. Instead of prompting for the number of extra empty index blocks to allocate, it prompts for the expected total number of records to configure the index for, and then calculates optimum block size and levels. For example: 

```
ISMBLD TEST/A
Key size: 30
Key position: 1
Size of data record: 64
```

```
Number of records to allocate: 1000
```

```
Auto-configure index for how many (expected) records: 5000000
```

```
    79 index blocks will be allocated
    IDX Configuration: 5 levels, 2048 byte blocks
    Projected IDX blocks by level: 1,3,108,3859,138889
```

```
Primary Directory?
```

```
Data file device:
```

```
Load from file:
```

Note that the prompt for the number of records to allocate only determines the size of the initial empty file, which is not particularly important since the file will auto-expand as records are added. The only advantage of pre-allocating would be the slight possibility of a more efficient arrangement of disk blocks. The prompt for the expected total is actually more important, as it determines the IDX configuration, which will affect the file performance as it gets larger. 

Note also that this version of ISMBLD.LIT is backwards compatible to 6.0. 

A-Shell Reference 

Page 737 

## **History** 

- 2013 April, A Shell 6.1.1348:  /A switch added to A-Shell 

A-Shell Reference 

Page 738 

## **ISMDMP** 

_Updated February 2022; see History_ 

## **ISMDMP fspec {switches}** 

ISMDMP displays information about and/or dumps an ISAM index. 

## **Parameters** 

## _fspec_ 

the name of the index you wish to display. On execution, you will be offered the following choices for output of the information: 

|**Option**|**Description**|
|---|---|
|TTY|Output to screen, starting with header|
|DDT|Output to screen, prompt for options on each block|
|<filespec>|Dump entire file in index order to the specified disk file|



## _switches_ 

|**Switch**|**Description**|
|---|---|
|/D|Display and input block numbers in decimal instead of octal/hex|
|/V|Verbose mode. Displays additional details, assumes TTY output.|
|/?|Writes switch listing and usage info to the screen.|



The verbose option (/V) scans the IDX file to get actual counts of the index blocks in use by level, instead of just estimating it as in previous versions of ISMDMP. To keep the scan time reasonable and focused on the most important top levels, the scan will terminate when it reaches a level which is known—from scanning the level above it—to contain more than 5000 blocks, or when 

A-Shell Reference 

Page 739 

twenty seconds have elapsed. You can also hit any key to terminate the scan. Regardless of how the scan is terminated, the remaining levels will be estimated, as before. Note that since it is inefficient for the top level to contain more than one or two blocks, use of this feature can help you identify files that would benefit from restructuring, either increasing the index block size or the number of levels. 

ISMDMP also indicates if the IDX was built using features that require a certain version of A-Shell, e.g.: 

```
.ISMDMP TEST/V
```

```
Size of data record:     16
Size of dir entry:       14
Size of dir block:       1024
Size of key:             10
Type of key:             200 (requires A-Shell 5.1.1122+)
Entries per dir block:   72
Index levels:            4
Count by level:          1,3,198,14223
etc.
```

## **See Also** 

- ISAM Performance. 

## **History** 

- 2022 February, A Shell 6.5.1711: ISAM 1.X enhancement: IDX rock now contains a count of the keys allocated (additions minus deletions) along with the records allocated. This may be useful as a quick way to compare the number of keys with the number of records. Typically these should be the same, except in cases where the application deliberately adds more or less than one 

A-Shell Reference 

Page 740 

key to the IDX per record. Note that the keys allocated value will only be valid for files that have been rebuilt under A-Shell 6.5.1711+. 

- 2022 February, A Shell 6.5.1711, ISMDMP.LIT 2.0(145): Display new "Keys allocated" count if A-Shell version 6.5.1711+ and non-zero. 

- 2013 March, A Shell 1346, ISMDMP.LIT 2.0(140): Change verbose mode operation from estimating to scanning. 

A-Shell Reference 

Page 741 

## **ISMUTL** 

_Updated October 2020; see History_ 

## **ISMUTL <fspec> {switches}** 

ISMUTL allows you to create a new ISAM-A file set or perform various maintenance operations on an existing one. The ISAM-A file sets consist of a data file with a DAT extension, and an index file containing from one to sixteen logical indexes with an IDX extension. Since the extensions are fixed, _<fspec>_ should not include an extension, and typically is just a name (e.g. `ISMUTL MYFILE` ). If necessary, see the following topics Compressed Records and Compressed Indexes. 

## **Switches** 

|**Switch **|**Function**|
|---|---|
|/A|(with /R, /S or /V) Append output to ISMUTL.LST.|
|/L|(with /R, /S or /V) Write output to ISMUTL.LST.|
|/R|Rebuild file and index(es) unconditionally.|
|/S|Display file stats in non-interactive mode.|
|/V|Verify file (data and all indexes).|
|/V:#|Verify one file component # (0=data, 1=1st idx, etc.).|
|/VRO|Verify in read only mode; skips some tests.|



A-Shell Reference 

Page 742 

|**Switch **|**Function**|
|---|---|
|/W|Wait for exclusive access, else abort if not available.|
|/?|Writes switch listing and usage info to the screen.|



If the specified file does not exist, you will be prompted for information needed to create the file, including: 

```
Number of records to allocate:
```

```
Size of data record:
```

```
Type of key (0=*, 1=integer, 2=concatenated, 3=binary):
```

```
Does key allow duplicates?
```

```
Is key allowed to change?
```

```
Size of key:
```

```
Position of key:
```

```
Extra index block percentage:
```

```
Loading factor:
```

```
Data file device:
```

The questions relating to keys will be repeated up to sixteen times if necessary to define up to sixteen indexes. These prompts are designed to be CMD file compatible with the AMOS version of ISMUTL, so that any command files you have to build ISAM-A files will work under A-Shell as they do under AMOS. However, the interpretation or significance of some of the parameters differs, as described below. 

A-Shell Reference 

Page 743 

The **number of records to allocate** is completely ignored under A-Shell, because ISAM-A files under A-Shell are automatically self-expanding. The DAT file always starts at zero bytes, and grows with each record added. 

The **size of the data record** is the same as for AMOS, except that the current maximum record size under A-Shell is 8196 bytes. 

The " **key allowed to change** " option is presented for CMD file compatibility, but under A-Shell, the key can always change. (It is considered the responsibility of the application to determine this.) 

The **extra index block percentage** and **loading factor** options are meaningless under A-Shell, since the index, like the data file, is self-expanding and self-adjusting. (That is not to say that it cannot benefit from reorganization from time to time, but only due to deletions, not to additions alone.) 

The **data file device** , is also ignored, as there is no conceivable excuse for putting the DAT file on one device and the IDX on another. (This was an option under AMOS where devices were often no more than 32 MB, but in the Windows and Unix world, this is hardly a consideration.) 

When the specified file set already exists, ISMUTL instead displays a menu of maintenance options: 

```
LOAD   - load a file
```

```
CHANGE - change data device name
```

```
ADD2ND - add secondary key directory
```

```
DELETE - delete existing secondary key directory
```

- `INIT   - preserves the structure of the file but removes all the data and keys. See History.` 

```
REBUILD- rebuild primary & secondary key indexes
```

```
DUMP   - dump ISAM file
```

```
STAT   - display statistical information
```

```
ADDIDX - add index block
```

```
DESCRP - change key description
```

A-Shell Reference 

Page 744 

```
EXIT   - exit to A-Shell
```

Again, these options are designed to be CMD file compatible with the AMOS version, so that any existing CMD files which execute ISMUTL commands will function the same way under A-Shell. 

ISAM-A under A-Shell is implemented via a clone of the Informix C-ISAM access method, which has many advantages over a homegrown implementation, but does suffer from a few small discrepancies with the AMOS implementation. Some of these were mentioned above. Another is that the data file extension is DAT (rather than IDA as for AMOS). This might create a conflict in programs that explicitly looked for that IDA file (although the MAPIDA option in miame.ini may handle most of those). There is also a one-block LCK file which is used for locking but which does not exist under AMOS. Another difference is that the actual record size on disk will be one byte larger than specified, due to the addition of a control byte. This, and the fact that the file grows on a record-by-record basis (unlike the AMOS version which is preallocated in blocks) makes even the data files (as well as the IDX files) not binary compatible between AMOS and A-Shell. To move them between platforms, you have to either use ISMUTL to dump on the source platform and then ISMUTL again to reload from the dump file on the target platform, or you can create a program in ASB which reconstructs the file from the existing IDA or DAT file (directly, albeit with some programming difficulty). 

## **History** 

- 2020 October, A Shell 6.5.1690: ISMUTL.LIT 1.4(143) enhancement: add INIT function to menu. INIT preserves the structure of the file but removes all the data and keys. The original DAT and IDX files are rolled over to D0? and I0?, up to three generations, i.e. D01, D02, D03. 

- 2017 February, A Shell 6.3.1545: ISMUTL.LIT 1.4(141) adds an option, when dumping directly from the DAT file, to dump just the active records (default), or just the deleted records, or all the records. The latter two options might be useful in exotic data recovery or other operations. For example, if you accidentally deleted some records, you could dump just the deleted records and then reload them, effectively un-deleting them. Or if you have a large file containing many deleted records, you could split it into two files—one for the active records and one to archive the deleted records—by dumping the active and deleted records separately and then using them to build two new files from scratch. 

- 2017 February, A Shell 6.3.1545: ISMUTL.LIT 1.4(140) adds a new feature to allow dumping directly from the DAT file rather than from one of the indices. 

A-Shell Reference 

Page 745 

## **COMPRESSED RECORDS** 

ISMUTL supports an option for compressed data records (which are very similar to variable length data records). Such records are made up of two parts: a fixed length, uncompressed part, and a variable length, compressed part. The fixed length part must be the first part of the record, and it must be long enough to accommodate all keys. From an application statement, the both parts are combined into a normal fixed length record map, and read/write operations behave as if you were dealing with fixed length records. Internally, the fixed length first part of the record is stored in the DAT file, and the remainder of the record is compressed and stored in the IDX file. (The IDX file was used because it already has solid and efficient infrastructure for dealing with variable-length chunks of data.) 

The compression algorithm is a simple run length encoding scheme which condenses contiguous runs of ASCII 0 (null), 32 (space) or 48 ("0") bytes. (By filling the unused trailing bytes of the record with one of these characters, you get the effect of a variable length record.) 

To specify this type of data record, at the record size prompt in ISMUTL, enter the total record size (as normal) followed by a slash and the size of the fixed length portion of the record. For example, if you have a 512 byte fixed record, with a 7680 byte variable length message area on the end, you would specify it as: 8192/512 

As with the compressed key options, this cryptic format was chosen to preserve compatibility with existing command files that execute ISMUTL. 

There is not yet a corresponding way to specify compressed records using ALLOCATE'INDEXED. 

A-Shell Reference 

Page 746 

## **COMPRESSED INDEXES** 

ISMUTL supports an option to create compressed indexes. There are three types of compression which can be used individually or in combination: 

- Leading duplicate characters. Here, a single byte is used to represent the number of leading characters that have been 

- duplicated from the prior key. This is beneficial when the average number of leading duplicate characters is greater than one. 

- Trailing blanks. A single byte is added to the key to represent the number of blanks on the end. This is beneficial when the 

- average number of trailing blanks is greater than one. 

- Duplicate keys. This only makes sense when duplicate keys are allowed. A two byte duplicate key flag is used to replace 

- duplicate keys. 

Combining all three gives you "maximum" compression. 

Compressed keys do add some processing overhead, but since file access is usually disk bound rather than CPU bound, the decrease in the size of the index generally more than makes up for any increase in CPU activity. They only make sense, though, with string keys, longer than about six bytes. 

To change the compression on a secondary index, you delete the key and then add it back, using the DELETE and ADD2ND options in ISMUTL. To change the compression on the primary index, you need to dump the file and then recreate and reload it. 

Note that the compression option has been appended (somewhat cryptically) to the "Duplicates allowed?" question in ISMUTL. This way it does not change the sequence of prompts and will not break an existing command files the execute ISMUTL. The ISMUTL STAT function will display output a new line indicating if the index is compressed. 

A-Shell Reference 

Page 747 

## **JSTAT** 

_Updated April 2025; see History_ 

## **JSTAT <jobname>** 

JSTAT is useful for monitoring the status and activity of another job. It displays a dynamically updated screen full of information such as the number of reads, writes and basic instructions, both total and rate/sec over the last sampling interval. It also shows the last basic instruction, last subroutine, last line number, current PPN, program, job status flags, etc. This can be useful in a variety of circumstances, such as debugging a job that appears to be in an infinite loop, or determining whether operator is actively keypunching or a remote job is safe to kill. 

As with other utilities that rely on inter-job communication, such as KILL, FORCE and SEND, there are privilege issues to consider under Unix, whereas under Windows the main issue is the IJCFREQ setting in miame.ini. Refer to File Ownership and Privileges for more information on the privilege issue. 

The job activity statistics are maintained in the jobtbl.sys file, making them available to be queried by utilities such as `SYSTAT/W` and JSTAT. Each job updates its own statistics in response to various triggers, the most universal of which is the Inter Job 

Communication clock, whose frequency is set by the IJCFREQ setting in miame.ini. Under Unix systems, jobs can send a request message to other jobs using XCALL ITC, asking them to update their statistics immediately so as to be able to report the very latest. In order for such messages to be delivered, the jobs have to share the same effective user, or the sender has to be root. Failing that, the stats reported may be between 0-<IJC frequency> seconds old; you may also see an ITC error message displayed. Refer to Advanced Privilege Settings for more information. 

## **Example** 

Below is the JSTAT display after the update of December 2023 / A-Shell 7.0.1753; see _History._ Note that: 

- the pink/purple fields are those that have changed since the last screen update (every n seconds) 

- the white fields at the top are relatively fixed per job 

- PID and PPID apply only to Unix. 

A-Shell Reference 

Page 748 

## **History** 

- 2025 April, A Shell 7.0.1771, JSTAT.LIT 3.3(118): the instruction counter, cumulative and per second, now scales itself more appropriately, using single, K or M units as appropriate. This avoids screen wrap and provides a more useful measure of activity for jobs that are either executing less than a thousand or more than several million instructions per second.. 

- 2023 December, A Shell 7.0.1753, JSTAT.LIT 3.3(114):  now displays the current SBX, if applicable. 

- 2021 January, A Shell 6.5.1696, JSTAT.LIT 3.3(113):  now displays the number of open files, and, if applicable, the number of open ISAM 1.x files. 

Aside from general interest, the information may also be useful for determining if the parameters of the `FILES=###,###` statement in miame.ini are adequate. The numbers displayed in JSTAT correspond directly to the parameters of the FILE statement. The first value counts all random, sequential, ISAMA, and ISAM files, plus the terminal itself. The second value counts each ISAM 1.x file opened. 

- 2017 August, A Shell 6.5.1614, JSTAT.LIT 3.2(111): status now shows PC location counter for target job, vastly improving the ability to track the activity of the target even if it is running a program without many line numbers—provided you have the LSX file for the target program. 

- 2015 May, A Shell 6.1.1408: Updated routine to recognize and preserve a new unique identifer field in the JOBTBL. The new version is backward compatible with earlier versions of A-Shell and has a "B" in the version number to help easily identify it. 

- 2011 September, A Shell 5.1.1235:  Add support for new job table layout and ten character program name. 

A-Shell Reference 

Page 749 

## **KILL** 

_Updated May 2015; see History_ 

## **KILL <jobname> {/k}{/y}** 

KILL is similar to, but more complex than, its AMOS counterpart, and works differently depending on whether you are running under Windows or Unix. The additional complexity arises from the dual nature of jobs running under A-Shell. (Such jobs have both an A-Shell/AMOS nature and an underlying Windows or Unix process nature.) It also arises from the fact that, unlike the AMOS counterpart, this version of KILL actually tries to clean up resources left in limbo by the target process. 

For Unix, KILL starts by checking if the underlying Unix process still exists. (Under extreme circumstances, it may be possible to abort a Unix process without A-Shell realizing it; thus leaving a phantom job in the A-Shell job table.) If the Unix process no longer exists, it offers to clean up the resources (file locks and other queue blocks) still associated with the job. Otherwise, it sends a trappable kill signal (SIGINT, same as CTRL+C sends) to the target process and waits a few seconds to see if the job goes away. If so, then we are done. If the process does not go away (possibly because the of insufficient privileges) then this fact is reported and nothing further can be done, unless the **/K** switch was specified. With **/K** , and provided that the user is logged into the OPR: account, it will then proceed to use a stronger (but still trappable) kill signal (SIGTERM) to abort the underlying Unix process (causing an ASB error 251 in the aborted program). Once this is complete, it checks to see if the job left any resources locked in the qflock.sys or jobtbl.sys files. If so, it prompts you to confirm whether you want them cleaned up. 

The **/Y** switch will assume that the answer to this question is "Y", allowing it to be used in unattended processes. An example of where you might want to use this is in a nightly processing routine that requires all users to be either logged out or at least at a known menu. This could be accomplished (under Unix) by executing `SYSTAT.LIT/L` , and then reading the resulting systat.lst file and checking to see which jobs are not in the proper state. Then a command file using `KILL <job>` for each such job can be generated and executed. Without the /K/Y arguments to KILL, it would only have the effect of forcing a CTRL+C to these jobs. Since this might not be sufficient to force the wayward jobs out of their programs, you could use `KILL <job> /K /Y` . Or if you want to really be fancy, you could try it first without the /K /Y, then run another SYSTAT to see if it succeeded, and only then use `KILL /K /Y` on the stragglers. 

Because of Unix security rules, it is impossible for one user to send signals to another unless the first user has superuser privileges, or unless they are both sharing the same effective user ID. Refer to File Ownership and Privileges for help on achieving this, or on setting the SETUID bit on ashkill so that it runs with root privileges. 

A-Shell Reference 

Page 750 

Under Windows, KILL uses the A-Shell Inter Job Communication (IJC) system to send a message to the target job, effectively telling it, in as friendly a manner as possible, to go kill itself. As with the Unix version described above, the /K switch determines how lethal the operation is. Without /K, it is basically no different than a CTRL+C (which may be trapped by the program, or ignored entirely). With /K, the instructions are to abort anything that is running, even VUE. (It is nice enough to save the file first though.) If an ASB program is running at the time, it will be aborted with error 251 (which can be trapped, but only temporarily, because as soon as the program goes into a keyboard operation it will terminated without any further delay). Note that the IJC system clock frequency is established by the IJCFREQ parameter in miame.ini. 

## **History** 

- 2017 January, A Shell 6.3.1542:  Updated to support localization; see LITMSG.xxx 039,### for message customization. 

- 2015 May, A Shell 6.1.1408: Updated routine to recognize and preserve a new unique identifer field in the JOBTBL. The new version is backward compatible with earlier versions of A-Shell and has a "B" in the version number to help easily identify it. 

A-Shell Reference 

Page 751 

## **LICENS** 

_Updated January 2016; see History_ 

## **LICENS {/ATESRV}** 

LICENS provides the means to display your A-Shell license information, and to optionally update that information. Other methods of updating the license are to edit miame.ini directly, and to respond to the prompt which appears on startup if your license has expired. 

When executed, LICENS displays information about the current license (similar to the ABOUT command), and asks if you want to update the license. It then prompts you for a new serial number, license key, and company name, verifies that they are correct, and asks if you want to save the updated information. 

To display the license information, you may be logged into any account. To update the license, you must be logged into the OPR: account. 

LICENS is also used to generate a license for ATE, the A-Shell Terminal Emulator. When updating the license, you will be asked whether you wish to update the license for A-Shell or ATE; select the appropriate one and proceed. 

The /ATESRV switch, which is only applicable when using ATE, causes LICENS to request an ATE license from the server. You do not need to be logged in as OPR: when using the /ATESRV switch. Note that for ATE GUI terminal emulations—i.e. those ending in "G"— `LICENS/ATESRV` will be executed automatically when the client connects. As of A-Shell build 997.3, this is also true for all clients connecting as wyse50, am65, and am75 emulations. However, it does no harm to execute the command manually, and this is can be helpful in debugging if the server-issued licensing isn't working.) 

For PC-based ATE licensing, the MAC address is automatically added to the company name if it is not done manually. 

## **Note** 

If you came to this page wanting to update your license, only to find out that LICENS does not run, the problem is that your version of A-Shell predates LICENS (version 4.8, build 830, of 30 April 2003). To update the license, you will need to use the "Old Method" described in Updating the License. In brief, you will have to run A-Shell from the host prompt with the start-up switch -k (e.g. `ashell -k` ), which will prompt you for license information. If you need to use this method, be advised that your version of A-Shell is no longer supported. You should update to a more recent version. 

A-Shell Reference 

Page 752 

## **See Also:** 

- Installing the Security Key 

## **History** 

- 2016 January, A Shell 6.2.1425, LICENS.LIT 2.4(133): Changed PIC code format to XXXXXXX-XXXXXX-XXXXXX-XXXXXXX to allow various extensions and improved localization in A-Shell 6.3. 

- 2015 May, A Shell 6.1.1408, LICENS.LIT 2.4B(132): Updated routine to recognize and preserve a new unique identifer field in the JOBTBL. The new version is backward compatible with earlier versions of A-Shell and has a "B" in the version number to help easily identify it. 

A-Shell Reference 

Page 753 

## **LOAD** 

## **LOAD <fspec> {switches}** 

## **LOAD <common-module-name> /c** 

The LOAD command loads a module into "user memory". See MEMORY for an explanation of the concept. 

## **Switches** 

|**Switch**|**Function**|
|---|---|
|/L{OCK}|Locks the module in memory so that it cannot be deleted, except by specifying the /UNLOCK switch on the<br>DELcommand.|
|/U{NLOCK}|Unlock is needed in order to reload (update in memory) a module that was previously locked with the /LOCK<br>switch.|
|/C|Indicates that the specified module name is not a disk file to be loaded into user memory, but the name of a<br>COMMON module, which is to be initialized. This distinction is necessary since COMMON modules continue to<br>be implemented via internal memory buffers within A-Shell rather than via user memory.|
|/?|Writes switch listing and usage info to the screen.|



## **Comments** 

The maximum number of modules which can be loaded into user memory per job is 96. 

## **See Also:** 

- DEL.LIT: deletes modules from memory 

- MAP.LIT: display memory modules and memory available 

- MEMORY.LIT: change memory size 

A-Shell Reference 

Page 754 

- MEMORYSP (system parameter): set memory size at system start up 

- MX_USRLODXS: load memory modules from within program 

A-Shell Reference 

Page 755 

## **LOG** 

_Updated June 2016, see History_ 

## **LOG {/n} <destination>** 

A-Shell maps DevPPN format file specifications onto host pathnames using the definitions given with the DEVICE statements in miame.ini. On entering A-Shell, your current working directory is translated into your current AMOS login account. If there is no mapping defined, then you enter A-Shell in a logged off state. You may use the LOG command to log in and subsequently change your login account to one with a valid mapping to an existing host machine directory. 

The implementation of LOG will check for the validity of the PPN, execute any start.cmd command file (unless /N specified), and accept and display ERSATZ names. It does not accept or ask for user names. The user name as returned by the GETJTB subroutine is your user name in the host operating system environment. 

The _/n_ switch disables the normal execution of a start.cmd file in the target directory. _Destination_ may consist of all or part of a device and PPN, or an ERSATZ device. 

## **Examples** 

```
LOG SYS:
```

```
LOG DSK0:[1,4]
```

```
LOG DSK0:1,4
```

```
LOG DSK0:
```

```
LOG 1,4
```

```
LOG ,4
```

```
LOG MYAPP:
```

## **History** 

A-Shell Reference 

Page 756 

- 2016 June, A Shell 6.3.1515:  LOG.LIT 3.0(124) now explicitly reports a log failure to the screen. 

A-Shell Reference 

Page 757 

## **LOGROLL** 

_Added September 2019_ 

## **LOGROLL {fspec1{,...fspecN}} {/switches}** 

LOGROLL rolls over—rotates—log files, for example events.log -> events.l01 -> events.l02, etc. It's a commonly accepted technique for keeping the current log file from getting endlessly large, while at the same time being able to maintain a number of historical/archived copies. 

## **Switches** 

|**Switch**|**Meaning**|
|---|---|
|Switches affecting user interface:||
|/Q|Query/prompt for confirmation on each file|
|/F|Force confirmation—i.e., roll over without asking|
|Switches limiting selection of files to roll over:||
|/MINDAYS:###|Roll over only files not modified in at least ### days|
|/<br>MINSIZE:####|Roll over only files larger than #### blocks|
|Switches limiting number of generations of rolled-over files kept:||



A-Shell Reference 

Page 758 

|**Switch**|**Meaning**|
|---|---|
|/MAXDAYS:###|Discard rolled-over copies beyond ### days old|
|/MAXGENS:###|Discard rolled-over copies beyond ### generations|



## **Comments** 

Retention of rolled-over copies stops after MAXDAYS or MAXGENS, whichever comes first. Defaults: DAYS=unlimited, GENS=5. If GENS < 100, rolled-over copies will use extension x##, where x is the first character of the original extension. Else rolled-over copies will use extension ### (001,002,...). 

## **History** 

- 2019 September, A Shell 6.5.1668:  Added to A-Shell 

A-Shell Reference 

Page 759 

## **LOKUTL** 

_Reviewed July 2020_ 

## **LOKUTL** 

_Unix only._ When LOKSER-type file locking is on (see LOKSERSP for more information), A-Shell translates LOKSER service requests into the corresponding system locking function supported by the host operating system. Under Windows (non-server versions), there is no convenient function to display a list of the current file locks. However, under some flavors of Unix (including AIX and Linux), a shareware utility, _lslk_ , is available which scans the system locking tables and produces a list of locks. For those flavors of Unix, the corresponding copy of _lslk_ is distributed with A-Shell (or can be obtained from the web). This utility by itself is not that helpful, though, as the information displayed is in terms of inodes rather than files, and process ids rather than jobnames. The LOKUTL utility acts as a front end to _lslk_ and is able to output a much more interesting display. 

Windows Server editions contain a mechanism to display files open and locks held by workstations, but the feature is not accessible from within A-Shell. 

A-Shell Reference 

Page 760 

## **MAP** 

## **MAP {/f}** 

MAP displays the contents of user memory, like its AMOS counterpart. If the /F (FULL) switch is specified, it displays the module flag codes associated with each module (from the table below) and also the module version. 

Beginning with version 2.2(106), MAP displays the version number of program modules if the /F switch is specified. This is particularly helpful when trying to figure out if you've got the proper version of an auto-loaded SBX or RUN file in memory. 

|**Flag **|**Function**|
|---|---|
|C|Module is cached in memory and will be deleted automatically as needed.|
|L|Module is locked (see LOAD / LOCK) and cannot be deleted except byDEL /UNLOCK.|
|P|Module is "permanent". (AMOS terminology, indicating that it was manually loaded and<br>thus will not be automatically deleted. UseDELto delete.)|
|R|Module is running and cannot be deleted under any circumstances.|
|T|Module is temporary (will be overwritten by next module loaded).|
|/?|Writes switch listing and usage info to the screen.|



A-Shell Reference 

Page 761 

## **MEMORY** 

## **MEMORY <size> {k}{m}** 

MEMORY resizes your current _user memory_ allocation or partition. User memory is a block of memory reserved for the private use of an individual process (aka job), and functions as a sort of hybrid between cache memory and heap memory. As with cache, programs and other modules are typically loaded and unloaded automatically without any need to pay much attention to it. But you can also perform the cache operations manually via the LOAD, MAP, and DEL commands. Note that loaded modules do not actually take up space in the _user memory_ allocation; they are allocated separately and dynamically. So it is mainly used as a heap to manage variables and stack space while running programs. See DIR /MEMREQ for a way of estimating the memory requirements of a program. 

Typically the user memory size is set via the MEMORY parameter in miame.ini, while the MEMORY system command discussed here is used mainly for experimentation and unusual situations. 

## **Example** 

## **`.MAP`** 

```
PCTDVG.IFX           652    P
Free             4290755
```

## **`.MEMORY 10M`** 

```
Changing main partition size to 10240K bytes
```

## **`.MAP`** 

```
PCTDVG.IFX           652    P
```

```
Free             9656515
```

A-Shell Reference 

Page 762 

## **MMAP** 

## **MMAP {switches}** 

Using the above format, MMAP displays the current list of files to be automatically memory mapped. 

## **MMAP <new mmap fspec>** 

Using the second format, MMAP replaces the current memory map list with the one contained in _new mmap fspec_ . The format of the list consists of one DevPPN filespec per line, the same as for MMAPLIST statement in miame.ini. 

## **Switches** 

|**Switch **|**Function**|
|---|---|
|/L|List, outputs to filemmap.lst. With this switch, the output is displayed on the screen.|
|/?|Writes switch listing and usage info to the screen.|



A-Shell Reference 

Page 763 

## **MOVE** 

_Updated June 2019; see History_ 

## **MOVE outspec = inspec1{,inspec2,...,inspecN} {/switches}** 

MOVE moves files from one place or name to another, which is effectively the same as copying the file and then erasing the source file. In A-Shell, MOVE.LIT and COPY.LIT are actually the same program, so refer to COPY for a description of available switches and other information. 

## **History** 

- 2022 June, A Shell 6.5.1717, COPY.LIT / MOVE.LIT 3.4(147): Updated to fix a very old bug which would result in the directory listing being duplicated if there were consecutive DEVICE statements for the same device—i.e. one normal DEVICE definition and one or more PPN-specific definitions. 

- 2019 June, A Shell 6.5.1662:  MOVE.LIT 3.4(132) has been updated to accommodate a change in maximum filename.ext size, from 10.3 to 72.8. 

A-Shell Reference 

Page 764 

## **MUSER** 

_Added February 2017_ 

## **MUSER** 

MUSER maintains a database of user info, and LOGON.LIT provides a menu-driven text-mode logon portal for A-Shell. Together they simulate the logon scheme used under AMOS. Most A-Shell users rely on the Windows or Unix logon scheme, thus eliminating the need for a separate emulation of the AMOS logon. But for those who have integrated aspects of the AMOS logon into their application logic, the A-Shell emulation of the feature may be useful. 

Note that although both AMOS and A-Shell store the user database in the file OPR:USER.SYS, the file layouts are not compatible. Thus you will have to manually enter all the users when porting from AMOS. Also, several of the AMOS-centric fields in the USER.SYS are ignored. 

Also note that when you use LOGON to log on as a user defined in the USER.SYS database, A-Shell will replace the native 

operating system logon name with the name specified in LOGON.LIT. This name will apply within A-Shell, but will not affect the real identity of the user from the host operating system perspective. 

## **History** 

2017 February, A-Shell 6.4.1543:  Function added to A-Shell 

A-Shell Reference 

Page 765 

## **PAGE** 

_Updated January 2023_ 

## **PAGE <command line>** 

PAGE can be used as a prefix to any other (non-screen-oriented) command to cause its output to be displayed one page at a time instead of scrolling. It stops after each screen-full of output and waits for any key to proceed. For example: 

```
PAGE DUMP FILE.TXT
```

This will dump the contents of the file a page at a time. 

This command can be very useful when dealing with commands that send lots of information to the screen very quickly, such as TYPE, DIR, DUMP, and COMPIL. 

You can terminate the command by entering _Q_ when prompted to proceed to the next page. 

## **See Also** 

- A-Shell's Scrollback feature, which is supported in A-Shell/Windows and ATE. 

## **History** 

- 2016 January, A Shell 6.2.1422, PAGE.LIT 1.0(104): PAGE.LIT now sets a flag allowing other LIT and RUN programs to detect if they are running under control of PAGE. This is mainly for the benefit of ERASE, which see—the History notes—for more information. 

- 2008 September, A Shell build 1125: Adds support for syntax display (PAGE /?), and also checks and adjusts for common mistake of using PAGE <file> to display a file, instead of PAGE TYPE <file>. In other words, if the argument list consists of a single filespec, and that filespec appears to be a text file, it is treated as if the command was PAGE TYPE <file>. 

A-Shell Reference 

Page 766 

## **PRE/OPRE** 

Originally, BASIC did not contain an include file facility, now achieved with ++INCLUDE. To get around this problem, a precompiler was developed, and was used by many dealers, particularly in the UK. This pre-compiler uses $COPY to indicate a file to be included in exactly the same way. The difference is that $COPY statements may be nested, whereas ++INCLUDE statements may not. The pre-compiler generates an intermediate file (.PRE) which contains the expanded source, and which is then normally compiled automatically and erased. It may be left on disk, however, by specifying the **/F** switch. In addition, any of the compiler line switches may be specified, and these are passed on to the compilation phase. 

The pre-compiler was traditionally called PREBAS under AMOS. As with the compiler itself, A-Shell contains two versions, one for BASIC 1.3 (OPRE) and one for BASIC 1.4 (PRE). A .DO file (with the name PREBAS if desired) may be set up to use the appropriate version. 

As with ++INCLUDE, $COPY will accept either AMOS-format file specifications or host pathnames as arguments. 

A-Shell Reference 

Page 767 

## **PRINT** 

_Updated June 2019; see History_ 

## **PRINT {spooler=}<wildcard list> {switches}** 

PRINT supports the switches given in the table below. You only need to include enough characters of the switch name to specify it uniquely. Thus /NOB is equivalent to /NOBANNER, etc. Also, the default for most switches may be set by a statement (e.g. BANNER = OFF) in the INI for that printer. 

If the spooler name is omitted, the default (as specified by the PRINTER property in miame.ini) will be used. It must match up with a spooler initialization file named %temp%\<spooler>.pqi or sys:<spooler>.ini or ashcfg:<spooler>.pqi which contains the configuration parameters for that logical printer. Under A-Shell/Windows, you can also use the special spooler name "PROMPT" (which displays a typical Windows printer selection dialog) or you can specify a printer name that is recognizable by Windows (i.e. the type that appear underneath the printer icons). In these last cases, there will be no printer initialization file, and a default configuration consisting of PASSTHROUGH=OFF and PITCH=AUTO will be used. 

A-Shell does not include an internal implementation of the spooler, and instead uses the "natural" spooler for the host operating system. Thus, the precise effect of most of the option switches described will vary from one operating system to the next. See Printer Configuration for more information. 

## **Switches** 

|**Switch**|**Function**|
|---|---|
|/{NO}B|Controls whether a banner is sent at the start of the printout. Under Windows this has no effect. Under<br>most Unix versions, the default spooler behavior is to force a banner regardless, unless the option to<br>request no banner has been specifically enabled with something like:<br>`# /usr/lib/lpadmin –p`<br>`<ptr> -onobanner`|
|/C:##|Specify number of copies of file to print.|
|/{NO}D|Controls whether the file is deleted after printing.|



A-Shell Reference 

Page 768 

|**Switch**|**Function**|
|---|---|
|/{NO}FF|Controls whether a formfeed is sent after the last page.|
|/{NO}H|Controls whether a header is printed at the top of each page indicating the filename, time, date, and<br>page number. Since this feature is not offered by most non-AMOS spoolers, the A-Shell PRINT command<br>has to simulate it by creating a temporary file with the headers and then spooling that file in place of the<br>original.|
|/{NO}LA|(Windows only) Overrides the ORIENTATION parameter in the printer ini file.|
|/LPP:##|When used in conjunction with the /HEADER option, defines the number of lines printed per page.|
|/M:##|When used in conjunction with the /HEADER option, defines a left margin size.|
|/{NO}PA|Passthrough switch: controls whether the file is sent "raw" to the printer or is allowed to be "cooked" by<br>the printer driver. Refer to the discussion onPASSTHROUGH<br> for more information on this important<br>topic.|
|/OVERLAY:fspec|Specifies anoverlay<br>file and overrides any such setting in the printer init file.|
|/PREFIX:fspec|Specifies aprefix<br> file and overrides any such setting in the printer init file.|
|/{NO}PREVIEW|Set behavior ofAPEX<br> to preview or not preview received reports. This value overrides user setting.<br>PRINT.LIT3.0(123).|
|/Q|Standard query switch – causes each matching filename to be displayed and the user given a Y/N choice<br>of whether to print that file.|
|/SUFFIX:fspec|Specifies asuffix<br> file and overrides any such setting in the printer init file.|



A-Shell Reference 

Page 769 

|**Switch**|**Function**|
|---|---|
|/SW:####|Provides an alternate way of passing switches. Instead of by name, you can pass the sum of the numeric<br>switch values, as you would in the SWITCHES parameter ofSPOOL/EZSPL.PRINT.LIT3.0(123).|
|/W:##|When used in conjunction with the /HEADER option, defines the position of the "Page #" at the right side<br>of the page header.|
|/?|Writes switch listing and usage info to the screen.|



The technique for displaying the print queue and canceling a printout varies from one operating system to the next. Under Windows, you just use the Print Manager (generally accessible by double-clicking on the printer icon in the system tray at the end of the task bar). Under Linux, the typical equivalents are lpq and lprm. To execute these from the A-Shell dot prompt, just create a DO file which uses the HOST command (e.g. HOST lpstat –t). Also, most Unix variations have a menu-driven or even GUI utility for doing these kinds of things. 

## **History** 

- 2022 June, A Shell 6.5.1717, PRINT.LIT 3.4(137): Updated to fix a very old bug which would result in the directory listing being duplicated if there were consecutive DEVICE statements for the same device—i.e. one normal DEVICE definition and one or more PPN-specific definitions. 

- 2019 June, A Shell 6.5.1662, PRINT.LIT 3.4(134): Updated to accommodate a change in maximum filename.ext size, from 10.3 to 72.8. 

- 2018 November, A Shell 6.5.1651, PRINT.LIT 3.3(131): Updated to avoid a read-only error related to the smart-scrollback activation feature. 

A-Shell Reference 

Page 770 

## **QUTL** 

_Updated January 2025; see History_ 

## **QUTL {switches}** 

QUTL is an interactive utility offering several functions related to QFLOCK.SYS and JOBTBL.SYS. As it is capable of interfering with other jobs, it can only be run from the OPR: account, which may be password-protected to limit access. When launched without any switches, it bring up this menu: 

```
A-Shell QFLOCK.SYS/JOBTBL.SYS utility program version 3.1
Enter:  STATUS - display status of queue file
        FLIST  - list all FLOCK locks
        FINIT  - initialize FLOCK lock list
        XLIST  - list all XLOCK locks
        XINIT  - initialize XLOCK lock list
        ZAP    - remove all queue entries for a job (by name)
        ZAPPID - remove all queue entries for a process id #
        ZAPURJ - remove all queue entries for unresponsive jobs
        EXIT   - exit to A-Shell
Enter choice: ________
```

A-Shell Reference 

Page 771 

## **Switches** 

|**Switch**|**Effect of Switch**|
|---|---|
|(none)|Program runs in interactive mode|
|/FL:fspec|Output flock list to specified fspec|
|/XL:fspec|Output xlock list to specified fspec|
|/ZAPURJ|Non-interactive version of ZAPURJ command|



## **Comments** 

A-Shell on multi-user (and even stand-alone) systems uses a queue file, qflock.sys, in which to store information which may be shared by multiple users. This file is in the form of a linked list, analogous to the AMOS queue blocks system, and is used by the FLOCK and XLOCK subroutines. 

The QUTL command is primarily intended to give some control over the FLOCK and XLOCK locks present on the system, by reading and processing the queue file. It can display which users currently have locks, and is also able to re-initialize the XLOCK and FLOCK queue lists , a process which normally requires a machine reset under AMOS, or some specially written assembly language routines. QUTL may also be used to zap a logged on A-Shell user. This will remove all locks and queue blocks associated with that user, and although the user may continue to be able run whatever program they are in, as soon as it attempts to make an XLOCK or FLOCK call, or when it exits back to the dot prompt, it will see that it has been removed from the queue and will abort with an appropriately (cryptic) error message. (Something like "your queue file has been zapped.") 

When used to list the existing XLOCKs and/or FLOCKs, QUTL provides an option to output the list to a file. This, combined with the fact that you can run QUTL from a command file, provides a mechanism for nightly processing programs to check if any locks 

A-Shell Reference 

Page 772 

were left in use, and optionally remove them (either by zapping the queue entirely, or just the user, or by using the KILL.LIT utility). 

## **History** 

- 2025 January, A Shell 7.0.1768, QUTL.LIT 3.1(137):  QUTL now displays additional statistics (in the STATUS option) that are now captured by A-Shell: 

```
JOBTBL.SYS created:           Tue Jan 14 10:08:40 2025
Number of job table entries:  2
Highwater job count:          4
Number of license denials:    0
Number of sessions started:   631
Number of sessions ended:     629
CGI sessions:       Current:  0    Cumulative: 629    Highwater: 2
```

Note that these fields will contain garbage (harmless) until the JOBTBL.SYS is recreated using 7.0.1768.0+. 

## - 2023 January, A Shell 6.5.1724, QUTL.LIT 3.1(133):  add option to choose job to ZAP from a pick list. 

- 2021 December, A Shell 6.5.1709, QUTL.LIT 3.1(132):  add new command/switch "ZAPURJ" (for ZAP UnResponsive Jobs) to remove all abandoned job table entries resulting from sessions terminating without cleanly exiting from A-Shell. The command may be specified interactively from the QUTL menu, or via the /ZAPURJ command line switch. 

2016 November, A-Shell 6.4.1534, QUTL.LIT 3.1(129):  Remove previous maximum of 20000 FLOCK or XLOCK records and reduce the fixed partition memory requirement from approximately 700K to 200K by using dynamic arrays. 

A-Shell Reference 

Page 773 

## **RENAME** 

_Updated June 2019; see History_ 

## **RENAME <out-wildspec>=<in-wildspec1> {switches}** 

RENAME renames files without moving them. 

## **Parameters** 

_out-wildspec_ 

may be a single file, or a wildcard specification. 

## _in-wildspec_ 

may be a single file, a wildcard specification, or a comma-delimited list of file or wildcard specifications. 

## **Switches** 

|**Switc**<br>**h**|**Effect**|
|---|---|
|/D|Overwrite the name of an existing output file (whose contents would then be deleted).|
|/Q|Queries the user for a confirmation before renaming each of the input files.|



Although RENAME appears to have the same syntax as COPY (and MOVE), it is restricted by the fact that the output file location must match the input file location. This is normally used on files in the current directory, eliminating the need to specify a device or PPN. 

Note that RENAME recognizes filespecs ending in a period ( "." ) as indicating a file with no extension, rather than as a wildcard. 

A-Shell Reference 

Page 774 

## **History** 

- 2019 June, A Shell 6.5.1662:  RENAME.LIT 3.4(117) has been updated to accommodate a change in maximum filename.ext size, from 10.3 to 72.8. 

- 2011 June, A Shell 5.1.1221:  Remove the limit on the number of PPNs allowed per device. 

A-Shell Reference 

Page 775 

## **RUN** 

_Added October 2016_ 

## **RUN <program-spec>** 

RUN loads the specified program into memory and starts the runtime interpreter executing it. 

## **Parameters** 

_program-spec_ 

an unqualified (e.g. PROG), partially or fully-qualified specification of a compiled ASB program file. 

## **Comments** 

The file extension defaults to RUN if not specified. If the path is not specified, the search path starts in the current directory, then the [p,0] directory, then DSK0:[7,6] (aka BAS: ). 

RUN file names, like other A-Shell filenames, are typically limited to ten characters, not counting the extension. And the RUN file locations are normally specified using AMOS-style notation, although as of 6.3.1530.0, you can use native-style file specifications as long as they are quoted. For example: 

```
.RUN MYPROG
```

```
.RUN MYDIR:INVOICES
```

```
.RUN DSK1:SENDMAIL[100,5]
```

```
.RUN "/vm/miame/dsk0/077077/yearend.run"
```

Regardless of whether the path is fully specified, RUN first checks to see if the <file>.RUN is loaded into memory (see LOAD.LIT). RUN programs loaded explicitly using LOAD.LIT will remain in memory; otherwise they are removed from memory on completion. 

Compiled SBX subroutines (see Subroutines vs. Programs) have the same internal format as regular programs and thus may be run by the RUN command, provided you specify the .SBX extension, e.g. 

A-Shell Reference 

Page 776 

```
.RUN BAS:SBXINP.SBX
```

Note that most SBX routines do not make sense to execute this way, but there is no technical obstacle to creating an SBX routine that can be executed both by RUN from the command prompt as well as by XCALL from within a program. 

## **History** 

- 2016 October, A Shell 6.3.1530: quoted native filespecs now supported with RUN, e.g. `.RUN "/vm/miame/webcache/hello.run"` 

A-Shell Reference 

Page 777 

## **RUNPROF** 

_Added July 2023_ 

## **RUNPROF <program name>** 

## **RUNPROF {switches}** 

RUNPROF generates a run profile log to be analyzed for an overview of the program call structure and performance. The first syntax runs <program name> and captures profile data to <pid>.rpl. When run without <program name>, RUNPROF returns its current status. 

## **Switches** 

|**Switch**|**Effect**|
|---|---|
|/ON {:output file}|Enable logging. Ddefault file is <pid>.rpl.|
|/VERBOSE|With /ON, logs calls not just returns.|
|/OFF|Disable profiling and close output file.|
|/CSV{:rplspec}|Create CSV from specified .rpl file.|
|/XL{:rplspec}|Create detailed spreadsheet from specified rpl file.|
|/XLSUM{:rplspec}|Create summary spreadsheet from specified rpl file.|



A-Shell Reference 

Page 778 

|ell Reference||
|---|---|
|/PROG:<program>|Use with /XL to specify target program.|
|/?|Writes switch listing and usage info to the screen.|



## **See Also** 

- MX_RUNPROF 

## **History** 

- 2023 July, A Shell 6.5.1735: Function added to A-Shell. 

A-Shell Reference 

Page 779 

## **SEND** 

_Updated and reviewed August 2020_ 

## **SEND {switches} <target> <message>** 

SEND delivers _<message>_ to one or all other jobs on the system. 

## _switches_ 

|**Switch **|**Effect**|
|---|---|
|/B|Send message to bottom status line.|
|/F|Queries one or all jobs to see which have a specified file open.|
|/T|Send message to top status line.|
|/W|Send message to pop-up window. Default.|
|/WAIT|Wait for message to be acknowledged|
|/?|Writes switch listing and usage info to the screen.|



If you use switches /T or /B and the applicable status line is not enabled on the target terminal, the message will not be displayed anywhere. 

## _target_ 

may be either the job name or the login user name of the person to whom you want to send a message. "ALL" or "TODOS" or "TOUS" will send a message to all users. Use SYSTAT to see which job and user names are available. 

## _message_ 

any text message or, if /F switch is specified, a filename. 

## **Unix** 

A-Shell Reference 

Page 780 

Under Unix, SEND is implemented via the operating system’s signal delivery system. If the target is running PolyShell, then the message will appear in a pop-up window. Otherwise, the message will simply appear at the current screen cursor location, overwriting whatever was there previously. 

Because of Unix security rules, it is impossible for one user to send signals to another unless the first user has superuser privileges, or unless they are both sharing the same effective user ID. See File Ownership and Privileges for instructions on achieving this. 

## **Windows** 

Under Windows, SEND is implemented using the "Inter Job Communication" (IJC) system, which was introduced in A-Shell 4.6. Unless the /T or /B switch is specified, the message is displayed in an independent pop-up window using the awmsg.exe utility which is distributed with A-Shell. The message window initially appears on top of all other windows, and does not interfere with the target A-Shell window in any way. 

Also under Windows, SEND may take a few seconds for the sent message to be received. The reason for the relatively slow reaction is that the IJC system sends messages between jobs by way of the JOBTBL, which depends on each job checking it's own entry every few seconds. The time period is configurable somewhat via  IJCFREQSP; the optimum appears to be somewhere in the range of 5 seconds, which makes it tolerable in the case of SEND and other commands dependent on it, such as `SYSTAT/W` and JSTAT, yet not creating an intolerable amount of useless overhead. 

## **Example** 

The command 

```
.SEND /F ALL CUSTO
```

queries all other jobs to see if they have a file named CUSTO—any directory or file extension—open. This can be a convenient alternative to the use of OS-level utilities to figure out which job is preventing your job from gaining access to a needed file resource. 

## **History** 

- 2020 July, A Shell 6.5.1688, SEND.LIT 2.3(125): New /F switch allows querying one or all jobs to see which have a specified file open. 

A-Shell Reference 

Page 781 

- 2015 May, A Shell 6.1.1408, SEND.LIT 2.2B(123):  Updated routine to recognize and preserve a new unique identifer field in the JOBTBL. The new version is backward compatible with earlier versions of A-Shell and has a "B" in the version number to help easily identify it. 

- 2011 September, A Shell 5.1.1235:  Minor adjustment to drop the sending job name from the message (in order to allow more space for the message itself, since part of that space was taken over for the new expanded program name.) 

## **Subtopics** 

- SENDing to ATE 

A-Shell Reference 

Page 782 

## **SENDING TO ATE** 

SEND under Unix supports a /W switch to send a "Windows" message if the terminal is a ZTERM or ATE workstation. Otherwise it acts just like SEND without a switch. 

The Windows version of the message launches an external application, asmsg.exe which must be in the path on the workstation. The best place to put it is in the directory where ATE or ZTERM is launched from—typically c:\program files\microsabio\ate\bin or c:\program files\cool.stf\zterm for windows—although it could also be the Windows directory. 

The idea of using an external program to display the message is to allow sites or resellers to customize the message utility. We provide a very simple example in the SYS: directory of the Unix releases. 

If you want to create your own, the requirement is that it support the following command line format: 

```
asmsg.exe /T:title /M:message
```

To distribute the utility, you may want to add logic to your application startup to use the ATSYNC mechanism, or a standard ZTERM file transfer, to copy it from the server to the workstation. The utility is small enough that this will take nearly no time at all. We would have done this automatically within the message handler, but since file transfers can sometimes require user intervention, it seems questionable to get into that during a signal receiving routine. 

Note that the existing awmsg.exe which is distributed with A-Shell/Windows and used by default with SEND.LIT will work fine with the Unix version (just copy it to asmsg.exe). The only difference between it and the standard release asmsg.exe is that asmsg.exe displays a much bigger window. 

A-Shell Reference 

Page 783 

## **SET** 

## **SET {function}** 

The SET command controls and displays a variety of A-Shell's behaviors; see the following list. Entering `SET` with no specifications will display current settings, and `SET/?` will display the functions shown in the table below. `SET TERM, SET TRACE` and `SET LANG` all return the current settings for the indicated function. 

|**Function**|**Displays**|
|---|---|
|{NO} ABSLOOKUP|Always return absolute value inLOOKUP.|
|{NO} HASH|Turn on and off AMOS compatible hash codes, and applies only to text files under A-Shell/Unix. The<br>default is off. When on, the A-Shell hash routine will pretend as if there were aCRto go along with<br>any LF line terminators when generating a hash code (since Unix text files normally only have LF line<br>terminators whereas AMOS, Windows, and DOS use CRLF).|
|{NO} AMOSRUNSBR|Execute Xcall ASHELL within current process.|
|{NO} AUTOTPRINT|Turn on/off AUTOTPRINT.|
|{NO}CMDINP|CMD file input.|
|{NO} CTRLC|CTRL+C|
|{NO}DEBUG<br>{#}|Cause RUN programs compiled with /X:2 but not /DEBUG, to interpret the DEBUG variable as 1 (or #<br>if specified.) SeeDEBUG<br>for more details.|
|{NO} ECHO|Character echo.|



A-Shell Reference 

Page 784 

|**Function**|**Displays**|
|---|---|
|{NO} EXTFIO|Extended file I/O.|
|{NO} FIELDEMU|Field Emulation.|
|{NO} FPROUND|Floating point expression rounding.|
|HEX|Set Hex output.|
|INFDEF|Change or display INFLD codes.|
|LANG|Set/display language: SET LANGUAGE {lang}. If_lang_is not specified, it displays the name of the<br>current language. Otherwise if tries to load the specified language file, interpreting_lang_as the LDF<br>file name in the same way thatMX_LANGUAGEdoes. Thus, while SET LANGUAGE may return<br>"SPANISH", to set the language to Spanish you may need to use SET LANGUAGE SPANSH, assuming<br>the LDF file name isdsk0:spansh.ldf[1,6].|
|{NO} LATIN1|LATIN1 eight-bit mode.|
|{NO} LOKSER|TurnLOKSER<br>on/off.|
|LOGDIR|Changes the ashlog.log directory.<br>`SET LOGDIR dirspec`|
|LONGDIR|ForcesDIRto act as if the /L{ONG} switch had been set.|
|OCTAL|Set Octal output (e.g. inDUMP).|



A-Shell Reference 

Page 785 

|**Function**|**Displays**|
|---|---|
|PROMPT <prompt>|Set command prompt to <prompt>.|
|{NO} STRICT|Strict AMOS compatibility mode.|
|TERM|Terminal options.|
|TITLE Definition<br>String|Set top status line or window title.|
|TRACE|Trace options.|
|WEBCACHE|Set various options for A-Shell WEBCACHE system.|



## **History** 

- 2022 May, A Shell 6.5.1716, SET.LIT 1.2(166):  now supports the SQL TRACE, and the TRACE options are now displayed alphabetically. 

- 2017 July, A Shell 6.5.1610, SET.LIT 1.2(161):  now makes the scroll bar visible if the environment supports it (A-Shell/Windows and ATE version 6.5.1610 or later) and the output of the command causes the screen to scroll. 

- 2017 February, A Shell 6.3.1543, SET.LIT 1.2(161):  adds LANG 

- 2016 October, A Shell 6.3.1531, SET.LIT 1.2(158):  adds WEBCACHE 

- 2016 September, A Shell 6.3.1526, SET.LIT 1.2(156): updated to support TRACE flags JOBLCK and EXEC, which were added in 6.3.1518.0. 

A-Shell Reference 

Page 786 

## **CMDINP** 

This turns on and off command file input within subroutines INPUT or INFLD. The default is off, in which case these input routines do not accept input from a command file. INFLD supports a _type_ **p** which turns on command file input, and you can force this on by adding SBR=INFDEF:P to miame.ini file. But these methods either require a change to your program or that you exit from A- Shell and modify miame.ini. The SET {NO}CMDINP command, on the other hand, can be used within A-Shell, or even within a command file. For example, you might have a command file which contains: 

```
:R
```

```
SET CMDINP
```

```
RUN MENU
```

```
15
```

```
<program inputs>
```

```
SET NOCMDINP
```

```
RUN MENU
```

```
HOST
```

The above command file starts by setting command input on, and then runs a menu program, and forces it to select option 15. It then continues to include the necessary prompts for the program corresponding to menu option 15, after which that program finishes and returns to the command file. Then it turns command file input back off again and starts up the main menu, which now waits for real keyboard input. Finally, when the user exits out of that menu, the command file picks up and forces A-Shell to exit. 

A-Shell Reference 

Page 787 

## **DEBUG SETTINGS** 

_Updated October 2025; see History_ 

Beginning with A-Shell 6.5.1639, SET.LIT 1.2(162), expanded DEBUG options are provided in order to take advantage of the expanded trace statement options: 

|**Option**|**Description**|
|---|---|
|.SET DEBUG ?|Show syntax options|
|.SET DEBUG <level>|Set debug level|
|.SET DEBUG MIN <level>|Set minimum debug level|
|.SET DEBUG TAGS {+}tag1,...tagn|Set tags to select/filter traces|
|.SET DEBUG OUTPUT <dest>|Specify where trace output goes|
|.SET DEBUG PREFIX <prefix-string>||



The standard SET DEBUG <level> command is unchanged, except that the maximum has been increased from 9 to 2^31. Note that except for programs which explicitly map a variable named DEBUG, the runtime system will recognize DEBUG as a special system variable whose value is that specified by the SET DEBUG <level> command. 

The DEBUG MIN option allows you set a minimum level, such that only those trace/debug statements specifying a level >= the DEBUG MIN level and <= the DEBUG level will be activated. The idea here is to allow different developers to set exclusive ranges 

A-Shell Reference 

Page 788 

so that they can easily enable their own debug traces independent of others'. Or to use different ranges for different modules (although the tags might be more suited for that). 

The DEBUG TAGS option allows you to specify a list of tags (comma delimited) to be matched up with the tags in the actual trace/debug statements for the purposes of filtering which will be enabled. Tags are not case sensitive. If the list starts with "+", then individual traces will be enabled if they meet the debug level criteria _or_ they contain a matching tag. Otherwise statements to be enabled must match both criteria, i.e. satisfy the level AND match one of the tags.  Note that setting the DEBUG TAGS list to "" is equivalent to a wildcard matching all tags. But within the trace/debug statements themselves, and empty tag list matches only an empty DEBUG TAGS list. 

To select statements by level without regard to tags, set the DEBUG TAGS to "". To select statements by tags without regard to level, specify a DEBUG TAGS list starting with "+". (To exclude traces that don't contain matching tags, use the DEBUG and/or DEBUG MIN levels to make sure that they won't match up with any of your traces. For example, if all of your trace statements are of the form DEBUG.XXX, instead of TRACE.XXX, or all of them explicitly specify a non-zero level, then just use SET NODEBUG to make sure that none are selected on the basis of the debug level. Alternatively, set the DEBUG MIN level higher than the DEBUG level.) 

Note that all TRACE.XXX and DEBUG.XXX statements automatically have a special tag associated with them that matches the current program name, so to select only traces for that program, use the technique just described with SET DEBUG TAGS +program. 

The DEBUG OUTPUT option controls where the trace/debug output messages go. The options for <dest> are: 

|**<dest>**|**Message Destination**|
|---|---|
|$WIN|System messages window; default for GUI environment|
|$TTY|Main screen; default for text environment|
|$LOG|A-Shell main log file (ashlog.log)|



A-Shell Reference 

Page 789 

|**<dest>**|**Message Destination**|
|---|---|
|$NULL|No output|
|$SBX:sbxnam|Specified <sbxnam>.SBX|
|<filespec>|Specified filespec|
|$SYSLOG|Syslog service|



## **See Also** 

- ++PRAGMA TRACE_BEGIN AND _END 

- DEBUG SYSTEM VARIABLE 

## **History** 

- 2025 October A Shell 7.0.1780, SET.LIT 1.2(172):  Add support for <dest> of $SYSLOG. Example: `SET DEBUG OUTPUT $SYSLOG` redirects trace.print output to the syslog service. 

- 2023 September, A Shell 6.5.1744, SET.LIT(1.2) 168: Add PREFIX option. See extended History note below. 

- 2018 July, A Shell 6.5.1639: Expanded options added to AShell. 

A-Shell Reference 

Page 790 

## **INFDEF** 

SET supports an INFDEF option to display or change the list of default INFLD codes (previously only able to be set via the SBR=INFDEF setting in miame.ini). Syntax: 

```
.SET INFDEF             (display)
```

```
.SET INFDEF <codes>     (replace current defaults with <codes>)
```

MX_INFDEFXS allows the same capability from within a program. If _opcode_ is 0, the current default type codes are returned in the INFDEF parameter, otherwise the current default type codes are replaced by those in the INFDEF string. 

The maximum size of the default string is currently 36. 

This feature is of course handy for experimenting with global INFLD _type_ codes within a single job (without interfering with other jobs). It may also be useful for changing the defaults with a single program. Note that for a particular INFLD call, you can disable the default _type_ codes by adding **m** to the _type_ parameter passed to INFLD. 

A-Shell Reference 

Page 791 

## **TERMINAL OPTIONS** 

`SET TERM` with no further arguments displays the current terminal settings, e.g.: 

```
.SET TERM
```

```
Current terminal settings for TSKAAA are:
```

```
Terminal driver:  PCTDVG
Baud rate:        19200
Terminal width:   80
Terminal height:  24
Foreground color: 6
Background color: 0
Beveling:         Auto
Sys bg color      None
Win bg color      0
Win text color    None
```

Otherwise you may specify one of the variables in the table below, along with one of the allowed values, to update the terminal settings accordingly, e.g. 

```
.SET TERM BCOLOR 2
```

```
.SET TERM HEIGHT 32
```

A-Shell Reference 

Page 792 

```
.SET TERMINAL DRIVER
```

```
AM75Z
```

|**Variable**|**Values**|**Description**|
|---|---|---|
|FCOLOR n|n|Set foreground color to n, where n is 0 to 7. Requires Windows or color emulation.|
|BCOLOR n|n|Set background color to n where n is 0 to 7. Requires Windows or color emulation.|
|HEIGHT n|n|Set height (number of rows) to any value of less than 51. See Comments, below.|
|WIDTH n|n|Set width (number of columns) to any value of less than 161; less than 40 not recommended.<br>A-Shell/Windows or ATE.|
|BEVEL|off, auto,<br>program|Set beveling option. A-Shell/Windows only.|
|SYSBCOLOR n|n|Link background color n to Windows dialog/button color (gray), where n is 0 to 7. A-Shell/Windows or ATE.|
|WINs n|n|Link background color n to Windows edit box color (white) , where n is 0 to 7. A-Shell/Windows or ATE.|
|WINTXTCLR n|n|Link foreground color n to Windows text color (black) , where n is 0 to 7. A-Shell/Windows or ATE.|
|TSTATUS|on / off|Turn top status line on/off. A-Shell/Windows or ATE.|
|BSTATUS|on / off|Turn bottom status line on/off. A-Shell/Windows or ATE.|
|WSTATUS|on / off|Turn Windows status line on/off. A-Shell/Windows or ATE.|
|DRIVER|name|Set the TERM envrionment variable and internal terminal driver|



## **Comments** 

The HEIGHT option is particularly complicated in its dependencies. For A-Shell/Windows and ATE (with any of the "G" emulations), the height may be adjusted from 1 to 50 rows. For remote terminal connections (A-Shell/Unix or ATSD), if the terminal/emulator is AM75, the valid options are 24 and 50. However, if the emulator is ZTERM v144+, and the TERM 

A-Shell Reference 

Page 793 

environment variable is set to "AM75Z", then the valid options are 24-50. The DRIVER option may be used to set the terminal environment variable (which also resets the terminal and internal driver accordingly). 

Note that terminal height/width can also be set via the TAB(-5,rows) and TAB(-6,cols) commands. 

## **See Also** 

- TRMCHRxs (retrive terminal characteristics) 

A-Shell Reference 

Page 794 

## **TITLE DEFINITION STRING** 

The SET TITLE command takes a string argument, optionally preceded by $TS, and which may contain any literal text that you want to appear as the title. If the $TS prefix is specified, the title will appear on the top status line; otherwise it will appear on the window title bar, providing you are running A-Shell/Windows, or you are using ZTERM as your terminal emulator to connect to some flavor of A-Shell/Unix. The following special variables may appear anywhere in the title string: 

|**Variabl**<br>**e**|**Displays**|
|---|---|
|$NC|Name of last executed command (e.g. "SET", "LOG") or program.|
|$ND|Name of current logged in device (e.g. "DSK0")|
|$NJ|Your job name|
|$NP|Name of last program executed (same as $NC but excluding LITs)|
|$PA|Platform A-Shell was compiled for (e.g. "Linux", "Windows/32", etc).|
|$PN|Current p,pn (e.g. "[7,6]")|
|$VA|Version of A-Shell (e.g. "4.6(753)")|
|$VP|Version of current program or command (e.g. "1.0(123)")|



If the title definition string contains any of the above variables, the title will be automatically updated when the value of that variable changes. For example, if the title is defined via: 

```
SET TITLE Job $NJ running $NP version $VP in $ND:$PN
```

Then whenever the program name (excluding LITs) or the current logged in device or PPN changes, the title line will be updated, and would appear something like this: 

```
Job TSKAAB running MYPROG version 1.0(123) in DSK0:[7,6]
```

If you do not specify the $TS prefix (for top status line) and you are not running on either A-Shell/Windows or using ZTERM as your emulator, then the title will just be ignored. 

A-Shell Reference 

Page 795 

If you do specify the $TS prefix and you are running PolyShell, then the title on the top status line will be updated whenever you switch to that window. If you have job-specific information in the title string, then it is highly recommended that you use SET TITLE on each of the processes running under PolyShell; otherwise, when switching to a job or session with no title definition, the previously displayed title will remain, possibly causing confusion for the user. 

A-Shell Reference 

Page 796 

## **TRACE OPTIONS** 

_Updated January 2024; see History_ 

These are equivalent to the identically-named TRACE options in miame.ini. Since they are primarily used only for debugging, it is a handy convenience to be able to turn them on temporarily for a single job or program execution without having to modify miame.ini and re-launch the session. These variables accept only ON or OFF settings. 

See the table in the TRACESP topic for a full listing of all options. 

## **Comments** 

- Depending on the operating system you are running, some of the options may not appear. For example, signals are only available under Unix. 

- In most cases the output of the traces go to the ashlog.log file, which is in the same directory as miame.ini, unless specified elsewhere with the LOGDIRSP property in miame.ini. 

- Any attempt to set any other parameter, even if it is a valid parameter under AMOS, will result in the same error message ("?Invalid function"). 

- With ATE or A-Shell/Windows most log messages can also be captured/displayed in the _System Message Window._ Use CTRL+SHIFT+DOUBLE-CLICK somewhere on the A-Shell window, then right click on the _System Message Window_ ), select _Properties_ , and check the _Show System Traces_ option along with any desired trace options. 

- Beginning with A-Shell 7.0.1754 of January 2024, NOTRACESP is available for turning off tracing for specified subroutines. 

## **History** 

2024 January, A-Shell 7.0.1754: NOTRACESP added to A-Shell. 

2022 May, A-Shell 6.5.1716, SET.LIT 1.2(166):  updated to support TRACE flag SQL. 

2016 September, A-Shell 6.3.1526 and SET.LIT 1.2(156):  updated to support TRACE flags JOBLCK and EXEC, which were added in 6.3.1518.0. 

A-Shell Reference 

Page 797 

## **WEBCACHE** 

_Rewritten August 2023_ 

The WEBCACHE feature involves checking a web location for files that are not found in the normal search path; if found online, they are downloaded and cached locally for subsequent use. Syntax: 

## **.SET WEBCACHE action {,options,...}** 

## **.SET WEBCACHE REPO url** 

## Actions: 

|**Action**|**Description**|
|---|---|
|ENABLE|Enable (for images and files subject to local cache)|
|DISABLE|Disable web cache; reset all options|
|CLEAR|Clear local cache|
|REFRESH|Clear from cache only those file(s) matching specification|



## Options: 

|**Option**|**Description**|
|---|---|
|PROG|download/cache programs (RUN,LIT,SBX)|



A-Shell Reference 

Page 798 

|**Option**|**Description**|
|---|---|
|||
|OPENI|download/cache files opened for input|
|LOOKUP|download/cache files subject toLOOKUP|
|DLL|download DLLs to bin if writeable; else webcache|
|ATE|forward  WEBCACHE options to ATE (see below)|
|ALL|same as PROG,OPENI,LOOKUP,DLL|



url: 

specifies a web directory to search for missing files 

## **Examples** 

```
.SET WEBCACHE ENABLE,PROG,OPENI,LOOKUP
```

```
.SET WEBCACHE REPO http://www.mysite.com/repo
```

## **ATE vs Server WEBCACHE** 

A-Shell Reference 

Page 799 

By default, WEBCACHE operates on the server side. But in many cases it makes as much sense for it to operate on the client side, which you can activate adding the ATE option to your list of SET WEBCACHE options. Note that if you want to assign different options and/or repository directory to ATE, use the following sequence: 

```
.SET WEBCACHE REPO <repo for ATE>
```

```
.SET WEBCACHE ENABLE,<options...>,ATE   ! forward options & repo to ATE
```

```
.SET WEBCACHE REPO <repo for server>
```

```
.SET WEBCACHE ENABLE,<options...>       ! set server options only
```

## **See Also** 

- WEBRUN.LIT 

- MX_WEBCACHEXS 

- AG_WEBCACHE 

## **History** 

- 2016 October, A Shell 6.3.1529, 1531, 1532: WEBCACHE function added to A-Shell. 

A-Shell Reference 

Page 800 

## **SHLEXC** 

## **SHLEXC <command or object spec> {waitflag}** 

SHLEXC, short for "Shell Execute," causes your PC to execute the command or object you have specified, using the Windows file association list of applications. This is the A-Shell command line equivalent of executing a file from Explorer. If you issue, for example, the command: 

## `shlexc %MIAME%\miame.ini` 

Windows checks the file association list to find out the application associated with ".ini" files (let's say it's Notepad), launches Notepad, and loads the file "miame.ini." 

_command or object spec_ can be in either A-Shell or native (Windows) format, and supports embedded environment variables as shown above. If the command or object contains spaces, it must be quoted. Possibilities include: 

- a URL, e.g. http://www.microsabio.com 

- a program, e.g. NOTEPAD.EXE 

- a document file, e.g. README.TXT 

- a directory, e.g. C:\VM\MIAME (to open folder in Explorer) 

## _waitflag_ can be used only with ATE: 

|**Value**|**Action**|
|---|---|
|0|no wait|
|1|wait for application to signal|
|2|don't wait, but try to get focus back|



**History** 

A-Shell Reference 

Page 801 

- 2017 January, A Shell 6.3.1542, SHLEXC.LIT 1.0(103): Enhanced using XSHLEX.SBX so that it now works in server environments with ATE or ZTERM clients, auto-transferring the file to the client if necessary. Requires XSHLEX.SBX and ATEAPX.SBX in BAS: 

A-Shell Reference 

Page 802 

## **SORT** 

## **SORT filespec** 

SORT performs line-by-line reordering of text files. It prompts for the necessary options, so it is largely self-explanatory, as shown in the following example. 

```
.SORT somefile.txt
```

```
Record size: 80
```

```
Key length: 10
```

```
Key position: 1
```

```
Key order (A/D{N}{F} or ? for help) : ?
```

```
   Enter: A(scending) or D(escending) followed optionally by N and/or F
```

```
   N=natural (more 'human' - group digits, ignore spaces, etc.)
   F=fold (treat upper/lower case as equivalent)
Key order (A/D{N}{F} or ? for help) : AN
```

```
Key length:
```

It prompts for up to three sets of key parameters (length, position, order). The file is then sorted in place, replacing the original. The "record size should be set to the length of the longest line in the file. 

Unlike XCALL BASORT, there is no option for binary or floating point key types, as this is intended purely for sorting text files. The "natural" sort order option (see History _,_ below) uses an algorithm by Martin Pool that relaxes the strict ASCII byte-by-byte sorting rules to yield something more likely to seem natural to humans. For example, "100 Main St." would sort after "99 Main St." 

A-Shell Reference 

Page 803 

## **History** 

- 2017 January, A Shell 6.3.1542, SORT.LIT 1.1(106):  now supports localization; see LITMSG.xxx 056,### for message customization. Also, the display has been updated to show the number of records sorted. 

A-Shell Reference 

Page 804 

## **SRCCOM** 

_Updated March 2025; see History_ 

## **SRCCOM {listfile=} oldfile, newfile {switches}** 

SRCCOM compares two source files, reporting the differences. This is useful, for example, when comparing two versions of a program to see what has changed between them. It is most useful when the differences between the files are few; when they are substantial, it becomes both overwhelmed and overwhelming. 

|**Switch **|**Effect**|
|---|---|
|/B|Brief listing: same as /Q but without line numbers|
|/Q|Quick listing: list only the lines that differ between the two files|
|/S|Silent: ignores blank lines and whitespace differences|
|/?|Writes switch listing and usage info to the screen|



Under Unix, there is a much more powerful file comparison utility call _diff_ , and in some cases, _diff3_ , which can compare three files at a time. See the notes on DIFF, an A-Shell front-end to _diff_ . 

Note also that SRCCOM.LIT includes the list file name and switches in the listing header, matching the format of the AMOS version. 

## **History** 

- 2025 March, A Shell 7.0.1774, SRCCOM.LIT 2.0(205):  optimization improvements, both in terms of performance and minimizing the amount of difference reported. Also, add lifesigns. 

- 2021 December, A Shell 6.5.1709, SRCCOM.LIT 2.0(201): routine rewritten to implement various improvements/fixes: 

- No longer requires a memory partition of 1MB or more. 

- Supports a new switch /S which ignores whitespace differences. 

A-Shell Reference 

Page 805 

- Removed limit on line length, which previously was 512 characters. 

- Supports inserted blocks of up to 10000 lines, up from 750. 

- Reduces tendency for single-line "premature matches". For example, when a block of new code is inserted, SRCCOM 

previously would re-sync on a single line match (even a blank line) between the original code and the new code, causing the inserted block to appear like a fragmented series of multiple insertions instead of a single block. 

- Is now able to recognize "parallel differences" of up to 100 lines. These result from line changes rather than 

- insertions/deletions. 

- The /Q mode now outputs the matching pair both before and after a set of differences. 

A-Shell Reference 

Page 806 

## **SUBMIT** 

_Revised and reviewed, July 2020_ 

To submit a task: 

## **SUBMIT ctlfile {do-params} {switches}** 

To kill a task: 

## **SUBMIT /K seqno | pidno | jobno** 

To list tasks submitted by this job that are currently running: 

## **SUBMIT** 

SUBMIT accepts the command line argument _++fspec_ , for which see History, below. 

The A-Shell SUBMIT command causes a new process to be launched, either now or at a specified later time, which executes commands specified in the control file. Under AMOS, this is managed by a background job called the Task Manager. Under A- Shell, there are actually three different possibilities, depending on the operating system and whether the _/after_ and _/next_ switches are used: 

## **Windows** 

Here, SUBMIT only partially simulates the Task Manager by launching a new instance of A-Shell to run the specified task. This is acceptable for tasks which have explicit outputs or side effects (for example, a report or series of COPY commands), but it does not really run in "background", and there is no log file. In the Windows environment, if you want to schedule a task that is launched by the operating system at the specified time, you should just use the Windows Task Scheduler (Programs...Accessories...System Tools...Scheduled Tasks). 

## **UNIX Immediate** 

A-Shell Reference 

Page 807 

In the case of A-Shell/Unix without the _/after_ or _/next_ switches, A-Shell launches a new process to run the specified task as a child of the current process. However, unlike the Windows case, the new process does run in background, with all of its screen output being written to the log file (e.g. a file with the same name and location as the _ctlfile_ , but with a LOG extension.) If the parent exits before the child does, the child task will continue to run but will be marked as a zombie. 

In the above case, if there is an error during the attempt to launch the new instance of A-Shell (perhaps because the ashell executable is not in the PATH or the MIAME environment variable is not defined), then information about the error will be written to the standard A-Shell log file (ashlog.log, in the directory where miame.ini is located). 

## **UNIX Via Schedule** 

The case of A-Shell/Unix with the _/after_ or _/next_ switches is the most similar to the AMOS Task Manager. The task is submitted to the Unix **at** manager, which, like the AMOS Task Manager, keeps track of it in a queue until it launches it at the specified time. The process will run with the same login identity and environment as the process that submits it, but since it runs as a child to the **at** manager, it is independent of the original submitter and thus not subject to becoming a zombie. As in the prior case, all output that would otherwise have gone to the screen is sent to the log file instead. 

The **at** manager is similar to the more familiar **cron** manager, both of which can be found on almost any Unix system. The **cron** manager is more suited to tasks that are to be run at regularly scheduled intervals; you submit jobs to it via the **crontab** command. The **at** manager, on the other hand, is more suited to jobs that are to be run once at a specified time in the (immediate or distant) future. To submit jobs to be run by the **at** manager, you can use the Unix **at** command. SUBMIT.LIT just acts as a front-end to **at** to allow you to use the simpler AMOS command syntax. 

In all cases, SUBMIT requires a control file (typically with a .ctl extension) which functions more or less just like a command or DO file—i.e. containing the commands necessary to run the job, along with any keyboard inputs. Programs running under the control of SUBMIT will automatically take their input from the control file, even if they wouldn’t normally accept input from a command file. The _do file parameters_ are processed in the same way as the argument list to a DO file; see DO File Arguments for details. When the control file runs out of input, the process terminates. The preferred way to terminate the process is for the 

A-Shell Reference 

Page 808 

program to cleanly exit back to the control file, and for the control file to end, optionally with a LOGOFF command. See the SBR option SUBMIT2 for related information. 

## **Switches** 

|**Switch**|**Effect**|
|---|---|
|<no switches>|Display list of jobs launched or scheduled via SUBMIT.|
|Do file<br>parameter|Unlike the AMOS implementation, the A-Shell version of SUBMIT allows DO file parameters to be<br>passed to the control file (which can use the $0-$9 syntax, just like normal DO files, to represent the<br>formal parameters). Any space-delimited tokens following the control file name and preceding the<br>first switch (marked by a slash) will be passed to the control file as DO parameters.|
|/AFTER:{+}<br>timspc|(Unix only) Causes the control file to be submitted via the Unix ‘at’ background processor, instead of<br>as a child to the current job. (See note above about the ‘at’ processor.) The timspc argument may be<br>specified using the form M-D-Y{,HH:MM}. The M-D-Y portion must be specified simply as zero for<br>today. The optional {+} makes the time specification relative to now. Examples:<br>/AFTER:0,23:00  (11 PM tonight)<br>/AFTER:06-30-20,00:30  (12:30 AM on June 30, 2020)<br>/AFTER:+1-0-0 (one month from now).|
|/BA buffile|Activates the auto-snapshot feature of INFLD and appends each snapshot to the specified file. The<br>default file extension is BUF, and the default location is MEM0:[1,1] (if it exists) or the current login<br>directory where the first snapshot occurs. Works internally by passing the –ba <buffile> switch to the<br>child A-Shell process and by adding the<br>**|S** _type_code to the INFDEF (default INFLD parameter)<br>string.|
|/BC buffile|Same as the /BA option except creates a new snapshot buffer file (overwriting any existing one).|
|/CU|Will display the group for each job, if applicable. Requires A-Shell 6.4.1540 or greater, and use of<br>group licensing.|
|/I "inifile"|Forces the child process to use a different A-Shell configuration file than the parent process. Note<br>that the inifile name should be a native file specification, and must be enclosed in quotes (to prevent|



A-Shell Reference 

Page 809 

|**Switch**|**Effect**|
|---|---|
||the slashes in the file spec from being confused with switches).|
|/J jobname|Functions just like the -j switch to A-Shell (allows you to give the background process a specific<br>name). Otherwise, a name of the form TASxxx (TASAAA, TASAAB, ...). will be generated<br>automatically.|
|/K seqno|<br>pidno|job|(Unix only) Kill a process currently running. To identify the process, you may specify either the<br>"sequence number", the "process id (pid) number", or the job name (which you can get by using the<br>SUBMIT display mode, with no arguments). Note that unless you are the superuser, you may not be<br>able to kill any background processes other than those that you have launched.|
|/L logfile|(Unix only) Overrides the default log file name. (Specify an AMOS-type filename.)|
|/LIST:fspec|Output the list of jobs launched or scheduled via SUBMIT to the specified file.|
|/W: #|(Unix only) Wait # minutes for the submitted process to complete, then kill it. If # is omitted, the<br>submitter will wait indefinitely. This may seem to defeat the purpose of running a process in<br>background, but can be useful either when the main objective is to look at the LOG file, or when you<br>want to run processes that otherwise would not accept input from a command file.|
|/NEXT:timspc|(Unix only) Equivalent to /AFTER:+timspc.|
|/?|Writes switch listing and usage info to the screen.|



## **Comments** 

Note that there are a number of differences between SUBMIT.LIT under A-Shell and submitting a task to the AMOS Task Manager. First, with SUBMIT.LIT, there is no task manager; instead, the process runs as a child to your current process. Second, there is no queue; the task starts executing immediately (and there is no particular limit to how many tasks you can submit this way with overlapping execution). Third, none of the AMOS embedded control file directives (which contain the $ symbol) are 

A-Shell Reference 

Page 810 

supported under A-Shell. Fourth, although you can use the SUBMIT.LIT program to check on the status of background tasks (and even kill them), under A-Shell, you can only do so for tasks which _you_ have submitted (unless you are the Superuser). 

## **See Also** 

- SUBMIT 

## **History** 

- 2026 February, A Shell 7.0.1782, SUBMIT.LIT 4.0(210): Refinement to the /K (kill) mode to stop prompting when there are no more submitted jobs and minor cleanup of the output 

- 2022 June, A Shell 6.5.1717, SUBMIT2.LIT 4.0(207): Updated to fix a very old bug which would result in the directory listing 

being duplicated if there were consecutive DEVICE statements for the same device—i.e. one normal DEVICE definition and one or more PPN-specific definitions. 

- 2016 December, A Shell 6.3.1540:  Implement /CU switch to display group. 

- 2014 November, A Shell 6.1.1398:  Improve granularity and therefore responsiveness of /W (wait) operation. Display wait times in hundredths of seconds. 

- 2011 November, A Shell 6.0.1240:  Remove the limit on the number of PPNs allowed per device. 

- 2011 August, A Shell 5.1.1227:  DO.LIT / MDO.LIT 2.1(124) and SUBMIT.LIT 3.1(150) now support file-based variable command line arguments using the ++fspec syntax. 

## **Subtopics** 

- 

A-Shell Reference 

Page 811 

## **SYSTAT** 

_Updated January 2025; added info on columns 9 - 16_ 

## **SYSTAT {switches}** 

SYSTAT displays "system statistics" like the following: 

## **Example 1: SYSTAT** 

```
Status of A-Shell/32 Ver. 6.5.1622.2 on Friday, July 13, 2018 08:33:34
TSKAAA TSKAAA  Ty                 DSK3:347,0     RN  SYSTAT         9428
4546K
1 jobs allocated on system, 1 in use
Total memory on system: unknown
Sys Uptime is unknown
DSK0     770087 MB free         DSK1     770087 MB free
DSK3     770087 MB free         DSK2     770087 MB free
4 devices on system, total free blocks may be shared among devices
```

## **Example 2: SYSTAT/C/N/ATE** 

A-Shell Reference 

Page 812 

```
Status of A-Shell Version 6.5.1692.4 on Tuesday, December 08, 2020
10:32:29
SSCALE SSCALE  tsk:30077          DSK1:300,200   RN  SSCALE
TASAAC TASAAC  tsk:7108           DSK1:300,200   RN  TCPXFR
TSKAAD TSKAAD  pts/3:5004         DSK1:300,200   RN  MASTMU ATE/SRV
6.4.1556.2
TSKACQ TSKACQ  pts/53:31587       DSK1:300,200   RN  SYSTAT ATE/SRV
6.5.1693.0
4 jobs allocated on system, 4 in use
Total memory on system: 12137428 kB
Sys Up:  10:32:29 up 190 days, 15:55, 65 users,  load average: 0.48, 0.61,
0.61
```

## **- Example3: Wide display showing columns 9 16** 

See under Wide. 

## **Column Descriptions** 

|**Col#**|**Description**|
|---|---|
|1|Jobname. Determined by the**-j**command line switch, or auto-generated using the format TSKxxx for|



A-Shell Reference 

Page 813 

|**Col#**|**Description**|
|---|---|
||foreground jobs and TASxxx for background jobs. In the example above, SSCALE was launched with -j<br>SSCALE; the others were auto-assigned.|
|2|Terminal name. This is a legacy hold-over and is virtually always the same as the job name.|
|3|Either the login name, or in the case of /C, the console identifier, or for /I, the IP address. The format of<br>console identifiers differs between operating systems, but as a general principle, those that match up to<br>the colon are originating from the same client machine.|
|4|Logged-in location.|
|5|Status. Either RN for running a program, or<br>^Cfor at the dot prompt.|
|6|Name of the running program.|
|7|Process ID. In the case of the /ATE switch, either "ATE/SRV" for a server-licensed ATE session, "ATE/PC"<br>for a PC-licensed ATE session, or blank for anything else.|
|8|Either the current direct memory allocation, or in the case of /ATE, the ATE version, or in the case of<br>/VER, the A-Shell version.|
||The following are displayed only inWide<br>mode, which see for an example.|



A-Shell Reference 

Page 814 

|**Col#**|**Description**|
|---|---|
|9, 10|Reads / Writes: number of file READ and WRITE operations.|
|11|Qlcks: number of accesses to the QFLOCK.SYS table.|
|12|Cmds: number of system commands executed.|
|13|Instr: number of ASB statements executed.|
|14|Keys: number of keystrokes.|
|15|HH:MM  how long since the session started.|
|16|mm:ss  how long since the JOBTBL has been accessed.|



## **Comments** 

• In the list of devices, one or more of the devices may share the same physical disk device on the host operating system, and thus the number of blocks free is the same. In the Windows example above, DSK0 thru DSK3 are all hosted on the same physical file system. So the actual total amount of free space is 770087 MB—as opposed to four times that, as it may appear from the display. 

• The display format is automatically widened, but only if necessary, to prevent numeric overflow of the available disk blocks, which is more than 999,999,999 blocks. 

A-Shell Reference 

Page 815 

- Beginning with A-Shell 1693 of December 2020, a plus sign ( + ) is shown next to the trmdef name for jobs that are current 

- using a node license. 

## **Switches** 

## SYSTAT switches can be listed on your screen with `SYSTAT/?.` 

|**Switch **|**Description**|
|---|---|
|/A|Displays all of the "allocated" jobs (i.e. those listed in TRMDEF.INI) even if no corresponding process<br>has been launched.|
|/ATE|Identifies ATE connections (in place of the pid); either "ATE/SRV" to indicate that the license was<br>issued by the server, or "ATE/PC" for other ATE connections. The ATE version number will be displayed<br>in place of the memory partition size (added in A-Shell build 1138).|
|/B|Displays only background jobs.|
|/C|Controlling Terminal<br>: Displays the controlling terminal’s device identification.|
|/CU|Like /C but displays both the machine name and unique identifier (in place of the user name and login<br>columns).|
|/E|MAC Address<br>:Displays the client MAC address if known.|
|/ERZ|Displays ersatz locations instead of dev:p,pn.|
|/F|Displays only foreground jobs (i.e., jobs with display devices attached).|
|/H|Displays available disk space in "human-readable" units (GB or MB) rather than 'blocks'. This feature<br>added in SYSTAT 3.0(161), A-Shell build 1169 of Dec 09.|
|/I|Displays IP address. This feature added in SYSTAT 3.0(150).|
|/K|Kill Phantoms<br>:Checks for and kills phantom jobs under Unix.|
|/L|Sends the output of the display to the filesystat.lstin the current directory rather than to the screen.<br>This is useful when you want to examine the state of the users programmatically.|
|/LIC|Causes a "+" to be displayed next to the trmdef name for jobs that currently are using a node license.|
|/M|Displays the minimum amount of free (unused) memory so far in the life of each job, instead of the|



A-Shell Reference 

Page 816 

|**Switch **|**Description**|
|---|---|
||allocated amount. This can be useful in judging whether your memory partitions are reasonably sized.|
|/N|Eliminates the display of the devices. This is particularly useful when you have a lot of devices,<br>especially if some of them are slow to respond due to being offline or connected over a WAN.|
|/P|Pause after each page of display. Also see the notes onPAGE.LIT<br>for another way to get the same<br>effect.|
|/R|Display "Real" jobs only. Omits PolyShell control jobs from the display.|
|/S|Sort the display of users by job name.|
|/SU|Sort the display of users by user name.|
|/ST|Sort by job type (daemon, pshell, background, foreground)|
|/V|Display the A-Shell version running for each job. This is useful during updates or in situations where<br>the executable may be loaded from different places in order to verify that all users are on same<br>version. Also reports the program version edit number—if available—as a parenthesized suffix to the<br>current program name.|
|/W|Display inWide<br> mode, show columns 9 through 16 and totals.|
|/X|May be used with /L to force the new layout in the file version. See History.|
|/Z|Kill Zombies<br>: Similar to /K but for zombies rather than phantoms.|
|/ZS|Identical to /Z except that it skips zombies that were launched via SUBMIT. Such jobs predictably<br>become zombies if the submitting job exits, even though they may continue to function as intended.<br>Thus you may not necessarily want to kill them along with other zombies.|
|/?|Writes switch listing to the screen.|



## **History** 

- 2024 November, A Shell 7.0.1765:  SYSTAT 3.2(187) now displays the time since the last JOBTBL.SYS access, next to the logged-in time in /W mode. Note that times much longer than one minute indicate a problem. 

A-Shell Reference 

Page 817 

- 2020 December, A Shell 6.5.1693:  SYSTAT 3.2(185) adds the switch "LIC" which causes a "+" to be displayed next to the trmdef name for jobs that currently are using a node license. 

- 2020 July, A Shell 6.5.1688: SYSTAT.LIT 3.2(183) adds /V switch. 

- 2018 November, A Shell 6.5.1651:  SYSTAT.LIT 3.2(182) has been updated to avoid a read-only error related to the smartscrollback activation feature. 

- 2017 July, A Shell 6.5.1610: SYSTAT.LIT 3.2(180) now makes the scroll bar visible if the environment supports it 

(A-Shell/Windows and ATE version 6.5.1610 or later) and the output of the command causes the screen to scroll. 

- 2017 March, A Shell 6.4.1546, SYSTAT.LIT 3.2(178):  (Unix) Reduce the excessive ITC error messages (one per job) to just one overall when the /W mode is unable to send ITC messages due to privilege issues. Allow clean exit with Q or ESC from paging mode. 

- 2015 May, A Shell 6.1.1408, SYSTAT.LIT 3.1B(171):  Updated routine to recognize and preserve a new unique identifer field in the JOBTBL. The new version is backward compatible with earlier versions of A-Shell and has a "B" in the version number to help easily identify it. Also: Added new switch /CU. 

- 2011 September, A Shell 5.1.1235: SYSTAT 3.1(164): Enhancements to support the revised job table layout: 

- Screen layout adjusted slightly to allow for ten character program name. (File layout with /L remains as before to preserve 

- compatibility with programs that generate a listing and then parse it.) 

- Add new switches /V and /X. 

Note that this version of SYSTAT will continue to work with the older job table, but older versions of SYSTAT will not see the program name or A-Shell version for jobs running A-Shell 5.1.1235+ 

- 2011 June, A Shell 5.1.1221:  Remove the limit on the number of PPNs allowed per device. 

A-Shell Reference 

Page 818 

## **CONTROLLING TERMINAL** 

The C switch displays the controlling terminal's device identification rather than the user's name. Under Unix, the user's name is set by the Unix login, whereas the terminal device is determined by the user's connection to the host. Under Windows, the controlling terminal device name will be the network ID of the workstation (i.e. the machine name or, lacking that, the IP address.) In either case, a suffix one or more suffixes is usually added to distinguish between multiple connections originating from the same device. Examples: 

|**ID**|**Meaning**|
|---|---|
|pts/1:571|Unix: first pseudo-terminal (network connection), process ID = 571|
|ttyS1:1009|Unix: connection on serial port S1, process ID = 1009|
|JACKT42:01|Windows: machine name=JACKT42, first A-Shell window on that machine|



A-Shell Reference 

Page 819 

## **MAC ADDRESS** 

This switch (E) displays the client MAC address if known. (In practice, this will only be known when the client is ATE.) This could be useful for distinguishing between clients that share an IP address due to some kind of proxy server, and those that are really from the same PC. 

Note that "MAC" stands for "Media Access Control," or physical hardware address, and is represented with a code like 00:0E:0C:50:B2:44 

A-Shell Reference 

Page 820 

## **KILL PHANTOMS** 

The K switch checks for and kills phantom jobs under Unix. These can occur when the underlying Unix process is somehow destroyed (such as by a **kill –KILL** operation performed by a superuser) without A-Shell being able to trap and recognize it. If such a process is found, SYSTAT will then remove it cleanly from the job table, and output both an asterisk in column seven of the display, as well as a more descriptive message on the following line. 

A-Shell Reference 

Page 821 

## **WIDE** 

_Updated January 2025; example added._ 

The W switch displays in wide (132) column mode (if terminal supports it). This allows the display of additional job status information, including the number of disk reads, writes, queue locking operations, commands (or programs) executed, ASB instructions executed, keystrokes entered, and accumulated time logged in. 

The job activity statistics are maintained in the jobtbl.sys file, making them available to be queried by utilities such as `SYSTAT/W` and JSTAT. Each job updates its own statistics in response to various triggers, the most universal of which is the Inter Job Communication clock, whose frequency is set by the IJCFREQ setting in miame.ini. Under Unix systems, jobs can send a request message to other jobs using XCALL ITC, asking them to update their statistics immediately so as to be able to report the very latest. In order for such messages to be delivered, the jobs have to share the same effective user, or the sender has to be root. Failing that, the stats reported may be between 0-<IJC frequency> seconds old; you may also see an ITC error message displayed. Refer to Advanced Privilege Settings for more information. 

## **Example** 

A-Shell Reference 

Page 822 

## **KILL ZOMBIES** 

This switch (/Z) is similar to /K but for "zombies" rather than "phantoms". A zombie is a job that is trying to exit but cannot because it lacks some kind of critical resource (like a terminal or its original parent). Unlike phantoms, zombies can be a significant drain on the CPU resources of the system. In most cases, zombies are related to some kind of messy telnet disconnection. (Activate TRACE=SIGHUP in miame.ini or using SET.LIT and then examine the ashlog.log file for further information about such disconnects.) 

A-Shell Reference 

Page 823 

## **TAIL** 

## **TAIL {outfile=} <wildspec> {switches}** 

The TAIL command is similar to the eponymous Unix command and is used to display or copy to another file the last N lines of a specified file (or wildcard list of files). 

## **Switches** 

|**Switch **|**Effect of Switch**|
|---|---|
|/D|The delete switch causes TAIL to overwrite the existing outspec.|
|/L:##|The lines switch causes TAIL to display or copy ## lines. The default is 20. As of A-Shell 1264,<br>TAIL supports a Unix-inspired variation of the /L:# switch, i.e. /L:+#, which causes the<br>display/output to start at specified line #, rather than starting that many lines from the end. For<br>example:<br>`.TAIL MYFILE.LST/L:+2`displays the entire file except for the first line. This can be<br>useful for removing the first N lines from a file. For example, to remove the first line of a file,<br>you could use the following command:<br>`.TAIL MYFILE.LST = MYFILE.LST/L:+2/D`|
|/Q|The query switch causes TAIL to prompt for confirmation on each file.|
|/?|Writes switch listing and usage info to the screen.|



## See the notes on HEAD for examples. 

## **History** 

- 2022 June, A Shell 6.5.1717, TAIL.LIT 3.4(107):  Updated to fix a very old bug which would result in the directory listing being duplicated if there were consecutive DEVICE statements for the same device—i.e. one normal DEVICE definition and one or more PPN-specific definitions. 

- 2012 December, A Shell 1264:  Add support for the /L:+# variation on the "L" switch, as noted above. 

A-Shell Reference 

Page 824 

## **TELNET** 

_Updated May 2014; see History_ 

## **TELNET <configuration> {switches}** 

(Windows only) TELNET launches ATE (the A-Shell Terminal Emulator) to establish a session with the specified configuration. The configuration name must have been previously defined using ATECFG (which see) or with the /E switch. 

You can terminate the session either from the remote host (i.e. by logging out) or by entering |D (vertical bar, D). 

TELNET also supports an ATEAUTH.SBX hook, allowing you to preconfigure aspects of the connection properties before the dialog is displayed or the connection takes place. If ATEAUTH.SBX exists in the %MIAME%\DSK0\007006 directory, it will be called via ATEAUTH.SBX; see bottom of this page for details. 

## **Switches** 

|**Switc**<br>**h**|**Function**|
|---|---|
|(none)|Write switch listing and usage info to the screen.|
|/E|Edit configuration.|
|/F|Auto-accept host fingerprint (SSH mode).|
|/I|Select configuration interactively.|
|/V|Verbose mode.|



A-Shell Reference 

Page 825 

|**Switc**<br>**h**|**Function**|
|---|---|
|/?|Write switch listing and usage info to the screen.|



## **Comments** 

TELNET uses AG_WINSETTINGS to reload the window settings after you select a connection profile, allowing the previously saved settings from that connection to be restored. 

## **ATEAUTH.SBX** 

## **xcall ATEAUTH, connection'name, status** 

## **Parameters** 

_connection'name_ (String)  [in] 

is the name of the connection configuration. 

_status_ (Num)  [out] 

may be set to a non-zero value by the SBX to abort the connection. It is pre-cleared, so the SBX doesn't need to update it unless it wants to abort. 

A-Shell Reference 

Page 826 

## **TYPE** 

## **TYPE <filespec> {switches}** 

TYPE displays the specified file on the screen (similar to the _cat_ utility under Unix). 

TYPE <file>/P is functionally equivalent to `PAGE TYPE <file>` ; see the notes on PAGE. 

TYPE will display control characters in "caret notation" (i.e., using a printable character preceded by a ^). For example, nulls will display as ^@, escapes will display as ^[, etc. 

## **Switches** 

|**Switch **|**Effect of Switch**|
|---|---|
|/P|Page mode: stops after each screen page|
|/S|Slow mode: displays only ten lines per second|
|/?|Writes switch listing and usage info to the screen.|



## **History** 

- 2018 November, A Shell 6.5.1651, TYPE.LIT 1.0(113): has been updated to avoid a read-only error related to the smartscrollback activation feature. 

- 2017 July, A Shell 6.5.1610, TYPE.LIT 1.0(112):  now makes the scroll bar visible if the environment supports it (A-Shell/Windows and ATE version 6.5.1610 or later) and the output of the command causes the screen to scroll. 

A-Shell Reference 

Page 827 

## **TELSER** 

## **TELSER <port#> <startup-command> {switches}** 

(Windows only) TELSER allows you to turn your current A-Shell/Windows session into a single-client telnet server. That is, it proceeds to listen on the specified port for a standard telnet client connection, at which point, the remote telnet client takes over the session. This is a rather advanced (or perhaps obscure) capability, which is mainly of use for remote support (sort of like pcAnywhere) or for environments where your application was written to depend on the capabilities of a particular terminal emulator. 

## **Switches** 

|**Switch **|**Effect of Switch**|
|---|---|
|/S|Display waiting window on task bar (otherwise it becomes invisible).|
|/T:tdv|Forces the client connection to use the specified terminal driver. Otherwise it will<br>negotiate the terminal type with the client terminal emulator.|
|/?|Writes switch listing and usage info to the screen.|



A-Shell Reference 

Page 828 

**U** 

## **U <command line>** 

U simply takes the command line which follows it and writes it to a command file called sys:u.cmd, so that it can be easily recalled later just by typing U. For example: 

```
.U dir/udate/cdate/adate *.bas[],*.run[*,0]
```

After executing the above command, you would then be able to type just `U` then ENTER to execute the command: 

```
dir/udate/cdate/adate *.bas[],*.run[*,0]
```

Since recording one command is of limited value, given that you can use ^R to retrieve previously typed commands from the command history buffer, you can make unlimited copies of the U.LIT command under different names. They will work the same way but will record their command lines in the correspondingly named command files. 

## **Example** 

```
.COPY U2=SYS:U.LIT
```

```
.U2 DIR/UDATE/CDATE/ADATE
```

The above would create a command file called U2 which could be later executed to execute the `DIR/UDATE/CDATE/ADATE` command line. 

A-Shell Reference 

Page 829 

## **UPDCUR** 

_Written July 2019_ 

## **UPDCUR** 

When executed from a directory with a corresponding online repository, mainly the SYS: and BAS: directories, UPDCUR downloads new and updated files. 

The files being updated are renamed with extension ?01 where ? is the first letter of the original file extension. Up to three generations are kept. For ABOUT.LIT, for example, the three old versions of the file would be ABOUT.L01, ABOUT.L02 and ABOUT.L03. 

This command is primarily for the benefit of A-Shell programmers / developers who are updating their LIT and other system files to the very latest versions for testing and development purposes. 

## **Example** 

```
.log sys:
```

```
Transferred from BAS: to SYS:
```

```
.updcur
UPDCUR 1.0(105) - Update current directory from online repository
A-Shell/32 Ver. 6.5.1725.0
Current dir: DSK0:[1,4]
Repo: http://www.microsabio.net/dist/65dev/dsk0/001004/
Retrieving 001004.dir
Status =  11520
Checking current files against repository...
```

A-Shell Reference 

Page 830 

```
errmsg.usa ...      Upd: ok
if.lit ...          Upd: ok
sbrmsg.usa ...      Upd: ok
sysmsg.usa ...      Upd: ok
versys.lit ...      Upd: ok
```

```
5 files updated, 0 new files, 151 already current, 0 errors
```

In the above example, the 5 files listed have been updated from the online repository, with the prior versions archived using extensions .?01, .?02, etc. 

A-Shell Reference 

Page 831 

## **VERIFY** 

## **VERIFY <dirspec> {/switches}** 

VERIFY reads a previously created directory listing and compares it to the actual files, reporting whether they agree or differ. The only available switch, _/f,_ directs the results to the file verify.lst; otherwise they are displayed to the screen. 

VERIFY implements a standard and very useful technique for verifying that a particular installation of files is up to date or not corrupted. (It seems amazing that there is no equivalent utility packaged with Windows or Unix, although the RPM package manager of Linux does have a similar capability.) 

The specified directory file must have been created with the DIR.LIT /D/V/H switches. For example, when building a release of A- Shell, we execute the following commands: 

```
.dir ashell.dir=dsk0:[]/d/v/h/k/sname
```

(The _/k_ switch is needed to overwrite a previous copy of ashell.dir, and the _/sname_ switch adds the optional nicety of listing the files sorted by name.) 

The resulting directory listing looks something the example below, with each line containing the complete filespec of a single file, followed by the version number and the hash code: 

```
DSK0:ABOUT.LIT[1,4]           1.0(103)          656-123-417-74
DSK0:APPEND.LIT[1,4]          2.1(111)          352-256-456-10
DSK0:ASTAT.LIT[1,4]           2.2(131)          121-772-424-00
DSK0:ATECFG.LIT[1,4]          1.0(100)          260-132-704-07
DSK0:C.LIT[1,4]               1.0(100)          167-604-517-71
DSK0:CHAT.LIT[1,4]            2.2(118)          632-367-207-57
DSK0:CLS.LIT[1,4]             1.0(100)          167-604-517-71
```

A-Shell Reference 

Page 832 

You may use VERIFY on this file to check if the standard files that come with A-Shell are still in sync with the release versions: `.VERIFY OPR:ASHELL.DIR` 

## The output looks something like this (hopefully): 

```
DSK0:ABOUT.LIT[1,4]           VERIFIED
DSK0:APPEND.LIT[1,4]          VERIFIED
DSK0:ASTAT.LIT[1,4]           VERIFIED
DSK0:ATECFG.LIT[1,4]          VERIFIED
DSK0:C.LIT[1,4]               VERIFIED
DSK0:CHAT.LIT[1,4]            VERIFIED
DSK0:CLS.LIT[1,4]             VERIFIED
```

If the version or hash of the actual file does not match that recorded in the directory listing, it will report the discrepancy, for example: 

```
DSK0:DIR.LIT[1,4]   ?Version mismatch  is - 1.5(125)  MDL = 1.5(124)
```

This would indicate that the actual version of the file DIR.LIT is 1.5(125) while the release version as recorded in the directory listing is 1.5(124). (MDL stands for Master Directory Listing) 

A-Shell Reference 

Page 833 

## **VERSYS** 

_Updated July 2022_ 

## **VERSYS <wildspec> {switches}** 

VERSYS displays version and resource information, about a runnable A-Shell program, that relates to the environment in which it was created. Normal runnable program extensions are .RUN, .LIT and .SBX. 

The file version shown in the examples below can also be gotten from the DIR/V command. But DIR/V cannot tell you the details about the ashell and CMDLIN resource files, which were used to compile the copy of DIR. Periodically we update these resource files, which when used to re-generate the LIT commands, may create subtle differences which are not reflected in the version number. 

VERSYS.LIT shows the program header flags, which indicate how the program was compiled and whether it is compatible with AMOS. Note that it cannot distinguish whether /A was used when compiling (although it can distinguish /AV, which implies /A), and it cannot tell between /X:1, /X:2 and /D, all of which show as /X and are incompatible with AMOS. 

## **Switches** 

/CSV 

creates VERSYS.CSV version of output 

## **Example1** 

```
.VERSYS SYS:DIR.LIT
```

```
DIR.LIT -- A-Shell Version & System Information:
   File Version:    1.5(125)
   System Resource: ashell[74]
   System Resource: cmdlin[24]: max devs = 300, max ppns = 512
```

A-Shell Reference 

Page 834 

## **Example2** 

```
.versys testsf
```

```
TESTSF.RUN -- A-Shell Version & System Information:
```

```
  File Version:      1.0(100)
  Program format:    0xF2F6 (compil/x?/av; requires A-Shell edit 1711+)
  Program Size:            1,493,577
  Object Code:               957,182
  MAP Definitions:           516,264
  Memory Required:         1,106,548
  Auxiliary Blocks:
    DynFunc Index:            14,861
    Embedded Defstructs:       5,208
    Defstruct Index:              32
  Embedded Resources:
    ashell.def[302]
    ashell.sdf[103]
```

## **History** 

- 2023 February, A Shell 6.5.1725, VERSYS.LIT 3.0(113):  Refinement to recognize header signatures &hF202 (OCMPIL with minimum version) and &hF03 (COMPIL with minimum version). 

- 2023 February, A Shell 6.5.1725, VERSYS.LIT 3.0(112):  Add dynamic function index to the display. 

A-Shell Reference 

Page 835 

- 2022 May, A Shell 6.5.1716, VERSYS.LIT 3.0(110):  The /CSV switch outputs all the display details to a CSV for a wildcard set of programs. . 

- 2022 May, A Shell 6.5.1715, VERSYS.LIT 3.0(109):  The VERSYS display now includes many additional details about the specified program, memory requirements and the existence of embedded resources such as dynamic functions and embedded structure definitions. 

- 2019 March, A Shell 6.5.1657, VERSYS.LIT 3.0(108): Now recognizes the new header signature and reports the minimum A- Shell version needed to run the program. For example: 

```
.VERSYS MYPROG.RUN
```

```
MYPROG.RUN -- A-Shell Version & System Information:
```

```
   File Version:    1.0(100)
   Program format:  0xF276 (compil/x?; requires A-Shell edit 1657+)
```

A-Shell Reference 

Page 836 

## **VIEWASHLOG** 

_Updated Octoer 2025; see History_ 

## **VIEWASHLOG {switches}** 

VIEWASHLOG.LIT provides a simple way to view the ashlog.log file contents, either in its entirety as text, or just the errors in a spreadsheet or XTREE grid. 

## **Switches** 

|**Switch**|**Effect of Switch**|
|---|---|
|/ERRORS{:errno}|Extract error info into interactive grid._errno_may be a number (#),<br>less than a number (<#), or greater than a number (>#). Default<br>is all.|
|/FILE:logspec|Use specified file instead of ashlog.###.|
|LOCAL{:dir}|Look for ashlog in current (_dir_) directory.|



Other switches are available only if /ERRORS is not set: 

|**Switch**|**Effect of Switch**|
|---|---|
|/LOOKBACK{:#}|look back # (default 1) ashlog.### files.|
|/MACHINE:machine id|Filter on machine id. Partial id ok.|
|/FUNCS:program{:sbx}|Filter function calls for program.|



A-Shell Reference 

Page 837 

|**Switch**|**Effect of Switch**|
|---|---|
|/LSX:dir|Directory forLSX files<br>;used with /FUNCS.|
|/PID:#####|Filter on pid.|
|/PROG:program|Filter on program.|
|/SESSION|Display traces for just this session.|
|/USER:name|Filter on login name, with sessions grouped separately.|



Note that while the traditional separator between switch names and their values is a colon, you can also use the equals sign as shown by the example in the FUNCS topic. This might be less confusing when the values themselves contain colons. 

In the XTREE display, you can select an error and if it can find the corresponding LSX file, allows you to bring it up in the VUE or APN editor. 

## **History** 

- 2025 October, A Shell 7.0.1780, VIEWASHLOG.LIT 1.0(113): Automatically detect ashlog.log file location if it has been altered via the SET LOGDIR command. 

2025 August, Ashell 7.0.1776, VIEWASHLOG.LIT 1.0(109): Add switches /FILE and /LOCAL. 

- 2025 MarchSeptember, A Shell 1750, VIEWASHLOG.LIT 1.0(107): Add switch /USER. 

- 2023 September, A Shell 1750:  Function added to A-Shell. 

A-Shell Reference 

Page 838 

## **FUNCS** 

_Written August 2025_ 

The /FUNCS=program switch facilitates viewing of the FUNCS traces with automatic translation of the @xxxxxx locations into the corresponding function and procedure names. This requires that VIEWASHLOG have access to the LSX file corresponding to the specified program, either in the current directory, or you can specify another directory via the /LSX=directory switch. Using the FNDATETIME example above and assuming that the FNDATETIME.LSX file is the SRCARC: directory, this command ... 

```
.VIEWASHLOG/FUNCS=FNDATETIME/LSX=SRCARC:
```

... creates a view similar to this with the @xxxxxx locations replaced by the actual function names... 

```
...<FNDATETIME:62e>     -> @Fn'Date'To'MM'DD'CCYY$( S50[today+3],S3[] )
```

```
...<FNDATETIME:1a3e>      -> @fn'isalpha( S1[t] )
```

```
...<FNDATETIME:101>       -1 <- @fn'isalpha()
```

```
...<FNDATETIME:1a50>      -> @Fn'Date'Alias'To'MM'DD'CCYY$( S50[today+3],S3[] )
...<FNDATETIME:3ad6>      08/21/2025 <- @Fn'Date'Alias'To'MM'DD'CCYY$()
```

```
...<FNDATETIME:1a66>    08/21/2025 <- @Fn'Date'To'MM'DD'CCYY$()
```

Note that although the FUNCS TRACE flag applies to all programs and SBX's, VIEWASHLOG can only translate the locations to names for one module at a time. In order to focus on an SBX, append it to the /FUNCS=program switch (separated by a colon), e.g. 

```
.VIEWASHLOG/FUNCS=MYPROG:MYSBX/LSX=SRCARC:
```

A-Shell Reference 

Page 839 

## **VUE** 

_Updated April 2017; see History_ 

## **VUE <file> {switches}** 

If you are new to VUE, see Learning VUE. That topic deals with concepts, basics and other introductory material. 

VUE is A-Shell's built-in text and program editor. It is handy for cross-platform, general-purpose editing of program source files and other text files, but is purely text based and limited to editing a single file at a time. While many programmers—particularly of the "old school" variety—use it exclusively, for most others, and for all but the simplest programming tasks, we recommend the A-Shell Programmers Notepad (APN). 

Some extended features have been added to accommodate the needs of our more demanding users; see Special Commands. 

|**Switch **|**Effect of Switch**|
|---|---|
|/?|HELP display.|
|/C|Enable command file input, including in display mode. Characters are input from the current command file and interpreted as if<br>they were typed. Note that it is critical to know which mode the session will start in (display vs. command) since the<br>interpretation of the commands would differ between the modes. See the START command in theini.vuefile for info on<br>starting in a specified mode.|
|/R|Read-only mode. All functions work normally except you cannot save the file. You might want to consider EZTYP as an<br>alternative to this.|
|/T|Trace steps involved in locating and processing theini.vuefile. Useful for debugging.|
|/W|Start in 132 column (wide) mode.|
|/Y|Automatically answer yes to the question about whether to create a non-existent file.|



The Help command is fully implemented. Enter _Help_ while in Command Mode to get several successive screens showing all available VUE commands, which are also listed in tables in this documentation. Also available from the VUE command line are 

A-Shell Reference 

Page 840 

help screens for INFLD (e.g. >HELP INFLD), INMEMO, TCRT, and SPOOL. To create your own help screen for the subject "ABC," create a file called ABC.HLV in [7,1] and invoke it by entering "HELP ABC" on the VUE command line. 

- 2022 August, A Shell 6.5.1719:  Embedded TAB characters are now expanded based on the TAB width setting as specified in ini.vue or in the current instance of VUE. Previously all embedded TABs were expanded to the next multiple of 8 columns, regardless of the TAB width setting. Note that the TAB key on the keyboard, as opposed to TAB characters previously embedded into a file, continues to be treated as a chr(9) if the TAB width is set to 8, and as spaces for any other TAB width setting. 

- 2017 May, A Shell 6.4.1548: Improve logic to avoid confusion between switches and native fspecs; add HELP display (VUE/?); support localization (LITMSG.xxx 066,###). 

- 2016 May, A Shell 6.3.1511, VUE edit 370:  VUE now disables AutoMouse on the ATE client during the VUE session, then restores the prior settings on exit. Previously, this only occurred for A-Shell/Windows local mode. Note that if the ATE version is prior to 6.3.1511.0, AutoMouse will get disabled on entry into VUE, but not restored on exit. 

- 2011 April, A Shell build 1214, VUE edit 307:  VUE now uses the AG_STATUSLINES feature to save the present status line 

configuration and then enable the bottom status line (which is used by VUE to display important information during editing). On exit, the previous status configuration is restored. 

- 2010 November, A Shell build 1196, VUE edit 305: A new variation of the >FORMAT command allows reformatting (wrapping) one line at a time to a specified width: 

## **>FORMAT #** 

where # is the desired wrap width. 

Unlike the standard FORMAT command, which reformats a paragraph using word wrap so that each line is as long as possible without exceeding the current width specified by the WIDTH command, FORMAT # operates on only the current line, wrapping it at exactly the specified width. This is mostly just a convenience for getting an overview of an extremely long line (as an alternative to successively using the >MARGIN # command, or RIGHT-ARROW, to view one screen width at a time). 

- 2010 November, A Shell build 1196, VUE edit 304: The old line length limit of 2022 bytes has been greatly expanded. For existing files, the new limit is 1000 bytes longer than the longest of the first 100 lines in the file. For new files, the limit is 4K. 

A-Shell Reference 

Page 841 

Also, the line concatenation function (^O) now beeps and otherwise does nothing when the concatenated line would exceed the current limit. (Previously it just truncated without warning.) 

## **Subtopics** 

- INI.VUE 

- Function Keys 

- Special Commands 

- Command Mode Commands 

- Display Mode Commands 

- Extended Display Mode Commands 

## · Learning VUE 1 

- Learning VUE 2 

A-Shell Reference 

Page 842 

## **INI.VUE** 

_Updated February 2024; see History_ 

When executed, VUE starts by searching for an ini.vue file. The search path consists of the current PPN, the [p,0] directory, and DSK0:[7,0]. If found, the contents are processed in much the same way they would be if they were typed in VUE’s Command Mode. Launch VUE with the /T switch to display details about ini.vue processing. 

The set of ini.vue directives is shown below. Most of the options work under A-Shell as they do under AMOS, with a few exceptions as noted. 

|**Directive**|**Value(s)**|**Default**|**Action**|
|---|---|---|---|
|ASCII7|Boolean||All characters with the 8th bit set display as dimmed question mark. Even when not set,<br>certain problem characters which appear to AM* and WY* terminals as commands are<br>also handled this way.|
|AUTODELETE|Boolean or number||Toggles autodeletion of old auto update history notes (see UPDATE) or sets the<br>maximum number to keep before deleting older ones.|
|AUTOSAVE|Number|Zero|If not zero, forces file to be automatically saved after every <number> changes. Each<br>character counts as one change, some commands count as five changes.|
|BAKDIR|||= <Unix directory spec>  Allows you to put the .BAK (backup) files into the specified<br>directory, rather into the current directory. Applies to Unix only, and generally only to<br>the standalone version.|
|CHARINS|Boolean|False|Start in character insert mode, vs. overwrite mode; use^Qduring editing to toggle;<br>also see INSERT.|
|COLOFFSET|Number|0|Set number of first column (see COLUMN).|
|COLUMN|Boolean|False|Displays cursor column number during editing, either on bottom status line or upper left<br>corner of screen.|
|CRNL|Boolean||Determines if file will be output with CRNL or just NL line terminators. Default=true for|



A-Shell Reference 

Page 843 

|**Directive**|**Value(s)**|**Default**|**Action**|
|---|---|---|---|
||||Windows or if OPTIONS=CRNL inmiame.ini, otherwise false (normal Unix case.)|
|CVTWARN|Boolean|True|Controls whether you get a warning that it will convert the CRLF line terminators<br>(AMOS/Windows format) to native format terminators (LF for Unix).|
|DEFAULT|Ext1, Ext2, ... Extn||Define up to 25 default extensions (to check if none specified on cmd line).|
|DRAW|Boolean|False|Change cursor advance direction.|
|ENCRYPT|Boolean|False|Causes any file written out by VUE to be encrypted using EFS. Ignored if EFS not<br>enabled. See EFS in the index for more details.|
|GO|One to several lines||Specifies command(s) to execute on GO exit.  ’%’ expands to file.ext; ‘@’ expands to<br>ext.|
|INSERT|Boolean|False|Start in line insert mode; use^\during editing to toggle. Also see CHARINS.|
|LCKFILE|Boolean|False|Lock file while editing level 1.|
|LOCKSTRICT|Boolean|False|Lock file while editing level 2.|
|MODEM|Boolean|False|If true, Command Mode display output is minimized.|
|MOUSEPOS|Boolean|True|Disable mouse position. This normally defaults to ON (mouse wheel enabled), and is<br>always re-enabled on exit. However, it defaults to OFF ifOPTIONS=NOWHEELis set in<br>miame.ini, and in any case, VUE always restores the original global setting on exit.|



A-Shell Reference 

Page 844 

|**Directive**|**Value(s)**|**Default**|**Action**|
|---|---|---|---|
|NARROW|||Forces VUE to start in the normal 80 column mode.|
|PCNAV|Boolean|False|Forces the Home and End keys to go to beginning/end of_line_instead of_file_.|
|QUITWARN|Boolean|True|Enables warning when quitting after changing file.|
|SAVEBAK|Boolean|False|When set to TRUE, each SAVE operation (whether explicit or triggered by the<br>AUTOSAVE feature) starts by copying the file being edited to the .BAK file prior to the<br>SAVE operation. The default is FALSE (traditional behavior) in which the SAVE operation<br>does not affect the .BAK file.|
|SEARCHFOLD|Boolean|True|If true, search is not case sensitive.|
|SHORT|||Forces VUE to start in the normal 24 row mode.|
|SHOWTABS|Boolean|True|Show TABs as specified character rather than as space.|
|START|"End" or "Command"|blank|Specify starting position: end of file, Command Mode, or top of file (blank).|
|TAB|Number|8|Specify <number> spaces per TAB. If 8, use TAB character. If not 8, use spaces.|
|TALL|Number|42|Forces VUE to start in a display mode consisting of the specified number of rows. If<br>equal sign and value are omitted, VUE begins with 42 rows.|
|UPDATE|Boolean or sc{,ec}||Automatically adds a note to the top of the file whenever the file is updated. Note<br>includes date, time, edit time, and operator. If the sc,ec parameters are specified (in<br>place of ON), they specify the characters to insert at the beginning and end of each|



A-Shell Reference 

Page 845 

|**Directive**|**Value(s)**|**Default**|**Action**|
|---|---|---|---|
||||update entry, e.g. UPDATE = !,*. (See AUTODELETE)|
|UPDSSL|Boolean|False|Force shifted status line to be the same as unshifted status line.|
|USETABS|Boolean|False|Determines whether the TAB key is stored as a TAB character or is expanded to spaces,<br>overriding the behavior previously determined by the TAB # directive, which otherwise<br>sets the tab width. If USETABS is not specified, the choice continues to be based on the<br>TAB # directive: TAB 8 effectively enables the USETABS option, any other TAB value<br>disables it.|
|WIDE|Number|132|Forces VUE to start with width set to <number> columns. If equal sign and value are<br>omitted, is treated like WIDE = 132.|
|WIDTH|Number||Determines column for wrap if WRAP=true.   Default=screen width-2.|
|WRAP|Boolean|False|If true, cursor wraps after column specified by WIDTH.|



## **History** 

- 2024 February, A Shell 7.0.1756, VUE.LIT 3.2(381):  Add SAVEBAK. 

A-Shell Reference 

Page 846 

## **AUTODELETE** 

The AUTODELETE and UPDATE directives (also available from Command Mode) are similar to the "d/VUE" directives of the same names. The both relate to an optional feature in which an automatic update notation is added to the top of the file whenever you finish out of it. The notation looks something like this: 

- `!*! Updated on 02-Oct-98 at 06:33 PM by Jack; edit time: 0:45:23` 

Appropriate default comment markers ("!*!", "/*" and "*/", or ";*;") are determined on the basis of the file extension. If the file extension is not recognized, the feature is turned off. If you prefer to define your own comment markers, then use the UPDATE = <sc>{,<ec>} syntax (where <sc> is the "start comment" sequence and <ec> is the optional "end comment" sequence). 

When the UPDATE feature is active, AUTODELETE may come in handy to automatically remove older entries (so you do not accumulate an infinite number of them or have to manually remove them). Setting it to ON results in just the last entry being preserved. If you specify a number instead, it will save that many entries before deleting older ones. See the notes on Special Commands for information about the related ^SE and ^_E commands. 

A-Shell Reference 

Page 847 

## **AUTOSAVE** 

This causes the file to be automatically saved after the specified number of changes are made during an edit session. Singlecharacter operations are counted each as one change; more complicated operations (e.g. replace, line and word delete, block operations, etc.) are arbitrarily counted as five changes. A reasonable number might be something in the vicinity of 1000. A value of zero disables the operation. (To aggravate your mates and waste a lot of resources, you can set the value to 1.) When triggered, the file is saved exactly as if a manual SAVE command had been issued. Note that even after several such SAVE operations, you can still recover your original file by using QUIT to exit and then making a copy of the .BAK file. (e.g. `.COPY MYFILE.OLD=MYFILE.BAK` ). 

A-Shell Reference 

Page 848 

## **COLOFFSET** 

Most of the VUE.INI directives have descriptions that are long enough to require their own page. Those with short descriptions are collected below. 

## **COLOFFSET** 

This directive, both at the command level and in ini.vue, adjusts the starting column number. By default, VUE calls the first column #0. If you want the first column to be numbered 1, then use > `COLOFFSET 1` at the VUE prompt or add `COLOFFSET = 1` ini.vue. 

## **DRAW** 

This controls whether you can invoke a d/VUE-inspired feature of the same name in which the control commands ^S^H, ^S^J, ^S^K and ^S^L can be used to change the default cursor advance direction to left, down, up and right (default), respectively. This feature can be handy for laying out forms, but if accidentally invoked could wreak havoc on a blind typist, which is why it is not enabled by default. 

## **LCKFILE** 

This directive can be used to force VUE to create a separate <file>.lck file while <file> is being edited with write privileges. The purpose of this is to allow yet another way for external editors to detect that a file may be in the process of being modified by VUE. 

## **MOUSEPOS** 

A-Shell Reference 

Page 849 

This directive may be used at the command level or in ini.vue to disable caret position with the mouse. This may be useful on some laptops with very sensitive touch pads, which otherwise may cause the typing position to jump around unexpectedly (considered rather bad behavior in a program editor). Default is TRUE. 

## **QUITWARN** 

This directive controls whether you get a warning message and request to confirm when you attempt to quit out of an editing session after making changes to the file. Of course if you still quit accidentally, you can always retrieve the .BAK backup file, but you must do that before you edit the file again. 

## **UPDSSL** 

This may be set to ON to force VUE to keep the shifted status line (if there is one) equal to the unshifted status line. This prevents the line from "blinking" when you hit the SHIFT key. This is only an issue in certain terminal emulation environments. 

A-Shell Reference 

Page 850 

## **GO** 

This directive specifies the action or sequence of directives to execute when the file is exited with the G or GO command. The sequence starts with the first directive following the equals sign, and continues until the **$** is encountered. The special character **%** may be used to refer to the name of the file being edited (without any extension) while the **@** character refers to the file’s extension. 

Under the standalone implementation of VUE, the GO directive must be limited to a single line (e.g. `GO=compil %$` ) 

## **Example** 

This example consists of four consecutive lines in INI.VUE, shown below with explanations. 

|**Line in INI.VUE**|**Effect**|
|---|---|
|`GO = COMPIL %/M/X:2/LF/PX`|COMPIL the file using COMPIL switches M, X:2, LF and PX ("COMPIL<br>TEST1.BAS/M/X:2/LF/PX")|
|`VERSYS %.RUN`|Display version information for the new fileTEST1.RUN|
|`COPY RUNS:=%.RUN`|CopyTEST1.RUNto the RUNS: ersatz directory|
|`$`|Done with GO directive sequence|



A-Shell Reference 

Page 851 

## **LCKFILE** 

Most of the VUE.INI directives have descriptions that are long enough to require their own page. Those with short descriptions are collected below. 

## **COLOFFSET** 

This directive, both at the command level and in ini.vue, adjusts the starting column number. By default, VUE calls the first column #0. If you want the first column to be numbered 1, then use > `COLOFFSET 1` at the VUE prompt or add `COLOFFSET = 1` ini.vue. 

## **DRAW** 

This controls whether you can invoke a d/VUE-inspired feature of the same name in which the control commands ^S^H, ^S^J, ^S^K and ^S^L can be used to change the default cursor advance direction to left, down, up and right (default), respectively. This feature can be handy for laying out forms, but if accidentally invoked could wreak havoc on a blind typist, which is why it is not enabled by default. 

## **LCKFILE** 

This directive can be used to force VUE to create a separate <file>.lck file while <file> is being edited with write privileges. The purpose of this is to allow yet another way for external editors to detect that a file may be in the process of being modified by VUE. 

## **MOUSEPOS** 

A-Shell Reference 

Page 852 

This directive may be used at the command level or in ini.vue to disable caret position with the mouse. This may be useful on some laptops with very sensitive touch pads, which otherwise may cause the typing position to jump around unexpectedly (considered rather bad behavior in a program editor). Default is TRUE. 

## **QUITWARN** 

This directive controls whether you get a warning message and request to confirm when you attempt to quit out of an editing session after making changes to the file. Of course if you still quit accidentally, you can always retrieve the .BAK backup file, but you must do that before you edit the file again. 

## **UPDSSL** 

This may be set to ON to force VUE to keep the shifted status line (if there is one) equal to the unshifted status line. This prevents the line from "blinking" when you hit the SHIFT key. This is only an issue in certain terminal emulation environments. 

A-Shell Reference 

Page 853 

## **LOCKSTRICT** 

As of VUE 3.2(284) of 5 December 2006, VUE reverts the locking under Windows back to the way it was prior to 3.2(280), meaning that although it prevents two Windows users from VUEing the same file in update mode, it allows read-only access to a file that is being VUE'd. Starting with 3.2(280), we made the locking more strict to better coordinate locking between crossplatform users, but this had the undesirable side effect of making it impossible to compile a program in one job if it was being VUE'd in another. To activate the stricter locking, you can add the following to the ini.vue: 

## `LOCKSTRICT = TRUE` 

Otherwise, the more permissive style locking will be in force. Note that the permissive locking is not believed to be reliable in cross-platform environments. (In such cases, or whenever you have mixture of VUE and EDITOR users, you should probably use the LCKFILE=TRUE option.) 

A-Shell Reference 

Page 854 

## **MODEM** 

This directive (also available from Command Mode) toggles between the normal display mode and a mode in which the amount of output characters is minimized. This mainly affects the way Command Mode works. In standard mode (MODEM = OFF) the entire screen is cleared and repainted when switching between Display and Command Modes. When MODEM = ON, only the top one or two lines of the screen are used for Command Mode, leaving the rest of the Display Mode screen display intact. This abbreviated directive mode is particularly appreciated by modem (or other slow baud rate) users, as well as people who tend to forget what they were doing when the screen is suddenly cleared. 

Note that this (MODEM=ON) behavior is similar to the venerable Unix editor _vi_ , except that vi uses the bottom line for Command Mode. 

A-Shell Reference 

Page 855 

## **MOUSEPOS** 

Most of the VUE.INI directives have descriptions that are long enough to require their own page. Those with short descriptions are collected below. 

## **COLOFFSET** 

This directive, both at the command level and in ini.vue, adjusts the starting column number. By default, VUE calls the first column #0. If you want the first column to be numbered 1, then use > `COLOFFSET 1` at the VUE prompt or add `COLOFFSET = 1` ini.vue. 

## **DRAW** 

This controls whether you can invoke a d/VUE-inspired feature of the same name in which the control commands ^S^H, ^S^J, ^S^K and ^S^L can be used to change the default cursor advance direction to left, down, up and right (default), respectively. This feature can be handy for laying out forms, but if accidentally invoked could wreak havoc on a blind typist, which is why it is not enabled by default. 

## **LCKFILE** 

This directive can be used to force VUE to create a separate <file>.lck file while <file> is being edited with write privileges. The purpose of this is to allow yet another way for external editors to detect that a file may be in the process of being modified by VUE. 

## **MOUSEPOS** 

A-Shell Reference 

Page 856 

This directive may be used at the command level or in ini.vue to disable caret position with the mouse. This may be useful on some laptops with very sensitive touch pads, which otherwise may cause the typing position to jump around unexpectedly (considered rather bad behavior in a program editor). Default is TRUE. 

## **QUITWARN** 

This directive controls whether you get a warning message and request to confirm when you attempt to quit out of an editing session after making changes to the file. Of course if you still quit accidentally, you can always retrieve the .BAK backup file, but you must do that before you edit the file again. 

## **UPDSSL** 

This may be set to ON to force VUE to keep the shifted status line (if there is one) equal to the unshifted status line. This prevents the line from "blinking" when you hit the SHIFT key. This is only an issue in certain terminal emulation environments. 

A-Shell Reference 

Page 857 

## **PCNAV** 

The typical PC interpretation of the HOME/END keys is supported via the switch PCNAV = TRUE. When enabled, the HOME (^^) and END (^E) keys go to the start and end of the current line, rather than the start and end of the file, as they do in the traditional VUE command set. This difference has been a long-standing irritation to people accustomed to using typical PC editors. 

To go to the start or end of the file when PCNAV=TRUE, the following new extended key commands have been implemented: 

|**Key Combo**|**Standard VUX Translation**|**Function**|
|---|---|---|
|CTRL+_ HOME|^_^^|start of file|
|CTRL+_ END|^_^E|end of file|



## **History** 

- 2011 November, A Shell 6.0.1241:  Function added to A-Shell 

A-Shell Reference 

Page 858 

## **QUITWARN** 

Most of the VUE.INI directives have descriptions that are long enough to require their own page. Those with short descriptions are collected below. 

## **COLOFFSET** 

This directive, both at the command level and in ini.vue, adjusts the starting column number. By default, VUE calls the first column #0. If you want the first column to be numbered 1, then use > `COLOFFSET 1` at the VUE prompt or add `COLOFFSET = 1` ini.vue. 

## **DRAW** 

This controls whether you can invoke a d/VUE-inspired feature of the same name in which the control commands ^S^H, ^S^J, ^S^K and ^S^L can be used to change the default cursor advance direction to left, down, up and right (default), respectively. This feature can be handy for laying out forms, but if accidentally invoked could wreak havoc on a blind typist, which is why it is not enabled by default. 

## **LCKFILE** 

This directive can be used to force VUE to create a separate <file>.lck file while <file> is being edited with write privileges. The purpose of this is to allow yet another way for external editors to detect that a file may be in the process of being modified by VUE. 

## **MOUSEPOS** 

A-Shell Reference 

Page 859 

This directive may be used at the command level or in ini.vue to disable caret position with the mouse. This may be useful on some laptops with very sensitive touch pads, which otherwise may cause the typing position to jump around unexpectedly (considered rather bad behavior in a program editor). Default is TRUE. 

## **QUITWARN** 

This directive controls whether you get a warning message and request to confirm when you attempt to quit out of an editing session after making changes to the file. Of course if you still quit accidentally, you can always retrieve the .BAK backup file, but you must do that before you edit the file again. 

## **UPDSSL** 

This may be set to ON to force VUE to keep the shifted status line (if there is one) equal to the unshifted status line. This prevents the line from "blinking" when you hit the SHIFT key. This is only an issue in certain terminal emulation environments. 

A-Shell Reference 

Page 860 

## **SHOWTABS** 

_Written October 2022_ 

The SHOWTABS directive in INI.VUE and Command Mode allows embedded TAB characters to be represented in the display by some other character. The argument can be boolean (in which case the default is to use a lower case "t"), or it can be the ASCII value of the character to use (in decimal, hex or octal notation). It also accepts the special value ">>" to use the right guillemet (aka double right chevron) character (requires ANSI/Latin1 character set). 

## **Examples** 

```
>SHOWTABS
```

```
    enables feature using "t"
```

```
>SHOWTABS OFF
```

```
    disables feature
```

```
>SHOWTABS >>
```

```
    use the ">>" character
```

```
>SHOWTABS 20
```

```
    use ASCII 20 (^T)
```

Note that in all cases, the character used will be dim to hopefully distinguish it from the normal text characters. Also, ASCII values between 1-31 are displayed like control characters, i.e. 1 displays as a dim "A", 20 as a dim "T", etc. 

## **History** 

- 2022 October, A Shell 1721: Added to A-Shell. 

A-Shell Reference 

Page 861 

## **FUNCTION KEYS** 

The MIAME environment contains full function key support, but these will only be usable within the editor if the appropriate function key translation files exist in account DSK0:[7,0]. These are files with the same name as defined for your terminal in the TRMDEF line of miame.ini, and extension .vux. pctdv.vux and pctdvg.vux are supplied with A-Shell/Windows, either of which may be copied or renamed if your A-Shell/Windows terminal driver is going by a different name. Under A-Shell/Unix, there are several available terminal drivers (am62a, am62c, am65, am75, wyse50, etc.), each of which needs its own vux file. 

The FIXTRN utility may be used to create, query or edit function key translation tables. 

Under Unix, the line terminator is a single \n, or LF character. Under AMOS and Windows, a CR-LF character pair is used. VUE is the only A-Shell module which under Unix will automatically convert from the either format and will always save files in the current native format. 

A-Shell Reference 

Page 862 

## **SPECIAL COMMANDS** 

A-Shell/Vue is mainly intended for the convenience of those already familiar with some other version of VUE, (e.g. VUE, XED, or d/VUE). Since the A-Shell/Vue supports mainly just the "core subset" of features that most people use, there did not seem to be much need to document it in detail here. However, there are a few editing features that are either non-standard extensions or just plain exotic, such that many people are not aware of them. Since it would be a shame to live without these features, they are hereby revealed. 

**Push/Pop:** Although these are supported in virtually all other versions of VUE, A-Shell/Vue offers a useful enhancement on the idea by providing a stack of up to ten push/pop locations. The standard PUSH and POP commands access this stack in the usual LIFO fashion, but if you specify a numeric stack location (e.g. >PUSH 5) it uses that entry directly. Thus is becomes something more like a "bookmark". Note that whenever you directly access the push/pop stack this way, it resets the "stack pointer" to that location, which will affect the operation of any subsequent "unadorned" PUSH or POP command. Note also that current implemention of POP restores the original screen position, whereas earlier versions positioned the window so that the popped line was the fifth line. 

**Edit History commands:** In addition to the automatic edit history feature (see UPDATE and AUTODELETE) above, there are also a couple of features which ease the maintenance of manual edit history notation. One is based on XED, and is invoked with ^_E (CTRL+SHIFT+UNDERLINE+E), while the other is based on d/VUE and is invoked with ^SE (CTRL+S followed by **E).** They both start by searching the file for the current edit number as defined by either a VEDIT = ### statement or a `PROGRAM xxxxx, #.##(###)` statement. (VEDIT is the symbol used by AMOS assembly language source files to define the edit number. If you want to use it with other program types, you will probably need to comment out the line to avoid compiler troubles.) Both commands search first for VEDIT, then for PROGRAM. If either is found with an acceptable syntax, it reads the three-digit edit number. Then, in the XED version, it increments the number within the VEDIT or PROGRAM statement and uses it to construct a two-line edit history entry, which inserts at the line where the cursor was, using the following format: 

```
![124] October 02, 2024 05:59 PM        Edited by jack
```

```
!    _
```

(The idea is that you will then add in your own information describing the purpose of the edit.) 

A-Shell Reference 

Page 863 

In the d/VUE version, the current edit number is not incremented, and the only thing inserted into the file at the position of the cursor is the current edit number in [###] notation. This form is particularly useful for commenting individual changes in a program and associating them with the program’s edit number. 

Use the Command Mode HELP command to get a complete list of all the available commands. 

A-Shell Reference 

Page 864 

## **COMMAND MODE COMMANDS** 

|**Command**|**Action**|
|---|---|
|ASCII7|Characters with the eighth bit set are displayed as a dimmed question mark.|
|Blanks #|Insert # blank lines|
|Center|Center line|
|Clear|ClearBlock<br>marks|
|Copy|CopyBlock<br>to cursor position|
|CopyC|CopyBlock<br>to cursor position and clear block marking|
|Delete|DeleteBlock|
|F)inish|Update file & exit|
|Format|Deletes line breaks and reformats a paragraph using word wrap so that each<br>line is as long as possible without exceeding the current width specified by<br>WIDTH.|
|Format #|Operates on only the current line, wraps it at exactly the specified width.<br>This is mostly just a convenience for getting an overview of an extremely<br>long.|
|G)o|Finish and execute|
|Global|Global replace string|
|Help|Display help file|
|Help <file>|Display contents of <file>|
|L)ine #|Goto to line #|
|MODEM|Efficient screen mode|
|M)argin {##}|Set left margin at position (column) ##|



A-Shell Reference 

Page 865 

|**Command**|**Action**|
|---|---|
|Move|MoveBlock<br>to cursor position|
|App <file>|Copy markedBlock<br>to specified file|
|N)ext|Search forward for text string|
|Pop {#}|Restore cursor location {from slot #}|
|Push {#}|Save cursor location {in slot #}|
|Q)uit|Exit without updating/saving|
|R)eplace<br><string>|Search and replace string|
|Save|Save current changes w/o exit|
|S)earch <string>|Search for string (from start)|
|Searchfold|Toggle case-sensitive search|
|Short|Switch to 24 row (normal) display|
|Tall|Switch to 42 row display|
|U)nyank #|Remove # of lines (or write)|
|U)nyank <file>|Copy markedBlock<br>to file|
|Wide {##}|Switch to ## columns; default = 132|
|Width {##}|Set width for Format and Wrap commands|
|Wildcard {x}|Replace default wildcard character ? with wildcard character x|
|Y)ank #|bring # lines from current file|
|Y)ank <file>|bring in specified file|



**Additional Points and Tips** 

A-Shell Reference 

Page 866 

You can use the UP ARROW and DOWN ARROW keys to cycle through the Command Mode commands you have previously used. 

The wildcard characters ? and * can be used in the Search and Replace operations. ? (question mark) means any one character, * (asterisk) means any number of characters. 

In addition to F{inish} or Q{uit}, programmers usually exit with G{o} which combines F{inish} with executing a command embedded in the INI.VUE, typically to compile the program. 

A-Shell Reference 

Page 867 

## **BLOCK** 

Several of the VUE commands involve acting on a block of text. The MOVE command, for example, moves a block of text from where it is to the new insertion point indicated by cursor position. In order to act on a block of text, you obviously have to be able to mark it somehow. 

## To mark a block of text: 

- In display mode (i.e., looking at file contents), move the cursor to the beginning of the text you wish to mark. 

- Use Ctrl+P to mark the position; the line will change color or intensity. Note that block operations are line-oriented—i.e., you 

- cannot mark parts of lines or anything smaller than one full line. 

- Move to last line you wish to include in the block. 

- Use Ctrl+P to mark the position; the line and all text in the block will change color or intensity. 

Important last step: move the cursor outside of the block before switching to Command Mode and executing the function that caused you to mark the block in the first place. 

A-Shell Reference 

Page 868 

## **DISPLAY MODE COMMANDS** 

|**Command**|**Action**|**Command**|**Action**|
|---|---|---|---|
|Ctrl+a|Previous word|Ctrl+p|Mark block|
|Ctrl+b|Insert line|Ctrl+q|Toggle insert char mode|
|Ctrl+c|Cancel changes to line|Ctrl+r|Previous page|
|Ctrl+d|Delete character|Ctrl+s|Extended command leadin #2|
|Ctrl+e|End of file|Ctrl+t|Next page|
|Ctrl+f|Insert character|Ctrl+u|Start of line|
|Ctrl+g|Control char leadin|Ctrl+v|Delete next word|
|Ctrl+h|Same as down arrow|Ctrl+w|Next word|
|Ctrl+i|Tab|Ctrl+x|Next match (search)|
|Ctrl+j|Same as down arrow|Ctrl+y|Clear to end of line|
|Ctrl+k|Same as up arrow|Ctrl+z|Delete line|
|Ctrl+l|Same as right arrow|esc|Toggle display/Command Mode|
|Ctrl+m|Same as return|Ctrl+/|Toggle line insert mode|
|Ctrl+n|End of line|Ctrl+^|Top of file|
|Ctrl+o|Concatenate lines|Ctrl+_|Extended command leadin #1|



A-Shell Reference 

Page 869 

## **EXTENDED DISPLAY MODE COMMANDS** 

Precede the commands in the following table with CTRL+UNDERSCORE. 

|**Command**|**Action**|
|---|---|
|C|Copy marked block|
|D|Delete marked block|
|E|Increment VEDIT or PROGRAM value, insert dated note|
|K|Capture macro keystrokes|
|P|Playback macro keystrokes|
|Q|Toggle insert mode (same as Control-Q)|
|R|Undo last Control-Z or Control-Y|
|S|Center current line|
|U|Clear (unmark) marked block|
|V|Move marked block to cursor position|
|X|End macro keystroke capture|



Precede the commands in the following table with CTRL+S. 

|**Command**|**Action**|
|---|---|
|Ctrl+a|Pop|
|Ctrl+b|Copy current line to scrap buffer|
|Ctrl+d|Copy marked block (to cursor location)|
|Ctrl+g|Move marked block (to cursor location)|



A-Shell Reference 

Page 870 

|**Command**|**Action**|
|---|---|
|||
|Ctrl+o|Playback scrap buffer|
|Ctrl+p|Unmark block|
|Ctrl+s|Center display vertically around current row|
|Ctrl+t|Push|
|Ctrl+v|Toggle capitalization of current word|
|Ctrl+z|Delete marked block|
|d|Output current date|
|e|Output edit number ([nnn] - from VEDIT or PROGRAM statement)|
|u|Output user name|
|t|Output current time|



A-Shell Reference 

Page 871 

## **LEARNING VUE 1** 

This topic was written for people who are new to VUE and are using it for the first time. 

## **Open a File** 

Any file containing text, regardless of its extension, may be opened with VUE. From the A-Shell prompt, simply type VUE, the name of the file, and hit ENTER. If you wish to edit the existing file TEST2.TXT, for example, the command to open the file for editing would be: 

```
VUE TEST2.TXT
```

If you want to create a new file, the procedure is the same: type VUE, the name of the file you wish to create, and ENTER. Since the file does not already exist, and assuming you issued the same command as above, VUE will respond with: 

```
TEST2.TXT does not exist, do you wish it created?
```

Answer with YES ("Y") ENTER to create the file and begin your VUE session, or NO ("N") ENTER if you typed poorly and wish to abort. 

If you try to open a file that does not contain text, such as a .RUN or .LIT or .SBX, VUE will open the file and display a bunch of gobbledygook—i.e., unreadable characters. You can't hurt anything by opening such a file, as long as you exit VUE without saving the file. 

See Learning VUE 2 for additional and related information. 

## **Modes** 

VUE has two modes. When using VUE, you are always operating in one of them. 

- DISPLAY mode shows the contents of the file 

- COMMAND mode does not show what's in the file, but rather allows you to enter commands to act on the file such as save, 

- search, etc. Note that the setting of the MODEM command comes into play here; if MODEM=ON, then you can be in Command Mode but still have the file contents displayed. 

A-Shell Reference 

Page 872 

To switch between the two modes, which you typically do many times during an editing session, the ESCAPE key is used. Whichever mode you're in, ESCAPE flips you into the other one. 

## **Exit** 

When you have edited a file, you may finish your VUE session in the following ways. 

- Save your work, such that the changes you have made to the text file overwrite the old text file. This is accomplished with 

- the FINISH ("F") command. Note that the old file is saved with a .BAK extension. 

- Discard your work, so that the changes you made are thrown away and the file remains unchanged. To do this use the QUIT 

- ("Q") command. 

See Learning VUE 2 for additional and related information. 

## **Sample Session** 

If you haven't already done your own experimenting, follow along with these steps for your first VUE session. 

- Step 1: Begin at the A-Shell prompt 

- Step 2: Type "VUE TEST2.TXT" and hit the ENTER key. Note that we're assuming the file TEST2.TXT does not exist. If it does, use some other name that doesn't exist, 

   - like MPL04J.DK8—i.e., the filename does not matter. A new screen will appear, looking something like this: 

This is VUE showing you an empty file. The cursor is on line one, position one, waiting for you to type something. The asterisks filling the screen are placeholders, meaning "nothing is in this space." 

- Step 3: Type something. For example, type in the first line below, hit ENTER at the end of 

A-Shell Reference 

Page 873 

the line, then type in the second line. 

```
PRINT "Hello World"
```

```
END
```

- Step 4: Press the ESCAPE key. You have just moved from display mode to Command Mode, and the command screen now displays something like this: 

- Step 5: At the command prompt >, type the letter "F" (for "finish") followed by ENTER. The file will be saved, VUE will exit, and the following line will be displayed: 

```
Exiting TEST2.TXT
```

A-Shell Reference 

Page 874 

## **LEARNING VUE 2** 

Here are some additional tips for your first steps in using VUE. 

## **Open a File** 

In addition to opening a file by entering VUE <filename>, where <filename> specifies a file in the A-Shell file system, you can also open files that A-Shell doesn't know about but which exist in the host operating system's file system. For example: 

```
VUE C:\VM\MIAME\MIAME.INI (Windows)
```

```
VUE "/vm/miame/ashlog.log" (Unix)
```

Note that you must enclose Unix file names in quotes, to avoid confusion between VUE switches and directory separators, since VUE uses slash characters to indicate switches. 

## **Exit** 

In addition to ending your session with FINISH or QUIT, you may also end with GO. This operation (a) saves the file, and (b) executes/runs the function specified in INI.VUE for this file type. For example, programmers typically create ".BAS" or ".BP" files. In INI.VUE they will have a line specifying that GO, in the case of .BAS files, means "COMPIL <filename>. So when they finish editing their program, they exit with GO ("G"), and the file is both saved and compiled. See GO for more information. 

## **Control Characters** 

Control characters are special, non-character characters used primarily for printer control. They may be embedded in the file by hitting CTRL+G (hold down the CONTROL key and hit the G key) followed by the character you are inserting, and will be displayed as dim characters. For example: . CTRL+G followed by CTRL+L inserts a Control-L (ASCII 12) into the file and displays it as a dim L. 

Although you may not need to insert control characters into a file, you will likely encounter them when trying to VUE files of uncertain origin. Note that an embedded null character is displayed as a dim @. 

## **VUE vs. Notepad** 

If you are familiar with Windows Notepad or similar text editors, you should be aware of the following: 

A-Shell Reference 

Page 875 

- Insert mode. In Notepad, you are always and automatically in insert mode, where what you type pushes existing text to the 

- right. In VUE, that is not the case; you are always in overwrite mode, unless you explicitly turn on insert mode with CTRL+Q. To exit insert mode, likewise use CTRL+Q. 

- HOME / END. In Notepad, these keystrokes take you to the beginning/end of the current _line_ . In VUE, they take you to the 

- beginning/end of the _file_ . 

- Wrap. Although VUE supports the WRAP option, as a program editor, there is no distinction between paragraph terminators 

- and line terminators. Every display line gets written with a CRLF or LF terminator. 

- VUE accepts files with either LF or CRLF line terminators. Use the CRNL command or option to toggle the terminator used 

- when saving a file. 

- VUE has very limited support for mouse commands. You may use the mouse only to: 

- move to a position in the file and then click the left mouse button to place the cursor at that spot. 

- select and copy to clipboard by click-hold-and-drag to create your selection; when you release the mouse button, the 

- selection is copied to the Windows clipboard. 

- The Windows clipboard commands CTRL+C, CTRL+X, and CTRL+V have different meaning in VUE. To copy/paste/move text, see 

- the following section Copy / Paste / Move. To paste text from the Windows clipboard, use A-Shell's Edit > Paste menu command. 

## **Copy / Paste / Move** 

Copying a block of text from point A in the file to point B is similar to conventional copy-and-paste, but is executed differently. 

To copy a block of text: 

- Move to the first line of the block and press CTRL+P. This marks the beginning of the block. Note how the line switched from 

- normal text to lightened text. 

- Move to the end of the block and press CTRL+P again. This is the end of the block. All of the text in block will now be marked 

- by being lightened. 

- Now move to the place in the file where you want to insert the copied text. 

- Press ESCAPE to go to Command Mode 

A-Shell Reference 

Page 876 

- To make a _copy_ of the block of text at the insertion point, type COPY. To _move_ the text—i.e., delete it from its old location— 

- type MOVE. 

- Press ESCAPE to go back to Display mode and see the results of your operation. 

Note that after the mark and copy operation is done, the original block that was marked remains selected. To clear the selection: make sure the cursor is outside the selection, ESCAPE to Command Mode, and type CLEAR followed by the ENTER key. 

**Caution** : pasting a block of text while in overwrite mode, which is the normal condition in VUE, can be dangerous; if you don't have sufficient blank lines to accommodate the block you are pasting, you will overwrite existing text. To avoid this problem, turn on both character insert mode ( CTRL+Q ) and line insert mode ( CTRL+BACKSLASH ) before pasting. 

## **Miscellaneous Tips** 

If you just want to view the contexts of a text file, and don't intend to change it, it is not necessary to use VUE and its editing capabilities. You can instead use any one of several display-only commands, namely TYPE, HEAD, TAIL, EZTYP. 

To shell out of A-Shell and use a text editor provided by the host operating system, enter EXPLORE to access the host's file system or HOST <program name> to run <program>. 

A-Shell Reference 

Page 877 

## **WEBRUN** 

_Added October 2016_ 

## **WEBRUN url {args}** 

WEBRUN.LIT is the front-end to RUN.LIT which enables A-Shell's WEBCACHE system. WEBRUN downloads the specified program from _url_ into the webcache directory and then runs it, passing any _args_ to it. If _url_ contains spaces, it must be quoted, and if any _args_ are specified, there must be at least one space between _url_ and the _args_ . If the url filename has no extension, .run is assumed. It also enables the webcache feature and all options—equivalent to SET WEBCACHE ENABLE,PROG,OPENI,LOOKUP— and sets the default URL based on URL given minus the filename. 

Note that this command bypasses the normal search path: it will ignore a copy of the target program in the current [p,pn], [p,0] or [7,6] directories. 

## **Examples** 

```
.WEBRUN http://www.mysite.com/app1/myprog
```

## This command: 

- enables all webcache options 

- sets the repo to http://www.mysite.com/app1 

- checks local webcache for myprog.run; if not there, tries to download it from the URL. 

- tries to execute it from the webcache directory. 

```
.WEBRUN "http://www.another site/app2/prog2.run" /demo
```

Similar to previous example except that it also passes the command line switch "/demo" to the target program prog2.run. 

## **History** 

- 2016 October, A Shell 6.3.1529 and 1531: WEBCACHE function added to A-Shell. The module includes a basic description, the SET.LIT options for WEBCACHE **,** new functions WEBRUN.LIT, MX_WEBCACHE and AG_WEBCACHE. 

A-Shell Reference 

Page 878 

## **WSET** 

## **WSET** 

TRACKER is a Debug/MicroSabio module which keeps track of all output sent to the screen. In doing so, it manages to implement the -1,148 (save screen area) and -1,149 (restore screen area) TCRT calls for those terminal types that do not perform these functions in firmware. Tracking is enabled and disabled with the WSET command. 

A-Shell includes a functional equivalent of TRACKER that is permanently enabled, and so the -1,148 and -1,149 TCRT codes are always available for terminals on an A-Shell system. The WSET command is included mainly for compatibility and to prevent A- Shell rejecting it as an illegal command, though some of the operational switches are implemented. It always responds as the AMOS version does when tracking is already enabled: 

```
%TRACKER flag already set
```

```
Allocated TRACKER buffer located - TRACKER 2.0C already installed
```

The TRACKER /?, /M, and /N operational switches have been implemented. 

A-Shell Reference 

Page 879 

## **XY** 

_Added February 2017_ 

## **XY x y** 

## **XY x,y** 

The two syntaxes shown above, identical except for the space versus comma, both position the cursor on the screen at position x,y. This is the equivalent of the ASB statement `? tab(x,y).` 

## **XY = m** 

The above syntax is the equivalent of the ASB statement `? tab(-1,m)` . 

## **XY -n m** 

## **XY -n,m** 

The above syntax is equivalent to the ASB statement `? tab(-n,m)` . 

## **See Also** 

- Tab Functions 

## **History** 

- 2017 February, A Shell 6.3.1545: Add usage help display, add support for XY x,y syntax. 

A-Shell Reference 

Page 880 

## **ZTXFER** 

_Updated October 2016; see History_ 

To send from host to PC: 

## **ZTXFER{/A} host-name PC-name** 

or 

## **ZTXFER{/A} host-name** 

To send from PC to Host: 

## **ZTXFER{/A} host-name=PC-name** 

or 

## **ZTXFER{/A} =PC-name** 

ZTXFER is the A-Shell implementation of ZTERM's AMOS-to-PC file transfer routine. It can be used when transferring files to/from an A-Shell host and a connected PC that is running either ZTERM or ATE. Binary transfers are performed unless ASCII is specified with the /A switch. The following syntax can be displayed by entering ZTXFER with no arguments. See also the discussion on the ATE environment variable. 

Note that ZTXFER requires an FTP server, so it won't work on most Windows servers unless an FTP server has been specifically set up. 

## **Switches** 

|**Switch **|**Effect of Switch**|
|---|---|
|/A|Forces ASCII mode.|



A-Shell Reference 

Page 881 

|**Switch **|**Effect of Switch**|
|---|---|
|/1|Forces FTPDLX mode.|
|/2|Default. Requests new FTP/SFTP implementation if available (faster).|
|/ATE|Raw transfer via ATE terminal channel (instead of FTP/SFTP); automatic<br>for ATE to ATSD connections.|



## **Using with ATE** 

ZTXFER supports wildcards if the client is ATE. Examples: 

Copy all files from current directory to PC: 

```
.ZTXFER *.* C:\VM\MIAME\DSK0\111222
```

Copy all RUN files from PC to current directory 

```
.ZTXFER = C:\VM\MIAME\DSK0\111222\*.RUN
```

Copy A*.B* from PC to BAS: 

```
ZTXFER BAS: = C:\VM\MIAME\DSK0\111222\A*.B*
```

ZTXFER also supports an /ATE switch to force alternative transfer protocol—i.e. using ATE terminal channel. This was already automatic for transfers between an ATE client and a Windows server, but can be forced in other situations. For example, under Unix, FTP/SFTP transfers may be blocked by some security or other obstacle, while the ATE terminal channel would work. 

## **See Also** 

- See FTP Debugging for tips on debugging ZTXFER FTP-based transfers. 

- ATEAPX and ATEGFK for alternate file transfer possibilities. 

A-Shell Reference 

Page 882 

## **History** 

- 2024 January, A Shell 7.0.1753:  ZTXFER.LIT 1.4(110): /2 mode (FTP vs FTPDLX) is now the default. To force FTPDLX mode, a new /1 switch has been added 

- 2019 June, A Shell 6.5.1662:  DIR.LIT 1.4(109) has been updated to accommodate a change in maximum filename.ext size, from 10.3 to 72.8. 

- 2016 October, A Shell 6.3.1531: ZTXFER.LIT 1.4(108) implements /ATE switch. 

- 2014 March, A Shell 1381:  ZTXFER.LIT 1.3(107) now supports filenames that exceed the 10.3 file.ext format. Also now treats server destination of "*" or "*.*" as equivalent to ""—i.e. uses file.ext from PC. 

- 2013 December, A Shell 1370:  ZTXFER.LIT 1.3(106) now supports PC to Windows server file transfers using the 

AG_GETFILEDATA protocol introduced in 6.1.1357 and vastly improved in 6.1.1370.0. PC to server file transfers are now typically 1 MB/sec, without requiring any special servers or ports. For the Unix server world, it also supports a new /2 switch to invoke the new FTP/SFTP protocol (implemented in ASHNET 1.6.139) if it is available. 

A-Shell Reference 

Page 883 

## **ZXPWIN** 

## **ZXPWIN {<pcdir=>} {(ext)} <file>** 

(Unix only) ZXPWIN is a handy utility for A-Shell/Unix users running the ZTERM terminal emulator. It transfers the specified file to the PC and launches it using the Windows application appropriate for the file type (thus combining two or three steps which might otherwise be done manually.) 

If the optional _<pcdir=>_ argument is not specified, then the file is transferred to the default directory, whatever that may be. Otherwise, it is sent to the specified PC directory. 

If you have ZTERM Build 143 or higher, you can use PC environment variables, such as TEMP, but enclosing them in % (e.g. `ZXPWIN %TEMP%=ABC.TXT` ) 

The optional _(ext)_ argument may be used to force the source file extension to be changed during the transfer. This is particularly useful since the extension determines which Windows application will be launched. For example, if you wanted to transfer a BAS file to the PC and view it in Notepad, you would want to specify (TXT). Otherwise, the default application for BAS files would probably be the Visual Basic editor, which is probably not present, and even if so, is probably not what you wanted. 

Since parentheses are significant to most Unix shells, if you are going to specify a ZXPWIN command as part of an ashell command line (which will be processed by the shell), you will need to enclose the parentheses in quotes (e.g. `ashell ZXPWIN %TEMP%="(TXT)"ABC.BAS)` 

The _file_ argument can be in native or DevPPN format. 

## **Examples** 

```
ZXPWIN TEST.DOC
```

Transfer the file test.doc to the PC in the default transfer directory and launch the Windows application which is associated with DOC files (probably Word or WordPad). 

```
ZXPWIN %TEMP%=(CSV)TEST.PRT
```

A-Shell Reference 

Page 884 

Similar to the previous example, except that we will send the file to the PC directory defined by the PC’s TEMP environment variable, and we will rename the file TEST.PRT to TEST.CSV on the PC (so that we launch the spreadsheet program). This would be most appropriate if the TEST.PRT file was actually in comma-delimited format. 

```
HOST ashell ZXPWIN %TEMP%="(DOC)"TEST.BAS
```

The above command launches a new instance of ashell, which in turn executes the same ZXPWIN operation as in the previous example. Note that we must enclose the (DOC) argument in quotes since the shell (which will process the ashell command line) would otherwise strip off the parentheses. 

```
ZXPWIN C:\TEMP=(TXT)/vm/miame/miame.ini
```

This command transfers miame.ini (note the use of the native Unix filespec) to the C:\TEMP directory on the PC, renaming it to miame.txt, and then launching the TXT file viewer (which is probably Notepad). 

A-Shell Reference 

Page 885 

## **COMMAND FILES** 

All modern operating systems have a script language whereby system commands can be grouped into a file and then executed as if they were being entered, one line at a time, by a person. In the case of the Microsoft Windows command prompt and PowerScript, those files were originally known as "batch" files and have the extension .BAT. In Unix/Linux, they are called "shell scripts." In A-Shell they are known as "command files" and may have the extension .DO or .CMD. Files with the .CMD extension do not allow argument substitution and macro expansion, but otherwise are identical to .DO files in both structure and execution. 

In addition to the normal commands that make sense at the command prompt, command files also support some special commands and symbols which only make sense within files, and which allow them to be somewhat more program-like. Consider the following sample DO file (main.do), then see the following sections for more information. 

## **Command File Comments** 

The comment character is the semicolon ( ; ). This is equivalent to Unix which uses the number sign ( # ) and Windows which uses "REM". The comment character may appear anywhere in the command line, with the exception that labels, which have the same syntax as a one-word comment, must start in column one. See the line ";DONE" in the sample file below. 

## **Example: MAIN.DO** 

```
$D 100 MENU                 ; defaults for $0 and $1
```

```
:T                          ; trace (echo) commands
```

```
LOG DSK0:[150,$0]
```

```
:R                          ; don’t trace commands
```

```
IF LOOKUP ("MENU.DAT") = 0
```

```
  :<Sorry, no MENU.DAT here
```

```
  >
```

```
  GOTO DONE
```

```
ENDIF
```

A-Shell Reference 

Page 886 

```
RUN $1
```

```
;DONE                       ; (this is a label)
IF "$NU" <> "admin"         ; force all users except "admin"
  HOST                      ; to exit A-Shell
```

```
ELSE
```

```
  :<
```

```
  Now returning to cmd prompt...
```

```
  >
```

```
ENDIF
```

## **Subtopics** 

- DO File Arguments 

- DO File Statements 

- Colon (:) Tokens 

- Special $ Variables 

- Global DO File Parameters 

- Input Case 

- Concatenate Parameters 

A-Shell Reference 

Page 887 

## **DO FILE ARGUMENTS** 

_Revised and reorganized June 2020_ 

## **Arguments $0 through $9** 

The formal arguments $0 through $9 within the DO file are replaced by the first through tenth space-delimited tokens on the command line that invokes the DO file, with the first token being the one following the name of the DO file itself on the command line. Thus, if the command line was: 

```
DO MAIN 22 GL
```

then $0 will be replaced by "22" and $1 by "GL". This differs from Windows (which uses %0 through %9) and Unix (which uses $0 through $9), both of which use the zero parameter to refer to the name of the batch or script file itself rather than the first user argument. 

Since the space is used as a token delimiter, a special trick is needed to create a single argument that contains a space. Angle brackets may be used for this purpose to combine multiple tokens into a single argument. For example, in the following command line: 

```
DO MAIN 22 <GL OPTION1 OPTION2>
```

"GL OPTION1 OPTION2" will be treated as $1. 

In addition to the literal text arguments just described, DO also accepts file-based variable arguments using the syntax _++fspec_ , which get replaced at execution time by the contents of the first line of the file specified by _fspec_ . 

For example, if the first line of the file mydata:c.txt contained "THIS DATA", then the DO file command line: 

```
DO MAIN 22 ++MYDATA:C.TXT
```

would expand to: 

```
DO MAIN A B <THIS DATA>
```

The <brackets> are employed when the line contains embedded spaces so that the entire line is treated as a single argument. 

A-Shell Reference 

Page 888 

Note that "DO" in the above examples is optional and included only for clarity. It is only needed when the filespec argument following it (e.g. "MAIN") is ambiguous, i.e. when it might refer to SYS:MAIN.LIT or cmd:main.cmd rather than cmd:main.do. 

## **Default Arguments** 

To establish default values for arguments which are not specified on the command line, the DO file can begin with the special command $D followed by the defaults for $0, $1, etc. Arguments not specified in this list will have no default. You can also specifically skip over a default argument by inserting just a $ in the argument’s position on the $D line. For example: 

```
$D DEF0 $ DEF2
```

This would set the default for $0 to "DEF0", the default for $1 to nothing, and the default for $2 to "DEF2". 

The $D command, if present, must be on the first line of the DO file. 

A-Shell Reference 

Page 889 

## **DO FILE STATEMENTS** 

_Reviewed and reorganized June 2020_ 

## **System Commands in DO Files** 

Several system commands are of use mainly or only in the context a command or DO file. Those system commands are: 

|**Command**|**Description**|
|---|---|
|ECHO|Echoes <text> to screen.|
|ELSE|Conditional flow in command file.|
|ENDIF||
|IF||
|EXIT|Exit command or DO file.|



## **IF / ELSE / ENDIF Statements** 

These statements are similar to their ASB counterparts. The following functions and expressions are supported by IF, with the same syntax as for ASB: 

ABS CHR FACT LEFT MID SPACE UCS ACS COS FIX LEN RIGHT SQR VAL 

A-Shell Reference 

Page 890 

ASC DATN INSTR LOG RND STR ASN DEVICE INT LOG10 SGN TAN ATN EXP LCS LOOKUP SIN TIME 

## The following operators are supported: 

|**Relational Operators**|**Relational Operators**||**Mathematical Operators**|**Mathematical Operators**|
|---|---|---|---|---|
|**Symbol**|**Meaning**||**Symbol**|**Meaning**|
|=|Equal||+|Addition|
|<>|Not equal||-|Subtraction|
|#|Not equal||*|Multiplication|
|>|Greater than||/|Division|
|>=|Greater than or equal||^|Raise to power|
|<|Less than||**|Raise to power|
|<=|Less than or equal||||



## **Comments** 

Note that unlike in ASB where many of the above functions could optionally have a $ suffix (e.g. LEFT or LEFT$), in DO files the $ variation is not acceptable. 

IF statements frequently operate on the Special $ Variables, which see for further comments and examples. 

A-Shell Reference 

Page 891 

## **GOTO and EXIT Statements** 

GOTO is similar to the ASB GOTO statement, except that it can only jump forward in the command file. The syntax of a label consists of a semicolon followed by the label name. See the label ";DONE" in the sample MAIN.DO file. 

EXIT causes an immediate exit to the A-Shell command prompt, even if you are currently nested multiple levels deep in a command file. 

## **LOOKUP Statement** 

The most useful of the above functions, LOOKUP, works slightly differently than the BASIC _plus_ equivalent. Instead of returning the file size, it always returns –1 if the file exists, else 0. The syntax is also different: 

## **LOOKUP <fspec>/Optional message if not found** 

If the specified file is not found, the optional message (following the /, which is mandatory) is displayed and execution continues with the following line. Otherwise, the following line is skipped. Typically this is used with GOTO to create a conditional branch, as in the following: 

```
LOOKUP $0/$0 does not exist!
```

```
GOTO DONE                           ; (EXIT might also be appropriate here)
```

```
VUE $0
```

```
;DONE
```

A-Shell Reference 

Page 892 

## **COLON (:) TOKENS** 

_Updated June 2022; see History_ 

Certain special commands or tokens begin with the colon, which may be in the first column or which can be indented. 

|**Command**|**Meaning**|
|---|---|
|:< .... >|outputs the text between the opening and closing angle brackets; may span multiple lines. This is the<br>normal way to print operational messages on the screen from within command files.|
|:T (trace)|causes all commands from that point forward to be traced—i.e., be displayed on the screen. This is very<br>useful for debugging, but may be too verbose for normal use.|
|:R (respond)|causes just the output of commands to be displayed; the commands themselves do not display. This<br>produces a somewhat cleaner looking result.|
|:S (silence)|silences all output. Unfortunately, this is the default, if neither :t or :r are supplied first.|
|:X (exit)|causes the CMD or DO file to exit. This is equivalent to theEXITcommand.|
|:K (keyboard)|stops and waits for keyboard input. The input is then processed by whatever process is currently in effect<br>(i.e. either a program or the command line processor itself). For example:<br>`SET CTRLC`<br>`:<This command erases all files!!!`<br>`Hit ENTER to proceed or ^C to abort: >`<br>`:K           ; ^C will abort here; ENTER will just proceed`<br>`ERASE *.*`|
|:K#(keyboard)|Variation on :K with numbered variables. See notes below.|
|:P (partial)|may be used in conjunction with :k to append the keyboard input to a partial command line. For example:<br>`:R`<br>`:<Enter name of file to display: >`<br>`:P`<br>`EZTYP`|



A-Shell Reference 

Page 893 

|**Command**|**Meaning**|
|---|---|
||`:K`|



## **- K0 K9 Tokens** 

The command file processor supports a variation of the :K token to input keyboard responses into variables which can be tested in IF statements and used as DO file parameters. The following sample file provides an example: 

```
:R
```

```
:<Enter desired ppn: >
```

```
:K0
```

```
:S
```

```
:<Enter password: >
```

```
:K9
```

```
IF "$KBD9" = "SECRET"
```

```
DOLOG $KBD0
```

The special token :K0 is like :K, in that it waits for a line of input, but instead of passing the input to the current program, it simply stores it as $KBD0. The same concept applies to :K1 thru :K2 ($KBD1 thru $KBD9). The special $KBDn variables may be tested in an IF statement or passed as a command line argument to a DO file. 

Note that when using $KBDn in an IF statement, it must be quoted as in the example above. However, when using it as a DO file command argument, it should not be quoted. In the example above, the DO file dolog.do will see the $KBD0 on its command line and convert it to whatever had been entered to the "Enter desired ppn" prompt. 

A-Shell Reference 

Page 894 

$KBDn variables cannot be used in any other context, even within a command file. Unlike other special $xx variables which can appear in DO files, which are expanded by DO.LIT when it loads the DO file, the $KBD variables cannot be expanded until after the input operation takes place, and thus it is left to individual commands (just IF and DO) to interpret them. 

## **History** 

- June 2022: A Shell 6.5.1715, DO.LIT 2.1(126): support indentation of the colon directives as illustrated in the example MAIN.DO; previously they had to be in column 1. 

A-Shell Reference 

Page 895 

## **SPECIAL $ VARIABLES** 

_Revised January 2024; see History_ 

The DO file processor supports various special information variables or built-in macros which  all have a $ prefix, followed by one or more alphabetic characters and possibly an arithmetic suffix. The supported variables are listed here; those that are A-Shell extensions are noted at the end of the list. 

Also note that the special $ variables are only expanded within DO files, not CMD files. 

|**Variable **|**Value**|
|---|---|
|$:|Original device (e.g. "DSK0:")|
|$P|Original ppn (e.g. "7,6")|
|$$|Real dollar sign|
|$TM|Time of day in 24 hour HH:MM format (e.g. "13:27")|
|$TD|Current date in YYMMDD format|
|$TW|Current day of week as a number (0=Mon, 1=Tue,...)|
|$NJ|Current job name (e.g. "TSKAAA")|
|$NT|Current terminal name|
|$ND|Current terminal driver name|
|$NS|Current OS (e.g. "AIX")|
|$SV|Current OS version|
|$UX|Current radix (e.g. "8" or "16")|
|$LG|Current language (e.g. "ENGLISH")|
|$LY|Yes character (e.g. "Y")|
|$LN|No character (e.g. "N")|
|$NU|Current login name (e.g. "root")|



A-Shell Reference 

Page 896 

## The following are supported only under A-Shell: 

|**Variable**|**Value**|
|---|---|
|$HF|Current host full path (e.g. "/vm/miame/dsk0/001004")|
|$HD|Current host disk (e.g. "/vm/miame/dsk0")|
|$HP|Current host ppn (e.g. "001004")|
|$HM|MIAME environmental variable definition (e.g. "/vm/miame")|
|$MMDDYY{+/-##}|Each of these evaluates to current date in the specified format,<br>with an optional +/- days adjustment.|
|$DDMMYY{+/-##}||
|$YYMMDD{+/-##}||



## **Comments** 

These special information variables are typically used in IF statements or in output messages. 

Note that unlike ASB string symbols defined with the DEFINE statement, these special $ variables in DO files do not contain their own quotes, so if they are used in a context that requires a quoted string, explicit quotes must be added. 

## **Examples** 

```
IF "$NU" = "jack"      ; (correct)
```

```
IF $NU = jack          ; (incorrect)
```

```
IF LEFT("$NJ",3) = "TAS"          ; (correct)
```

```
IF LEFT($NJ,3) = "TAS"            ; (incorrect)
IF "LEFT($NJ,3)" = "TAS"          ; (incorrect)
```

A-Shell Reference 

Page 897 

## If today were December 1, 2023, then: 

```
$MMDDYY       equals     120123
$MMDDYY+15    equals     121623
$DDMMYY       equals     011223
$DDMMYY-1     equals     301123
$YYMMDD       equals     231201
$YYMMDD+32    equals     240101
```

## **History** 

- 2024 January, A Shell 7.0.1753:  Support added for date variables. 

A-Shell Reference 

Page 898 

## **GLOBAL DO FILE PARAMETERS** 

_Reviewed and reorganized June 2020_ 

This is another A-Shell extension that functions something like the special $ information variables, except that their values may be set from within an ASB program. Once set, they retain their value for the duration of that session (unless specifically overwritten by an ASB program). There are ten possible global DO file parameters, and they may be invoked on a command line using %0 through %9. The DO file processor substitutes these formal parameters for their values before passing them on to the DO file. For example, consider the command line: 

```
XYZ ONE %3 TWO %0
```

Assuming that global parameter %3 had previously been set to "gee whiz" and global parameter %0 had previously be set to "humdinger", then this command would be processed as if it were: 

```
XYZ ONE <gee whiz> TWO humdinger
```

"ONE" would be substituted for $0, "gee whiz" for $1, "TWO" for $2, and "humdinger" for $3. 

There is no particular limit on the size of these variables, although there is limit of 200 characters on the length of any expanded command line. 

To set global parameters, use XCALL MIAMEX as follows: 

## **xcall MIAMEX, MX_SETGDO, status, g0, g1, g2, g3, g4, g5, g6, g7, g8, g9** 

The values of the variables _g0_ through _g9_ (all of them optional, all of them string or unformatted) will be plugged into the corresponding global parameters. Any of the parameters _g0_ through _g9_ that are not specified will cause the corresponding variable to be cleared. _Status_ (F,6) will be returned as 0 for success, else error. 

See the sample program MIAMEX.BP in EXLIB:[908,30] for an example of setting and even retrieving these global DO parameters. Although they were designed to be used with DO files, there is nothing stopping you from using them for holding and passing parameters amongst your own programs. 

A-Shell Reference 

Page 899 

## **INPUT CASE** 

_Reviewed and reorganized June 2020_ 

The DO file processor supports the ability to specify the upper or lower case version of a $KBDn variable on the command line, which can be handy when building case-sensitive Unix commands from input strings. The following example makes this clear: 

```
;TEST.CMD
```

```
:<Input something >
:K1
DOTEST $KBD1 LCS($KBD1) UCS($KBD1)
```

```
;DOTEST.DO
```

```
:<Command line: $0 $1 $2
>
```

Assuming that the user had input "SiLly" in response to the prompt in test.cmd, the output of the DOTEST command would be: `Command line: SiLly silly SILLY` 

Note that these two functions , LCS($KBDn) and UCS($KBDn), are the only ones supported on the DO command line. 

A-Shell Reference 

Page 900 

## **CONCATENATE PARAMETERS** 

The DO file processor supports a mechanism for concatenating parameters on the command line before they are bound to the $0 thru $9 formal parameters. The syntax consists of prepending $+ to the start of a parameter that you want to combine with the prior parameter. For example, consider a generic dothis.do file consisting of the following command: 

```
HOST $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
```

If you executed it with: 

```
.DOTHIS play ina $+gada $+davida real loud
```

The resulting host command would be: 

```
play inagadadavida real loud
```

Note that "real" and "loud", which started out in positions $4 and $5, got shifted by the concatenation down to $2 and $3. 

You can also use the $+ operator in the middle of an argument to avoid the argument renumbering problem just described, i.e.: 

```
.DOTHIS play ina$+gada$+davida real loud
```

In this case, it is more clear that there are only 4 arguments ($0 thru $3) being passed to DOTHIS. This technique is mainly of interest in conjunction with $KBDn variables and the UCS/LCS functions where you may want to concatenate some folded keyboard input with a hardcoded value, and doing do so directly would interfere with the interpretation of the $KBDn and LCS() / UCS() syntax. For example: 

```
:R
```

```
:<Enter command: >
```

```
:K0
```

```
:<Enter ini file: >
```

```
:K1
```

```
DOTHIS /vm/miame/bin/ $+LCS($KBD0) -i /vm/miame/ $+LCS($KBD1)
```

A-Shell Reference 

Page 901 

Assuming the user input "ASHELL" to the first prompt and "MIAME.INI" to the second, then the dothis.do file would execute: 

```
HOST /vm/miame/bin/ashell -i /vm/miame/miame.ini
```

Without the concatenation, the user would have had to enter the entire paths or do without the LCS() function. 

A-Shell Reference 

Page 902 

## **- A SHELL BASIC (ASB)** 

A-Shell BASIC, normally referred to as "ASB," is the programming language used for developing applications in A-Shell. A super set of the original AlphaBASIC, which was introduced in 1976, it shares many features with other BASIC-like languages, while adding a number of features particularly useful for developing vertical market applications in Windows and Unix environments. These include a mechanism for precise memory layout of structures (MAP statements), various integrated, cross-platform, file access methods, and the ability to call external routines written in C or ASB. It is partially compiled to p-code, which is then executed within the A-Shell runtime environment. 

The following sections attempt to provide the necessary details so that both newcomers and long-time A-Shell developers can get the most out of ASB. 

## **Naming Programs** 

Like all file names, ASB programs consist of two parts: a base name or stem, and an extension. 

The base name of your program can be up to 72 alphanumeric characters (including dash, underline and apostrophe but no spaces, parentheses, asterisks, or question marks). File names are not normally case sensitive; they are displayed using upper case within A-Shell but stored using lower case in the host operating system.. 

The extension normally identifies the type of program file, with the two major type categories being source files and compiled programs. 

## **Source Files** 

The extension of your source code files can be anything you want, such as .PPP for Perry's Perilous Programs; A-Shell doesn't care. When you compile a program using A-Shell's COMPIL command, it will work on any filename you specify, such as confused2.ppp, 222much.abc, 1234567890.bas, etc. 

By convention, source files are named with extensions of either BAS or BP, with the latter being recommended. 

BAS is the historical extension, and has been used as the extension for BASIC programs of all types and on all platforms for many years. In the case of A-Shell, BAS always has the benefit of being automatically recognized by COMPIL. To compile a program with the extension BAS, you do not need to specify the extension; the compiler knows to look for a BAS file with the stem name you have specified. So entering `COMPIL ABC` will result in the file abc.bas being compiled, whereas the same 

A-Shell Reference 

Page 903 

command results in the program source file ABC.XYZ being ignored. 

The other common extension is BP, and there are a few good reasons to use it instead of BAS. 

- Many email programs will not allow the sending of BAS files, recognizing them as programs. So if you ever need to send 

- program source files via email, you should not use BAS extensions. 

- BAS is also the default source file name for Microsoft's Visual Basic programs. Since it's easier for you to rename your 

- programs than to get Microsoft to rename its programs, not using BAS is a good idea just to avoid confusion in the Windows world. 

- BP can serve as an indicator that this program (a) was written in and for the A-Shell environment, and (b) contains A-Shell 

- extensions which require the /X:2 switch when compiling. 

- When compiling using the /X:2 switch (use A-Shell extensions), the compiler will find and act on BP files as well as BAS files 

- without you having to specify the extension. If you have a file abc.bp, for example, the statement `COMPIL ABC/X:2` will result in abc.bp being compiled. 

## **Compiled Programs** 

Compiled programs, sometimes referred to as "RUN files" or "executables," even though the latter is somewhat misleading since they need to be processed by a run-time interpreter and are thus not truly executable, must have one of the following file extensions: 

- RUN: standard programs, to be executed with the RUN command. 

- SBX: external, dynamically loadable subroutines; see Calling External Routines. 

- LIT: commands, to be executed without the RUN command. 

See Edit, Compile, Run for more details on the three forms of compiled programs. 

## **Program Structure** 

A-Shell Reference 

Page 904 

The structure of an ASB program is rather loose, consisting of one or more lines satisfying the following syntax: 

## **{line #}{label:}{statement(s)} {! comment}** 

Throughout this document, squiggly brackets {  } indicate optional elements, so each of the four parts of the typical program line above is optional. 

Line numbers served two purposes in early versions of BASIC: as a target for GOTO or GOSUB / CALL statements, and as a way of identifying locations of runtime errors. Although they remain supported, their use is generally deprecated now in favor of labels, which are themselves typically limited to places where they are needed to identify the target of a GOTO or GOSUB. Some programmers insert labels as a kind of road map (e.g. **BEGIN:** or **MAIN'BODY:** ) but a label without any references to it should probably be replaced by a comment, just to eliminate any doubt as to whether the location could be the target of a GOTO statement. 

Statements are terminated implicitly by the end of the source text line (LF or CRLF), or explicitly by the comment character **!** . To extend a logical statement over multiple source text lines, use the **&** character to indication continuation, e.g. 

```
statement'syntax$ = lineno$      &
```

```
                    + label$     &  ! optional comment may follow "&"
                    + statement$    ! another comment
```

As shown in the example above, comments may follow the & continuation character without interfering with the continuation. However, be careful about ending a comment with the **&** continuation character, since it effectively extends the comment to the next line. For example, in the following, the "print b" statement will become part of the comment at the end of the previous line, due to it ending in **&** ... 

```
print a    ! don't end a comment with &
```

```
print b    ! else following line (this one) will be part of comment
```

A-Shell Reference 

Page 905 

Multiple statements may also be combined on a single source text line by separating them with a colon, e.g. 

```
if SWAP then &
```

```
    V1 = V1+V2 : V2 = V1-V2 : V1 = V1-V2    ! 3 statements on a line
```

Note that while the above form is typical in older code, the style— _if_ without _endif_ , continuation, multiple statements per line— like the archaic verb "LET", is generally deprecated in favor of the more readable: 

```
if SWAP then
```

```
    V1 = V1 + V2
    V2 = V1 - V2
    V1 = V1 - V2
```

```
endif
```

Statements fall into the following categories: 

- Declaration of Variables 

- Control Structures 

- User-Defined Functions and Procedures 

- Assignment Statements 

- File I/O Statements 

- Miscellaneous Statements 

## **See Also** 

A-Shell Reference 

Page 906 

- ASB Program Symbols 

## **Flow of Control** 

ASB program execution starts at the first executable statement in the program as defined by the source code. This is unlike some languages, such as C, which start executing at a specially named routine. The flow proceeds forward, or as directed by explicit control statements, until it hits an explicit END or CHAIN statement or simply comes to the end of the program. 

User defined functions and procedures, however, are ignored except when explicitly called. In other words, the program will never "fall into" a function or procedure merely by virtue of its position. This is not true of GOSUB or error trap routines, which are not automatically protected from being fallen into. 

Note that MAP statements are considered executable, so the program needs to flow through them in order for them to get properly initialized. 

## **See Also** 

- ++INCLUDE 

- ++PRAGMA PRIVATE_BEGIN AND _END 

## **Sample Program I** 

Here is the canonical _Hello World_ program in ASB: 

```
PRINT "Hello World"
```

```
END
```

A-Shell Reference 

Page 907 

The program must exist first as a text file, typically with a BAS or BP extension, created in any text editor such as VUE or APN. Assuming the file is assigned the name hello.bas, it can be compiled from the A-Shell dot prompt as follows: 

```
.COMPIL HELLO.BAS
```

## The compiler responds: 

```
Phase 1 - Parse source and generate object code
```

```
Phase 2 - Adjust object file and process errors
```

```
Memory usage:
```

```
Total work space - 18600 bytes
```

```
Label symbol tree - 16 bytes
Variable symbol tree - 20 bytes
Declaration tree - 16 bytes
Structure symbol tree - 16 bytes
Data statement pool - 0 bytes
Variable indexing area - 0 bytes
Compiler work stack - 16 bytes
Excess available memory - 1911620 bytes
```

```
End of compilation
```

The compiled program will typically have a .RUN extension, can be seen and manipulated with file commands such as DIR, SIZE, COPY, etc. (see LIT Commands), and can be executed with the **RUN** command. For example: 

A-Shell Reference 

Page 908 

```
.DIR HELLO
```

```
HELLO      BAS  1
```

```
HELLO      RUN  1
Total of 2 files in 2 blocks.
```

```
.RUN HELLO
```

```
Hello World
```

```
.
```

## **Sample Program II** 

Here is a slightly larger sample program that provides a better sense of the typical ASB program structure and illustrates a few features of the language, including: 

- PROGRAM assigns a version to the RUN module (visible with `DIR/V` ) 

- ! (exclamanation point) starts a comment up thru the end of the line 

- ? (question mark) is an alias for PRINT, outputting text to the screen or a stream file 

- ; (semi-colon) at end of print statement stifles CRLF output. 

- ++INCLUDE reads in source code from external file, like #include in C 

- MAP statements dfine variables in a fixed layout 

- Dynamic arrays (DIMX) allocate a dynamic array 

A-Shell Reference 

Page 909 

- Dynamic Structure Functions 

- DEFINE statements (symbol definitions) 

- Error trapping (ON ERROR GOTO) 

- IF … ENDIF conditional statements 

- DO / WHILE / UNTIL and FOR … NEXT loops 

```
program factor,1.0(100)  ! factorization example
```

```
!-------------------------------------------------------
```

```
!Edit History
```

```
![100] April 05, 2014 12:51 PM          Edited by jack
```

```
!   created as example
```

```
!-------------------------------------------------------
```

```
on error goto TRAP
```

```
++include ashinc:types.def          ! extended data type defs (e.g. BOOLEAN)
```

```
define TRUE = -1
define FALSE = 0
```

A-Shell Reference 

Page 910 

```
map1 params
```

```
    map2 nf,i,4                     ! the number to factor
    map2 nx,i,4                     ! working value
    map2 i,i,4                      ! loop counter
    map2 count,i,2                  ! # of factors found
```

```
dimx factors(1),i,4, auto_extend    ! array of factors
```

```
    input "Enter number to factor: ",nf
```

```
    nx = nf
```

```
    i = 2                           ! first factor to consider
```

```
    do while i <= nx
```

```
        if fn'is'factor(i,nx) then
```

```
            nx /= i
            count += 1
            factors(count) = i
            ? "found ";i;" target now ";nx
            repeat
```

A-Shell Reference 

Page 911 

```
        endif
```

```
        i += 1
```

```
    loop
```

```
    ? "Factors of ";nf;": ";
```

```
    if count then
```

```
        for i = 1 to count
```

```
            if i > 1 ? ",";
```

```
            ? factors(i);
```

```
        next i
```

```
    elseif nf = 1 then
```

```
        ? 1                         ! only factor of 1 is 1
```

```
    else
```

```
        ? "none found"
```

```
    endif
```

```
    ?
```

```
    end
```

```
TRAP:
```

A-Shell Reference 

Page 912 

```
    ? "Error #";err(0)
    end
```

```
!---------------------------------------------------------
```

```
! return TRUE if candidate is a factor of target
```

```
!---------------------------------------------------------
function fn'is'factor(candidate as i4, target as i4) as BOOLEAN
    if (target mod candidate) = 0 then
        fn'is'factor = TRUE
    endif
endfunction
```

## **Additional Samples** 

The set of files accompanying a normal A-Shell installation includes a collection of sample and test programs in the [90?,*] directories, as well as a reusable function library in [907,10]. See SOSLIB and EXLIB for more information. 

A-Shell Reference 

Page 913 

## **EDIT, COMPILE, RUN** 

Programming largely consists of a repeating iteration of editing, compiling, and running programs (with occasional breaks for snacks). The following overview and tips should help you get started on the A-Shell version of this timeless activity. 

## u **Editors** 

Although you can use any text or program editor you like, most A-Shell programmers use one or more of the following: 

**VUE** is an old-school full-screen plain text editor, vaguely similar to the famous Unix editor vi. Its strong points are that it is: 

- built in to A-Shell, which means it can be launched from the dot prompt or via a subroutine within a program 

- available as a standalone executable in the Unix environment 

- platform independent 

- very fast and responsive if you know the keyboard commands 

**APN** (A-Shell Programmer's Notepad) is a modern Windows program editor / IDE ("Integrated Development Environment"), similar to other IDEs such as Visual Studio. Its strong points are: 

- follows typical Windows conventions so will be instantly familiar to most programmers experienced with other Windows 

- editors 

- multi-file, multi-window 

- understands ASB syntax and A-Shell directory structure so is able to recognize/locate/open ++INCLUDE files 

- integrated compiler: click on errors in the output window to jump directly to the file/line for editing 

- can be extended with scripts written in Python 

- supports workspaces and projects 

- syntax highlighting, call tips, code completion, undo/redo 

A-Shell Reference 

Page 914 

**Visual Studio Code:** Matt Swann, an independent A-Shell developer, created an open source VS code extension for A-Shell. As of June 2024, it is a work in progress, and is not yet as capable as APN. But for those developers already familiar and comfortable with Visual Studio, this may be the preferred option—or one at least worth exploring. For details and more information, see Matt's posting on the A-Shell Forum. 

## u **Compilers** 

The ASB compiler processes your source code (typically with a .BAS or .BP extension), creating a run module (typically with a RUN, LIT, or SBX extension, depending on the intended use). There is really only one compiler, but it is packaged in a number of forms to match your working style: 

From the A-Shell dot prompt: 

- COMPIL.LIT, e.g. . `COMPIL MYPROG/M/I/X:2` 

- COMPLP.LIT - variation (supporting BASIC _plus_ ) that assumes .BP file extension, /X:1 

- OCMPIL.LIT - variation (supporting the original BASIC 1.3) that assumes /13 

From within a program (if you want to create your own compilation wrapper), you can invoke the compiler using: 

```
XCALL MIAMEX, MX_COMPIL, filename, switches, ...
```

From the Windows shell prompt: 

```
>COMPIL.EXE <switches> <program>
```

(The compil.exe package is also used by APN for integrated ASB compilation.) 

From the Unix shell prompt: 

- `$ compil <switches> <program>` 

A-Shell Reference 

Page 915 

## u **Execution** 

There are three forms of compiled programs, identified by the file extension. All have essentially the same internal format but are executed in different ways: 

- RUN modules (e.g. PROG.RUN) are executed using the RUN command from a dot prompt or from within a CMD or DO file, 

- e.g. `RUN PROG` . 

- SBX modules (e.g. PROG.SBX) act as subroutines and are called from within another program using the XCALL statement—for 

- example, `Xcall PROG` . See Subroutines vs. Programs for details on differences between SBX and RUN modules. • LIT modules (e.g. PROG.LIT) act as system commands and are executed from the dot prompt, or from within a CMD or DO file, by specifying just the module name, e.g., `PROG` . 

All three have the same fundamental structure; the file extension determines the usage and behavior. You can use COPY or RENAME to convert from one type to another, or use the FORCE_FSPEC ++pragma within the source code to instruct the compiler how to name the compile program directly. 

A running program can also launch another LIT or RUN program, either as a subroutine using Xcall ASHELL or by chaining to it using the CHAIN statement. 

## u **Examples** 

RUN modules from the dot prompt or a CMD or DO file: 

```
.RUN MYPROG
```

- `.RUN APP:MYPROG/ARG1/ARG2=5` 

- `.RUN DSK2:MYPROG.RUN[100,2]` 

A-Shell Reference 

Page 916 

LIT modules from the dot prompt or a CMD or DO file (see Command Search Path) : 

```
.LOG SYS:                      ; LOG.LIT
.DIR/W                         ; DIR.LIT
.TEST.LIT                      ; TEST.LIT
```

## From within a program: 

```
XCALL FOOBAR,1,2               ! call FOOBAR.SBX; search [p,pn], [p,0], DSK0:[7,6]
CHAIN "INVOIC"                 ! link to INVOIC.RUN; search [p,pn], [p,0], DSK0:[7,6]
XCALL ASHELL,"RUN TEST"          ! execute TEST.RUN as subroutine
```

A-Shell Reference 

Page 917 

## **ASB KEYWORDS** 

Notes: 

1. The "Switches" column shows the compiler switch(es) required to enable this feature. 

2. When more than one switch is listed, "or" is implied—i.e., just one of the switches is required. 

3. Some keywords ("Note 3" references below) behave differently depending on the compiler switch specified; see topic link for details. 

- 

- 4. Although not listed here, both System Defined Functions and Dot Variables are also effectively keywords in that they cannot be used as custom variable names. 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|ALLOCATE||File I/O Statement|Allocate a random file.|
|AMOS|X:1|Control Statement|Execute AMOS commands as subroutines.|
|AND||Operator|Logical AND.|
|AUTO_EXTERN|X:2||Enables or disables the visibility of variables defined globally.|
|.BINDSTRUCT|X:2|Dyn Struct<br>Statement|Binds the specified DYNSTRUCT variable to the structure definition.|
|BYTE|||BYTE(x) reads memory-mapped ports.|



A-Shell Reference 

Page 918 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|CALL||Control Statement|Unstructured subroutine call.|
|CASE|X:1, RC|Control Struc Stmt|Label option withinSWITCH<br>.|
|CHAIN|||Provides the ability to pass command line arguments.|
|.CLEAR|X:2|Array Statement|Removes all the elements of the array without destroying the array itself.|
|CLOSE||File I/O Statement|Close file.|
|CMDLIN|X:1||Retrieve command line.|
|DATA||General Statement|List of data elements with program.|
|DATE||System Variable|Returns system date.|
|DEBUG|X:2|||
|DEFALIAS||Compiler Directive|Allows aliases to be defined for the names of functions and procedures.|
|DEFAULT|X:1, RC||Default label option withinSWITCH<br>.|



A-Shell Reference 

Page 919 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|DEFINE|X:1, RC|Compiler Directive|Define a symbolic constant.|
|DEFSTRUCT|X:2|Compiler Directive|Define a structure.|
|DEFTYPE|X:2|Compiler Directive|Defines an alias for a data type.|
|DIM|||Deprecated; useDIMX<br>instead. Dimension an array at runtime.|
|DIMX|X:2||Enhanced dynamic array allocation.|
|DIVIDE’BY’0|X:1||Treat division by zero as zero rather than error.|
|DO|X:1, RC|Ctrl Struct Statement|Repeat loop while (or until) a condition is (or becomes) true.|
|DPRINT|X:2||Like PRINT but creates a static text control.|
|ECHO|X:1||Set terminal echo mode; same asXcall ECHO<br>.|
|++ELIF|||Conditionals based on evaluating a constant expression.|
|ELSE||Ctrl Struct Statement|Final alternative clause within an IF statement.|



A-Shell Reference 

Page 920 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|ELSEIF|X:2, RC|Ctrl Struct Statement|Intermediate alternative clauses an IF statement.|
|END||Control Statement|Terminate execution of program.|
|ENDFUNCTION|X:2||Marks end of a function.|
|ENDIF||Ctrl Struct Statement|Terminates IF...ENDIF blocks.|
|ENDPROCEDURE|X:2||Marks end of a procedure.|
|ENDSTRUCT|X:2||End of a DEFSTRUCT ... ENDSTRUCT block.|
|ENDSWITCH|X:1, RC||End of SWITCH statement.|
|EQV||Operator|Logical equivalence.|
|++ERROR|X:2||Force error within compilation.|
|$EXIT|X:2||Special exit label within function / procedure.|
|EXIT|X:1|Control Statement|Exit from inner-most loop or block (DO, FOR, SWITCH).|



A-Shell Reference 

Page 921 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|EXITFUNCTION|X:2|Control Statement|Exit the current function.|
|EXITPROCEDURE|X:2|Control Statement|Exit the current procedure.|
|EXITPROGRAM|X:2|Control Statement|Exit the current function or procedure to label $EXITPROGRAM|
|++EXTERN|X:2||Exposes individual global variables.|
|FILEBASE||File I/O Statement|Set numeric offset for first file record.|
|FOR|Note 3|Ctrl Struct Statement||
|FOREACH|X:2|Ctrl Struct Statement|Used to iterate throughOrdered Maps<br>.|
|.FSTAT|X:2||Returns file status for the last ISAM-A operation on the specified channel.|
|FUNCTION|X:2||Begin definition of function.|
|GOSUB||Control Statement|Same as CALL.|
|GOTO||Control Statement|Jump to specified line number, label or variable.|



A-Shell Reference 

Page 922 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|GRIDMAP|X:2|GRIDMAP|A variation of ordered map with two keys and one value.|
|IF|Note 3|Ctrl Struct Statement|Traditional form ofIF<br>statement, and block-structured form ofIF … ENDIF<br>.|
|++IF||Ctrl Struct Statement||
|++INCLUDE|Note 3||Include specified file at compile time.|
|INPUT||File I/O Statement|Input field(s) from keyboard or file.|
|INDEXED||File I/O Statement|FileOPEN for ISAM<br>or forISAM-A<br>mode.|
|INDEXED'EXCLUSIVE||File I/O Statement|FileOPEN for ISAM<br>or forISAM-A<br>mode.|
|IO|||IO(X) pseudo reads from memory-mapped I/O port.|
|ISAM'INDEXED||File I/O Statement|FileOPEN for ISAM<br>mode.|
|ISAM'INDEXED'EXCLUSIVE||File I/O Statement|FileOPEN for ISAM<br>mode.|
|ISAMP'INDEXED||File I/O Statement|FileOPEN for ISAM-A<br>mode.|



A-Shell Reference 

Page 923 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|ISAMP'INDEXED'EXCLUSIV<br>E||File I/O Statement|FileOPEN for ISAM-A<br>mode.|
|.KEY|X:2||May be appended to an ordered map iterator, i.e. $$iKEY, to reference the<br>key associated with that interator. $$i.KEY is equivalent to .KEY($$i).|
|KILL||File I/O Statement|Delete a file.|
|LET|||Assignment statement.|
|LOCK||||
|LOOKUP|||Return size of file in blocks.|
|LOOP|X:1, RC|||
|MAP|||Variable declaration.|
|MAX||Operator|Maximum of two operands.|
|++MESSAGE|X:2||Output message during compilation. Also see++ERROR<br>.|



A-Shell Reference 

Page 924 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|MIN||Operator|Minimum of two operands.|
|MLIST|X:2|Multi-level List|A bidirectional linked list.|
|MOD||Operator|Modulo.|
|NO’DIVIDE’BY’0|X:1||Force divide by zero to generate error 10 (default).|
|NOECHO|X:1||Set terminal noecho mode. Same asXcall NOECHO<br>.|
|NOT||Operator|Logical NOT.|
|ON - GOSUB|||Call one of list of subroutines, based on value.|
|ON - GOTO|||Goto one of list of labels, based on value.|
|ON ERROR GOTO||Control Statement|Specify error handling routine.|
|OPEN||File I/O Statement|Open file.|
|OPEN for APPEND|X:1||Enhancement to OPEN #CH, FSPEC, APPEND.|



A-Shell Reference 

Page 925 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|OR||Operator|Logical OR.|
|ORDMAP|X:2||An associative array that maps keys to values|
|ORDMAPM|X:2||Same as ORDMAP but supports multiple keys of the same value.|
|POP|||Deprecated. Pops the current GOSUB return address from the stack.|
|.POPBACK|X:2|Multi-level List|Remove last element from an MLIST.|
|.POPFRONT|X:2|Multi-level List|Removes first element from an MLIST.|
|++PRAGMAs|X:1||Compiler Directives<br>.|
|PRINT||File I/O Statement|Output variables and expressions to screen or file.|
|PROCEDURE|X:2||Start definition of a procedure.|
|PROGRAM|||Program header declaration.|
|RANDOMIZE||Numeric Function|InitializeRandom Number Generator<br>with a randomly selected seed.|



A-Shell Reference 

Page 926 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|READ||File I/O Statement<br>Misc Statement|Read record from file or from embeddedDATA<br> statement.|
|READL||File I/O Statement|Read record and lock. See file access statements|
|READ'ONLY||File I/O Statement|FileOPEN<br> mode modifier.|
|READ'READ'ONLY|X:2|File I/O Statement|Read record, explicitly without locking.|
|REDIMX|X:2|Array Statement|Re-dimensions an array originally created withDynamic Arrays (DIMX)<br>.|
|REPEAT|X:1, RC|Control Statement|Jump to top of loop structure to begin next iteration.|
|RESTORE||General Statement|Reset DATA access pointer to beginning.|
|RESUME||Control Statement|Resume execution after trapping an error.|
|RESUME WITH ERROR|X:2|Control Modifier|Modifier for RESUME within an error trap in a function|
|RETURN|Note 3|Control Statement|Return from unstructured subroutine. Also return value fromXFUNC()<br>.|
|SCALE|||Declare scaled arithmetic.|



A-Shell Reference 

Page 927 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|SET'RECNO|X:2|File I/O Statement|Sets the record number of a file.|
|SIGNIFICANCE||General Statement|Set output/format significance of floating point values.|
|SLEEP|X:1|General Statement|Sleep for specified seconds. Same as Xcall SLEEP.|
|.SORT|X:2|Multi-level List|Sort elements in MLIST by value.|
|SPAN||File I/O Statement|FileOPEN<br> mode modifier.|
|.SPLICE|X:2|Multi-level List|Splice elements from one MLIST to another.|
|STEP|||Set loop counter increment.|
|STOP||Misc Statement|Program stop, wait for CR to continue.|
|STRSIZ||Compiler Directive|Sets the default length of string variables.|
|.SUBLIST|X:2|Multi-level List|Specify sublist of element.|
|SWITCH|X:1, RC|Ctrl Struct Statement|Conditional execution based on value of an expression.|



A-Shell Reference 

Page 928 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|TAB|||Convert high-level display commands into ESCAPE sequences for terminal.|
|THEN||Ctrl Struct Statement|Separates IF condition from statement.|
|TIME|X:2|System Function|Returns system time in number of seconds since midnight.|
|TO||Ctrl Struct Statement||
|TPRINT|X:2||See Expressions<br>.|
|TRACE|X:2|||
|UNDEF||Compiler Directive|Cancels (UNDEFines) a symbol created by a prior DEF... directive.|
|UNLOKR|X:2|File I/O Statement|Release lock on file or record.|
|UNTIL|X:1, RC|Ctrl Struct Statement|Repeat loop while (or until) a condition is (or becomes) true.|
|USING||Operator|Formatting by template.|
|VXCALL|X:2||Same as XCALL but uses a string expression for the subroutine name.|



A-Shell Reference 

Page 929 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|WEND|/D||Same as ENDIF.|
|WAIT'FILE||File I/O Statement|FileOPEN<br> mode modifier.|
|WAIT'RECORD||File I/O Statement|FileOPEN<br> mode modifier.|
|WHEN|/D||Same as IF.|
|WHILE|X:1, RC|Ctrl Struct Statement|Repeat loop while (or until) a condition is (or becomes) true.|
|WITH_ERROR|X:2|Modifier|Modifier forRESUME<br>within an error trap in a function.|
|WORD|||WORD(X) reads memory-mapped ports.|
|WRITE||File I/O Statement|Write to random file.|
|WRITECD|X:2|File I/O Statement|Output comma delimited values.|
|WRITEL|X:1|File I/O Statement|Write record not previously locked.|
|WRITELN|X:1|File I/O Statement|Same as WRITEL but leave record locked.|



A-Shell Reference 

Page 930 

|**Keyword**|**Switches**|**Category**|**Description**|
|---|---|---|---|
|WRITEN|X:1|File I/O Statement|Same as WRITE but leave record locked.|
|WRITETD|X:2||Deprecated; seeWRITECD<br>.|
|XCALL|||Call subroutine.|
|XGETARG(S)|X:2|General Statement|Retrieve subroutine parameters.|
|XOPEN|X:2|File I/O Statement|Variation on OPEN statement fo ISAM-A.|
|XOR||Operator|Logical XOR; exclusive OR.|
|XPUTARG|X:2|General Statement|Return subroutine parameters.|
|XREAD, XWRITE, XUNLOKR|X:2|File I/O Statement|Allow record access via explicit record numbers.|



A-Shell Reference 

Page 931 

## **ASB PROGRAM SYMBOLS** 

The following table provides a reference to the significance, meaning and usage of all ASCII characters within the ASB language. 

|**Symbol**|**Name**|**Description**|
|---|---|---|
|'|apostrophe|May appear in variable or defined symbol names (after first character).|
|-|minus sign|Subtraction operator, or unary negative operator.|
|!|exclamation point|Start of comment; anything to right is ignored by compiler.|
|"|quote|Used to enclose literal strings. Two quotes in succession ( "" ) translates to a single literal<br>quote.|
|#|number sign, aka<br>hash or octothorp|Not equals comparison operator, equivalent to <>. Also used inExplicit Plus Operators<br>and<br>Explicit Comparison Operators<br>.|
|$|dollar sign|As a suffix on a variable or function name, indicates string type. Also used inExplicit Plus<br>Operators<br> andExplicit Comparison Operators<br>.|
|%|percent sign|Not used.|
|&|ampersand|Line continuation (if last character on line, not counting comments to the right). Also used<br>to indicate "and" inShortcut Operators<br>.|



A-Shell Reference 

Page 932 

|()|open and closed<br>parentheses|Used to override operator precedence in expressions, to enclose function and procedure<br>argument lists, with array variables to specify the subscripts, and with ordered maps to<br>specify the map key. An empty pair of parentheses on the end of an array or ordered map<br>refers to the array or map as a whole.|
|---|---|---|
|*|asterisk|Multiplication operator.|
|,|comma|Used to separate parameters (XCALLs, function calls) or expressions within a PRINT<br>statement.|
|.|period|Used as a prefix for some keywords to distinguish them from ordinary variables. Also used<br>to join structure and member names (e.g. cust.name). SeeDot Functions<br>,Dot Variables<br>,<br>MLIST Dot tokens<br>,Special ORDMAP Functions<br>.|
|/|forward slash|Division operator.|
|:|colon|Separates multiple statements on one source line. Also required as last character of a<br>label.|
|;|semi-colon|Used at the end of a PRINT statement to suppress the output of CR or CRLF line terminator|
|@|at sign|Used in overlay declarations. SeeMAP Statements<br>, Dynamic Overlays<br>.|
|[]|square brackets|Substring Operator<br>.|



A-Shell Reference 

Page 933 

|\|backslash|Not used.|
|---|---|---|
|^|caret|Exponentiation operator.|
|_|underscore|May appear in variable or defined symbol names (after first character).|
|`|grave accent|Not used.|
|{}|squiggly brackets|Not used.|
|||vertical bar or pipe|Used to indicate "or"Shortcut Operators<br>.|
|~|tilde|Not used|
|+|plus sign|Numeric addition or string concatenation; seeOverloaded Plus Operator<br>,Explicit Plus<br>Operators<br>.|
|<>|angle brackets|Used individually as greater-than or less-than operators, or together as the not-equal<br>comparison operator.|
|=|equal sign|Assignment or comparison operator. Also seeShortcut Operators<br>.|
|LF|line feed|Implicit termination of a statement, usually as the second character in the CRLF pair.|



A-Shell Reference 

Page 934 

|0-9|numeric digits|May appear in numeric literals or variable or defined symbol names (after first character)|
|---|---|---|
|A-Z,<br>a-z|alphabetic<br>characters|May appear in variable or defined symbol names (case sensitive unless compiled with /CI<br>switch); or in keywords.|
|ASCII<br>1-31|control characters|Used only in literal strings. Note that CR, LF may require encoding using the chr(#)<br>function to avoid syntax issues with compiler.|
|ASCII<br>128-255|upper range, (high<br>bit set); accented<br>characters, etc.|Used only in literal strings.|



A-Shell Reference 

Page 935 

## **VARIABLES** 

## _Written January 2023_ 

ASB variable names start with an alphabetic character, with the exception of system dot variables, followed by zero or more alphanumeric characters plus underlines and apostrophes, up to a maximum of 260 characters. Unlike language keywords, variable names are case sensitive, unless the /CI compiler switch is used. Typically they are declared explicitly—via MAP or DIMX statements—but optionally may be implicitly or auto-created by the compiler. The fundamental data types—integer, floating point, string and raw—are supported in various sizes, including dynamic, and may be packaged as individual scalars, compound structures, arrays (fixed or dynamically dimensioned), or collections (ordered maps and lists). 

See the following subtopics for more details. 

## **Subtopics** 

- MAP Statements 

- DIMX 

- Data Types 

- Dynamically Sized Variables 

- Arrays 

- Collections 

- Implicit Variable Declarations 

- System Variables 

A-Shell Reference 

Page 936 

## **MAP STATEMENTS** 

_Rewritten July 2025_ 

Declaration Only: 

## **{scope} MAP# varname {,vartype {,varsize}} {,@origin}** 

## **{scope} MAP# varname {,usertype} {,@origin}** 

Declaration and Initial Assignment: 

## **{scope} MAP# varname {,vartype {,varsize}} {,initialvalue}** 

## **{scope} MAP# varname {,usertype} {,initialvalue}** 

MAP statements explicitly define (declare and initialize) variables in terms of size and data type as well as position in memory relative to other variables. The latter capability is particularly useful for defining compound structures such as file records so as to match precisely with a physical byte layout on an external medium. All variables are implicitly initialized to zero or null, although you can optionally specify a different initial value. 

## **Attributes** 

## _scope_ 

Optional indicator of the variable's scope, both in space and in time. If omitted, the scope is determined by the context: global/static if outside of a function or procedure, local/automatic if inside. See Variable Scope for details. 

## _MAP#_ 

# is a single digit 1 though 9 (i.e. MAP1 thru MAP9) indicating the relative level of the variable within a hierarchy. MAP1 is the top, MAP9 the bottom. Ordinary independent variables that are not part of compound structures are normally declared with MAP1, although may be grouped under a heading just for aesthetic purposes, e.g. 

```
MAP1 TEMP'WORK'VARS
```

```
    MAP2 COUNTER,B,2
```

A-Shell Reference 

Page 937 

```
    MAP2 AMOUNT,F,6
    MAP2 SUBTOT,F,6
    MAP2 LOOPVAR,I,2
    MAP2 TITLE$,S,30
```

The first variable declared must be at the top level (MAP1), and any lower level variables (MAP2 thru MAP9) must have a higherlevel parent which does not have an explicit type. In the example above, `TEMP'WORK'VARS` has no explicit type or size, making it effectively X,46 based on the total size of the lower level variables beneath it. 

MAP1 (level 1, i.e. top-level) variables are positioned on even byte boundaries, subject to override by the ALIGN# PRAGMAs. Lower-level MAP statements  are aligned on byte boundaries (no inter-variable spacing), and may be addressed individually or as a group via the higher level variable(s). 

A single MAP1 group can only consist of lower-level MAP statements; any other kind of statement effectively terminates the group, requiring that the next MAP statement, if any, be at MAP1 level. See _initialvalue_ below. 

Note that as with all other parts of ASB source code, blank spaces and indentation have no significance. While it is customary to indent at the MAP# level increase, for aesthetic and readability purposes, it is only the level numbers themselves that matter to the arrangement. 

## _varname_ 

Variable names must start with a letter, followed by zero or more alphanumeric characters plus underlines and apostrophes, up to a maximum of 260 characters. Unlike language keywords, variable names are case sensitive, unless the /CI compiler switch is used. An optional $ suffix may be appended, typically used to denote string variables. Note that while the $ suffix forces an implicitly defined variable to be a string, it has no effect on the type of an explicitly mapped variable, whose type is defined by the explicit or implicit _vartype_ attribute. 

## _vartype_ 

A single character indicating one of the built-in Scalar Types (F,B,I,S,X). Must be blank if the MAP statement is followed by another MAP statement at a lower level as in the `MAP1 TEMP'WORK'VARS` example above. 

A-Shell Reference 

Page 938 

## _varsize_ 

Literal numeric size of the variable in bytes. Must be one of the valid sizes in the Scalar Types table. Note that dynamic length variables (X,0 or S,0), while not illegal at levels MAP2 and below, should never be included within a compound structure intended to be referenced as a whole, like a record structure. See Dynamically Sized Variables for more details. 

## _usertype_ 

## A user-defined type which encompasses both a type and a size. A simple example: 

```
deftype BOOLEAN = I,2
```

```
    ...
```

```
map1 Taxable, BOOLEAN   ! same as map1 Taxable, I, 2
```

## A more complex example: 

```
defstruct ST_CUST
```

```
    map2 CusNum,b,4
    map2 CusName,s,30
    map2 Taxable,BOOLEAN
```

```
endstruct
```

```
map1 CUS, ST_CUST
```

## See DEFTYPE and DEFSTRUCT for more details. 

## _@origin_ 

A-Shell Reference 

Page 939 

This optional attribute allows you to alter the alignment of variables in memory. Instead of following the prior variable—see note about alignment under _MAP#_ above—in memory, you can specify that it starts at the same position as a previously declared variable—i.e. overlays it; the mechanism is effectively equivalent to the union construct in the C language. For example: 

```
map1 CONTACT                      ! Byte position
```

```
    map2 NAME,S,30                ! 1
    map2 WORLD'PHONE, @US'PHONE   ! 31
        map3 COUNTRY'CODE,S,2     ! 31
        map3 W'NUMBER,B,14        ! 33
    map2 US'PHONE                 ! 31
        map3 ONEPLUS,S,1          ! 31
        map3 AREA,S,3             ! 32
        map3 US'NUMBER,S,6        ! 35
    map2 POSTCODE,S,7             ! 47
```

In the above structure the variable WORLD'PHONE and its two encapsulated children are overlaid by the variable US'PHONE and its three children. Not only do WORLD'PHONE and US'PHONE have different layouts, they are different in overall size (16 vs 10 bytes). The next implicitly positioned variable (POSTCODE) follows the larger of the two preceding structures, i.e. it directly follows W'NUMBER (which occupies thru position 46), not US'NUMBER (which occupies thru position 40). 

## _initialvalue_ 

An optional initial value to assign the variable other than the default 0 or null. Note that adding an initialvalue attribute is similar in concept to inserting an assignment statement immediately following the declaration. For example: 

```
MAP1 TAX'RATE,F,6, 39.
```

A-Shell Reference 

Page 940 

is conceptually the same as... 

```
MAP1 TAX'RATE,F,6
```

```
TAX'RATE = 39.7
```

... except that assignment statements like the above are not allowed within a group of MAP statements below level 1. 

Note that unlike Declaration Only MAP statements, which are really just declarations for the compiler, as opposed to statements to be executed at runtime, _initialvalue_ will only take effect if the statement is executed at runtime. For example: 

```
GOTO START
```

```
    ...
```

```
    MAP1 WHO,S,10,"Amigo"
```

```
    ...
```

```
START:
```

```
    PRINT "Hola "; WHO; "!"
```

The above code snippet will display only "Hola!" instead of "Hola Amigo!", because the `GOTO START` jumped over the embedded assignment of the initial value to the variable WHO, which needs to happen at runtime. However, the compiler did see the variable declaration and knows that WHO is a string. Otherwise you would either get an unmapped variable compile error, or WHO would be treated implicitly as a floating point variable and display as "0". 

```
MAP1 CALORIES'CONSUMED,B,3
```

```
MAP1 CALORIES'BURNED,B,3
```

A-Shell Reference 

Page 941 

The above example defines two top-level 3-byte binary variables which are logically independent but in fact will be adjacent in memory (subject to alignment fill characters). 

```
MAP1 TIME'REC
```

```
    MAP2 ID,S,4
    MAP2 WORKDAYS(7)
        MAP3 DTX
            MAP4 MON,B,1
            MAP4 DAY,B,1
            MAP4 YR,B,1
        MAP3 INOUTS(2)
            MAP4 IN,B,3
            MAP4 OUT,B,3
    MAP2 RATE,F,6
```

```
MAP1 TIME'REC$,S,115,@TIME'REC
```

The second example above illustrates a more complex MAP structure which includes multi-level arrays and an overlay. The actual layout in memory and the syntax for accessing the individual variables is as follows: 

|**Memor**<br>**y**<br>**Offset**<br>**s**|**Variable**|**Aliases**||**Memory**<br>**Offsets**|**Variabl**<br>**e**|**Aliases**|
|---|---|---|---|---|---|---|
|0|ID|TIME'REC, TIME'REC$||12|||



A-Shell Reference 

Page 942 

|**Memor**<br>**y**<br>**Offset**<br>**s**|**Variable**|**Aliases**||**Memory**<br>**Offsets**|**Variabl**<br>**e**|**Aliases**|
|---|---|---|---|---|---|---|
|1||||13|||
|2||||14|IN(1,2)|INOUTS(1,2)|
|3||||15|||
|4||||16|||
|5|MON(1)|WORKDAYS(1), DTX(1)||17|OUT(1,2<br>)||
|6|DAY(1)|||18|||
|7|YR(1)|||19|||
|8|IN(1,1)|INOUTS(1,1)||20|MON(2)|WORKDAYS(2), DTX(2)|
|9||||21..34|...||
|10||||35|MON(3)|WORKDAYS(3), DTX(3)|
|11|OUT(1,1)|||36..109|...||



Note the way the array addressing syntax percolates down through the levels. For example, the variable OUT appears in the map as a scalar, but it is a child of the array INOUTS(2), which is itself a child of the array WORKDAYS(7), which makes OUT an array with two subscripts, as if it were mapped as OUT(7,2), except that the individual elements, are not contiguous with each other. (Only the elements corresponding to the top level first subscript are contiguous.) 

The example also illustrates overlaying an entire map structure, TIME'REC, with another variable, TIME'REC$, can be a different type and size. The variable TIME'REC, like all top-level compound variables, is itself an unformatted (data type X) variable whose length is determined by the sum of all its lower-level dependent variables (115 bytes in this case). So the entire structure can be accessed via the single unformatted variable TIME'REC (useful for manipulating the structure as a whole, such as performing record-level file operations). By means of the @ overlay mechanism, we can define additional variables that occupy the same 

A-Shell Reference 

Page 943 

space and thus provide alternate views (or aliases) of the same data. In this case, the variable TIME'REC$,S,115 is overlaid on top of TIME'REC. (TIME'REC and TIME'REC$ are different variables, although in this case they happen to occupy the same space.) Overlaying a string on an unformatted/structured variable can be useful for some advanced techniques. You might also use the same technique in cases where a file contains multiple record layouts, or where you want to manipulate the data at a higher or lower level. For example, we could also overlay TIME'REC with an array of 1 byte elements to simplify operating on it at the byte level. 

Note that when overlaying, the variables do not have to be the same overall size. The next position in memory (i.e. the location for the next MAP1 variable) will be determined by the larger of the variables overlaid on each other. 

## **See Also** 

- DEFSTRUCT 

- DEFTYPE 

- 2015 August, A Shell 6.1.1416, compiler edit 748:  MAP2+ statements are now flagged as illegal if not preceded by a finalized MAP1 statement. Unfortunately, ASB does not make it clear when a MAP1 statement is finalized, other than by the next MAP1 statement. But it is never quite clear if there will be another MAP statement since they are technically legal anywhere in a program. In retrospect, the language could have used an "ENDMAP" statement, although you could effectively create your own just by defining a dummy MAP1 statement at the end of your last multi-level MAP structure. 

The ambiguity did not really have much significance in earlier versions of ASB, except perhaps in certain kinds of nested overlays, where one variable was overlaying another whose position was still in flux because it was part of a higher level array whose element members had not been finalized. But it became more of a problem with the introduction of the language features such as DEFSTRUCT, SIZEOF(), .OFFSIZ(), etc. 

As of now, the rule is that any reference to a previous variable, except in a MAP statement initializer—and when the referenced variable has been finalized, causes the current MAP1 level to be finalized. If you attempt to follow that with a MAP2 or higher, it will be triggered as an illegal MAP level. 

A-Shell Reference 

Page 944 

This may cause compile errors in programs that previously compiled, but it will prevent the kind of problem fixed in compiler edit 747 from escalating into a runtime problem. If you are not sure whether you have used the technique described, recompilation with this version or higher is highly recommended. 

## **Subtopics** 

- Variable Scope 

A-Shell Reference 

Page 945 

## **VARIABLE SCOPE** 

_Updated September 2024_ 

ASB supports a series of extensions related to variable declarations, providing programmers more control over the scope and persistence of variables. This topic presents an overview of the general subject, followed by a detailed look at the related keywords. 

**Scope,** the context within which a vairable can be referenced: 

**Global:** Potentially visible from everywhere in the program. (Global/External Variables are not visible within functions and procedures unless ++PRAGMA AUTO_EXTERN is declared within the routine.) This is the default for MAP variables except when declared inside a function or proc. 

**Local:** Visible only within the function or procedure in which the variable was declared. This is the default for variables mapped within a function or procedure. 

**Module:** Visible only within the current source file, whether the main or a ++INCLUDE module, including any functions or procedures contained therein. Invisible to any other source files, including a parent (that included this module) and any children (included by this module). Declaration requires the PRIVATE keyword or ++PRAGMA PRIVATE_BEGIN and must appear outside of any functions or procedures. 

**Persistence,** the duration of a variable's validity: 

**Static:** Variable persists for duration of program. This is the default except for variables mapped within functions/procedures. Prefixing such MAP statements with STATIC will give them static duration. Unlike automatic variables (see below), there is only one copy of each static variable in memory, even in the case of recursion. 

**Automatic:** Variable is automatically created and destroyed at runtime for each instance of a function or procedure. This is the default for variables mapped inside of a function or procedure. These are also called "stack" variables, because they are allocated on the stack. When the function or procedure returns, they get popped off the stack. Note that in the case of recursion, you can have multiple instances of a stack variable, one for each nesting level of the function call. Like all variables, they are always preinitialized to zero or null unless the MAP statement contains an explicit initialization value. 

Use of the keywords STATIC, PRIVATE, and PUBLIC in conjunction with MAP and DIMX statements to control the scope and persistence of variables: 

A-Shell Reference 

Page 946 

MAP **...** Defines a global, static variable, unless it occurs within a function or procedure, in which case it defines a local automatic variable. Local variables, whether static or automatic, are invisible outside that routine. Note that if a MAP statement contains an explicit initialization value, then it has the effect of an assignment statement that gets executed at runtime. Thus, if MAP statement is in the flow of control in such a way that it can be executed multiple times, the definition of the variable only occurs once by the compiler but the optional initialization would occur each time the MAP statement was executed. 

**STATIC MAPn...** Used only within functions and procedures to give the variable static persistence; the scope remains local. Note that if the MAP statement contains an initial value, it will only be assigned once. **Warning:** initialization of a static variable changes the actual RUN module in memory, which could create a logic problem if the module is inadvertently called (via indirect recursion) while it is still in use. For example, if ONE.SBX contains a static initialized variable, and ONE.SBX calls TWO.SBX, which in turn calls ONE.SBX again, that variable would not be re-initialized. Whether or not that is a problem may depend on whether TWO.SBX realizes that the call is recursive. 

**PRIVATE MAPn...** Used only within a ++INCLUDE file, and outside of any function or procedure to define a variable with module scope and static persistence. This technique is useful to allow a group of related functions and procedures to share some common variables without having to expose them to the rest of the program. Note that like all MAP statements, they must be executed in order to achieve anything but null initialization. See ++PRAGMA PRIVATE_BEGIN for details on a technique to ensure proper initialization, and Global/External Variables for additional context regarding the visibility of variables within functions and procedures. 

**DIMX...** Defines an array to be dynamically allocated at runtime. Note that the compiler defines the variable when the DIMX statement is encountered, as it would for a MAP statement, but the variable cannot be referenced at runtime until the DIMX statement is executed. The actual memory for the variable is allocated outside the user partition, and gets cleaned up when the program (or SBX) ends. If DIMX occurs within a function or procedure, by default the variable would be have local scope and persist only for the duration of the procedure or function. The memory allocation is freed automatically when the routine returns. You can add one of the keyword modifiers (STATIC, PRIVATE, PUBLIC) to change the scope and persistence. Note that DIMX is an extended implementation of the original DIM statement, which is deprecated and not officially supported within functions. 

**STATIC DIMX...** STATIC DIMX is to DIMX as STATIC MAPN is to MAPn. Used only within functions or procedures to cause the DIMX allocation to persist across calls to the routine, while retaining local scope. To achieve both persistence and module scope, use PRIVATE DIMX instead. As a practical matter, to avoid executing the STATIC DIMX statement multiple times if the function is 

A-Shell Reference 

Page 947 

called multiple times, you will probably have to associate it with another local STATIC MAP flag variable that you set when the DIMX is executed. 

**PRIVATE DIMX...** PRIVATE DIMX is to DIMX as PRIVATE MAPN is to MAPN—i.e. declares the array to have module scope and static persistence, except that a PRIVATE DIMX statement may occur anywhere in the module, including within a function or procedure. Because DIMX statements must be executed to initialize them before they are referenced (unlike MAP statements, there is no default null initialization for DIMX), module-scope DIMX arrays are typically initialized inside a function or procedure. Making sure such initialization occurs once and only once, before any use of the array, requires additional control logic, the failure of which can be a common source of runtime bugs. The ++PRAGMA PRIVATE_BEGIN feature provides an elegant solution for the initialization problem. 

**PUBLIC DIMX...** This is a special form of DIMX that can occur only inside a function or procedure. Unlike PRIVATE DIMX, it doesn't have to be within a ++INCLUDE file. It overrides the normal default of local scope and stack persistence for variables defined within a function of procedure, instead making the variable visible anywhere in the entire program. This is handy in a situation where you want to use a function or procedure to create a dynamic memory structure, perhaps by loading the data from or across the internet, that is then available in the main program. 

A-Shell Reference 

Page 948 

## **DIMX** 

_Written June 2025_ 

## **{qualifier} DIMX arrayname, definition** 

DIMX statements are used to create arrays and collections. They are similar to MAP statements in that they declare variables and thus need to be seen by the compiler before the corresponding variables can be referenced. But unlike MAP statements— except those containing initial values—DIMX statements also need to be initialized (or allocated) via run time execution before they can be used. Unlike variables created by MAP statements, those created by DIMX can be re-dimensioned and de-allocated (by REDIMX statements). The  following list provides links to the specific variations of DIMX statements according to variable type, along with some related statements and functions. 

- Dynamic Arrays 

- Ordered Maps 

- Multi-Level Lists 

- Gridmaps 

- REDIMX (redimension or deallocate) 

- .EXTENT() (test size and whether allocated) 

A-Shell Reference 

Page 949 

## **DATA TYPES** 

_Updated July 2024_ 

## ASB supports the data types shown in the tables below. 

## **Scalar Types** 

|**Type**|**Code**|**Size**|**Description**|**Description**|**Description**|**Description**|
|---|---|---|---|---|---|---|
|Floating Point|F|4|Single precision IEEE float, ~7 significant digits||||
||F|6|48 bit (WD16, M68000, AMOS) float, ~11 significant digits||||
||F|8|double precision IEEE float, ~16 significant digits||||
|Unsigned<br>Integer (little-<br>endian byte<br>order)|B|1|8 bit unsigned||||
||B|2|16 bit unsigned||||
||B|3|24 bit unsigned||||
||B|4|32 bit unsigned||||
||B|5|40 bit signed (two's complement)||||
||B|6|48 bit signed (two's complement, little-endian)||||
|Signed Integer|I|1|8 bit signed (two’s complement)||||
||I|2|16 bit signed (two’s complement, little-endian); see|||Boolean<br> below|
||I|4|32 bit signed (two’s complement, 2301 order)||||
||I|6|48 bit signed (two's complement); see||B6 and I6 Variables<br>below||
|String|S|#|fixed length string of # bytes; see|String Variables<br>below|||
||S|0|variable length string; seeDynamically Sized Variables||||
|Unformatted<br>(raw bytes)|X|0|fixed length raw bytes||||
||X|0|variable length raw bytes; seeDynamically Sized Variables||||



A-Shell Reference 

Page 950 

|**Type**|**Code**|**Size**|**Description**|
|---|---|---|---|
||(none)||Size determined by lower-levelMAP<br> declarations.|



## **Compound or Structure Types** 

|**Type**|**Example**|**See**<br>**Note #**|
|---|---|---|
|Multi-level MAPs|`MAP1 CUST`<br>`MAP2 NAME,S,30`<br>`MAP2 CUSNO,B,4`<br>`MAP2 TOTSALES,F,6`<br>`READ #CH, CUST       ! read/write entire group as a unit`<br>`? NAME               ! individual fields referenced by name`|1, 2|
|DEFSTRUCT|`DEFSTRUCT ST_CUST    ! define structure layout`<br>`MAP2 NAME,S,30`<br>`MAP2 CUSNO,B,4`<br>`MAP2 TOTSALES,F,6`<br>`ENDSTRUCT`<br>`...`<br>`MAP1 CUSREC,ST_CUST  ! define instance of structure`<br>`...`<br>`READ #CH, CUSREC     ! read/write entire struct at once`<br>`? CUSREC.NAME        ! use structvar.member notation for fields`||
|DYNSTRUCT|`MAP1 DS, DYNSTRUCT`||



A-Shell Reference 

Page 951 

## Table Notes: 

- 1 Also known as "records", the multi-level MAP arrangement is physically equivalent a DEFSTRUCT, except for the syntax of accessing its members. Programmers are encouraged to use DEFSTRUCT as it makes the code more self-documenting and simplifies creating multiple instances and arrays of the layout. 

- 2 Any MAPn level with higher-numbered levels defined within it. 

## **See Also** 

- BINDSTRUCT 

## **B6 and I6 Variables** 

## **String Variables** 

## **Boolean** 

A-Shell Reference 

Page 952 

## **DYNAMICALLY SIZED VARIABLES** 

As the title suggests, these variables automatically re-size themselves to accommodate the data you assign to them. 

Dynamic variables are allocated and maintained outside your user partition, so the only limit on how big they can become would be determined by available memory on the system. If unable to expand as needed, the program will get an error 3 - out of memory. The are understandably not as efficient as fixed-length variables, but can be extremely useful in situations where you don't have a good way of knowing the appropriate maximum size required at the time the program is written. (Letting the computer work a little harder is nearly always a better option than making the programmer work harder or risking bugs caused by inadvertent truncation!) 

To declare a dynamic variable, assign it an explicit size of zero, e.g.: 

```
MAP1 STRING,S,0     ! dynamically sized string
```

```
MAP1 UNF,X,0        ! dynamically sized unformatted
```

```
MAP1 DARY(75),S,0   ! fixed-length array of dynamic strings
MAP1 XARY(24,9),X,0 ! fixed-length array of dynamic unformatted
```

## **Comments** 

Dynamic variables are impossible to align in memory with respect to other variables, so should normally only be declared at the MAP1 level. However, see Dynamic Variables Below MAP1 for a relaxation of the rule. 

An array may be made up of dynamic elements, but the range of index values for the array remains fixed. However, you may use DIMX and REDIMX to dynamically allocate and resize such as array, e.g. 

```
DIMX ZARY(A,B,C),S,0
```

```
REDIMX ZARY(A*2,B,C)
```

Re-dimensioning an array doesn't preserve the original contents unless only the first dimension changes, as in the example above. 

A-Shell Reference 

Page 953 

Dynamic variables may also be used in function and procedure parameter lists, as well as for the return value of a function, i.e.: `Function Fn'Test$(a$ as s0) as s0` 

Dynamic variables (and array elements) initially take up 8 bytes of storage memory (used as a descriptor), so it won't make much sense to use them if they aren't going to expand beyond 8 bytes. 

When an assignment is made to the variable, either via an assignment (e.g. STRING = "abc"), INPUT statement, or via a subroutine, Function, or Procedure, the variable will be expanded as needed to contain the data. If referenced in an expression before any value is assigned, they act like null strings. 

It is not wise to use INPUT RAW with dynamic X variables, since the amount of data input depends on the current size of the variable, which would be 0 initially, but could be anything later (after some other kind of assignment). 

As currently implemented, the internal memory allocated to a variable does not shrink, so first assigning a large amount of data and later assigning a small amount does not free memory. (This may change as the implementation evolves.) 

The run-time system maintains several pools of dynamic variable memory, including one for global or persistent variables (which lasts for the duration of a RUN program), and one each for the automatic (aka local or stack) variables at each level of function/procedure nesting. All are allowed to grow without any particular limit during the execution, but are cleared as soon as the variables contained within go out of scope—i.e. at the end of a procedure, function, or program. 

To compile programs with dynamic variables, you must use compiler edit 439+, and the /X:2 switch. Any legally compiled program containing dynamic variables will receive a new RUN header value of 0xF167 or 0xF1E7 (if /av), and will generate a "? RUN file incompatible" error if executed under any A-Shell runtime prior to 5.1.1159. Programs which do not contain dynamic variables should continue to compile and run exactly as before. 

## **Example** 

To load an entire binary file into a dynamic X variable: 

```
map1 bytes,f
```

```
map1 rcv,f
```

```
map1 ch,b,2,1
```

```
map1 blob,x,0                    ! dynamic var to hold file
```

A-Shell Reference 

Page 954 

```
xcall SIZE, fspec$, bytes        ! get size of file
open #ch, fspec$, input
xcall GET, blob, ch, bytes, rcv  ! blob now contains file
```

```
close #ch
```

- `! create an exact copy of the original file...` 

```
open #ch, "copy.dat", output
```

```
print #ch, blob;
```

```
close #ch
```

See fnfilestr.bsi in SOSLIB:[907,10] for a set of related routines for copy files to memory variables and vice versa. 

## **Subtopics** 

- Dynamic Overlays 

- Dynamic Variables Below MAP1 

A-Shell Reference 

Page 955 

## **DYNAMIC OVERLAYS** 

A dynamic overlay is similar to a dynamic X variable, except that it is designed specifically for overlaying DIMX arrays. Such an overlay permits you to pass an entire DIMX array by value to a subroutine or procedure / function. It is much more efficient to pass such an array by reference, but the technique may be useful in particular cases. 

There are two steps involved in creating a dynamic overlay: 

Step 1: Declare the Overlay 

Declare the overlay variable using the special ,@0 overlay syntax, e.g.: 

```
MAP1 OVERLAY,X,@0
```

Note that the size field is optional but ignored, and only S and X variables are allowed. (In most cases, only X makes sense; use S-type overlays only when you are sure that the target variable contains no embedded null bytes.) 

Step 2: Assign the Overlay 

Assign the overlay at runtime using the "=@" operator, e.g.: 

```
OVERLAY =@ VAR          ! or, OVERLAY = @VAR (spaces are not significant)
```

This effectively gives the OVERLAY variable the same data storage location and size as the VAR variable. As mentioned above, the main motivation is to do this with dynamic arrays, e.g.: 

```
DIMX DYNARY(x,y,z),S,n
```

```
...
```

```
OVERLAY =@ DYNARY()
```

Note that you may NOT specify any array subscripts for the array on the right side of the @= operator, since this technique is currently only supported to overlay the ENTIRE array. 

## **Comments** 

A-Shell Reference 

Page 956 

The overlay does not automatically get updated if the target array changes in size—i.e. due to either REDIMX or AUTO_EXTEND. However, you can reassign the overlay as needed. For example: 

```
MAP1 AOVL,X,@0         ! declare the dynamic overlay
DIMX A(5,10),S,7    ! dimension an array
AOVL =@A()          ! assign the overlay to the array
PRINT LEN(AOVL)     ! prints 350 (5 x 10 x 7)
REDIMX A(10,10)     ! redimension the array
PRINT LEN(AOVL)     ! still prints 350 (still tracking the old allocation)
AOFL =@A()          ! reassign the overlay
PRINT LEN(AOVL)     ! now prints 700 (10 x 10 x 7)
```

So the best practice would be to (re)assign the overlay immediately before you need to use it. 

## **Example** 

There is currently no corresponding operation to overlay a dynamic array on top of an X variable, which admittedly might be handy when passing such an array between routines via parameter lists. But you can get around that limitation using the technique in the following example, which passes a dynamic array to a procedure for processing: 

```
DIMX ARY(X),S,Y
```

```
MAP1 OVL,X,@0
```

```
...
```

```
<load the array with some data>
```

```
...
```

```
OVL = @ARY()   ! overlay the array with the XARY variable
```

A-Shell Reference 

Page 957 

```
CALL MYPROC(OVL,X,Y)  ! pass array plus its dimensions to a function
```

```
...
```

```
! (our ARY() may have been updated by the MYPROC() procedure)
```

```
END
```

```
!-----------------
```

```
PROCEDURE MYPROC(XXARY AS X0, ELEMENTS AS F, WIDTH AS F)
```

```
DIMX LOCARY(ELEMENTS),S,WIDTH   ! allocate local array to match array passed in
```

```
MAP1 LOCOVL,X,@0
```

```
MAP1 I,F
```

```
LOCOVL =@ LOCARY()  ! overlay the local (currently empty) array
LOCOVL = XXARY      ! now copy the data on top of that
```

```
FOR I = 1 TO ELEMENTS
```

```
    <perform operations on LOCARY(I)>
```

```
NEXT I
```

```
XPUTARG 1,LOCOVL    ! update caller's overlay (which is the same as
```

A-Shell Reference 

Page 958 

- `! caller's actual array) with the local array data` 

```
ENDPROCEDURE
```

A-Shell Reference 

Page 959 

## **DYNAMIC VARIABLES BELOW MAP1** 

_Added February 2015_ 

Note: This function was added to A-Shell in an **experimental context** . Please use with caution, test thoroughly, and report your experiences back to the A-Shell developers. 

It is possible to allow dynamic variables (s,0 and x,0) below the MAP1 level. For example: 

```
DEFSTRUCT ST_REC
```

```
    MAP2 SKU,S,10
```

```
    MAP2 DESCR,S,0      ! variable length!!
```

```
    MAP2 PRICE,F
```

```
ENDSTRUCT
```

This can be a useful technique for encapsulating data with variable-length components, but it creates an implicit linkage between the structure and the variable length elements that opens the door to various kinds of risks if not handled carefully. The size of the structure is fixed—the variable length field appears to have a fixed length of 16 bytes—but the contents of the variable length member are stored outside the structure, in the dynamic variable pool. The structure can be passed as a parameter to a function, and the variable length elements will remain intact, but at that point they should be treated as read-only. Both copies of the structure would link to the same variable-length text, but if that text is changed, only the current structure would remain properly linked to the updated text. 

Writing the structure to a file would also make no sense; in that case, what would actually be written for the dynamic members would be their 16 byte descriptors, which would be useless outside the immediate context of the program. 

## **History** 

- 2014 October, A Shell 6.1.1391, compiler edit 712: Added to A-Shell 

A-Shell Reference 

Page 960 

## **ARRAYS** 

The scalar and compound data types may be combined into arrays as follows: 

|**Description**|**Example**|
|---|---|
|Fixed arrays of scalars|`MAP1 SALES(25),F,6`|
|Fixed compound arrays|`MAP1 CUST(10)`<br>`MAP2 NAME,S,30`<br>`MAP2 CUSNO,B,4`<br>`MAP2 SALES(25),F,6`<br>`...`<br>`for I = 1 to 10`<br>`? NAME(I),CUSTNO(I)`<br>`for J = 1 to 25`<br>`? SALES(I,J)`<br>`next J`<br>`next I`|
|Dynamic Arrays|`ECOUNT = 1000`<br>`ESIZE = 50`<br>`dimx MESSAGES(ECOUNT),S,ESIZE  ! dynamically`<br>`allocate array`<br>`...`<br>`redimx MESSAGES(2000)          ! increase extent of`<br>`array`<br>`...`<br>`redimx MESSAGES(0)             ! discard array`|
|Dynamic Array of Structures|`dimx CUSRECS(50),ST_CUST   ! array of 50 ST_CUST`<br>`structures`|



A-Shell Reference 

Page 961 

|**Description**|**Example**|
|---|---|
||`...`<br>`? CUSRECS(25).CUSNO        ! element.member notation`|
|Dynamic auto-extended arrays; may<br>be either scalar or structure types|`dimx CUSRECS(0),ST_CUST,auto_extend`<br>`...`<br>`CUSRECS(N).NAME = "MicroSabio"  ! auto-expand to N`<br>`elements`<br>`! if needed (on`<br>`assignment)`|
|Multi Level List|dimx $JSONDOC, mlist(varstr)   ! JSON doc stored as multi-level list<br>...<br>$JSONDOC(.pushback) = name$ + ":" + value$   ! push<br>name:value pair on end of list|



## **Subtopics** 

- Dynamic Arrays (DIMX) 

A-Shell Reference 

Page 962 

## **DYNAMIC ARRAYS (DIMX)** 

## **{qualifier} DIMX arrayname(expr1,...,exprn),type{,sizeexpr {,AUTO_EXTEND}}** 

## **{qualifier} DIMX arrayname(expr1,...,exprn),structname {,AUTO_EXTEND}** 

DIMX declares an array whose element size and extent may be determined at run time. The size of the array can be changed explicitly after the initial DIMX using REDIMX or, with the AUTO_EXTEND keyword, it can be extended automatically. 

## _qualifier_ 

An optional keyword to qualify the scope and longevity of the array.  Valid qualifiers are STATIC, PRIVATE and PUBLIC. (See MAP Statement Extensions) 

## _expr1,...,exprn_ 

One or more expressions (literal values, variables or arithmetic expressions) evaluated when the statement is encountered at runtime.  The number of expressions given determines the number of dimensions of the resulting array. 

## _type_ 

standard variable types (F, B, X, S, I) 

## _sizeexpr_ 

Arithmetic expression (evaluated at runtime) for the size of each element in the array 

## _structname_ 

Name of a structure previously defined with DEFSTRUCT. See Defined Structures and Dynamic Array of Structures. 

## _AUTO_EXTEND_ 

This keyword (case insensitive) causes the array to be automatically extended as required by direct Assignment Statements. See notes below for more details. 

A-Shell Reference 

Page 963 

## **Examples** 

```
IMX FDATA(COUNT),F
```

```
STATIC DIMX SDATA(COUNT1,A*B,C),S,LEN(S2$)
```

```
PRIVATE DIMX CUSARY(0),ST_CUS,AUTO_EXTEND
```

The first DIMX statement above represents a simple example of allocating a single-dimensioned array of COUNT (evaluated at runtime) items, each of them a floating point value (using the default floating point size). This is similar to the original DIM statement. 

The second statement declares a three-dimension array of string elements whose size matches the logical length of the string S2$ (evaluated at the time the DIMX statement is encountered). The STATIC qualifier would make sense only within the context of a function or procedure; see MAP Statement Extensions for further notes. 

The third statement declares an auto-extending array of ST_CUS DEFSTRUCT. The initial size of this array is 0 elements, but will grow automatically as assignments are made to it; see comments about AUTO_EXTEND in the notes below. The PRIVATE keyword would limit access to the array to routines within the same ++INCLUDE file. In order for that to make any sense, the statement would have to appear at the top of the ++INCLUDE file, above any functions and procedures. Furthermore, the + +INCLUDE file would need to be positioned at the top of the main program, or otherwise in arranged so that the run time flow of execution encountered the DIMX statement before it encountered any other references to it. 

## **Notes** 

- DIMX allocations are automatically freed (and memory recovered) when the RUN or SBX in which they are created exits. 

- DIMX allocations that occur within functions and procedures are automatically freed on return from the routine, unless the STATIC qualifier is used. 

- To reset (i.e. delete / free) a DIMX allocation explicitly, use REDIMX to set the subscript extents to zero. 

- The contents of a DIMX array (including any extensions to it due to the **AUTO_EXTEND** feature) are always pre-cleared to 

- nulls. 

A-Shell Reference 

Page 964 

- The maximum size of an individual DIMX array is determined by the MALLOCLIMIT (default 8MB) option in miame.ini. The 

- limit is tested whenever a DIMX or REDIMX operation takes place, including implicit REDIMX operations triggered by **AUTO_EXTEND** . 

- When an array is automatically extended by the AUTO_EXTEND it will be extended somewhat beyond the amount actually 

- needed for the assignment (on the theory that subsequent expansions are likely to follow). The exact amount of extra expansion is based on a heuristic that is subject to change, but as of build 1191, it consists of the smallest of 110% of the minimum amount required, and 150% of the previous array size. But in no case will the excess expansion (beyond what is immediately needed) be more than 128K. Also see the .EXTENT() function. 

- The MALLOC trace option will trace DIMX and REDIMX memory allocations (along with most other memory allocations/de- 

- allocations), making it a useful debugging tool. 

- Because there is no support for it under AMOS, DIMX is not normally supported by the /RC compiler switch. However, you can 

- override that (i.e. cause DIMX to be allowed when compiling in /RC mode) by adding the statement "OPTIONS=RC_DIMX" (without quotes) to miame.ini. Just be careful to make sure that you don't actually try to execute that statement when running your program under AMOS. 

- Global DIMX arrays can be made visible to functions and procedures either via the ++EXTERN mechanism or via Dynamic 

- Overlays. Only the latter will work for SBXs. DIMX arrays declared within functions and procedures are normally only visible within that routine; the PRIVATE or PUBLIC qualifiers may be used to extend visibility to the ++INCLUDE file containing the routine or to the entire program, respectively. 

- Like MAP statements, DIMX statements must occur physically prior to any statements referencing the array, so that the 

- compiler can define the variable. Also, as with MAP statements, the array gets initialized (or in this case, allocated) when it is encountered at run time. This generally requires some care in properly positioning the statement to suit the requirements of both the compiler and the run time system; often coupled with some conditional logic to prevent it from being executed more than one time by the run time interpreter. 

- Passing DIMX Arrays 

A-Shell Reference 

Page 965 

- REDIMX 

- DIMX vs DIM 

- Dynamic Array of Structures 

- MAP Statement Extensions 

- .EXTENT() 

## **Subtopics** 

- Dynamic Array of Structures 

- DIMX vs DIM 

A-Shell Reference 

Page 966 

## **DYNAMIC ARRAY OF STRUCTURES** 

A dynamic array of DEFSTRUCT may be defined and allocated as follows: 

```
DEFSTRUCT ST_MOVIE_PROD
    MAP2 TITLE$,S,30
    MAP2 PRODUCERS(9),S,30
```

```
ENDSTRUCT
```

```
...
```

```
DIMX DMVPR(N),ST_MOVIE_PROD  ! dynamic array of N structures
DIMX FX(N),X,300             ! dynamic array of N ordinary X,300 variables
MAP1 FMVPR(10),ST_MOVIE_PROD ! fixed array of 10 structures
...
DMVPR(1) = FX(1)             ! assign one X,300 var to another
```

**Note** : initial values specified in the MAP Statements within the structure definition are ignored by DIMX. All elements/fields are - " " initialized to null. See the A Shell forum discussion MAP initializers in DEFSTRUCT. 

As shown above, the declaration of the dynamic array of structures is syntactically consistent with both static arrays of structures and dynamic arrays of ordinary types (with the structure name replacing the type,size pair). The assignment statement following the declarations also illustrates that the DMVPR() array of structures and the FX() array of simple X,300 variables are, at the top level, compatible, since at the top level, an instance of the ST_MOVIE_PROD structure is equivalent to an instance of an X,300 variable. The FX() array though, provides no direct means of referencing individual fields within each 

A-Shell Reference 

Page 967 

unformatted element, so we'll set that aside for a moment and concentrate on the differences between the fixed and dynamic arrays DMVPR() and FMVPR(). 

Although the fixed and dynamic arrays are logically similar, the normal organization of fixed arrays of structures, in which each member can be accessed as if it were an independent array, i.e. FMVPR.TITLE$(J), is not efficient for dynamic (moveable) arrays. Consequently, both the structure and the syntax of accessing the individual element members of dynamic arrays is reversed, so that you append the "dot member" name after the structure element subscript, e.g.: 

```
PRINT DMVPR(J).TITLE$    ! member of dynamic array of structures
```

```
PRINT FMVPR.TITLE$(J)    ! member of fixed array of structures
```

C programmers will recognize the correspondence to the way elements within arrays of structures are accessed in that language. 

When the member is itself an array, as in the case of PRODUCERS(), you end up with two sets of parentheses: 

```
PRINT DMVPR(J).PRODUCERS(K)    ! dynamic array
```

```
PRINT FMVPR.PRODUCTS(J,K)      ! fixed array
```

As with other DIMX arrays, the AUTO_EXTEND, PUBLIC, and PRIVATE modifiers are all available. See Dynamic Arrays (DIMX)  and MAP Statement Extensions. 

## **See Also** 

- Passing DIMX Arrays  (as parameters) 

## **History** 

- 2011 October A Shell 5.1.1235: DIMX structures implemented. 

A-Shell Reference 

Page 968 

## **DIMX VS DIM** 

DIMX is an enhanced version of the venerable DIM statement used to allocate an array at runtime. The enhancements of DIMX over DIM are: 

- It accepts optional type and size specifiers rather than being limited to F6 and string with size determined by STRSIZ. 

- The element size is evaluated at runtime, whereas with DIM, it is evaluated at compile time. 

- It allocates the memory needed out of the system memory pool, rather than from the user partition. Memory used by DIMX 

- automatically released when the program ends. 

- If the AUTO_EXTEND option is specified, the first dimension (first subscript) of the array will be automatically extended as 

- needed whenever an assignment is made to the array. 

- The AUTO_EXTEND feature is only activated for explicit assignments like those shown above; it is not normally activated for 

- ambiguous or implicit assignments, such as when array elements are passed as parameters. 

A-Shell Reference 

Page 969 

## **COLLECTIONS** 

In addition to traditional arrays, ASB supports the following types of collections: 

|Ordered Maps|dimx $CAPITALS, ordmap(varstr;varstr)     ! map of strings<br>...<br>$CAPITALS("FRANCE") = "PARIS"|
|---|---|
||dimx $STATES, ordmap(varstr;varx)      ! map of blobs/structures<br>...<br>Map1 STATE,ST_STATE<br>...<br>$STATES(“California”) = STATE        ! load structure into map<br>...<br>STATE = $STATES(“California”)       ! retrieve structure from map by key<br>? STATE.POPULATE, STATE.CAPITAL, …  ! access members|
|Multi Level List|dimx $JSONDOC, mlist(varstr)   ! JSON doc stored as multi-level list<br>...<br>$JSONDOC(.pushback) = name$ + ":" + value$   ! push name:value pair on end of list|
|Two-dimensional<br>Ordered Maps<br>(Gridmaps)|dimx $GMAP, gridmap(int, int, varstr)<br>...<br>$GMAP(row, col) = "Blue Moon"|
||dimx $GMAP, gridmap(int, varstr, varstr)<br>...<br>$GMAP(row,"Nationality") = "Utopian"|



A-Shell Reference 

Page 970 

## **ORDERED MAPS** 

An ordered map is a type of associative array that maps keys to values, maintaining an order to the keys. The concept is similar to an indexed file with a single variable length key and a single variable length data structure, either a simple string or a multimember structure. ORDMAPM allows multiple key-value pairs with the same key, while ORDMAP does not. 

## **Subtopics** 

- Declaration / Creation 

- Destruction 

- Special ORDMAP Functions 

- Element Assignment and Removal 

- Accessing Elements 

- Element Arithmetic 

- Iterators 

- Ordered Multi-Map ORDMAPM 

## **See Also** 

- Copy, Add, Subtract Collections 

## **History** 

2022 May, A-Shell 6.5.1716:  Increase key length from 511 bytes to unlimited. 

- 2016 August, A Shell 6.3.1520:  Ordered Multi-Map (ORDMAPM) added. 

- 2015 July, A Shell 6.1.1414, compiler edit 742:  Add ordmap(varstr;varx) and .ISNULL(var) 

A-Shell Reference 

Page 971 

2013 June, A-Shell 6.1.1354, compiler edit 638:  .CLEAR function added 

- 2012 June, A Shell 6.1.1300:  Ordered maps introduced; (varstr;varstr) only 

A-Shell Reference 

Page 972 

## **DECLARATION / CREATION** 

_Updated May 2022_ 

## **{qualifier} DIMX $arrayname, ordmap (varstr; varstr)** 

## **{qualifier} DIMX $arrayname, ordmap (varstr; varx)** 

## **{qualifier} DIMX $arrayname, ordmapm (varstr; varstr)** 

## **{qualifier} DIMX $arrayname, ordmapm (varstr; varx)** 

_$aryname_ is the name of the ordered map. It follows the normal rules of ASB variable names except that it must begin with a $. Also note that although _$aryname_ is an array, and you will need to use parentheses to reference it later, e.g. `$aryname("some key") = "some value"` , the parentheses are omitted from the declaration. 

The _varstr; varstr_ and _varstr; varx_ suffixes following the data types _ordmap or ordmapm_ refer to the types of the keys and the types of the values. The only supported key type is _varstr_ , meaning a variable-length, null-terminated string. The value type can also be _varstr_ or it can be _varx_ , meaning a variable-length raw or unformatted blob, such as can be stored in a type X or a structure variable. 

The _ordmap_ variant does not allow multiple key-value pairs with the same key. (The assignment **$m("foo") = "bar"** will replace any prior key-value pair with the key "foo".) The _ordmapm_ variant allows any number of pairs to have the same key. 

The ordered map grows dynamically as items are added or deleted, so there is no need to declare any sizes. 

## **See Also** 

- Element assignment and removal 

A-Shell Reference 

Page 973 

## **DESTRUCTION** 

## **REDIMX $aryname()** 

This is similar to the syntax for destroying other dynamic arrays, except here the parentheses must be empty. 

As with other dynamic arrays, gridmaps will be automatically destroyed when they go out of scope—i.e. when the function or procedure in which it was declared returns, or for global and module scope arrays, when the program ends or SBX returns. Explicit destruction is not typically necessary. 

## **See Also** 

- REDIMX 

A-Shell Reference 

Page 974 

## **SPECIAL ORDMAP FUNCTIONS** 

_Reviewed and updated December 2025_ 

|**Function**|**Description**|
|---|---|
|.EXTENT($a())|Returns the number of elements (key-value pairs) in the ordered map $a. See.EXTENT()<br> for<br>more details.|
|.ISNULL($a(key$)), .ISNULL(var)|Tests for the .NULL condition. See example below.|
|.KEY($$i)|Returns the key associated with the element currently indexed by the iterator. Equivalent to$ $I.KEY. See example underIterators<br>.|
|.NEXT($$i)|Advances the iterator, returning the associated key or.NULLif no more. This is mainly used<br>internally by theNEXT $$istatement, which is translated to something like:<br>`if .next($$i) # .null <repeat loop>`|



## **.ISNULL() Example** 

```
A$ = $MYMAP(KEY$)
```

```
if A$ = .NULL then ...             ! requires A$ >= 6 bytes
if .ISNULL(A$) then ...            ! requires A$ >= 6 bytes
if .ISNULL($MYMAP(KEY$)) then ...  ! works in all cases
IF NOT .ISNULL(A$) THEN ? "$MYMAP(KEY$) = ";A$
```

A-Shell Reference 

Page 975 

The first two tests in the example above only work if the variable (A$) is a string of at least 6 bytes in length because the internal representation of .NULL is the 6 byte string "<null>". So the third method is the most universal since $MYMAP(KEY$) will always return .NULL if the element doesn't exist, regardless of the ordered map type. However, the first two methods have the advantage of avoiding the need to retrieve the element from the ordered map a second time in order to use it (if not null). See examples notes under Accessing Elements for more details. Note that since .ISNULL() returns a proper BOOLEAN value, you can negate it with the unary NOT operator to test if the item exists. 

## **Comments** 

Use of the .ISNULL() function sets the minimum runtime version to 1414. See History. 

Attempting to use the .ISNULL() function with a non-string argument generates an illegal expression error. See History. 

Side note: although this addresses one mistaken use of .ISNULL(), it doesn't address the case where the argument is a string or structure variable but is less than 6 characters long. For example, this works: 

```
IF .ISNULL($MAP(A$)) THEN ...  ! good
```

but this only works if VAR is an S or X type (or structure) at least 6 bytes long: 

```
VAR = $MAP(A$)
```

```
IF .ISNULL(VAR) THEN ...       ! only good if sizeof(VAR)>=6
```

## **See Also** 

- .NULL 

- Special GRIDMAP Functions 

## **History** 

- 2020 June, A Shell 6.5.1683:  Use of the .ISNULL() function now sets the minimum runtime version to 1414. 

- 2019 November, A Shell 6.5.1671:  Add error on non-string argument. 

A-Shell Reference 

Page 976 

2015 July, A-Shell 6.1.1413: Add .ISNULL(). 

A-Shell Reference 

Page 977 

## **ELEMENT ASSIGNMENT AND REMOVAL** 

_Updated July 2015_ 

Once declared, elements (i.e. key,value pairs) can be added to the ordered map with standard array assignment syntax, except that the array subscript (the key) is a string rather than a numeric value: 

```
$capitals("california") = "sacramento"   ! for ordmap(varstr;varstr)
```

```
$products("SKU12345") = PROD’REC         ! for ordmap(varstr;varx)
```

If the specified key exists already, the operation will replace the value of the existing element. To delete an element, a special value .NULL (“dot null”) is assigned: 

```
$capitals("california") = .NULL
```

Note: Assigning an empty string (“”) to the value of a key does **not** delete the item! 

## **See Also** 

- ORDMAPM for details and example of adding and deleting keys with a multi-map. 

A-Shell Reference 

Page 978 

## **ACCESSING ELEMENTS** 

_Updated July 2015_ 

To refer to the value of an element (i.e. use it as a source string in an expression), just use the standard array syntax with the key as the subscript: 

```
print "The capital of "; state$; " is "; $capitals(state$)
```

For ordered maps with unformatted elements (i.e. blob, binary, structures, X type), you can use the subscripted array reference in the same was as you would the MAP1 (X type) variable or structure,e.g. 

```
Map1 Prod’rec
```

```
Map2 sku$,s,10
```

```
Map2 price,f,6
```

```
Map2 qtyonh,I,4
```

```
…
```

```
Dimx $products,ordmap(varstr;varx)
```

```
…
```

```
Prod’rec = $products(“AB-1234”)    ! retrieve map element into structure
```

```
? “Product “;sku$;” price is “;price;” qtyonh is”;qtyonh
```

```
…
```

```
Write #ch, $products(“AB-1234”)    ! or use element directly as structure
```

The traditional mapped “structure” in the above example could also be replaced with a formal structure (defined via DEFSTRUCT), in which case after retrieving the element into the structure, you would use the structure.member syntax to access the members. 

A-Shell Reference 

Page 979 

Note that when accessing ordered map elements by key, just as with indexed file access, you really need to test for the possibility that the element does not exist. A non-existent element will return the special value .NULL, which for varstr type elements can be tested for with a standard string comparison, i.e. 

```
City$ = $capitals(state$)
```

```
If City$ = .NULL then
? “capital of “;state$;” is undefined”
```

```
Else
```

```
? “capital of “;state$;” is “;City$
```

```
Endif
```

For _varstr_ elements, attempting to print the .NULL value will display “<null>”, which may be acceptable in some casual situations. 

For _varx_ elements, the .NULL value cannot be tested with a simple string comparison, and attempting to reference members of a null structure will result in undefined values. Instead, you must use the function .ISNULL(var) to test it, so the above example should really be coded as: 

```
Prod’rec = $products(“AB-1234”)    ! retrieve map element into structure
If .ISNULL(Prod’rec) then
? “No such product defined”
```

```
else
```

```
? “Product “;sku$;” price is “;price;” qtyonh is”;qtyonh
```

```
endif
```

A-Shell Reference 

Page 980 

The .ISNULL(var) test works equally well for both _varstr_ and _varx_ elements, so the best strategy is to use it in all cases, thus avoiding difficult-to-diagnose bugs resulting from accidentally attempting to compare a _varx_ value to the .NULL string value. So the _varstr_ example above would be better coded as: 

```
City$ = $capitals(state$)
```

```
If .ISNULL(City$) then             ! (better than testing if City$ = .NULL)
```

A-Shell Reference 

Page 981 

## **ELEMENT ARITHMETIC** 

_Written August 2024_ 

Although ordered map values are stored as strings ( _varstr;varstr_ ) or as raw bytes ( _varstr;varx_ ), you can also store numeric values and do arithmetic with them, more or less like you would with a traditional array of numeric (B, I, or F) values. Consider the following comparison of the two approaches: 

```
dimx ary(0), F, auto_extend         ! plain numeric array
dimx $omap, ordmap(varstr;varstr)   ! ordered map
```

```
...
```

```
ary(x) = value        ! assign a value to element
$omap(key$) = value   ! (expanding array as needed)
ary(x) *= 3.5         ! multiply element value by 3.5
$omap(key$) *= 3.5    !
```

```
ary(x) += 1           ! add 1 to element value
$omap(x) #+= 1        ! (note #+ to force addition rather than concatenation)
```

Notes: In the first pair of assignments, the only real difference is the index used: **x** in one case, which must evaluate to an integer, and **key$** in the other. Internally the value will be stored differently (as a floating point variable in one case, and as its string representation in the other), but since string/numeric conversion is easy (and usually automatic), we haven't lost any 

A-Shell Reference 

Page 982 

flexibility. The second pair of multiplication assignments illustrates that point. The ordered map value will be automatically converted to numeric format for the multiplication, and then converted back to string to update the storage. 

The third pair of assignments above illustrates two additional considerations. The first is that even though ordered map keys are always treated as strings, there is nothing stopping you from specifying a numeric variable as the index, i.e. _$omap(x)_ instead of _$omap(key$)_ ; the **x** in this case will be automatically converted to string, i.e. STR$(X). Note that if you iterate over the map, numeric keys will be ordered like strings (e.g. 1,10,100,11,2,29,3,...) rather than numbers (e.g. 1,2,3,10,11,29,100,...), but that doesn't affect direct access to elements. The second consideration is that the **+** operator acts as concatenation rather than addition when working with strings, but you can force it to act as addition by inserting **#** in front of the **+** (e.g. #+= vs. +=). The VAL() function will not work in this scenario. 

Of course the ordered map data structure is more complex and thus not as efficient as the plain array, so even though it can be used in place of the array, it isn't necessarily a good idea. But it becomes attractive in situations where the index values may include non-integers or are a sparsely populated range of integers. For example, a plain array makes sense for counting people by age, but maybe not for counting real estate listings by 5-digit zip code, where the plain array would need to support 99999 elements even if only a few dozen are actually in use for the data set. Switching to the ordered map is a convenient solution in such a case with on little or no change to the code syntax or logic. 

## **See Also** 

- Explicit Plus Operators 

A-Shell Reference 

Page 983 

## **ITERATORS** 

_Updated February 2025_ 

To access elements from a collection without knowing the specific keys, an “iterator” iterator is used. Iterators are special variables which receive the value of the next element of a collection each time through the loop. 

## To iterate through a collection, a FOREACH loop is used: 

```
foreach $$i in $aryname({startkey,{endkey}})  ! fwd iterator
```

```
    print $$i                                 ! print the element value
    print .key($$i)                           ! print the element key
```

```
next $$i
```

```
foreach’reverse $$j in $aryname({startkey,{endkey}})     ! reverse iterator
```

```
    print $$j                         ! print the element value
    print .key($$j)                   ! print the element key
```

```
next $$j
```

See Special ORDMAP Functions for a description of the .KEY() and other related functions. 

The optional _startkey_ and _endkey_ values may be any kind of expressions that could appear on the right side of an assignment statement (aka "rvalues"), i.e. literals, variables, expressions with USING, function calls, etc. Numeric values are converted to string format, truncating to integer. Note that if there is not an exact match on _startkey_ , the loop will iterator zero times, unlike in an ISAM lookup, where a failed initial key match will nevertheless affect the subsequent next operation. See History below for chronology of refinements. 

A-Shell Reference 

Page 984 

Note: the above examples assume varstr elements; for varx elements, you wouldn’t try to print the $$i or $$j iterator values directly; instead you would assign them to a structure and then access the members, i.e. 

```
Prodstruct = $$i                      ! copy iterator value to structure
```

```
print Prodstruct.field                ! print a field of the element value
print .key($$j)                       ! print the element key
```

## Although this is similar to a standard for/next loop, there are some noteworthy differences: 

- First, unlike the standard _for/next_ loop where the loop variable must have been previously defined, in the FOREACH loop, the 

- iterator variable ( _$$i_ in the example above) is created on the fly and exists just for the duration of the loop. Iterator variables must all start with $$ (which should not be used for any other variable type.) Since it is destroyed at the end of the loop, the same iterator variable name can be used in other FOREACH loops. 

- Unlike the standard for/next loop, here the starting and ending values are optional; if omitted, the are effectively 

- interpreted as the first and last items in the collection.  The concept is similar to sequencing through an indexed file from a starting key (or one end of the file) to an ending key (or the opposite end of the file), except that if there is not an exact match on startkey, the entire loop will be skipped. To iterate the entire collection, use empty parens, e.g. `$aryname()` . 

- The order of the sequence will be according to the key, either forward (foreach) or reverse (foreach'reverse). 

- Modifications to the collection index (including deleting key-value pairs) during iteration should be strictly avoided. See 

- Writeable Iterators for details. 

## **See Also** 

- FOREACH 

## **History** 

- 2023 November, A Shell 7.0.1752.0: _endkey_ parameter extended to gridmaps. 

- 2023 October, A Shell 7.0.1751.0: _startkey_ support added to FOREACH'REVERSE; _endkey_ added for ordered map iteration. 

A-Shell Reference 

Page 985 

- 2023 August, A Shell 6.5.1739:  In FOREACH, if the specified starting key is not found, the iteration now starts with the next key. Previously, the result would have been an empty iteration. In FOREACH'REVERSE, the starting key is now recognized whereas previously it was ignored. As with FOREACH, if not found, the iteration starts with the next key—i.e. the next one lower in the collating sequence. 

- 2018 May, A Shell 6.5.1636, compiler edit 859:  the starting key in a FOREACH statement may now be any kind of expression. Previously, it only allowed a simple variable or a literal string or numeric constant; numeric literals were allowed but weren't converted to string and thus typically failed to match any items in the map. 

## **Subtopics** 

- Writable Iterators 

A-Shell Reference 

Page 986 

## **WRITABLE ITERATORS** 

_Added April 2018_ 

Adding, deleting or modifying keys while iterating will render the iterator unpredictable, and thus should be strictly avoided. You may, however, modify the values of the key-value pairs as you iterate through them, either by using the .KEY() function or by assigning a new value to the iterator directly; see _History_ below. For example, the loop below shows both methods of modifying the value of each element by prefixing it with “Beautiful” and folding the preexisting part to upper case, assuming _varstr_ elements: 

```
foreach $$i in $capitals() ! fwd iterator
```

```
    $capitals(.key($$i)) = "Beautiful " + ucs($$i)    ! method 1
! or...
    $$i = "Beautiful " + ucs($$i)                     ! method 2
next $$i
```

Note that while setting an iterator to .NULL (to delete the key-value pair) is considered an error, a possible alternative would be to set the value to "" thereby preserving the key-value position in the ordmap but perhaps indicating to your own application to ignore the item. Another approach would be to copy the items you want to keep during the iteration to another ordmap. The following example illustrates both techniques, selectively copying a portion of the ordered map _$state1_ (i.e. capital cities and their states) to a new ordered map _$state2_ , which will contain just the capitals starting with "C". We also clear the value associated with the capital "Cococabana" in the source ordmap before copying it. 

```
dimx $state1, ordmap(varstr;varstr)   !  capital -> state
```

```
dimx $state2, ordmap(varstr;varstr)   !  capital (starting with C) -> state
```

```
map1 cap$,s,40
```

```
...
```

```
foreach $$i in $state1("C","Czz")     ! >= "C", <= "Czz"
```

A-Shell Reference 

Page 987 

```
    cap$ = .key($$i)
    if cap$ = "cococabana" then
        $$i = ""                      ! $state1("cococabana") -> ""
    endif
    $state2(cap$) = $$i
```

```
next $$j
```

Note that in the above example, we didn't have to introduce the temporary variable _caps$_ , but doing so probably increases efficiency by eliminating redundant use of the _.key($$i)_ operation. Ordered map operations are extremely efficient given what they involve, but they are still considerably more costly than ordinary variable or array references, particularly as the map gets large. Also note that as with other control loops, the control statements EXIT and REPEAT are available. 

## Notes: 

- This technique works with all collection types: ORDMAP, ORDMAPM, GRIDMAPS, GRIDMAPI, MLIST. 

- In the case of ORDMAPM, it is the only way to change the value of an existing element for which there are duplicate keys. 

- In the case of ORDMAP, the direct assignment to the iterator in the above example would be equivalent to ... 

- `$state1(.key($$i)) = ""` 

... except much faster, since the key lookup, deletion, and re-addition steps are all eliminated. 

- In the case of MLIST, it eliminates the need for the .ref($$i) function, (which is now effectively deprecated). 

- The iterator is only writeable when it appears on the left side of the equals sign in an assignment statement. In all other 

- cases, particularly when passing an iterator as an argument to a function, it remains read-only. 

## **History** 

A-Shell Reference 

Page 988 

- 2025 February, A Shell 7.0.1770, compiler edit 1063:  Compiler now treats explicit deletions to ordered maps during iteration as errors—i.e., invalid collection operation or reference. 

- 2023 November, A Shell 7.0.1752:  Extend FOREACH statement to gridmaps for iterating across a row. 

- 2023 October, A Shell 7.0.1751: Support for _endkey_ parameter added. 

- 2023 August, A Shell 6.5.1739:  If _startkey_ not found, iteration now starts with the next key. Previously the result would have been an empty iteration. Add support for _startkey_ to _foreach'reverse_ , which previously would have been ignored. 

- 2018 May, A Shell 6.5.1636, compiler edit 859:  the starting key in a FOREACH statement may now be any kind of expression. Previously, it only allowed a simple variable or a literal string or numeric constant; numeric literals were allowed but weren't converted to string and thus typically failed to match any items in the map. 

- 2018 April, A Shell 6.5.1633:  Writeable Interators added to A-Shell. 

A-Shell Reference 

Page 989 

## **- ORDERED MULTI MAP ORDMAPM** 

_Added October 2016_ 

Collection type ORDMAPM is equivalent to ORDMAP except it supports multiple keys of the same value. This structure is typically known as an ordered multi-map but we went with ORDMAPM instead ORDMMAP or ORDMULMAP or ORDMULTIMAP because it seemed easier to read and type. 

As with the standard ORDMAP, ORDMAPM collections are declared with the DIMX statement and support the same two variations, one with a variable length string value, the other with a variable length binary/blob value; both with a variable length string key: 

```
DIMX $mymap, ORDMAPM(varstr;varstr)
```

```
dimx $mymap, ordmapm(varstr;varx)
```

Note that are no promises regarding the internal order of elements with the same key, nor of which of those elements will be the one returned when retrieving an element by key. However, iterating through the entire array will return all of the elements. In addition, iterating from a specific key will also return all of the matches for that key. 

For example: 

```
dimx $MM, ORDMAPM(varstr;varstr)
```

```
...
foreach $$i in $MM(key$)   ! will iterate through all of the elements
....                       ! matching key$, followed by all of the
next $$i                   ! elements after key$
```

Here is a more complete example illustrating adding, iterating and deleting multiple entries for the same key: 

```
! ordmapm example - adding and deleting elements
```

A-Shell Reference 

Page 990 

```
dimx $mm, ordmapm(varstr;varstr)
```

```
map1 key1$,s,0,"one"
map1 count,b,4
```

```
$mm(key1$) = "1"        ! three elements with same key
```

```
$mm(key1$) = "uno"
$mm(key1$) = "ein"
```

```
foreach $$i in $mm()
    ? .key($$i);" --> ";$$i
```

```
next $$i
```

```
? "Deleting all $mm(";key1$;")...";
count = fn'delmapm($mm(), key1$)
```

```
? count; "elements deleted"
```

```
if .isnull($mm(key1$)) then
    ? "Confirmed: all $mm(";key1$;") deleted."
```

```
else
```

A-Shell Reference 

Page 991 

```
    ? "Error: $mm(";key1$;") still exists: ";$mm(key1$)
```

```
endif
```

```
end
```

```
!---------------------------------------------------------------------
```

```
!Function:
```

```
!   delete all elements from ordmapm matching specified key
```

```
!Params:
```

```
!   $map()  (ordmapm(varstr;varstr) [byref] - map to delete from
!   key$    (str) [in] - key to delete
```

```
!Returns:
```

```
!   # deleted
```

```
!---------------------------------------------------------------------
```

```
function fn'delmapm($map() as ordmapm(varstr;varstr), key$ as s0) as b4
```

```
    do while not .isnull($map(key$))
```

```
        fn'delmapm += 1
        $map(key$) = .NULL
```

```
endfunction
```

A-Shell Reference 

Page 992 

## **History** 

- 2016 August, A Shell 6.3.1520:  Add capability to A-Shell. 

A-Shell Reference 

Page 993 

## **- MULTI LEVEL LIST** 

_Added October 2016_ 

## **{qualifier} DIMX $arrayname, mlist(varstr)** 

## **{qualifier} DIMX $arrayname, mlist(varx)** 

MLIST, short for “Multi-level LIST,” is a bidirectional linked list, with the added feature that each element may contain a link to a child MLIST. Aside from the links, each element may contain a variable length string (varstr) or blob (varx). The MLIST is effectively a kind of tree structure, useful for representing a variety of real-world data such as disk directories and XML/JSON documents, where the ability to maintain a particular order and to efficiently insert, delete, and splice elements or branches at arbitrary points is required. 

Unlike the ORDMAP and ORDMAPM collections, there is no direct access to an element by its key; there is only direct access to the first and last elements in the list, with the ability to iterate forwards, backwards, or down from there. The order of the elements in the list is preserved based on the order in which you build it. 

The syntax for assigning and accessing elements is similar to that for ORDMAP, modeled on single-dimension array syntax. But instead of using string keys for the array index as in ORDMAP, the MLIST uses various special dot variables which act as pseudokeys. In addition, there are several new dot statements and dot functions and dot members to perform operations particular to MLISTs that cannot be easily represented with existing statements and functions. These are summarized below, following by descriptions and syntax for the various operations. 

|**Dot Variable**|**Description**|
|---|---|
|.FRONT|First element, e.g.<br>`? $m(.FRONT)`.|
|.BACK|Last element, e.g.<br>`? $m(.BACK)`.|
|.NULL|May be assigned to an element to delete any attached sublist, e.g.|



A-Shell Reference 

Page 994 

|**Dot Variable**|**Description**|
|---|---|
||`$m(.BACK) = .NULL`.|
|.PUSHFRONT|Add new element to front, e.g.<br>`$m(.PUSHFRONT) = X`.|
|.PUSHBACK|Add new element to end, e.g.<br>`$m(.PUSHBACK) = X`.|
|**Dot Statement**|**Description**|
|.POPFRONT|Remove first element from list, e.g.<br>`.POPFRONT $m()`.|
|.POPBACK|Remove last element from list, e.g.<br>`.POPBACK $m()`.|
|.SPLICE|Splice elements from one list to other, e.g.<br>`.SPLICE $$i.SUBLIST,`<br>`$REF($$j), count`.|
|.SORT|Sort elements in list by value, e.g. .<br>`SORT $m() .SORT $kids()`sorts<br>according to the collating sequence, just as the ordered map does.|
|**Dot Function**|**Description**|
|.BEFORE($$i)|Specify insertion position, e.g<br>`$m(.BEFORE($$i)) = X`.|



A-Shell Reference 

Page 995 

|**Dot Variable**|**Description**|
|---|---|
|.EXTENT($mlist)|Return number of top-level elements in specified list.|
|.REF($$i)|Return a reference to iterator location, used when modifying an element by<br>iterator, e.g.<br>`$m(.REF($$i)) = X`.|
|**Dot Member**|**Description**|
|.SUBLIST|Specify sublist of element, e.g.<br>`$$i.SUBLIST`, or<br>`$m(.BACK).SUBLIST`.|



All of the following descriptions and examples will assume the prior definition of these two MLISTs: 

```
dimx $m, MLIST(varstr)
```

```
dimx $m2, MLIST(varstr)
```

## **See Also** 

- Copy, Add, Subtract Collections 

## **History** 

- 2016 August, A Shell 6.3.1522:  Added MLIST to A-Shell 

## **Subtopics** 

- Adding MLIST Elements 

A-Shell Reference 

Page 996 

- Deleting MLIST Elements 

- Retrieving MLIST Elements 

- Splicing Lists 

- Sublist Operations 

- MLIST Parameter Passing 

- MLIST Example 

A-Shell Reference 

Page 997 

## **ADDING MLIST ELEMENTS** 

New elements may be added to the front or back of a list using array assignment syntax equivalent to that used for the ORDMAP collection, except instead of string keys, you must use one of the special dot variable pseudo keys: 

```
$m(.PUSHFRONT) = X     ! add new element to front; assign value X
```

```
$m(.PUSHBACK) = X      ! add new element at back; assign value x
```

You may also“ insert an element into the middle of the list using the special dot function .BEFORE($$i). In the following example, we scan the list until locating an element whose value is "something", and then insert a new element before it: 

```
foreach $$i in $m()
```

```
    if $$i = "something" then
        $m(.BEFORE($$i)) = x    ! insert new element before $$i position
        exit
```

```
    endif
```

```
next $$i
```

Modifying existing elements uses the same syntax as adding or inserting new elements, except with a different set of Dot Variables and Dot Functions: 

```
$m(.FRONT) = y         ! change value of first element to y
$m(.BACK) = y          ! change value of last element to y
```

To update the value of an element by iterator, you must use the special dot function .REF($$i) to return to updateable reference to the iterator (since $$i by itself is a read-only copy of the value of the element). 

A-Shell Reference 

Page 998 

```
foreach $$i in $m()
```

```
    $m(.REF($$i)) = $$i + "y"  ! update value of each element
```

```
next $$i
```

A-Shell Reference 

Page 999 

## **DELETING MLIST ELEMENTS** 

Elements can be deleted by iterating to them and then assigning .NULL to the element using the .REF($$i) function, as in the following example which deletes the element whose value is "something." 

```
foreach $$i in $m()
```

```
    if $$i = "something" then
        $m(.REF($$i)) = .NULL   ! delete the element
        exit                    ! always exit foreach loop
    endif                       ! after removing an element, as it
next $$i                        ! may invalidate the iterator
```

In addition, you can use the following dot statements to delete: 

```
.POPFRONT $m()                  ! delete first element
.POPBACK $m()                   ! delete last element
```

Note that deleting an element will also delete any sublist attached to it. 

## **See Also** 

- Sublist Operations for details on deleting sublists 

A-Shell Reference 

Page 1000 

## **RETRIEVING MLIST ELEMENTS** 

```
X = $m(.FRONT)                  ! retrieve value of first element into X
```

```
X = $m(.BACK)                   ! retrieve value of last element into X
```

```
foreach $$i in $m()             ! access by iterator
```

```
    X = $$i                     ! X receives value of iterated element
```

```
next $$i
```

A-Shell Reference 

Page 1001 

## **SPLICING LISTS** 

One or more elements from one list can be spliced on to another using the dot statement .SPLICE. Note no elements are actually allocated or deleted in this operation; they are just moved from the source list to the destination list. The general syntax for the .SPLICE statement is: 

## **.SPLICE dst-list-ref, src-list-ref {, count} {, dstpos}** 

## _dst-list-src, src-list-ref_ 

specify the destination and source lists, respectively, either as base arrays (e.g. _$m()_ or as explicit iterator references (e.g. _.REF($$i)._ 

## _count_ 

specifies the number of elements to move (defaulting to the entire _src-list-ref_ ) 

## _dstpos_ 

specifies the splice position within the destination list, according to the following: 

|**Value**|**Meaning**|
|---|---|
|-1 (default)|end of the destination list|
|0|the start of the destination list|
|n (n > 0)|after the nth item in the destination list|



Note that the dstpos parameter only applies when the destination list is expressed as a base array, e.g. $m(). Attempting to specify dstpos when the destination is expressed as an iterator or other individual element reference, e.g. .REF($$i), will result in a syntax error. 

A-Shell Reference 

Page 1002 

## **Example1** 

If _$kids()_ contains the list: "john", "fred", "sally", "pilar", and $pets() contains the list "dog", "cat", "mouse", "lizard", then: `.SPLICE $kids(), $pets(), 1, 0` 

would splice "dog" to the start of the $kids() array. 

```
.SPLICE $kids(), $pets(), 3, 2
```

would splice the first 3 pets ("dog", "cat", "mouse") after the 2nd kid, i.e. in between "fred" and "sally". 

```
.SPLICE $kids(), $pets(), 0, -1
```

would be the same as 

```
.SPLICE $kids(), $pets()
```

## i.e. would splice all of the pets (count=0), to the end of the kids (-1). 

```
.SPLICE $kids(), $pets(), 0, 0
```

would splice all of the pets to the start of the kids array. 

## **Example2** 

To splice _from_ the middle of the source list, specify a position via an iterator reference. For example, to move the 3rd and 4th items from _$m2()_ to the end of _$m1()_ ... 

```
count = 0
```

```
foreach $$i in $m2()
```

```
    count += 1
```

```
    if count = 3 then                ! 3rd iterated item
        .SPLICE $m(), .REF($$i), 2   ! splice 3rd & 4th items
        exit                         ! iterator corrupted after splice! must exit!
```

A-Shell Reference 

Page 1003 

```
    endif
```

```
next $$i
```

The _.REF($$i)_ iterator technique also works for the destination, i.e. to insert at a destination other than the end of the target list. To splice from an arbitrary Xth position in the source to the Yth position in the destination, use a double-nested FOREACH loop: 

```
! splice count elements from position srcpos in m1$() to dstpos in m2$
```

```
idst = 0                         ! counter for dest position
```

```
foreach $$i in $m2()
```

```
    idst += 1
```

```
    if idst >= dstpos then       ! $$i is the dst splice-to position
        isrc = 0
        foreach $$j in $m1()
            isrc += 1
```

```
            if isrc >= srcpos    ! $$j is the src splice-from position
                .splice .ref($$i), .ref($$j), count
                exit             ! must exit after splice!
            endif
        next $$j
```

```
        exit                     ! must exit after splice!
```

```
    endif
```

```
next $$i
```

A-Shell Reference 

Page 1004 

Note that as with other modifications to a collection, the use of .SPLICE corrupts the iterator; thus you must exit from the FOREACH loop after the .SPLICE operation. In the above example, we have to exit from both loops. 

## **History** 

- 2016 October, A Shell 1532: .SPLICE now accepts limited use of a reverse iterator, but only when the count is 1. Also, the third argument, count, can be any numeric expression. 

## **Subtopics** 

- SPLICE Parameter DSTPOS 

A-Shell Reference 

Page 1005 

## **SPLICE PARAMETER DSTPOS** 

_Added November 2016_ 

The fourth parameter, _dstpos_ , allows you to specify the splice position in the destination array. _dstpos_ may be: 

Note that this option only applies when the destination parameter is expressed as a base array, as in the above example. Attempting to specify the dstpos parameter when the first parameter is an iterator or other individual element reference will result in a syntax error. 

A-Shell Reference 

Page 1006 

## **SUBLIST OPERATIONS** 

The sublists in an MLIST structure are themselves MLISTs, so all of the above operations work the same way on sublists. However, you do need a special dot member, .SUBLIST, to specify when you are referring to the sublist for an element, rather than to the element as a member of the parent list. 

There are two ways to create a sublist, both involving the .SPLICE statement and the special .SUBLIST qualifier.  The first method involves iterating through the destination list to the element you want to attach a sublist to, and then using the .SPLICE as in the following example which splices the first 3 elements of the $mpets() list into the $mkids() list as a sublist of the element whose value is "blake": 

```
foreach $$i in $mkids()
```

```
    if $$i = "blake" then
        .splice $$i.sublist, $mpets(), 3
        exit
```

```
    endif
```

```
next $$i
```

The second way to create a sublist involves passing it as a parameter to a function or procedure, which is dealt with in a separate section below, after the discussion of deleting sublists. 

To delete a sublist, iterate to the parent element and then assign its sublist to .NULL, as in the following example which removes the sublist (whether it existed or not) from the element whose value is "something"... 

```
foreach $$i in $m()
```

```
    if $$i = "something" then
        $$i.SUBLIST = .NULL       ! delete just the sublist
        ! $m(.REF($$i)) = .NULL   ! delete the element and its sublist
```

A-Shell Reference 

Page 1007 

```
        exit
```

```
    endif
```

```
next $$
```

Assigning an element to .NULL (as in the commented-out line in the example above) deletes both the element and any sublist attached to it. 

## **See Also** 

Example program MLIST2.BP in EXLIB:[907,53] 

A-Shell Reference 

Page 1008 

## **MLIST PARAMETER PASSING** 

MLISTs can be passed by reference to functions and procedures. This is similar to the way it works with Ordered Maps except that with MLISTs there is also a variation for passing sublists. 

To pass a regular MLIST to a function or procedure, use the following syntax (nearly identical to that for ORDMAPs except for the "AS" clause): 

```
call Proc( $m() )   ! passing the entire $m list by reference
```

```
Procedure Proc( $mloc() as MLIST(varstr) )
```

```
    $mloc(.PUSHBACK) = "new element"
```

```
EndProcedure
```

The above example adds the element "new element" to the MLIST $m(). Note that the local list $mloc() is effectively just an alias for the $m() list. As with passing ORDMAP arrays and other DIMX arrays by reference, you have to initialize the array first in the calling routine. 

The pre-initialization requirement does not apply to sublists though, which are automatically initalized when passing them to another routine: 

```
call Proc( $m(.back).SUBLIST )
```

In the above example, the sublist for the last element of the $m() list is passed to the Proc procedure (given in the previous example). Note that the procedure does not know, or care, that the caller passed a sublist rather than an MLIST base reference; they are indistinguishable from the perspective of the procedure. Also note that since the sublist gets auto-initialized if necessary, the same syntax works regardless of whether the sublist initially exists. 

You can also pass a sublist of an iterator, e.g. 

```
foreach $$i in $m()
```

A-Shell Reference 

Page 1009 

```
    if $$i = "something" then
        call Proc($$i.sublist)
```

```
    endif
```

```
next $$i
```

In the above example, for each element in the MLIST $m() whose value is "something", we pass the sublist to the Proc procedure, which adds a "new element" to the end of that sublist. 

A-Shell Reference 

Page 1010 

## **MLIST EXAMPLE** 

Here is an example of an MLIST usage, following up on the MLIST exercises from the 2016 Developers Conference: a set of - " - " routines to parse a JSON document into an MLIST. This was posted in the A Shell forum under MLIST JSON. 

The representation scheme chosen here is that each MLIST element contains one of the following: 

```
code:
```

```
[]              (sublist contains array)
{}              (sublist contains object)
string          (string scalar)
scalar          (number, true, false, null)
"name":"string" (name:value pair)
"name":scalar   (name:value pair)
"name":{}       (value part of pair is object in sublist)
"name":[]       (value part of pair is array in sublist)
```

So for the following JSON document (a common sample found on the Internet)... 

```
code:
```

```
{ "store": {
    "book": [
```

```
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
```

A-Shell Reference 

Page 1011 

```
        "price": 8.95
```

```
      },
```

```
      { "category": "fiction",
        "author": "Evelyn Waugh",
```

```
        "title": "Sword of Honour",
        "price": 12.99
```

```
      },
```

```
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
```

```
        "price": 8.99
```

```
      },
```

```
      { "category": "fiction",
```

```
        "author": "J. R. R. Tolkien",
```

```
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
```

```
        "price": 22.99
```

```
      }
    ],
```

```
    "bicycle": {
```

A-Shell Reference 

Page 1012 

```
      "color": "red",
```

```
      "price": 19.95
```

```
    }
  }
}
```

... the MLIST representation would appear as shown below (using the Mlist'Multi'Level'Display() routine from mlistdemo.bsi; note that the ">" characters are just to indicate the nesting level) ... 

```
code:
```

```
> {}
  > "store":{}
    > "book":[]
```

```
      > {}
```

```
        > "category":"reference"
        > "author":"Nigel Rees"
```

```
        > "title":"Sayings of the Century"
```

```
        > "price":8.95
```

```
      > {}
```

```
        > "category":"fiction"
```

```
        > "author":"Evelyn Waugh"
        > "title":"Sword of Honour"
```

A-Shell Reference 

Page 1013 

```
        > "price":12.99
```

```
      > {}
```

```
        > "category":"fiction"
```

```
        > "author":"Herman Melville"
```

```
        > "title":"Moby Dick"
        > "isbn":"0-553-21311-3"
```

```
        > "price":8.99
```

```
      > {}
```

```
        > "category":"fiction"
        > "author":"J. R. R. Tolkien"
```

```
        > "title":"The Lord of the Rings"
        > "isbn":"0-395-19395-8"
        > "price":22.99
```

```
    > "bicycle":{}
```

```
      > "color":"red"
```

```
      > "price":19.95
```

In other words, the JSON document was mapped onto an MLIST five levels deep: 

- The top level contains just one element - {} - i.e. a single JSON object. 

- Attached to that parent node is a sublist consisting of of a single name:value pair, where the name is "store" and the value is 

- another object, stored in its sublist. 

A-Shell Reference 

Page 1014 

- The contents of the store object at the next level down consists of two name:value pairs. The first is a "book", whose value is 

- an array of books; the second is "bicycle", whose value is another object. 

- Below "books":[] we have an array of objects, each of which has a sublist containing a series of name:value pairs 

- representing attributes of the books. 

- And so on. 

Representing the JSON document in an MLIST like this may not seem like a great simplification over the original text format, particularly in this case where the JSON was already nicely formatted for human reading—although in general, that isn't necessarily the case. The advantage the MLIST structure is that because it is normalized it is thus more amenable to the use of generic routines (possibly with custom callback functions) to perform routine operations such as walking the tree, searching, formatting, etc. The Mlist'Multi'Level'Display() display routine is a simple example of such a generic routine which is able to format with standard indentation any such document. 

See the module FNMLISTJSN.BSI in SOSLIB:[907,10] for a set of ready-to-use MLIST/JSON helper routines, and MLISTJSON1.BP in EXLIB:[908,053] for a complete working example. 

Although there are a couple of helper functions to read text from the file and grab the next token, the bulk of the logic translating between the JSON and MLIST representations is all in this relatively simple (but recursive) routine: 

## `code:` 

```
!---------------------------------------------------------------------
```

```
!Function:
```

- `!   parse a JSON array or object, up to final "]" or "}"` 

```
!Params:
```

- `!   $json()  (mlist) [ref] - parsed JSON data stored here (see notes at top)` 

- `!   endtoken$ (s) [in] - ending token to look for ("]" or "}")` 

```
!Returns:
```

- `!   >= 0 for success` 

A-Shell Reference 

Page 1015 

```
!   < 0 for error
```

```
!Module vars:
```

```
!   chin, workbuf$
!Notes:
```

```
!---------------------------------------------------------------------
Function Fn'MLJ'Parse($json() as mlist(varstr), endtoken$ as s2:inputonly) as i4
    map1 locals
        map2 token$,s,0
        map2 status,i,4
        map2 bdone,BOOLEAN
        map2 subendtoken$,s,2
```

```
    level += 1
    do
```

```
        ! get next [,{,],},name:{,name:[, or scalar from file
        token$ = fn'mlj'next'token$()
```

```
        switch token$
            case "["            ! parse a new array
            case "{"            ! parse an object
                $json(.pushback) = token$
```

A-Shell Reference 

Page 1016 

```
                subendtoken$ = ifelse$(token$="[","]","}")
                status = Fn'MLJ'Parse($json(.back).sublist,subendtoken$)
                if status >= 0 then
                    $json(.back) += subendtoken$
                else
                    $json(.back) += " !!Error: missing terminator: "+subendtoken$
                endif
                exit
            case "]"
            case "}"
                status = ifelse(token$=endtoken$,0,-1)
                bdone = .TRUE
                exit
            case ""             ! no more data (error?)
                bdone = .TRUE
                status = -1
                exit
            default
                switch token$[-1,-1]
                    case "{"            ! name:{
                    case "["            ! name:[
```

A-Shell Reference 

Page 1017 

```
                        $json(.pushback) = token$
                        subendtoken$ = ifelse$(token$[-1,-1]="[","]","}")
                        status = Fn'MLJ'Parse($json(.back).sublist,subendtoken$)
                        if status >= 0 then
                            $json(.back) += subendtoken$
                        else
                            $json(.back) += " !!Error: missing terminator: "+subendtoken$
                        endif
                        exit
                    default
```

```
                        ! add an name:value, or scalar element to our list
                        $json(.pushback) = token$
                        exit
```

```
                endswitch
```

```
                exit
```

```
        endswitch
```

```
    loop until bdone
```

```
    if status < 0 then
```

```
        Fn'MLJ'Parse = -1
```

```
    endif
```

A-Shell Reference 

Page 1018 

```
    level -= 1
```

```
EndFunction
```

A-Shell Reference 

Page 1019 

## **GRIDMAPS** 

A gridmap is a variation of ordered map with two keys and one value, intended for use with data structures that can be represented by rows and columns, such as CSV files, spreadsheets, SQL query results sets, and any data values that can be plotted on a two dimensional graph. There are two variations; one uses integers for both the row and column index; the other uses integers for the row index but a string for the column. 

## **History** 

## - 2023 March, A Shell 6.5.1728:  Added GRIDMAP to A-Shell 

## **Subtopics** 

- Declaration / Creation 

- Destruction 

- Special Gridmap Functions 

- Element Assignment and Removal 

- Accessing Gridmap Elements 

- Gridmap Iteration 

A-Shell Reference 

Page 1020 

## **DECLARATION / CREATION** 

## **{qualifier} DIMX $arrayname, gridmap(int; int; varstr)** 

## **{qualifier} DIMX $arrayname, gridmap(int; varstr; varstr)** 

The first variation indexes both the row and column by integer values; range is -10M to +100M for the rows and -10K to +100K for the columns. The second variation uses a numeric row index but an alphanumeric column index—i.e. column names in a result set, column headers in spreadsheet, etc. 

A-Shell Reference 

Page 1021 

## **DESTRUCTION** 

## **REDIMX $aryname()** 

This is similar to the syntax for destroying other dynamic arrays, except here the parentheses must be empty. 

As with other dynamic arrays, gridmaps will be automatically destroyed when they go out of scope—i.e. when the function or procedure in which it was declared returns, or for global and module scope arrays, when the program ends or SBX returns. Explicit destruction is not typically necessary. 

## **See Also** 

- REDIMX 

A-Shell Reference 

Page 1022 

## **SPECIAL GRIDMAP FUNCTIONS** 

_Updated August 2023; see History_ 

|**Function**|**Type**|**Type**|**Type**|**Type**|**Description**|
|---|---|---|---|---|---|
|.EXTENT($a())||||Num|Returns the total # of values, i.e. (row,col,value) triplets, in the gridmap $a(). Returns -1<br>if the gridmap has not yet been initialized or was subsequently destroyed withREDIMX<br>.|
|.ISNULL(var)||Boolean|||Tests the expression expr for null (same as for ordered maps). Expression may be an<br>iterator, e.g. .ISNULL($$i), or a gridmap element reference, e.g. .ISNULL($a(row,col)), or<br>a string variable.|
|||||||
|.KEY($$i, 1)|||String||Returns the row key (key #1), associated with the element currently indexed by the<br>iterator $$i. See Comments below.|
|.KEY($$i, 2)|||String||Returns the column key (key #2), associated with the element currently indexed by the<br>iterator $$i. See Comments below.|
|||||||
|.MINROW($a())||||Num|Returns the first row number.|
|.MAXROW($a())||||Num|Returns the last row number.|
|.MINCOL($a(),row)||||Num|Returns the first (lowest) column number on the specified row (or -99999999 if none).<br>Applies only to gridmaps with numeric column indices, i.e. gridmap(int;int;varstr).|
|.MAXCOL($a(),row)||||Num|Same as .MINCOL($a(),row) except for the last (highest) column number on the row.|



A-Shell Reference 

Page 1023 

|**Function**|**Type**|**Type**|**Description**|
|---|---|---|---|
|.COLNUM($a(),colname$)||Num|Returns the column number associated with colname$ (or -99999999 if no match).<br>Applies to both gridmap variations. For gridmaps with numeric column indices, it scans<br>row 1 to find a value match on the colname$; the resulting column number can be used<br>(along with a row number) to directly address the gridmap. For gridmaps with string<br>column indices, it scans row 1 (presumed to be the first data row) for a key match on the<br>colname$, returning the ordinal sequence # (starting from 1) of the matching column.<br>That mainly serves just to verify the existence of the target column.|



## **Comments** 

Note that the .KEY() functions are of type string; use the VAL() function to convert the result to a numeric value suitable for comparing to row and column numbers. Otherwise you may be tripped up by the fact that "2" > 10. 

## **See Also** 

- INPCSVX.BP in the EXLIB for an example involving some of these gridmap functions. 

## **History** 

- 2023 July, A Shell 6.5.1736: .MINCOL(), .MAXCOL() and .COLNUM() added. 

- 2023 July, A Shell 6.5.1734: .MINROW() extended to work for negative row numbers. 

A-Shell Reference 

Page 1024 

## **ELEMENT ASSIGNMENT AND REMOVAL** 

Once declared, elements (i.e. row,col,value triplets) can be added to the gridmap with standard two-dimensional array assignment syntax, except for the variation with a string column index: 

```
$table(n, "Description")  = "Left-Handed Smoke Shifter"    ! string column index
```

```
$table(row,col) = 123987     ! numeric row and column indices
```

As with ORDMAP, if the specified key exists already, the operation will replace the value of the existing element. To delete an element, a special value .NULL ("dot null") is assigned: 

```
$table(row, "SerialNumber") = .NULL
```

## **Comments** 

All values in a gridmap are stored as strings. That doesn't prevent you from assigning a numeric value, as in one of the examples above; but keep in mind that it will behave as a string, i.e. auto-converted in numeric expressions but treated as text in string expressions. 

Assigning an empty string (“”) to the value of a key does _not_ delete the item. 

A-Shell Reference 

Page 1025 

## **ACCESSING GRIDMAP ELEMENTS** 

_Rewritten December 2025_ 

Gridmap elements are accessed using the same two-dimensional (row,column) array syntax as for assignments, as in the example below. 

```
dimx $items, gridmap(int; varstr; varstr)     ! alphanumeric column key
```

```
dimx $table, gridmap(int; int; varstr)        ! numeric column key
```

- `? $items(row,"SKU")` 

- `? $table(15,22)` 

You can also access the elements sequentially using Gridmap Iteration. 

Since gridmaps are conceptually equivalent to files (rows=record numbers, columns=fields), you may want to create wrapper functions to simulate record I/O—i.e., indexing by column values, accessing a row using record.field syntax, etc. See fngridutl.bsi in SOSLIB:[907,10] for a collection of such utility functions. 

A-Shell Reference 

Page 1026 

## **GRIDMAP ITERATION** 

Although you can use a regular FOR…NEXT loop to effectively iterate through the rows (and for gridmaps with numeric columns, the columns as well), keep in mind that unlike a regular two dimension array, there is no guarantee that the rows start at 1. And there is no way to use a FOR…NEXT loop to iterate through alphanumeric columns. You can use the .MINROW() and 

.MAXROW() functions to obtain the range of row numbers, and in the case of numeric columns, the .MINCOL() and .MAXCOL() functions to obtain the range of column numbers for each row. 

Alternatively, you can use a FOREACH $$I loop to iterate through the gridmap as you would through an ordered map, except that it will iterate through the columns of each row before starting on the next row.  Use the .KEY() function to determine the row and column position of the iterator. For example, to iterate through an entire gridmap, listing the row, column and cell values: 

```
foreach $$i in $map()
```

- `? "Row "; .key($$i,1); ", Col "; .key($$i,2); "-->"; $$i` 

```
next $$i
```

As with iteration through an ordered map, you can limit the range of iteration by specifying a starting starting (or a starting and ending) key, although in this case the key only applies to the row numbers. The above example could be limited to just rows 5 through 10 as follows: 

```
foreach $$i in $map(5,10)        ! iterate through rows 5-10
```

To iterate through the rows on a single column, you would have to use a FOR...NEXT loop as follows: 

```
for row = .minrow($map) to .maxrow(.map)
```

- `? row, $map(row,col)     ! (col numeric or alphanumeric, depending on gridmap type)` 

```
next row
```

A-Shell Reference 

Page 1027 

**Warning:** when iterating through numeric rows and columns, although negative values come before positive values in the iteration (as expected), the negative values in the iteration will be ordered according to their absolute value. For example, if the grid contains a range of row numbers from negative two to positive two, they will iterate in the sequence:  -1, -2, 0, 1, 2 (rather than -2, -1, 0, 1, 2). This is a consequence of the way the keys are stored as strings, and also because negative row values are mainly intended to be used for special meta data. 

## **Writeable Iterators** 

As with ordered map iterators, you can write to the value of a gridmap iterator, but deleting or modifying a key will render the iterator unpredictable. 

A-Shell Reference 

Page 1028 

## **IMPLICIT VARIABLE DECLARATIONS** 

In addition to explicit declaration of variables via MAP or DIMX statements, provided you do not use the /M COMPIL switch, you may implicitly declare variables simply by using them. In the absence of the /M switch, when the compiler sees a variable that has not previously been declared, it creates an implicit MAP statement for it, based on the following rules: 

• If the variable name ends in $, it will be auto-mapped as a string according to the default string size specified by a prior STRSIZ statement (which has a default value of 10 bytes). 

- Otherwise it will be auto-mapped as F,6 

Note: it is strongly recommended that you do not take advantage of this dubious feature, since it makes it all too easy to introduce bugs into programs via typos and misspellings of variable names. Furthermore, it is recommended that you use `COMPIL /M` to force all variables to be explicitly declared. If you are working with a large set of code which uses a lot of implicit variable declarations, an easy way to locate and create explicit MAP statements for all of the undeclared variables is to use the `COMPIL /L` switch, which creates an .LSX file listing, at the end of which will appear the auto-mapped variables. You can review the list— perhaps sort it first to help spot similar names possibly referring to the same thing—and then just yank the set of MAP statements into the source code to make those variable declarations explicit, after which you can take advantage of the /M switch. 

A-Shell Reference 

Page 1029 

## **SYSTEM VARIABLES** 

System variables are special variables that are automatically and always defined. Unlike normal variables, they cannot be explicitly mapped, and their names are not case sensitive; _DATE_ , _date_ and _Date_ all refer to the same system variable—although they are however independent of the dot variables .DATE and .TIME. They also don't have explicit date types/sizes: they are simply either numeric or string. 

You may consider them equivalent to system functions, except that they don't take any arguments. 

Note that while you cannot map normal variables whose names conflict with system variables, this restriction does not apply to members of defined structures. For example, even though DATE, TIME, and CMDLIN are system variables, the following structure members, despite their names, are ordinary variables unrelated to their system variable namesakes: 

## `DEFSTRUCT ST_EXAMPLE` 

```
    MAP2 DATE,B,4          ! (not related to system variable DATE)
```

```
    MAP2 TIME,B,4          ! (not related to system variable TIME)
```

```
    MAP2 CMDLIN,S,100      ! (not related to system variable CMDLIN)
```

```
ENDSTRUCT
```

## **Subtopics** 

- CMDLIN 

- DATE 

- DEBUG 

- TIME 

- Dot Variables 

A-Shell Reference 

Page 1030 

## **CMDLIN** 

This system variable is automatically set to contain the remainder of the command line used to start the current program. For example, if the program was started with: 

```
RUN FALALA do re mi
```

Then `A$=CMDLIN` would set A$ to "DO RE MI" (always folded to upper case). 

`xcall LSTLIN, A$,` on the other hand, would return "RUN FALALA do re mi," the complete command line with no folding. 

A-Shell Reference 

Page 1031 

## **DATE** 

The DATE system variable always contains the current date in 'separated date format' as given below. Also see the related but separate dot variable .DATE. 

Note that in order to split the DATE system variable out into the individual fields, you have to assign it to a B,4 variable that overlayss the 4 byte structure (BDATE in the example above). Setting SDATE = DATE will not work, since SDATE is an unformatted variable, which will result in a data conversion during the assignment. 

You may also use the formal structure ST_SEPDATE defined in ashell.sdf as: 

```
defstruct ST_SEPDATE          ! standard separated date format
```

```
    map2 sdate
```

```
        map3 mon,b,1          ! month of year (1-12)
        map3 day,b,1          ! day of month (1-31)
        map3 yr,b,1           ! year - 1900
        map3 dow,b,1          ! day of week (0=mon, 6=sun)
    map2 sysdate,b,4,@sdate   ! use for assigning from DATE sys var
```

```
endstruct
```

For example... 

```
++include ashinc:ashell.sdf
```

```
map1 birthdate, ST_SEPDATE
```

```
birthdate.sysdate = DATE
```

```
? "month: ";birthdate.mon;  ", day: ";birthdate.day; ", year: "; (1900+birthdate.yr)
```

A-Shell Reference 

Page 1032 

## **See Also:** 

- .DATE and .YYMMDD dot variables 

- ODTIMXS 

- ODTIM() 

- DATES[XS] 

- DSTOIXS 

- JULCVTXS 

A-Shell Reference 

Page 1033 

## **DEBUG** 

_Rewritten December 2023_ 

The identifier DEBUG can be either a read-only system variable returning the debug level as set by SET.LIT, or a standard variable, depending on the following: 

- If the /X:2 compiler switch is specified, then DEBUG is treated as the system variable, provided it has not been previously 

- mapped as a regular user variable. 

- If the /DEBUG compiler switch is specified, then DEBUG is always treated as a read-only system variable whose value is 1. 

- This is intended to allow an easy way of compiling a program in "debug mode". 

- If neither /X:2 nor /DEBUG switches specified, then DEBUG is treated as an ordinary variable. If not mapped and /M not 

- specified, it will be auto-mapped like any other unmapped variable. 

## **Example** 

```
if DEBUG then
```

```
? "--DEBUG level set to ";DEBUG
```

```
else
```

```
? "--DEBUG not set"
```

```
endif
```

If the above program was named SHOWDEBUG and compiled using the /X:2 switch, then... 

```
.SET DEBUG
```

```
.RUN SHOWDEBUG
```

- `-DEBUG level set to 1` 

A-Shell Reference 

Page 1034 

```
.SET DEBUG 9
```

```
.RUN SHOWDEBUG
```

- `--DEBUG level set to 9` 

```
.SET NODEBUG
```

```
.RUN SHOWDEBUG
```

- `--DEBUG not set` 

If compiled without the /X:2 switch, DEBUG would be treated as an unmapped variable, either initialized to 0, or if /M specified, generating an unmapped variable error. 

If compiled with both the /DEBUG and /X:2 switches, then regardless of any prior SET DEBUG statement, the result would be... 

```
   .RUN SHOWDEBUG
```

- `--DEBUG level set to 1` 

## **Comments** 

Regardless of the compiler switches, DEBUG acts like a variable and not a symbol, and thus cannot be tested by the ++IFXXX Conditional Compilation directives. 

## **See Also** 

- SET.LIT 

- DEBUG Statements 

- COMPIL.LIT 

A-Shell Reference 

Page 1035 

## **TIME** 

The TIME system variable always contains the number of seconds since the prior midnight. 

## **See Also** 

- .TIME dot variable 

- DATE 

- IDTIMXS 

- ODTIMXS 

- ODTIM() 

- TIMESXS 

A-Shell Reference 

Page 1036 

## **DOT VARIABLES** 

_Updated December 2024; see History_ 

Dot variables, so named because they begin with a period (dot), are read-only system variables useful for retrieving certain kinds of information like the date, program name, etc. In many cases, the same information is available via other methods, such as subroutines, but the dot variable approach is generally the most elegant, efficient, and transparent. They were originally considered part of the d/BASIC extensions (COMPIL /D), because most of them originated with d/BASIC. But over time, A-Shell has added its own dot variables and they are available as part of the A-Shell extensions (COMPIL/X:2). All string dot variable values are stripped of trailing spaces. 

|**Extension**|**Notes**|
|---|---|
|.ACCOUNT|Evaluates to the user’s current ppn (e.g. "100,22").|
|.ARGCNT|Number of parameters passed in the last function, procedure call, or SBX.|
|.ASFLAGS|Returns the current set of flags otherwise accessible viaASFLAG<br>xs. Note that the dot variable is read only,<br>whereas the Xcall always writes (with an optional read). The two can be used together to avoid having to call the<br>Xcall twice to set a single flag without changing any of the others. For example, to set the AF_SBXASRUN flag<br>without touching the others...<br>`XCALL ASFLAG, (.ASFLAGS or AF_SBXASRUN)`|
|.ASHEDIT|Returns the A-Shell edit and patch numbers, e.g. version 7.0.1767.1 would return 1767.1.|
|.BACK|Last element of MLIST.|
|.CCYYMMDD|Returns current date in CCYYMMDD format.|



A-Shell Reference 

Page 1037 

|**Extension**|**Notes**|
|---|---|
|.DATE|Returns the date as a decimal number which displays as MMDDYY. So March 16, 2025 should return the numeric<br>value 31625.|
|.DDMMYY|Returns current date in DDMMYY format|
|.DEVICE|Returns the user’s current device (e.g. "DSK0:")|
|.EXPERIENCE|Returns the numeric value 100 (since "experience" level is not one of the AMOS job attributes that is emulated<br>under A-Shell).|
|.FALSE|.TRUE and .FALSE may be used as self-documenting replacements for -1 and 0.|
|.FN|Alias for the variable holding the return value of a function. SeeReturn Expression<br>.|
|.FN'xxx|Used to simplify referencing the result of a previously called function without having to map a variable and<br>explicitly assign the value to it. SeeImplicit Function Return Value Capture<br>.|
|.FRONT|First element of MLIST.|
|.JOBNAME|Returns the jobname.|
|.LAST_LABEL|Name of last label passed. Requires++PRAGMA TRACK_LAST_LABEL.|
|.LAST_ROUTINE|Name of last called function or procedure. Requires++PRAGMA TRACK_LAST_ROUTINE.|



A-Shell Reference 

Page 1038 

|**Extension**|**Notes**|
|---|---|
|||
|.LINENO|Returns the last line number, similar to ERR(1) except without requiring an error. Not to be confused with the dot<br>function .LINENO(ch), which returns the physical line # since the last page break in the output file open on the<br>specified channel.|
|.LOCATION|Returns the current program location counter, i.e. the offset in bytes from the start of the current program (RUN,<br>LIT or SBX) to the current statement position. Note that the location counter is generally represented in hex (as<br>it appears in the LSX file<br>created by the compiler /LF switch), so you would probably want to print it using the<br>SOSLIB function Fn'Dec2Hex(.LOCATION).|
|.MILLITIME|Returns number of milliseconds since midnight.|
|.MICROTIME|Returns number of microseconds since midnight. Note that due to quirks of the system scheduling clocks on<br>different platforms, the resolution of the results may not be as granular as one might expect.|
|.MMDDYY|Returns current date in MMDDYY format.|
|.MONTH|Returns the three character abbreviation for the current month.|
|.NEST_LEVEL|Number of levels deep with nested function/procedure calls.|
|.NULL|Special string value distinguished from the empty string "" with particular uses. Also see.NULL Files<br>.|
|.PGMNAME|Returns the current program name.|



A-Shell Reference 

Page 1039 

|**Extension**|**Notes**|
|---|---|
|.PGMVERSION|Returns the current program version (e.g. "1.2A(100)").|
|.PID|Returns the current process ID, same asMX_GETPID<br>xs.|
|.PUSHFRONT|Add new element to front of MLIST.|
|.PUSHBACK|Add new element to end of MLIST.|
|.SBXNAME|Returns name of current SBX or "" if not applicable.|
|.SBXVERSION|Returns version string for current SBX or "" if not applicable.|
|.TERMINAL|Returns the current TRMDEF name.|
|.TIME|Returns the current time, in HHMMSS format.|
|.TRUE|.TRUE and .FALSE may be used as self-documenting replacements for -1 and 0.|
|.USERNAME|Returns the user name.|
|.YYMMDD|Returns the current date in YYMMDD (String) format.|



A-Shell Reference 

Page 1040 

## **See Also** 

- Dot Functions 

## **History** 

2024 December, A-Shell 7.0.1767:  Version patch number added to .ASHEDIT. 

- 2020 July, A Shell 6.5.1687, compiler edit 935:  Add new variables .MILLITIME, .MICROTIME. Use of these will tag the RUN file as requiring A-Shell version 6.5.1687 or higher to 

run. 

- 2020 July, A Shell 6.5.1685, compiler edit 933:  Add new 

variables .SBXNAME, .SBXVERSION, .CCYYMMDD, .MMDDYY, .DDMMYY, .RECSIZ(). Use of these will tag the RUN file as requiring A-Shell version 6.5.1685 or higher to run. 

- 2016 December, A Shell 6.3.1538, compiler edit 792: Add .LINENO and .LOCATION 

- 2016 September, A Shell 6.3.1528:  Add .ASHEDIT 

- 2016 September, A Shell 6.3.1524:  Add special file name .NULL 

- 2014 October, A Shell 6.1.1391, compiler edit 710: Add .TRUE and .FALSE 

A-Shell Reference 

Page 1041 

## **.ARGCNT** 

_Rewritten June 2020_ 

.ARGCNT evaluates to the number of arguments passed to the current SBX, function or procedure, or -1 if not applicable. The value remains valid throughout the scope, i.e. despite prior calls to other SBXs, functions, or procedures from within the current scope. 

## **History** 

- 2016 November, A Shell 6.3.1534, compiler edit 790:  use of .ARGCNT within a PRIVATE_BEGIN / PRIVATE_END block now generates a compile error. Although the expression wouldn't technically be illegal, because the PRIVATE block is essentially called for initialization by whatever function or procedure in the module gets called first, there is really no good way to predict in advance what the .ARGCNT value will represent, and thus it is almost certain to create a discrepancy between the expected and actual behavior. 

- 2012 November, A Shell 6.0.1262:  The current .ARGCNT value (# of arguments passed to the current subroutine, function or procedure) is no longer wiped out by calls to functions or procedures. This eliminates the need to copy it to a local variable immediately upon entrance into a routine. 

A-Shell Reference 

Page 1042 

## **.NULL** 

_Updated January 2026; see History_ 

This string dot variable represents a special null value meant to represent "nothing", and is separate from the empty string "". If printed, it typically appears as "<null>" (except within a concatenation expression, see _History_ below), but it should be referenced exclusively by the dot variable .NULL, or the dot function .ISNULL(var). It has a variety of particular uses, including: 

- An attempt to access an ordered map pair by its key will return .NULL if there is no such element. See Ordered Maps: 

- Accessing Elements. 

- An existing ordered map pair may be deleted by assigning its value to .NULL,  whereas assigning it to the empty string "" 

- merely changes the value of the item without deleting it. See Ordered Maps: Accessing Elements. 

- Similarly, an MLIST element may be deleted by assigning it the value .NULL. See Deleting MLIST Elements. 

- It is also used with the MLIST sublist to indicate a non-existent sublist, or to delete one. See Multi-level List Operations. 

- When passing complex types (collections, iterators, etc.) to functions, .NULL may be used to indicate that nothing was 

- passed. 

- Sequential files opened with the filename .NULL have certain special properties. See .NULL Files. 

## **See Also** 

- IFE$() 

- ISEMPTY() 

## **History** 

- 2026 January, A Shell 7.0.1782:  String concatenation operation now converts .NULL operands to "" rather than "<null>" except within TRACE and DEBUG statements. 

A-Shell Reference 

Page 1043 

## **OPERATORS** 

The following table lists all of the built-in operators, according to the order of precedence. 

|**Operato**<br>**r**|**Precedence**<br>**1=highest**|**Description**|
|---|---|---|
|^|1|Raise to power, e.g. 5^3 is 5 to the 3rd power or 125|
|**|1|Equivalent to ^|
|+|2|Unary plus|
|-|2|Unary minus|
|*|3|Multiplication|
|/|3|Division|
|+|4|Addition or string concatenation|
|#+|4|Explicit addition; seeExplicit Plus Operators|
|$+|4|Explicit concatenation; seeExplicit Plus Operators|
|-|4|Subtraction|
|=|5|Relational equals, e.g. IF A = B OR C = D THEN ...|
|<|5|Relational less than; string or numeric|
|<=|5|Relational less than or equals; string or numeric|
|>|5|Relational greater than; string or numeric|
|>=|5|Relational greater than or equals; string or numeric|
|<>|5|Relational not equal; string or numeric|
|#|5|Relational not equal; same as <>|
|NOT|6|Logical NOT, e.g. IF NOT (A OR B) THEN ...|
|AND|7|Logical AND|



A-Shell Reference 

Page 1044 

|**Operato**<br>**r**|**Precedence**<br>**1=highest**|**Description**|
|---|---|---|
|OR|7|Logical OR|
|XOR|7|Logical XOR; exclusive OR|
|EQV|7|Logical equivalence; exclusive NOR|
|MIN|7|Minimum (of two operands), e.g. A = B MIN C + D|
|MAX|7|Maximum (of two operands), e.g. A = B + C MAX D + E|
|MOD|7|Modulo, e.g. A = 37 MOD 8 (remainder of 37 / 8)|
|USING|8|Formatting, e.g. A USING "###.##"|



## **Subtopics** 

- Implicit String Conversion 

- USING Mask 

- Unary Operators 

- Overloaded Plus Operator 

- Explicit Plus Operators 

- Explicit Comparison Operators 

- Binary Arithmetic and Logical Operators 

- Boolean Bitwise Arithmetic 

- Logical vs. Arithmetic Operators 

A-Shell Reference 

Page 1045 

- Shortcut Operators 

- Substring Operator 

- Copy, Add, Subtract Collections 

A-Shell Reference 

Page 1046 

## **IMPLICIT STRING CONVERSION** 

One somewhat unique—or at least quirky—feature of ASB is the implicit or automatic conversion strings to numbers, and vice versa, according to the statement context. For the most part this is intuitive and may even go without notice, but the fact that the + operator acts as addition for numeric arguments but concatenation for string arguments can easily lead to unexpected results if you're not aware of the way it works. The basic principle is that every expression, whether a literal value, a variable, or a more complex expression involving operators and functions, is either considered to be a number or a string. As the compiler parses statements, it is always in one state or other, i.e. numeric or string, based on the types of the arguments and operators it has seen so far, and when it runs into an operand that doesn't match the current expression state, it inserts a conversion operation into the expression so that each operand matches the current expression state. An example will make this more clear. Consider the following code: 

```
op1 = 12.3
op2 = 4.56
```

```
op3 = 7
```

```
result = (op1 + op2 - op3) using "###.#"
```

If none of these variables were mapped and the /M switch was not specified, the compiler would auto-map them as numeric F variables and process the final statement as follows: 

- The l-value, result, is numeric, so that sets the initial expression mode. 

- The next operands, op1, is numeric, matching the current mode, and the mode remains numeric. 

- Since the mode is numeric, the + operator is compiled as addition, and the mode remains numeric. 

- The next operand, op2, is also numeric; the result is the numeric 16.86, and the mode remains numeric. 

- The - operator is always numeric. 

- The next operand, op3, matches the mode so the subtraction proceeds, resulting in the numeric value 9.86. Mode remains 

- numeric. 

A-Shell Reference 

Page 1047 

- The using operator expects to start in numeric mode (the value to be formatted) but then expects the next argument to be 

- a string (the mask), and the result is string. So now the expression mode is string. 9.86 using "###.#" results in "9.9". 

• Finally the assignment operator = is processed. It's a mixed mode operator with the rule being that the r-value type must be converted to match the l-value type. In this case, the l-value, result is numeric, and the r-value ("9.9") is a string, so the compiler inserts a VAL() operator into the expression to convert the string "9.9" to a number that can be assigned to and stored in a numeric variable. 

Now let's make it more interesting by mapping the variables as follows: 

```
map1 result,s,10
```

```
map1 op1,f,6
```

```
map1 op2,f,6
```

```
map1 op3,s,8
```

The introduction of strings into the mix causes the expression evaluation logic to change: 

- The first token encountered, result, is now a string variable, causing the expression mode to be set to string. 

- The first operand, op1, is numeric. Since that doesn't match the current expression mode, the compiler effectively 

- converts it to STR(op1), and the mode remains string. 

- Since the expression mode is string, the + operator is compiled as concatenation and expects the next argument to be 

- string (i.e. the expression mode remains string). 

- The same goes for the next operand, op2, i.e. it gets converted to STR(op2) to match the current expression mode of 

- string. The result of the concatenation is "12.34.56". 

• The - operator is always numeric; since that does not match the current expression mode, the compiler inserts a VAL() function into the expression to convert the string "12.34.56" to a number, resulting in the value 12.34. String to numeric conversion stops at the first character that isn't legal for numbers, which in this case is the second decimal point. The expression mode changes to numeric. 

A-Shell Reference 

Page 1048 

- The next operand, op3, is a string, which doesn't match the expression mode, so the compiler converts it to VAL(op3). The 

- subtraction 12.34 - 7 = 5.34 is carried out and the expression mode remains numeric. 

• The next operator, using, expects to start in numeric mode (with the current expression numeric value to format), but it expects the next argument to be a string (the mask), so it changes the expression mode to string. 

• The next argument "###.#" is a string as expected; the formatting operation is carried out resulting in the string "5.3" (due to the mask rounding), and the expression mode remains string. 

- Finally the assignment operator = is processed. As in the previous example, the compiler inserts a VAL() operator into the 

- expression to convert the string "5.3" to a number that can be assigned to and stored in a numeric variable. 

As the above example illustrates, the implicit string/numeric conversion, combined with the dual addition/concatenation treatment of the + operator can cause unexpected results if you're not careful. Which leads to the question of how to avoid such confusion. There several possibilities: 

- Avoid using string variables in arithmetic expressions, or numeric variables in string expressions. 

• Insert your own explicit STR() and VAL() functions to make your intentions explicit. Note that although it may be redundant, there is nothing illegal about VAL(x) where x is already a numeric expression or variable. This is because numbers can always be represented as strings and it is both understood and expected the value of a string like "ABC" is going to be zero. The reverse, however, is not true. STR("ABC") evaluates to "0", not "ABC". This is because the STR() function expects a numeric argument; if it gets a string argument instead, it first converts it to a numeric argument, in this case effectively become STR(VAL("ABC")). The same goes for the VAL() function, i.e. VAL(27) actually gets compiled as VAL(STR(27)), but VAL("27") is still 27. 

- Avoid the addition vs. concatenation confusion of the + operator by using Explicit Plus Operators instead, or perhaps the 

- NUMEXPR() and STREXPR$() functions. 

## **Also See** 

- Forum discussion: Displaying the Total of 2 Numeric Values 

- Forum discussion: STR() Conversion Quirk 

- NUMEXPR() 

A-Shell Reference 

Page 1049 

- STREXPR$() 

- Explicit Plus Operators 

A-Shell Reference 

Page 1050 

## **USING MASK** 

_May 2015_ 

USING creates a formatted string expression based on a coded "picture" of how the value(s) should appear. The mask may be multi-field or single-field. The multi-field case is only used in the PRINT statement, prior to the list of values, e.g.: 

## _**num**_ **USING** _**mask**_ 

## **PRINT USING** _**mask**_ **,** _**v1**_ **{, ...,** _**vn**_ **}** 

Where: 

_num_ is a numeric expression. 

_v1_ thru _vn_ are string or numeric expressions. 

_mask_ is a string describing how to format the value(s), according to the rules described below. 

Note that while similar, the two cases shown above are distinct in important ways. 

The first form, _num_ USING _mask_ , is a string expression, made up of a numeric value, the USING operator, and a string mask, which returns a string—i.e. the value formatted as a string. As a string expression, it can be used anywhere a string expression can be used. Note that the expression preceding the USING operator must be numeric, and that the mask should contain format instructions for only a single value, plus optional literal characters. Another name for this would be a Single Valued Numeric USING Expression. Examples: 

```
PRINT #0, "Batting average: ";(HITS / AT'BATS) using "N.###"
```

```
TOTAL$ = (QTY * PRICE * (1 - DISCOUNT)) USING "Your total is: $#####.##"
```

In the second form, USING _mask_ is an optional clause affecting the operation of the PRINT statement. Another name for it would be a PRINT USING Clause. In this case, the mask should contain formatting instructions for the same number of values as will be supplied as arguments to the PRINT statement. This kind of mask can deal with a mixture of numeric and string values, whereas the Single Valued Numeric USING Expression can only deal with numeric formatting. For example: 

A-Shell Reference 

Page 1051 

```
MASK$ = "Name: \-------------\ Age: ###     Sex: ! Score: ###.#%"
```

```
PRINT #0 USING MASK$, name$,age,sex$,hits*100/tries
```

While the masks are intended to be somewhat self-explanatory, the interpretation of the various special characters is described in the following table. Note that for clarity, an underscore character is used to show a space in the Result column. 

|**Specifie**<br>**r**|**Description**|**Example (produces --->)**|**Result**|
|---|---|---|---|
|#|Marks a position to be filled by a numeric digit or leading minus sign. Masks<br>allowing for more digits than necessary will result in right justification with<br>leading spaces; see Z. Fractional values will be rounded to the nearest integer<br>unless the mask contains a decimal point.|123 using "####"<br>123.6 using "###"|_123<br>124|
|Z|To replace leading spaces with leading zeroes, replace all but the first # with Z.|123 using "#ZZZ"|0123|
|.|(period) Marks the position of the decimal point. Any # characters to the right of<br>the of the decimal point will be zero-filled.|123 using "###.##"|123.00|
|,|(comma) Causes thousands separators to be output between each three digits.|123456 using "###,###"|123,456|
|$|Outputs the currency symbol at the specified position; may be leading or<br>trailing.|123 using "$#####.##"|$ 123.00|
|$$|Same as $ but when used in the leading position, shifts the currency symbol<br>over to immediately before the first digit with the leading spaces in front of the<br>currency symbol.|123 using "$$#####.##"|_$123.00|
|*|A format mask starting with two asterisks followed by a dollar sign will act like<br>the $$ case but will replace the leading spaces with asterisks.|123 using "**$#####.##"|****$123.00|
|^|Outputs exponential format.|12345 using<br>".####^^^^"|.1236E05|



A-Shell Reference 

Page 1052 

|**Specifie**<br>**r**|**Description**|**Example (produces --->)**|**Result**|
|---|---|---|---|
|-|(minus sign) When put at the trailing end of a numeric mask, causes negative<br>numbers to print with a trailing minus sign. Otherwise negative values will print<br>with leading minus signs, and the minus sign takes up a position otherwise<br>available to a digit.|-123 using "#####"<br>-123 using "####-"<br>123 using "####-"|-123<br>123-<br>123_|
|\|(String specifier, PRINT USING clause only) A pair of backslashes marks a string<br>field in the multi-field version of the USING clause. If the string value is too long<br>it will be truncated. Characters between the backslashes each define a position<br>in the output but are not printed, allowing you to use self-documenting<br>descriptions instead of dashes or blanks.|using "Name: \-----\ Age:<br>##",<br>nam$, Fn'Age(dob)|Name: Jack   Age:<br>99|
|!|(String specifier, PRINT USING clause only) Defines a single-character field.|using "Sex: ! Age: ##",<br>gender$, age'nearest|Sex: M   Age: 25|
|!|(Single Valued Numeric USING Expression only) Behaves like ".", except that if<br>there are no non-zero digits to the right of the decimal point in the formatted<br>output, it changes the decimal point in the formatted output to a space. Note<br>that "!" is also used to denote a single character field in a PRINT USING MASK<br>statement. The two different uses of the same mask character should be clear to<br>the interpreter from the context.|See "Examples" below||
|N|Behaves the same as "#", except that when placed after a decimal point, it<br>causes any trailing zeros to be converted to blanks. If placed before the decimal<br>point, and it is not followed by any "#" character prior to the decimal point, then<br>it causes leading zeros to be convered to blanks. This is similar to the normal<br>case with "#", except that for values less than 1, "#" will display a leading zero<br>whereas "N" will not. SeeN Character Handling<br>.|See "Examples" below||
|n|Behaves just like "N", except that to the left of the decimal point it causes<br>leading blanks to be stripped, and to the right of the decimal point, trailing<br>blanks to be stripped. SeeN Character Handling<br>.|See "Examples" below||
|Any<br>other<br>characte<br>r|Treated as a literal.|123 using "[A-###]"|[A-123]|



A-Shell Reference 

Page 1053 

## **Examples (!, N, n)** 

```
1234.5 using "$$###,###.###"  displays "   $1,234.500"
1234.5 using "$$###,###.NNN"  displays "   $1,234.5  "
1234.5 using "$$###,###.nnn"  displays "   $1,234.5"
1234.5 using "$$###,###!nnn"  displays "   $1,234.5"
1234.5 using "$$nnn,nnn!nnn"  displays "$1,234.5"
1234.5 using "nnn,nnn.nnn$"   displays "1,234.5  $"
1234.0 using "$$###,###!NNN"  displays "   $1,234    "
1234.0 using "$$###,###!nnn"  displays "   $1,234"
1234.0 using "$$nnn,nnn!nnn"  displays "$1,234"
1234.0 using "$nnnn,nnn!nnn"  displays "$   1,234"
0 using "###.#"               displays "  0.0"
0 using "###.N"               displays "  0. "
0 using "NNN.n"               displays "   ."
0 using "NNN!n"               displays ""
0 using "nnn.N"               displays ". "
0 using "nnn!N"               displays ""
0 using "nnn.n"               displays "."
0 using "nnn!n"               displays ""
1.23 using "n.###"            displays "1.230"
```

A-Shell Reference 

Page 1054 

```
0.23 using "n.###"            displays ".230"
```

## **Comments** 

For numeric specifiers, the maximum width of the formatted number will be equal to the total number of characters in the specifier, including the special characters. If the number doesn't fit in that space, the result will be a percent sign (%) followed by the number with default numeric formatting. In the case of string specifiers, the string will simply be truncated to fit the specifier. 

String specifiers can only be used in the multi-field variation of the USING MASK clause, i.e. `PRINT #CH USING MASK$, expr1, expr2,...` 

Although the decimal point, comma, and dollar sign characters in the mask are invariable, the actual decimal, thousands separator and currency symbols used in the formatted result will be based on the Language Definition. 

Although the USING operator is primarily associated with PRINT statements, the single-field version may be used like any other string expression, such as in Assignment Statements, as parameters to functions, etc. They are often used as a convenient and elegant way to round results in arithmetic operations. For example, in the following statement the formatting mask is being used as a convenient way to round each item total to an even number of cents: 

```
TOTAL = (QTY * PRICE) USING "#######.##"
```

Note that what really happens in the above assignment statement is that the floating point result (QTY * PRICE) is rounded to the nearest cent and then represented as a string, which is then converted back to a floating point value stored in TOTAL. This technique is a good solution to the problem of making sure the internal values exactly match the printed values so that, for example, column totals add up as expected. Traditional arithmetic approaches to rounding are more syntactically complex and run the risk of deviating from the way the printed results are rounded.) However, when using masks for rounding purposes, make sure there are no non-numeric characters in the mask (dollar signs and commas in particular), and that the mask is big enough to handle any possible value (since the leading % in an overflow will cause the result to evaluate to zero). 

## **See Also:** 

- Shortcut Operators for a special case of USING. 

**History** 

A-Shell Reference 

Page 1055 

2015 May, A-Shell 6.1.1410: Add additional N Character Handling. 

- 2015 April, A Shell 6.1.1407:  Add specifiers !, N, n. 

A-Shell Reference 

Page 1056 

## **N CHARACTER HANDLING** 

_Revised May 2026_ 

The characters **N** and **n** characters in PRINT USING MASK expressions present a potential ambiguity problem as to whether to treat them as literal or as special mask specifiers. To resolve this ambiguity, the following rules are applied: 

- If immediately preceded by another alphabetic character, treat as literal 

- If there are any other alphabetic characters anywhere to the right of the N or n, up to the end of the mask, treat as literal 

- Otherwise (i.e., if immediately preceded by a non-alphabetic character, with no alphabetic characters to the right), treat 

- as numeric field mask specifier. 

For example: 

```
PRINT USING "Neg. scans: NNN", X
```

```
PRINT USING "Neg. scans: NNN (total)", X
```

```
PRINT USING "Neg. scans: #nn (total)", X
```

In all three statements, the "N" in "Neg." and the "n" in "scans" are treated as literals, since they are adjacent to alphabetic characters. 

In the first statement, the "NNN" acts as a mask, because there are no subsequent non-alphabetic chars. In the second, the "NNN" is treated as a literal, because of the trailing alphabetic chars in "total". In the third, the "#nn" is treated as a mask because "#" is an unambiguous leading mask character. 

Note that this limitation effectively disables the use of the leading "N" and "n" mask characters in PRINT USING MASKs containing trailing text, but it doesn't affect the use of "N" or "n" as trailing mask characters (e.g. "##.nn"), and doesn't generally affect the common case of `<VALUE> USING MASK` expressions unless they contain trailing alphabetic characters, which is odd but legal. 

## **History** 

- 2015 May, A Shell 6.1.1410.1:  Revise handling of N and n characters in the mask to match the above description. Previously, all **N** and **n** characters were treated as numeric mask specifiers. 

A-Shell Reference 

Page 1057 

## **UNARY OPERATORS** 

|**Function**|**Description**|
|---|---|
|NOT|Bitwise inversion of operand. This is generally used as a logical operator, but care<br>should be taken when dealing with any values other than 0 (FALSE) and -1 (TRUE).<br>(NOT 0 is -1 and NOT -1 is 0, but applying NOT to any other non-zero (i.e. TRUE)<br>values just returns another non-zero (also TRUE) value, which can easily lead to<br>confused logic.|
|-|Unary minus, arithmetically negates the value of the operand.|



A-Shell Reference 

Page 1058 

## **OVERLOADED PLUS OPERATOR** 

The overloaded plus operator ( + ) performs either addition or concatenation, depending on whether the arguments are strings or numbers. How does this work with Mode Independence, which automatically converts between numbers and strings according to the operator and statement context? It depends on the type of the operand to the left of the plus sign. If it is a string expression, then the operation is concatenation and the right-side expression will be converted to string if necessary. Otherwise, the operation is addition and the right-side expression will be converted to a number if necessary. Determining the type of the left operand isn't always so obvious though, since it may be affected by a prior implicit conversion. Assignment Statements, for example, will expect the first operand after the equals sign to be of the type of the destination, and if not, will convert it accordingly, which could then affect how a subsequent + operation is interpreted. The following examples may help clarify this. 

```
10 map1 num,f,6
```

```
20 map1 s$,s,10
```

```
30 print "1" + 2              ! "12" (concatenation)
```

```
40 print 1 + "2"              ! "3"  (addition)
```

```
50 num = "1" + 2              ! num = 3
```

```
60 s$ = "1" + 2               ! s$ = "12"
```

```
70 num = 1 + "2"              ! num = 3
```

```
80 s$ = 1 + "2"               ! s$ = "12"
```

The print statement (line 30 and 40) accepts either numeric or string argument expressions and does not coerce them either way, so the compiler decides between concatenation or addition purely on the type of the left operand with the results as shown in the comments above. Assignments, however, expect the first operand to the right of the equals sign to match the type of the destination variable, and will convert it if needed. So in the assignment on line 50, even though the left operand of the + is a 

A-Shell Reference 

Page 1059 

string, it gets converted to a number to match the type of the destination variable (num), which in turn forces the + to be treated as addition. On line 60, since the destination s$ is a string, the left operand "1" also remains a string, which forces the + to be treated as concatenation, with the right operand 2 converted to the string "2". Line 80 shows the reverse effect, with the left operand 1 being converted to the string "1" because the destination is a string, and that causes the + to be treated as concatenation. 

You can use the functions STR$() and VAL(), which convert numeric expressions to string and vice versa, to coerce this behavior, although that too can be confusing. For example: 

**==> picture [271 x 10] intentionally omitted <==**

```
110 s$ = val("1") + 2           ! s$ = "12"
```

You might have expected the `STR$(1)` in line 100 to force that operand to be a string expression and thus force concatenation, but it gets overridden by the implicit conversion in the assignment statement, i.e. `STR$(1)` effectively becomes `VALl(STR$(1))` . Conversely, in line 110 val("1") converts the "1" to a numeric 1, but it is overridden by the implicit conversion back to string for the assignment to the string variable s$, which results in the + operator being treated as concatenation. 

If you have to do arithmetic or concatenation with a mixture of string and numeric expressions and find yourself unsure, the best approach is to break up your logic into multiple statements—possibly using temporary variables—to avoid the implicit conversions. Or, use the unambiguous addition and concatenation operators and/or casting functions added in A-Shell 6.5.1655. 

## **See Also** 

- .VALX() 

A-Shell Reference 

Page 1060 

## **EXPLICIT PLUS OPERATORS** 

_Added February 2019_ 

The #+ and $+ operators may be used as unambiguous alternatives to the + operator, eliminating any doubt as to whether the operation will be addition (#+) or concatenation ($+). This is particularly useful in the context of DYNSTRUCTs, since the compiler is unable to know at compile time the types that the members will be bound to at run time, which could easily lead to confusion in a statement like: 

```
foo.bar = a + b         ! addition or concatenation?
```

If foo is a DYNSTRUCT, then the compiler will treat foo.bar as a string (without knowing its eventual bound type). So that would cause it to compile the + in the above statement as concatenation. 

To avoid such confusion (and logical errors), use the unambiguous operators, e.g.: 

```
foo.bar = a #+ b        ! addition
```

```
foo.bar = a $+ b        ! concatenation
```

Note that since "$" could be a suffix on a variable, the $+ operator must be preceded by a delimiter (preferably a space for clarity), else the compiler may try to associate it with the prior variable name, i.e. 

```
a = b$+c                ! compiler reads as b$ + c
```

```
a = b $+ c              ! compiler reads as b $+ c
a = b$$+c               ! compiler reads as b$ $+ c
```

Note that these unambiguous operators achieve the same objective as the casting functions NUMEXPR() and STREXPR$(). You can freely mix and/or combine them for clarity, but generally only one method of resolving ambiguity is necessary. 

## **History** 

- 2019 February, A Shell 6.5.1654, compiler edit 890:  Added to A-Shell. 

A-Shell Reference 

Page 1061 

## **EXPLICIT COMPARISON OPERATORS** 

_Added February 2019_ 

|**Operator**|**Description**|**Operator**|**Description**|
|---|---|---|---|
|#>|numeric greater than|$>|string greater than|
|#>=|numeric greater than or equal|$>=|string greater than or equal|
|#<|numeric less than|$<|string less than|
|#<=|numeric less than or equal|$<=|string less than or equal|
|#=|numeric equal|$=|string equal|
|##|numeric not equal|$#|string not equal|
|#<>|numeric not equal|$<>|string not equal|



These are equivalent to the traditional comparison operators except that instead of the type of comparison being determined by the type of the leading value, here the type of comparison is established by the relative operator, which in turn may cause the leading comparator to be converted accordingly. 

They are mainly useful when working with dynstruct members, which are treated by the compiler as strings, but which may be bound at runtime to numeric variables. If you know that you are working with a variable that should be treated as a number (or 

A-Shell Reference 

Page 1062 

will be bound to a number), then using the explict-type comparisons will force the compiler to generate the comparison that you want, rather than the code that it thinks is appropriate. 

For example: 

```
if foo.price > foo.value then ...
```

```
if foo.price #> foo.value then ...
```

If foo is a dynstruct, then the compiler will treat foo.price and foo.value as strings, so it will interpret the first greater than operator as a string comparison. If foo.price and/or foo.value get re-bound to numeric variables at runtime, the string-type comparison will not yield the intended result. The second statement above resolves this by forcing the compiler to generate code for a numeric comparison. 

Note that these operators are purely compiler constructs and do not require a corresponding update of the runtime system. 

## **See Also** 

- Explicit Plus Operators 

## **History** 

- 2019 February, A Shell 6.5.1656, compiler edit 892:  Added to A-Shell. 

A-Shell Reference 

Page 1063 

## **BINARY ARITHMETIC AND LOGICAL OPERATORS** 

These operators are placed between the two operands that they act on (e.g. A + B, Q MAX R, etc.). Note that while some of these are typically thought of and used as logical operators, internally they all act in numeric bitwise fashion, with the logical interpretation based on whether the result is zero or non-zero. This is discussed in more detail in the following two topics. 

|**Operato**<br>**r**|**Description**|
|---|---|
|+|addition|
|-|subtraction|
|*|multiplication|
|/|division|
|^|raise first operand to power of second operand|
|**|same as ^|
|AND|bitwise AND|
|OR|bitwise OR|
|XOR|bitwise XOR|
|MAX|X MAX Y returns the larger of X and Y, i.e. equivalent to MAX(X,Y) in some other languages.|
|MIN|X MIN Y returns the smaller of X and Y, i.e. equivalent to MIN(X,Y) in some other languages.|
|=|Returns TRUE (-1) if the two operands are equal, else FALSE (0); not to be confused with = assignment operator|
|<>|not equal (reverse of =)|
|#|not equal (same as <>)|
|>|returns TRUE (-1) if the first operand is greater than the second|
|>=|returns TRUE (-1) if the first operand is greater than or equal to the second|
|<|returns TRUE (-1) if the first operand is less than the second|



A-Shell Reference 

Page 1064 

|ell Reference||
|---|---|
|<=|returns TRUE (-1) if the first operand is less than or equal to the second|
|MOD|X MOD Y returns the "modulo" of X relative to Y, i.e. the integer remainder after dividing Y into X. For example, a<br>Julian date can be converted to the day of the week using JULDATE MOD 7 (returning a value in the range of 0-6,<br>which you may then want to adjust according to what value you want to assign to what you consider the first day of<br>the week).|



A-Shell Reference 

Page 1065 

## **BOOLEAN BITWISE ARITHMETIC** 

_Reviewed and updated December 2025_ 

The Boolean operators labeled "Logical" in the Operator Table above (AND, OR, NOT, etc.) can give rise to two kinds of confusion. The first results from general confusion about the rules of Boolean logic when multiple operators are combined. For example, forgetting that [ `NOT X AND NOT Y` ] is equivalent to [ `NOT (X OR Y)` ] rather than [ `NOT (X AND Y)` ]. This isn't the place to resolve that kind of confusion; instead consult a textbook on Boolean logic. The second kind, which hopefully we can resolve here, has to do with the fact that, at least in ASB, these so-called "logical" operators are actually arithmetic operators, similar to other arithmetic operators except that they work at the bit-by-bit level with no borrowing or carrying between bits. So while you may be tempted to view the expression [ X AND Y ] as having a purely logical value, i.e. TRUE or FALSE, in fact it has a purely numeric value resulting from the bitwise ANDing operation, which can then be used like any other numeric expression, e.g. P = (X AND Y) * Z. 

The following example should make this more clear: 

```
MAP1 X,B,1
```

```
MAP1 Y,B,1
```

```
X = 1
```

```
Y = 4
```

- `? (X OR Y)       ! 00000001 OR 00000100  = 00000101 (5)` 

```
? (X AND Y)      ! 00000001 AND 00000100 = 00000000 (0)
? NOT X          ! NOT 00000001 = 11111110 (-2)
? NOT (X AND Y)  ! NOT 00000000 = 11111111 (-1)
? (X + Y)        ! 00000001 + 00000100 = 00000101 (5)
```

A-Shell Reference 

Page 1066 

This is pure bitwise Boolean arithmetic. Note that negative values are represented using 2's complement notation; -1 is represented by all 1 bits. Also note that in the above example, ( `X OR Y` ) is equivalent to ( `X + Y` ), because when viewed one bit at a time, the OR and + operations are equivalent. The difference between the two only shows up when there is a carry operation, e.g. 

```
X = 1
```

```
Y = 5
```

**==> picture [364 x 9] intentionally omitted <==**

```
? (X + Y)        ! 00000001 + 00000101 = 00000110 (6)
```

So the Boolean operators are for all practical purposes like other arithmetic operators, except that the Boolean operations never result in borrowing or carrying from one bit position to the next. 

The question of truth value, i.e. is the expression TRUE or FALSE, only arises in conjunction with relational operators (=, >, <, etc.) or conditional statements (IF, WHILE, UNTIL, etc.), which convert the numeric value of an expression to TRUE or FALSE according to the simple rule: 

```
Zero is FALSE
```

```
Non-Zero is TRUE
```

If we revisit our first example above, this time using IF statements to test the logical truth value of the expressions instead of directly printing the numerical value, we get the following: 

```
10 X = 1 : Y = 4
```

```
20 IF (X OR Y)       ? "TRUE" ELSE ? "FALSE"  ! TRUE  (5)
```

```
30 IF (X AND Y)      ? "TRUE" ELSE ? "FALSE"  ! FALSE (0)
40 IF NOT X          ? "TRUE" ELSE ? "FALSE"  ! TRUE (-2)
```

A-Shell Reference 

Page 1067 

```
50 IF NOT (X AND Y)  ? "TRUE" ELSE ? "FALSE"  ! TRUE (-1)
```

```
60 IF (X + Y)        ? "TRUE" ELSE ? "FALSE"  ! TRUE (5)
```

These results follow directly from the rule just stated, that 0 is FALSE and any other value is TRUE. Yet line 30 often confuses programmers, considering that since both X and Y are non-zero—i.e. both are TRUE when considered individually—the expression (X AND Y) should be equivalent to (TRUE AND TRUE), i.e. should be TRUE. Similarly, in line 40, since X is non-zero, it must be TRUE, and therefore NOT X must be FALSE. Right? Wrong. The discrepancy is caused by the fact that the Boolean operators act arithmetically at the bitwise level resulting in a numeric value which is only converted to logical TRUE or FALSE when needed for the conditional IF statement. 

A-Shell, like most other languages, does not have a specific built-in Boolean data type and relies instead on the above rule for converting numeric expressions to logical TRUE/FALSE as required by relational operators and statements. It does however have two built-in dot variables -- .TRUE (-1) and .FALSE (0) whose use is highly recommended. 

If you prefer your own variables or symbols instead, e.g. VERDADERO and FALSO, then you can either MAP them, e.g.: 

```
MAP1 LOGICAL'CONSTANTS
```

```
    MAP2 VERDADERO,B,1,-1
    MAP2 FALSO,B,1,0
```

or use DEFINE statements, e.g.: 

```
define VERDADERO = -1
```

```
define FALSO = 0
```

Although you might be tempted to use 1 for your TRUE value, and that might work in some cases, but -1 is a far better choice, since its binary representation is all 1's, and thus any bitwise operation will always be dealing with a 1 on the TRUE side. If you used 1 (i.e. 00000001), then only the first bit would get the benefit of the non-zero value and all the other bitwise operations would be dealing with zeroes (i.e. FALSE bits). See Boolean Data Type. 

A-Shell Reference 

Page 1068 

Note that when a logical expression is converted back to a numeric expression, as in the statement PRINT (X = Y), FALSE becomes 0 and TRUE becomes -1. So there is an asymmetry in the conversion back and forth between numeric and logical truth. When converting from numeric to logical, any non-zero value becomes TRUE; but when converting logical to numeric, TRUE always becomes -1. This is another reason why if you're going to define a constant TRUE, it should be set to -1. 

Also note that while the use of symbolic names for the Boolean truth values  may be convenient for the readability of code similar to the following: 

```
IF (X AND Y) THEN
```

```
    AUTHORIZED = .TRUE
```

```
ELSE
```

```
    AUTHORIZED = .FALSE
```

```
ENDIF
```

... be careful not to casually use a relational operator to compare a numeric expression directly with your constant TRUE, e.g. 

```
IF AUTHORIZED = TRUE THEN ...     ! bad!!!
```

Instead, use the logical equivalence operator EQV: 

```
IF AUTHORIZED EQV TRUE THEN ...   ! good
```

Or better yet, just test the variable directly and let the IF operator convert it from a number to a truth value: 

```
IF AUTHORIZED THEN ...            ! best
```

The problem with using the relational equals operator (=) is that the result of the expression is TRUE only if both operands are numerically equal (i.e. AUTHORIZED = -1). Almost surely what you mean to be testing is if they are logically equivalent to TRUE (i.e. both are non-zero). And since TRUE is obviously equivalent to itself, `X EQV TRUE` is the same as X, so just testing the target variable directly as in the last example is the simplest. 

To take another example: 

A-Shell Reference 

Page 1069 

```
10 define F_DOG   = &h0001
20 define F_CAT   = &h0002
30 define F_TAME  = &h0010
30 IS'PET = (ANIMAL'TYPE AND (F_DOG OR F_CAT or F_TAME))
40 IF IS'PET = TRUE THEN CALL FEED'IT    ! bad idea, pet will starve
```

```
50 IF IS'PET THEN CALL FEED'IT           ! good, pet gets fed
```

Line 30 sets IS'PET to a non-zero value if the ANIMAL'TYPE bit representation contains either of the dog or cat or tame bits. Line 40 would virtually always fail, since the result of the assignment at line 30 will almost surely not be -1 (i.e. all bits set). Line 50 shows the correct approach, since the numeric expression IS'PET will be converted to logical TRUE if any of the bits are set. 

## **Beware of Boolean combinations** 

When dealing with bit flags, we are often interested in testing whether if one among several bits is set, or if two or more bits are together set. We can use the AND operator to test if bits are set, and the OR operator to create an expression containing multiple bits that can then be tested as a group. Continuing with the pet example above, to test if our animal represented by ANIMAL'TYPE is either a dog or is tame, we can do either of the following: 

```
IF (ANIMAL'TYPE AND F_DOG) OR (ANIMAL'TYPE AND F_TAME) THEN ...  ! if dog or tame
```

```
IF (ANIMAL'TYPE AND (F_DOG OR F_TAME)) THEN ...                  ! "    "    "   "
```

So far so good.  But to test if it is a tame dog (i.e. is both a dog and tame), don't make the mistake of just flipping the central Boolean from OR to AND: 

```
IF (ANIMAL'TYPE AND F_DOG) AND (ANIMAL'TYPE AND F_TAME) THEN ... ! bad
```

```
IF (ANIMAL'TYPE AND (F_DOG AND F_TAME)) THEN ...                 ! bad
```

A-Shell Reference 

Page 1070 

The problem with both of the above statements is that F_DOG and F_TAME are non-overlapping bit patterns (&h0001 and &h0010). Thus the numeric expressions (ANIMAL'TYPE AND F_DOG) and (ANIMAL'TYPE AND F_TAME) are also going to be nonoverlapping bit patterns, so ANDing them together will always result in zero (FALSE). Even worse, the expression (F_DOG AND F_TAME) is always zero (both are constants), and anything ANDed with zero is zero, so the second conditional will might as well be a null statement . The way to test if both bits are set is to introduce relational operators to strategically convert the numeric sub-expressions to logical ones, e.g. 

```
IF ((ANIMAL'TYPE AND F_DOG) # 0) AND ((ANIMAL'TYPE AND F_TAME) # 0) THEN ... ! good
```

```
IF (ANIMAL'TYPE AND (F_DOG OR F_TAME)) = (F_DOG OR F_TAME) THEN ...          ! good
```

Here, in the first statement we used the relational operator # (not equal) to convert the numerical expressions (ANIMAL'TYPE AND F_xxx) to logical expressions (i.e. to -1 for TRUE or 0 for FALSE). That allows the central AND operator to give us a numerical result which is non-zero if both of the sub-expressions were non-zero (matching the expected logical behavior). In the second line, we mask out all of the other bits in ANIMAL'TYPE except for the F_DOG and F_TAME bits, and then use the relational operator = to numerically compare if that equals the combination of those two bits, i.e. if both bits are set. 

A-Shell Reference 

Page 1071 

## **LOGICAL VS. ARITHMETIC OPERATORS** 

Although the operators AND, OR, and NOT are generally used as if they were purely logical, in fact, in ASB they are really arithmetic (bitwise). The apparent logical nature is a side effect of the fact that in an **IF** statement (which has the general form **IF <expression>** ), after all of the operations which make up the <expression> have been evaluated, reducing the expression to a single value, the IF statement then treats the result as TRUE if non-zero or FALSE if zero. 

So, for example, in evaluating the statement `IF X AND Y THEN` ..., the expression evaluator first performs an arithmetic bitwise AND of the two operands X and Y, and if the result is non-zero, the expression is considered TRUE and the THEN clause will be executed. This is not the same as a truly logical AND, which would return a TRUE value for the expression if either A was TRUE or B was TRUE. To illustrate, consider the case where X=6 and Y=1. In binary form, this is 110 and 001, and the bitwise AND operation returns 000 (FALSE), even though each operand was individually TRUE (non-zero). This is one reason why you should always use -1 rather than 1 to represent the logical value TRUE. 

When used properly, the arithmetic bitwise nature of the operators AND, OR, and NOT may be used to advantage when dealing with bit patterns. For example, if X is a bit field (where each bit represents a flag), you can test if a one or more individual bits are set using AND. For example, the statement `IF X AND &h0011` will test whether either of the two lowest bit flags are set in the variable X. Similarly, you can use the OR operator to set the bits, e.g.: 

```
BIT1 = &h0001
```

```
BIT2 = &h0002
```

```
BIT3 = &h0004
```

```
FLAGS = FLAGS OR BIT1 OR BIT3   ! sets the first and third bit, leaving the others alone.
```

## To reset (clear) a bit, you can use the combination AND NOT: 

```
FLAGS = FLAGS AND NOT BIT2      ! clears the 2nd bit, leaving the other bits alone
```

A-Shell Reference 

Page 1072 

When creating compound IF statements involving multiple operators, it is wise to use the equals (=) and not equals (#) operators, with parentheses, to force the individual sub-expressions to be converted from bit fields to logical results. For example, instead of: 

```
IF (FLAGS AND BIT1) AND (FLAGS AND BIT3) THEN...        ! this will never be TRUE unless BIT1 and BIT3
overlap
```

## you should use: 

```
IF ((FLAGS AND BIT1)  # 0) AND ((FLAGS AND BIT3) # 0) THEN   ! TRUE if both BIT1 and BIT3 are set in FLAGS
```

The parentheses in the first expression above don't really accomplish anything, and the result of the entire expression will only be non-zero (TRUE) if BIT1 and BIT3 overlap each other and one or more "1" bits in FLAGS, which is clearly not the intended meaning. The use of the # (not equal) operators in the second expression converts the arithmetic result of each subexpression into a truth value (i.e. either -1 for TRUE or 0 for FALSE), so that the central AND will actually operate in the expected (logical) fashion. 

## **See Also** 

- .TRUE and .FALSE dot variables 

A-Shell Reference 

Page 1073 

## **SHORTCUT OPERATORS** 

_Using <mask> rewritten February 2020_ 

## A-Shell offers the following shortcut operators: 

```
var += <expr>     ! equivalent to var = var + <expr>
var -= <expr>     ! equivalent to var = var - <expr>
var *= <expr>     ! equivalent to var = var * <expr>
var /= <expr>     ! equivalent to var = var / <expr>
var |= <expr>     ! equivalent to var = var OR <expr>
var &= <expr>     ! equivalent to var = var AND <expr>
var #+= <expr>    ! equivalent to var = var #+ <expr>   (explicit addition)
var $+= <expr>    ! equivalent to var = var $+ <expr>   (explicit concatenation)
```

## **Comments** 

These require COMPIL /X:2 or /RC, but they do not have any compatibility effect on the resulting RUN module. Note that the += operator works equally well for numeric addition as well as string concatenation; see _Explicit Operators_ below. 

## **Operator Precedence** 

While the shortcut operators do not change anything about the rules of operator precedence, it may make the rules easy to overlook.  (To compound the potential confusion, the compiler handling of shortcut operators changed in compiler edit 970 - see History Notes for details.) 

For example, the syntax of the statement: 

```
a *= b + c
```

may lead one to think of it as equivalent to: 

```
a = a * (b + c)
```

A-Shell Reference 

Page 1074 

but since there are no automatic parentheses in the expansion of the shortcut syntax, the actual equivalent is simply this: 

```
a = a * b + c
```

which, due to the fact that multiplication has higher precedence than addition, is equivalent to this: 

```
a = (a * b) + c
```

Another potentially confusing case involves USING, e.g. 

```
a *= b + c USING mask$
```

Since USING has lower precedence than addition, this is equivalent to: 

```
a = ((a * b) + c) USING mask$
```

When in doubt, add your own parentheses, and if really in doubt, revert to the original equivalent syntax—i.e., without the shortcut operator. 

See History Notes below. 

## **Explicit Operators** 

Shortcut operators #+= and $+= are equivalent to the existing shortcut operator += except that they unambiguously and explicitly specify either addition or concatenation, respectively, regardless of the destination type. For example: 

```
map1 a$,s,10
```

```
dimx $num, ordmap(varstr;varstr)
```

```
map1 n,f
```

```
a$ += 1             ! sets a$ = "1"
a$ += 1             ! sets a$ = "11", e.g. "1" + "1"
a$ #+= 2            ! sets a$ = "13", e.g.  val("11") + val("2")
```

A-Shell Reference 

Page 1075 

```
? "a$ = ";a$        ! "13"
```

```
$num("one") = "1"                  ! sets $num("one") = "1"
$num("one") #+= "1"                ! sets $num("one") = "2"
$num("one") #+= $num("one")        ! sets $num("one") = "4"
```

```
? "$num(""one"") = "; $num("one")  ! "4"
```

```
n += 1              ! n = 1
n #+= $num("one")   ! n = 5, e.g. 1 + val("4")
? "n = ";n          ! 5
```

## **History** 

- 2022 March, A Shel 6.5.1712, compiler edit 970: back out edit 958 and remove the parentheses that were previously added by the compiler to the expression on the right side of the shortcut operator. 

- 2021 October, A Shell 6.5.1708, compiler edit 958: Implement special handling of a trailing USING operator. Later deleted/superceded by version 6.5.1712. 

- 2020 July, A Shell 6.5.1686, compiler edit 934:  Added explicit operators #+= and $+=. 

- 2017 May, A Shell 6.5.1605: Added vertical bar | and ampersand & shortcut operators. 

A-Shell Reference 

Page 1076 

## **SUBSTRING OPERATOR** 

(Also known as the "Slice" Operator.) In addition to more traditional BASIC substring functions LEFT$(), MID$(), and RIGHT$(), ASB also supports an array-like syntax for directly referencing substrings (aka string slices), both in general source expressions, as well as for making assignments directly to a substring. There are two variations: 

## **var[spos,epos]** 

## **var[spos;length]** 

The parameters _spos_ (starting position), _epos_ (ending position), and _length_ may be positive or negative. When positive, they are relative to the left side of the string (first position is 1). When negative, they are relative to the right side of the string (rightmost position is -1). In the case of _length_ , a negative value adjusts the ending position to the left, rather than the right. 

For example: 

```
map1 var,s,16
```

```
var = "1234567890"
```

**==> picture [205 x 106] intentionally omitted <==**

When the edge of the slice goes outside the boundaries of the string, it is effectively shifted over to the nearest edge. So `var[0,3]` is equivalent to `var[1,3]` , but note that `var[0;3]` is equivalent to `var[1;2]` , since the ending position is calculated from the requested starting position and length, before the adjustment is made. 

A-Shell Reference 

Page 1077 

Note that in the above examples, when negative _spos_ and _epos_ values were taken to be relative to the logical end of the string. But when the substring operator appears on the left side of an assignment operator, the rule changes and the indices are taken to be relative to the physical string memory allocation. Continuing the example above with the same var mapped as a 16 byte string containing "01234567890"... 

```
var[5;3] = "ABC"  : ? var        ! "01234ABC890"
```

```
var[-3,-1] = "XYZ" : ? var       ! "01234ABC890   XYZ"
```

The result of the second statement above often comes as a surprise, since it is asymmetric with the way `var[-3,-1]` is interpreted when on the right of an assignment. But as previously noted, when making an assignment directly to a substring, the indices operate on the physical rather than logical string variable. Furthermore, in the case of a string (rather than unformated) variable, any positions between the previous logical end of the string and the beginning of the assigned area will be filled in with spaces. Otherwise, the "XYZ" in the above example would not appear in the print statement because they would be beyond the first null terminator. In the case of unformated variables, there is no special filling of the intermediate positions. 

When assigning to a substring beyond the current length of a dynamic variable, the behavior depends on the A-Shell version. See History notes below. 

## **See Also** 

- Substring Assignment 

## **History** 

- 2018 June, A Shell 6.5.1639.0:  Assignments to substrings (slices) of dynamic variables now automatically extend the target variable as needed to contain the slice. Previously, the target variable was not extended, acting instead more like a fixed length variable in that case. 

A-Shell Reference 

Page 1078 

## **COPY, ADD, SUBTRACT COLLECTIONS** 

_Reviewed August 2025_ 

Collections —e.g. ORDMAP, ORDMAPM, GRIDMAP, and to a limited extent, MLIST—may be copied, added or subtracted en masse using the following overloaded operators: 

```
$map1() = $map2()       ! copy $map2() to $map1()
```

```
$map1() += $map2()      ! add $map2() to $map1()
```

```
$map1() -= $map2()      ! subtract elements matching $map2() from $map1()
```

Notes: 

- The copy operation destroys any prior contents of the destination before copying the source to it. 

- The append operation adds elements from the source collection to the destination collection. If the destination is an ORDMAP, 

- any key-value pairs with keys matching destination elements will be updated with the source value. If the source and destination are MLISTs, the append operation is equivalent to concatenating the source list to the end of the destination list. 

• The subtraction operation iterates through the source map and for each element, if the key exists in the destination map, that element is removed from the destination. If the destination is an ORDMAPM and there are multiple matching keys, only one is removed per source element (and you have no way of knowing which). Subtraction does not apply to MLIST. 

• These operations primarily make sense only for collections of the same type, i.e. ORDMAP to ORDMAP, or MLIST to MLIST. You may mix ORDMAP and and ORDMAPM, but note that the destination retains its original attributes. In other words, copying or appending an ORDMAPM to an ORDMAP does not change the fact that the destination is still an ORDMAP and thus cannot contain duplicate keys. (In this case, each source pair with a key matching an existing destination pair will result in that destination element being replaced with the new value.) Copying or appending ORDMAP collections to ORDMAPM collections makes perfect sense. The reverse is of dubious value due to the potential loss of elements with the same key. 

- Copying/appending between ORDMAP(varstr;varx) and ORDMAP(varstr;varstr) is legal, but only makes unambiguous sense 

- when copying from (varstr;varstr) to (varstr;varx). That is, the varx format can store any data, but the varstr format cannot handle embedded nulls. However, no data is actually lost in either conversion; copying from varx to varstr and back to varx should be okay. 

A-Shell Reference 

Page 1079 

## **History** 

- 2019 September, A Shell 6.5.1668, compilter edit 918:  The Shortcut Operators (+= and -=) are now accepted, along with the above longer forms. 

- 2018 November, A Shell 6.5.1650, compiler edit 888:  Add function to A-Shell 

A-Shell Reference 

Page 1080 

## **EXPRESSIONS** 

ASB expressions are combinations of variables, literal values, operators, functions and parentheses that can be reduced to a single value. Generally speaking, wherever you can use a single value or variable in a source rather than destination context, you can use an expression of arbitrary complexity. Although there are several types of variables, there are only two fundamental types of expressions: numeric—which evaluate to a floating point value—and string—which evaluate to a string. Mostly this is all quite familiar and intuitive, although there are few quirks—"mode independence", the Overloaded Plus Operator, and Boolean Bitwise Arithmetic, which see for more discussion. 

## **Mode Independence** 

This mysterious term, brought over from the original AlphaBASIC, refers to the ability to use and intermix string and numeric expressions, with the compiler and runtime interpreter performing conversions as necessary for the operations to make sense. For example, since multiplication only makes sense with numeric operands, if you supply string operands, they will be converted to numeric expressions automatically before the multiplication is performed. If a string starts with non-numeric characters, the corresponding value is simply zero. This is all fairly straightforward for operators and statements that expect a certain type of operand; the confusion comes with the _Plus_ operator, which works with both strings and numbers. 

## **See Also** 

- NUMEXPR() 

- STREXPR$() 

## **Subtopics** 

- Constants and Literals 

A-Shell Reference 

Page 1081 

## **CONSTANTS AND LITERALS** 

_Updated March 2019_ 

Constants are values fixed at compile time and thus immutable during execution. As with all ASB expressions, they come in two fundamental types: string and numeric. Each of these may be created or expressed in various ways as detailed below. 

## **Numeric Literals** 

These come in the following flavors: 

Decimal values (integer or floating point), with optional leading minus sign. Note that the decimal point character is the (American-style) period; commas are not allowed, nor is scientific/exponential notation. Examples: 

- Decimal values (integer or floating point), with optional leading minus sign and optional trailing base-10 exponent suffix or 

- "L" suffix. In most cases, these constants are stored in the compiled program as floating point values (up to 11 significant 

- digits). The exceptions are that any integer constant with an explicit "L" suffix and any hex or octal value representing more than 32 bits will be stored as 48 bit integers; see History below.  Examples: 

```
25                 ! Good:  decimal integer
```

- `-2.3               ! Good: negative decimal floating point` 

- `2.3-               ! Illegal: trailing unary minus sign not allowed` 

- `12345.67           ! Good: positive decimal floating point` 

```
12,345.67          ! Illegal: commas not allowed
```

- `1.234E5            ! Good: positive exp notation (e.g. 123400)` 

- `98765e-3           ! Good: negative exp notation (e.g. 98.765)` 

```
12345678923L       ! Good: L suffix for 48 bit integer
```

A-Shell Reference 

Page 1082 

Note that although the decimal separator character may be swapped via the LDF file (see LANGUAGE), this only affects the interpretation of numeric expressions input as data at run time; the compiler always uses (requires) the American-style decimal point (period). 

- Hexadecimal and octal values are denoted with a leading "&h" or "&o" (case sensitive), respectively; e.g. 

```
&h01c8             ! Good: hex 01c4 (456 decimal)
```

- `&hFF               ! Good: hex FF (255 decimal)` 

```
&o100              ! Good: octal 100 (64 decimal)
&H100              ! Bad: &H not recognized (must be lower case)
&O100              ! Bad: &O not recognized (must be lower case)
&habc12341234L     ! Good: hex abc12341234 stored as 48 bit integer
&hFFABCD5678       ! Good: hex FFABCD5678 48 bit integer (L implied)
```

- Single-byte ASCII values are denoted by enclosing the ASCII character in single-quotes, e.g. 

```
A = 'A'            ! Good: ASCII A (65 decimal); same as A = 65
```

Note that the hex and octal notation described above is also recognized by the various forms of INPUT statements, DATA, and GDI print directives. The ASCII byte notation, however, is not. 

## **String Literals** 

A string literal consists of text enclosed in quotes, e.g. 

```
"Smiley O'Reilly"
```

To include a quote character (ASCII value 34) within a string literal, use two of them together, as in these assignments: 

```
TOOL$ = "6"" Wrench"                ! 6" Wrench
```

```
GOV$ = "Edmund G. ""Jerry"" Brown"  ! Edmund G. "Jerry" Brown
```

A-Shell Reference 

Page 1083 

There is no syntax for embedding control characters or escape sequences directly within literal strings. Instead, such strings must be built using a combination of concatenation and the CHR$ function, e.g.: 

```
ONE'TWO$ = "Buckle" + chr(13)  + chr(10) + "my shoe."     ! (CRLF embedded in middle of string)
```

Note that the above statement only contains two true string constants, i.e. the literals "Buckle" and "my shoe.". Although the chr() functions are run time operations (not true constants), when given constant (literal numeric) arguments, e.g. chr(13), the result is effectively a constant because there are no variable elements subject to change according to run time logic. The same can be said of the overall expression (three concatenations and two string functions). 

Also note that string literals may appear in a variety of auxiliary contexts (e.g. input files, CSV files, DATA statements, tab functions, etc.) where they may or may not need to be quoted. Typically the rule is that quoting is optional except when the string contains problematic characters (e.g. control characters, quotes, delimiters, etc.), in which case quoting is mandatory. See related topics WRITECD, INPUT CSV, XCALL STRTOK, INSTR(). 

## **Defined Symbols** 

These are created by the DEFINE statement and are treated by the compiler equivalently to literal string or numeric constants, depending on whether the symbol name ends in a dollar sign, e.g.: 

```
DEFINE FREEDOM_FRIES$ = "French Fries"    ! define string constant
```

```
define FF_COUNT = 25                      ! define numeric constant
? FF_COUNT;FREEDOM_FRIES$;" per serving"  ! this statement compiles to same RUN code...
```

```
? 25;"French Fries";" per serving"        ! ...as this statement
```

Symbol names have the same form and syntactic rules as variable names, but to help make them easily identified in source code, a common convention is to use all upper case characters and one or more underlines, as in the examples above. 

Defined symbols were not implemented in the original AlphaBASIC. This forced programmers to either use variables or literals as pseudo-symbol workarounds, neither of which was a very satisfactory solution—the former due to the possibility of the variable being changed at run time, the latter due to the lack of clarity in the meaning of the literals in the source code. 

A-Shell Reference 

Page 1084 

Modern ASB programs typically make extensive use of defined symbols, often starting with `++include ashinc:` which defines hundreds of symbols relevant to common A-Shell functions, subroutines and other resources. 

Defined symbols require the /X:2 compiler switch. 

Symbols can also be defined via command line arguments passed to the compiler; see Compiler Symbol Definitions. 

## **- Auto Defined Symbols** 

- These are equivalent to defined symbols (see above) except that they are automatically pre-defined by the compiler. See Auto Defined Symbols for details. 

## **Compiler Functions** 

Compiler functions such as .OFFSIZ$(), .OFFSET(), and .SIZEOF() are converted to literals by the compiler. 

## **See Also** 

- .OFFSIZ$() 

- .OFFSET() 

- .SIZEOF() 

## **History** 

- 2016 October, A Shell 6.4.1533, compiler edit 789: Automatically treat hex and octal literals as 48 bit if larger than 32 bit. Otherwise store the literal as a floating point unless the L suffix is explicit. 

- 2016 June, A Shell 6.4.1515, compiler edit 763:  L suffix introduced for 48 bit integer contants 

A-Shell Reference 

Page 1085 

## **STATEMENTS** 

A complete list of statements, along with other keywords, can be found in the alphabetized ASB Keywords table. Statements are organized into the categories shown below. 

## **Subtopics** 

- Assignment Statements 

- Control Statements 

- Terminal I/O Statements 

- File I/O 

- TRACE Statements 

- DEBUG Statements 

- Array Statements 

- Miscellaneous Statements 

A-Shell Reference 

Page 1086 

## **ASSIGNMENT STATEMENTS** 

_Added January 2018_ 

## **{LET} <variable> = <expression>** 

Assignment statements assign values to variables. The LET keyword is a holdover from ancient versions of BASIC and is normally omitted. <variable> can be any scalar variable or an array element or, in some limited cases, an entire array; see Whole Array Assignment. <expression> can be any expression compatible or convertible to the type of the specified variable; see Operators. Examples: 

```
TOTAL = (QTY * PRICE) USING "######.##"
```

```
today$ = odtim(0,0,0)
```

```
month(m) = "December"
```

```
Price = Fn'Get'Price(sku)
```

```
$capitol("California") = "Sacramento"
ATE'SUPP = FLAGS and AGF_ATE
```

```
IS'BOY = GENDER$ = "M"
```

In all cases the assignment operator is the first "=" following the variable. Any other equal signs, as in the last example above, would be treated as comparison operators, resulting in a logical expression returning TRUE (-1) or FALSE (0). 

In some cases where the first operand is the same as the variable being assigned, you can use a shortcut syntax; see Shortcut Operators. Example: 

```
GRAND'TOTAL += LINE'TOTAL  ! same as GRAND'TOTAL = GRAND'TOTAL + LINE'TOTAL
```

```
FLAGS |= MBF_KBD           ! same as FLAGS = FLAGS or MBF_KBD
```

A-Shell Reference 

Page 1087 

MAP Statements may also contain implicit assignment statements by appending the value after the size parameter, e.g. 

```
MAP1 PI, F, 6, 3.14159
```

The above would be the equivalent of: 

```
MAP1 PI, F, 6
```

```
PI = 3.14159
```

## **See Also** 

- Dynamic Overlays 

- Ordered Map Key-Value Pair Assignment 

- Ordered Map Assignment 

- Gridmap Row-Column-Value Assignment 

## **Subtopics** 

- Substring Assignment 

- Whole Array Assignment 

A-Shell Reference 

Page 1088 

## **SUBSTRING ASSIGNMENT** 

_Added November 2018_ 

A rather unique feature of ASB is the ability to use the Substring Operator on the left side of an assignment in order to update a substring of the destination variable. For example: 

```
a$[x,y] = z$
```

```
dst$[-4,-1] = src[-4,-1]
```

```
rec[1;5] = "12345"
```

Although this is a very handy feature, unfortunately it is also potentially confusing, for multiple reasons: 

- The substring specifications are based on the physical size of the destination variable, but the logical size of the source 

- variable. 

- Null bytes in string (but not X) destination variables preceding the start of the target substring will typically be converted to 

- spaces. 

- The preceding rule gets more complicated in the case of dynamic variables (see History below). 

The forum article " Question About Substrings" provides some additional explanation. 

## **History** 

- 2018 July, A Shell 6.5.1639: Language runtime refinement: when an assignment is made to a substring (aka slice) of a dynamic variable, the variable is now expanded as needed for the referenced slice to be part of the variable. For example: 

```
map1 var,x,0
```

```
var[9;3] = "foo"
```

```
print var[9;3]
```

A-Shell Reference 

Page 1089 

Previously, the print statement would have printed nothing; the assignment statement would have had no effect, since the variable var was not long enough for the [9;3] slice to be applicable. 

Now, it will be expanded, with leading bytes filled with spaces for string type variables or nulls for X type variables, so that the print statement will always display "foo". 

This brings the behavior more into line with the expectation for dynamic variables, which are normally expanded as needed during assignment statements. But the slice assignment has always been a very special case. 

A-Shell Reference 

Page 1090 

## **WHOLE ARRAY ASSIGNMENT** 

_Reviewed and Revised December 2023_ 

ASB provides the following two convenient methods for assigning elements to an array in a single operation from a CSVformatted string. This topic addresses the first method;  see INPUT CSV into Array for the second). 

## **ary() = <string-expression>** 

and 

## **INPUT CSV #ch, ary()** 

Where: 

ary() is a DIMX array 

<string-expressions> is a string expression in a CSV compatible format. 

The operation follows the same general rules as INPUT CSV into an array, i.e. the array elements can be fixed length or dynamic elements and the array extent can be fixed or auto_extend. In the case of an auto_extend array, the extent will be reset for each assignment statement. Likewise, the string expression can have comma, tab or pipe delimiters and may contain quoted elements; leading and trailing spaces are trimmed. 

## **Example** 

```
dimx a(0), s, 0, auto_extend
```

```
a() = "red,green,blue"
```

```
a() = "Golden Retriever | Doberman | German Shepard | Chihuahua"
```

The first assignment would result in an array with an extent of 3:  a(1) = "red";  a(2) = "blue";  a(3) = "green". The second assignment would result in an array of an extent of 4:  a(1) = Golden Retriever";  a(2) = "Doberman";  a(3) = "German Shepherd"; a(4) = "Chihuahua". 

A-Shell Reference 

Page 1091 

## **Comments** 

Note that for maximum generality, the array should be of type S,0 with the auto_extend flag.  However, if you know the source expression consists only of numbers or of fields of a limited length,  you can adjust the array declaration to be use a more specific type or size. 

If the array is not declared with the auto_extend flag and there are more fields in the expression than elements in the array, the additional fields will be ignored. 

## **History** 

- 2023 September, A Shell 6.5.1741:  The CSV assignment convenience operator (see 6.5.1739.0) now recognizes the delimiter set via MX_CSVDELIM[XS] . 

- 2023 August, A Shell 6.5.1739:  Feature added to A-Shell. 

A-Shell Reference 

Page 1092 

## **CONTROL STATEMENTS** 

The various kinds of control statements have their own topics, as listed below. 

## **Subtopics** 

- Control Structures 

- AMOS 

- CALL 

- CHAIN 

- EXIT 

- END 

- GOSUB 

- GOTO 

- ON ERROR GOTO 

- REPEAT 

- RESUME 

- RETURN 

- XCALL 

A-Shell Reference 

Page 1093 

## **CONTROL STRUCTURES** 

A-Shell Reference 

Page 1094 

**IF** 

## **IF <condition> {THEN} <statements> {ELSE <statements>}** 

This is the original IF statement supported by the first version of A-BASIC. Multiple statements were possible in both the THEN and ELSE clauses, but all had to be combined into a single logical line using colons to separate the statements and ampersands to continue on to subsequent physical lines. Although inelegant, this form of the IF statement was often combined with the GOTO statement in early A-BASIC to create primitive loops. Now deprecated, this primitive form of the IF statement has been superseded by the more powerful and elegant IF...ENDIF construction. 

**Compatibility:** Supported in all versions of the compiler. A-Shell implementation matches the AMOS implementation at both the source and RUN level. 

## **Example** 

```
if TOTAL > CREDIT'LIMIT goto LIMIT'EXCEEDED
```

```
if CHROMO = XY then &
```

```
    SEX = “M” : ? “It's a boy” &
```

```
else SEX = “F” : ? “It's a girl”
```

A-Shell Reference 

Page 1095 

## **IF…ENDIF** 

## **IF <condition> {THEN}** 

```
    <statements>
```

```
{ELSEIF <condition>
```

```
    <statements>
```

```
{ELSE
```

```
    <statements>
```

## **ENDIF** 

This newer form of block-structured IF statement was originally introduced in BASIC _plus_ , and later extended by A-Shell build 1125 to support the ELSEIF clause. Advantages over the original IF statement include: 

- No need to use colons to separate statements or ampersands to continue on to additional lines. 

- For conditions that divide more than two mutually exclusive ways, you can use as many optional _elseif_ clauses as you need. 

- Ability to nest statements (including other IF...ENDIF or other control structures within the clauses.) 

**Compatability:** requires /X:2 or /RC. The A-Shell implementation is compatible with the BASIC _plus_ version at the source code level, except for the ELSEIF clause which is an A-Shell extension. 

## **Example** 

```
if COST < 10 then
```

```
    PAY'METHOD = PM_CASH
```

A-Shell Reference 

Page 1096 

```
    PETTY'CASH -= COST
elseif COST < 100 then
```

```
    PAY'METHOD = PM_CHECK
    CHECKING'ACCOUNT -= COST
elseif COST < 1000 then
    PAY'METHOD = PM_CREDIT
else
```

```
    CALL BUY'LOTTERY'TICKET
    if TICKET = WINNER then
        CALL GET'AN'ACCOUNTANT()
    else
```

```
        CALL ROB'BANK()
```

```
    endif
```

```
endif
```

## **Comments** 

The compiler determines whether an IF statement is of the original or new (block-structured form) by whether there is a statement following the condition prior to the end of the logical line. It is possible to insert old-style IF statements into the body of new-style IF..ENDIF statements, but this goes against most tenets of style. 

Once you get more than a couple of ELSEIF clauses, you may find the conceptually-equivalent SWITCH statement to be a better match. 

A-Shell Reference 

Page 1097 

Beware: ELSEIF (one word) and ELSE IF (two words) are not equivalent! The former marks the beginning of a/another mutually exclusive conditional clause that ends with either the next ELSEIF, ELSE, or ENDIF. The latter marks the beginning of an _else_ clause, and within that clause, starts a new IF statement. 

## **Subtopics** 

- ELSEIF Clauses 

A-Shell Reference 

Page 1098 

## **ELSEIF CLAUSES** 

Beginning with A-Shell build 1125 of September 2008, one or more _elseif_ clauses may be inserted into an extended _if/elseif/else/endif_ statement (in /RC or /X:2 modes), e.g.: 

## **IF <expr1> THEN** 

```
   <statements>
```

```
ELSEIF <expr2> THEN
```

```
   <statements>
```

```
ELSEIF <expr3> THEN
```

```
   <statements>
```

```
ELSE
```

```
   <statements>
```

## **ENDIF** 

Previously, to accomplish the same thing you would have had to use nested _if/else/endif_ clauses, e.g.: 

```
IF <expr1> THEN
```

```
   <statements>
```

```
ELSE
```

```
   IF <expr2> THEN
      <statements>
```

```
   ELSE
```

```
      IF <expr3> then
```

A-Shell Reference 

Page 1099 

```
         <statements>
```

```
      ELSE
```

```
         <statements>
```

```
      ENDIF
```

```
   ENDIF
```

```
ENDIF
```

The _elseif_ version is mainly just cleaner and easier to follow. 

A-Shell Reference 

Page 1100 

## **SWITCH / CASE / ENDSWITCH** 

## **SWITCH <expr>** 

```
CASE <constant>{...{<constant>}}
```

- `{` **`CASE`** `<constant>{...{<constant>}} }` 

```
          <statements>
```

```
          EXIT
```

- `! (any number of case-statement blocks and each statement` 

- `!  block can have multiple case statement headers)` 

- `{ {` **`CASE`** `<constant>{...{<constant>}} }` 

- `{` **`CASE`** `<constant>{...{<constant>}} }` 

```
          <statements>
```

```
          EXIT }
```

- `{` **`DEFAULT`** 

```
          <statements>
```

```
          EXIT }
```

## **ENDSWITCH** 

A-Shell Reference 

Page 1101 

Note that while the <expr> can be essentially anything, each <constant> must be a literal string, numeric value or defined symbol matching the <expr> type, and not a variable! 

The <expr> is first evaluated, and then the list of CASE statements is scanned from top to bottom until a match is found between the <expr> and the <constant>. At that point, the <statements> below the matching CASE are executed. If there is no EXIT, the flow of control will continue on through the <statements> following the subsequent CASE statements. In other words, once a match is found with a CASE, then all subsequent CASE and DEFAULT statements will match, which is why you almost always want to terminate the <statements> associated with a particular CASE with an EXIT. 

The optional DEFAULT statement is like a CASE that always matches, so its sub-statements will be executed if none of the above CASE statements match, or if a previous CASE statement matches but had no EXIT statement, so that control continued to flow. 

Multiple CASE statements can share the same set of <statements>, and a single CASE statement can contain a range of values. A range consists of two constants separated by three dots (although one of the two ends of the range can be omitted to indicate an open-ended range). For example: 

```
SWITCH dues
```

```
    CASE 101...
```

```
        free'massages = -1
```

```
        EXIT
    CASE 100
    CASE 75
        free'massages = 3
        EXIT
    CASE 50...74
        free'massages = 1
        EXIT
```

A-Shell Reference 

Page 1102 

```
    CASE ...49
```

```
        free'massages = 0
```

```
        EXIT
```

```
ENDSWITCH
```

In the above SWITCH, if DUES>=101, FREE'MASSAGES is set to -1. If DUES=100 or DUES=75 then FREE'MASSAGES = 3. If DUES>=50 and DUES<=74, the FREE'MASSAGES = 1, and if DUES<=49 then FREE'MASSAGES = 0. If DUES>75 and DUES<100, then none of the CASE statements match, and since no DEFAULT was specified, the SWITCH ends up having no effect. 

Note that as is typical with numeric expressions in Basic, they can evaluate to integers or floating point values. Although it is somewhat unorthodox to use a SWITCH with non-integers, there is no law against it. 

The <expr> given in the SWITCH statement can be any type, but the <constants> in the CASE statements must match that type. In other words, if the <expr> is a string, then the CASE <constants> must be literal (quoted) strings, as shown here: 

```
SWITCH member'type$
```

```
    CASE "Platinum"
```

```
        free'upgrades = 5
```

```
        free'upgrades = 3
        dues = 100
        EXIT
    CASE "G"..."Gold"
```

```
        free'upgrades = 3
```

```
        free'upgrades = 3
```

Page 1103 

A-Shell Reference `dues = 75 EXIT DEFAULT free'upgrades = 0 free'upgrades = 1 dues = 50 EXIT ENDSWITCH` 

In the above example, the second CASE statement would match when MEMBER'TYPE$>="G" and MEMBER'TYPE$<="Gold" (using normal Basic string comparison logic). As a reminder, ASB treats trailing blanks the same as nulls in string comparisons, so the second CASE would match even if MEMBER'TYPE$="Gold   ". 

See _History_ below regarding length and compatibility limitations on the use of string constants. 

For the more common type of SWITCH (numeric), the CASE constants can also be ASCII constants, or hex/octal constants, for example: 

```
SWITCH ASC(A$[B;1])
```

```
    CASE 'A'...'Z'
    CASE 'a'...'z'
        TYP$ = "Alpha"
        EXIT
    CASE '0'...'9'
        TYP$ = "Number"
```

A-Shell Reference 

Page 1104 

```
        EXIT
```

```
    CASE &h80...
        TYP$ = "8 bit"
        EXIT
```

```
    CASE ...&o37
        TYP$ = "Control"
        EXIT
```

```
    DEFAULT
```

```
        TYP$ = "Punc"
        EXIT
```

```
ENDSWITCH
```

## **Comments** 

Note that any statements between the SWITCH statement and the first CASE are actually executed in all cases under A-Shell, whereas they may not be in other implementations of SWITCH statements (such as AMOS). Consequently you should avoid putting any statements there, except perhaps for debugging purposes. 

Requires /X:2 or /RC. 

## **History** 

- 2018 January, A Shell 6.5.1624:  Eliminate limitation on length of string constants used in CASE statements. Previously the limit was determined by the current STRSIZ. 

A-Shell Reference 

Page 1105 

## **FOR…NEXT** 

_Revised June 2021; see History_ 

## **FOR <loopvar> = <startexpr> TO <endexpr> {STEP <stepexpr>}** 

```
<statements>
```

```
{IF <condition> REPEAT}
```

```
{IF <condition> EXIT}
```

## **NEXT <loopvar>** 

The FOR…NEXT loop executes the enclosed set of statements (aka the body) repeatedly until the value of _loopvar_ (aka the loop counter) reaches the value of _endexpr_ (the ending condition). More precisely, the terminating condition is met when _loopvar_ >= _endexpr_ (for positive _stepexpr_ values), or _loopvar_ <= _endexpr_ (for negative _stepexpr_ values). The body of the loop may optionally include REPEAT statements (which effectively jump to the NEXT statement to execute the next iteration of the loop, skipping the remaining statements in the body for this iteration), and EXIT statements (which terminate the loop immediately, as if the _loopvar_ had hit the ending condition). 

The _loopvar_ must be either a floating point or integer (I) variable. If preceded by a % (e.g. %i or %counter), a temporary variable will be automatically created as an F,6, limited in scope to the loop and destroyed when the loop terminates. See History. 

The _startexpr_ and _endexpr_ can be any numeric expressions that are compatible with the _loopvar_ type. Do not, for example, try to use fractional starting or ending values with an integer loop variable. These expressions are only evaluated once, prior to the first test for the termination condition. 

The optional _stepexpr_ clause determines the amount by which the _loopvar_ will be incremented at the end of each loop (default 1). As with the _startexpr_ and _endexpr_ , the type should be compatible with the _loopvar,_ and the expression is evaluated only once. 

A-Shell Reference 

Page 1106 

Note: the test for the loop terminating condition may occur at the start or end of each iteration, depending on compiler switches. See Comments. 

## **Examples** 

The following example illustrates a pair of FOR...NEXT loops, one nested inside the other. The inner loop uses an auto-generated loop variable (%j) whose scope is limited to the body of the inner loop. It also illustrates the EXIT statement, which exits from just the current loop, i.e. the inner loop, continuing with the next iteration of the outer loop. 

```
for i = 1 to 10
```

```
    for %j = i to 100 step 2
        if fn’foo(i,%j) then
            exit        ! terminate inner loop
        else
            print i * %j
        endif
    next %j
```

```
next i
```

The next example illustrates a more complicated FOR statement, involving a STEP clause and calculations for _startexpr_ and _endexpr_ , both of which include the variable `y,` which is modified within the loop—but as noted in the source comment, that doesn’t affect the loop termination since the _endexpr_ is only evaluated once. 

```
for x = y*2 to fn’foo(y) step -1
```

```
    if x = w exit        ! terminate on this condition
```

```
    if fn’bar(x) repeat  ! skip to next iteration
```

```
    y += z               ! note this does not affect the loop terminating condition
```

A-Shell Reference 

Page 1107 

```
next x
```

## **Comments** 

When compiled with OCMPIL or COMPIL without one of the /X or /RC switches, the _loopvar_ is checked against the _endexpr_ after each iteration, so the loop always executes at least once, even if the _startexpr_ exceeds the _endexpr_ at the very start. Also, in this mode, there is no source level enforcement of block structuring, i.e. there is no physical limitation on the relationship between the FOR statement and its associated NEXT statement(s). This variation exactly matches AlphaBASIC, down to the byte codes in the RUN file. 

In contrast, when compiled with /X:1 or higher, or with /RC, the _loopvar_ is checked against the _endexpr_ before each iteration, so it is possible for the loop to execute zero times. Also block structuring is enforced, i.e. there must be a one-to-one physical relationship between the FOR and its subsequent NEXT statement. This variation matches the BASICplus behavior and is more in line with other modern languages/implementations. 

The REPEAT and EXIT statements require /X:1 or /RC. 

## **See Also** 

- Auto-Mapped %Var Variables 

## **History** 

- 2021 June, A Shell 6.5.1704, compiler edit 946:  the auto-mapped _loopvar_ (e.g. %i, %loopvar, etc.) option introduced. 

A-Shell Reference 

Page 1108 

## **FOREACH** 

_Reviewed July 20252 December 2023_ 

## **FOREACH{'REVERSE} $$<itervar> in $<aryvay>({<startkey>{,<endkey>}})** 

```
<statements>
```

- `{IF <condition> REPEAT}` 

- `{IF <condition> EXIT}` 

- `{<statements>}` 

## **NEXT $$<itervar>** 

As with other loops, the FOREACH loop body may contain nearly any legal statement, plus REPEAT and EXIT. Iteration proceeds in key order. In the case of FOREACH, it starts with the first key (or the first key >= startkey if specified) and proceeds through the last key (or the last key <= endkey if specified. In the case of FOREACH'REVERSE, it starts with the last key (or the first key <= startkey if specified) and proceeds through the first key (or the last key >= endkey if specified). In addition, the following apply to FOREACH loops: 

- $$<iterator> contains the value of the current key,value pair in the iteration 

- The .KEY() function may be used to extract the key from the current key,value pair. 

The FOREACH and FOREACH'REVERSE loops are used to iterate through Ordered Maps and Gridmaps, which see for details. 

Iteration proceeds in key order, starting with the first key (or the first key >= _startkey_ if specified), and proceeding through the last key (or last key <= _endkey_ if specified). 

## **Examples** 

The loop below would list all of the state capitals, in alphabetical state order, until hitting the capital "Sacramento" after which it would exit. 

```
dimx $state'capitals, ordmap(varstr;varstr)   ! state -> capital
```

A-Shell Reference 

Page 1109 

```
$state'capitals("Washington") = "Olympia"
```

```
...
```

```
foreach $$i in $state'capitals()
```

```
    ? "The capital of "; .key($$i); " state is "; $$i
    if $$i = "Sacramento" exit
```

```
next $$i
```

The variation below  would list the states in reverse alphabetical order, but only listing those that begin with "South"—i.e. starting with the first state <= "South!" and ending with the first state < "South". Note that FOREACH'REVERSE treats the startkey as relative to the reverse direction, i.e. the key >= the the first one to include in the iteration. 

```
foreach'reverse $$i in $state'capitals("SouthZ","South")
```

```
    ? "The capital of "; .key($$i); " state is "; $$i
```

```
next $$i
```

The following shows three variations of iterating through a gridmap. 

```
dimx $gridi, gridmap(int;varstr;varstr)
```

```
...
foreach $$i in $gridi(3,3)         ! iterate across row 3
    ...
```

```
foreach $$i in $gridi(srow,erow)   ! iterate across row #'s srow to erow
```

A-Shell Reference 

Page 1110 

```
    ...
```

```
foreach $$i in $gridi(srow)        ! iterate from row # srow thru last row
```

```
    ...
```

## **See Also** 

- Iterators 

- Special ORDMAP Functions 

- Special GRIDMAP Functions 

## **History** 

- 2023 November, A Shell 7.0.1752.0: _endkey_ parameter extended to gridmaps. 

- 2023 October, A Shell 7.0.1751.0: _startkey_ support added to FOREACH'REVERSE; _endkey_ added for ordered map iteration. 

- 2023 August, A Shell 6.5.1739:  In FOREACH, if the specified starting key is not found, the iteration now starts with the next key. Previously, the result would have been an empty iteration. In FOREACH'REVERSE, the starting key is now recognized whereas previously it was ignored. As with FOREACH, if not found, the iteration starts with the next key—i.e. the next one lower in the collating sequence. 

- 2018 May, A Shell 6.5.1636, compiler edit 859:  the starting key in a FOREACH statement may now be any kind of expression. Previously, it only allowed a simple variable or a literal string or numeric constant; numeric literals were allowed but weren't converted to string and thus typically failed to match any items in the map. 

A-Shell Reference 

Page 1111 

## **DO / WHILE / UNTIL** 

## **DO {WHILE or UNTIL condition}** 

```
     <statements>
```

```
     {if <condition> REPEAT}
```

```
     {if <condition> EXIT}
```

- `{<statements>}` 

## **LOOP {WHILE or UNTIL condition}** 

For example: 

```
DO WHILE A > B
```

```
    A = A + 1
    B = B * 2
```

```
LOOP
```

Another example: 

```
DO
```

```
    A = A + 1
```

```
LOOP UNTIL A = 10
```

A-Shell Reference 

Page 1112 

**Compatibility:** BASIC _plus_ at the source level; requires /X:1 or higher. 

A-Shell Reference 

Page 1113 

## **AMOS** 

## **AMOS {/switch} <command>** 

Invokes a system command from within ASB. Similar to ASHELL[XS] . The optional _/switch_ may be /T or /S to either force tracing or silencing of all output, just as with :T and :S in command files). If omitted, the default is to display the output of commands but not the commands themselves (like :R). 

A-Shell Reference 

Page 1114 

## **CALL** 

_Updated August 2022; see History_ 

## **CALL <label>** 

## **CALL <procedure>(<param list>)** 

## **CALL <function>(<param list>)** 

## **CALL DYNFUNC(<function>,<paramlist>)** 

The CALL statement may be used to call traditional BASIC subroutines, in which case it is equivalent to GOSUB, as well as to call structured Procedures and User-Defined Functions (including dynamically). 

## **Examples** 

```
CALL HELP                              ! equivalent to GOSUB HELP
call Print'Cus'Addr'Label(CUSTNO, CH)  ! procedure
Call Fn'Status'Message$(code)          ! function
call DYNFUNC$(func$, code)        ! dynamic function
```

## **History** 

- 2022 August, A Shell 6.5.1720: CALL can now be used to invoke a dynamic function. 

A-Shell Reference 

Page 1115 

## **CHAIN** 

_Written September 2024_ 

## **CHAIN <command>** 

CHAIN terminates the current program (see END) and executes the specified command line as it would be executed from the shell prompt in the current directory. If the first specified filename/token does not have a file extension, it is assumed to be RUN program, executed as "RUN <command>". To chain to a system command, it must be fully qualified. Both variations accept additional command line arguments. The system command variation also supports the ability to string multiple commands together, separated by chr(13) + chr(10). 

## **Examples** 

```
CHAIN "MENU1"                    ! (RUN MENU1)
CHAIN "MENU2/OPTION:1/SILENT"    ! Argument passing
CHAIN "SYS:HOST.LIT"             ! Exit A-Shell
```

```
CHAIN "SYS:LOG.LIT/N AR:" + chr(13) + chr(10) + "RUN ARMENU"
```

A-Shell Reference 

Page 1116 

## **EXIT** 

A-Shell provides several different EXIT statements as described below. 

## **EXIT** 

The EXIT statement may be used within a control structure (FOR...NEXT, DO/WHILE/UNTIL, SWITCH, FOREACH) to exit the structure, proceeding to the next statement following the end of the structure. For example: 

```
DO WHILE A < B
```

```
    ...
```

```
    IF TIME > 82800 EXIT    ! exit loop after 11 PM
    ...
```

```
LOOP
```

## **EXITPROGRAM** 

The EXITPROGRAM statement causes an exit directly from a function or procedure, regardless of how nested, to a special label $EXITPROGRAM in the main program, or to the END if the $EXITPROGRAM label doesn't exist. Although this is effectively an unstructured GOTO, it handles the stack cleanup and provides an solution to the problem of how percolate the desire for a program exit up from a nested function to the top level. 

The EXITPROGRAM token can also be used in a RESUME statement in place of EXITFUNCTION, EXITPROCEDURE, or $EXIT... 

```
RESUME EXITPROGRAM {WITH_ERROR {N}}
```

```
RESUME $EXITPROGRAM {WITH_ERROR {N}}   ! (equivalent)
```

A-Shell Reference 

Page 1117 

## **EXITFUNCTION** 

EXITFUNCTION is used exclusively within functions to exit the routine and return to the caller.  Note however that if the function contains an $EXIT label, then EXITFUNCTION becomes equivalent to GOTO $EXIT, allowing for some final cleanup code to be executed and even opening the possibility of canceling the exit and jumping to some other place within the current function. 

## **See Also** 

- EXITPROCEDURE 

_Written February 2024_ 

## **EXITPROCEDURE** 

EXITPROCEDURE is used exclusively within procedures to exit the procedure and return to the caller.  Note however that if the procedure contains an $EXIT label, then EXITPROCEDURE becomes equivalent to GOTO $EXIT, allowing for some final cleanup code to be executed and even opening the possibility of canceling the exit and jumping to some other place within the current procedure. 

## **See Also** 

- EXITFUNCTION 

A-Shell Reference 

Page 1118 

## **END** 

## **END** 

Terminates the current program. Regardless of where END occurs inside a program, including within User-Defined Functions, the effect is the same: immediate termination of the program. 

## **Comments** 

For a normal (non-SBX) program, END will return control to the command prompt. END inside an SBX subroutine, on the other hand, returns to the caller at the statement following the Xcall that invoked the subroutine. 

If not specified, the compiler effectively appends an END statement to the end of the main routine. 

A-Shell Reference 

Page 1119 

## **GOSUB** 

GOSUB is used to call a "traditional BASIC subroutine". It is essentially equivalent to a GOTO (to the label at the start of the subroutine), with an internal stack marker used so that the next occurrence of a RETURN statement causes execution to proceed with the statement following the GOSUB. For example: 

```
SECS = 4
```

```
GOSUB TARRY           ! same as CALL TARRY
```

```
PRINT "LET'S GO!"
```

```
...
```

```
TARRY:
```

```
SLEEP SECS
```

```
RETURN
```

Note that in "modern BASIC", structured procedures are generally preferable to GOSUB routines, since they allow parameter passing and local variables, eliminating the need for global variables such as the SECS variable in the example above. 

Also note that the keyword CALL, while used to call Functions and Procedures, may be used in place of GOSUB to call traditional subroutines like the one above. 

A-Shell Reference 

Page 1120 

## **GOTO** 

_Added June 2023_ 

## **GOTO ####** 

## **! go to line #### (deprecated)** 

**GOTO <label>** 

## **! go to specified label** 

## **GOTO @<variable>** 

## **! indirect go to** 

The GOTO statement transfers control to the specified line number or label. The indirect form (third syntax) requires that the specified variable first be assigned to point to the desired label; see following example. 

## **Example** 

```
    MAP1 END'PLACE,B,4
```

```
    END'PLACE = *PURGATORY       ! set END'PLACE to point to PURGATORY label
```

```
    GOTO ADMISSIONS
```

```
...
```

```
ADMISSIONS:
```

```
    GOTO @END'PLACE              ! go (indirectly) to PURGATORY
```

```
    ...
```

```
PURGATORY:
```

## **History** 

- 2023 June, A Shell 6.5.1733:  Add indirect GOTO (third syntax above) 

A-Shell Reference 

Page 1121 

## **ON ERROR GOTO** 

_Written July 2020_ 

## **ON ERROR GOTO <label>** 

## **ON ERROR GOTO** 

ON ERROR GOTO establishes the specified label as an error trap, such that the runtime system redirects to that location when an ASB error is detected. The error trap routine should then handle any appropriate error recovery activities such as logging, reporting and/or determining what to do next. In order to clear the error and resume operation of the program, see the RESUME statement. 

ON ERROR GOTO without any label effectively disables the error trap. When there is no error defined, the default response to an error is to abort the program and output a message to the screen giving the error number, last file, and last location. 

## **Example** 

```
    ON ERROR GOTO TRAP
```

```
    ...
```

```
START:
```

```
    ...
```

```
TRAP:
```

```
    ? "Error ";ERR(0)
    IF ERR(0) = 1 THEN    ! if ^C ...
        RESUME START      ! resume at START label
```

```
    ELSE
```

```
       CHAIN "MAIN"       ! else chain to main menu
```

```
    ENDIF
```

A-Shell Reference 

Page 1122 

## **See Also** 

- ERR function 

- RESUME 

- XCALL ERRMSG 

- XCALL FILNAM 

- Error Trapping in Functions 

- Error Trapping in SBX routines 

A-Shell Reference 

Page 1123 

## **REPEAT** 

## **REPEAT** 

REPEAT is similar to EXIT in that it can occur inside a DO loop, a FOR...NEXT loop, or FOREACH loop; it causes the control to transfer to the next iteration of the current loop without executing any remaining statements in the body of the current loop. For example: 

```
TOT = 0
```

```
FOR I = 1 TO 10
```

```
    IF I = 5 REPEAT
```

```
    TOT = TOT + I
```

```
NEXT I
```

The above loop would set TOT to the sum of all the numbers 1 through 10, except 5. 

The compiler supports the REPEAT statement when compiling in X:1 or X:2 or /RC mode. 

A-Shell Reference 

Page 1124 

## **RESUME** 

_Updated February 2024_ 

## **RESUME {label}** 

RESUME is used exclusively within error trap routines (see ON ERROR GOTO) to clear the error status and resume the program. You have the option of resuming at a specific location by specifying a _label_ , or you can resume at the statement that caused the error by omitting _label_ . Note that the latter case only makes sense when the error trap routine—or some external event, such as releasing a lock on a file—effectively resolves the problem which caused the error. Otherwise you will have an infinite loop, trapping and resuming the same error over and over again. 

## **See Also** 

- ON ERROR GOTO 

- Error Trapping in Functions 

- Error Trapping in SBX routines 

A-Shell Reference 

Page 1125 

## **RETURN** 

## **RETURN ! from traditional subroutine** 

## **RETURN (<expression>) ! from SBX, setting return function value** 

In the first case—when used without any arguments—RETURN transfers control back to the statement following the last GOSUB, i.e. returns from a traditional BASIC subroutine. 

The second case—when followed by an expression—can be optionally used prior to the end of an SBX routine to push a value on to the expression stack, allowing the SBX routine to be called as a function using XFUNC() (which see, along with Call SBX as a Function, for details). Note that if the SBX routine is called by the XCALL or VXCALL statements, the `RETURN <expression>` statement will be treated as the equivalent of END, which returns to the caller without any value pushed on the expression stack. 

A-Shell Reference 

Page 1126 

## **XCALL** 

## **XCALL <subroutine> {,parameters}** 

This statement is used to call subroutines, and is one of ASB's most powerful and frequently-used operations. A major portion of this document is devoted to discussing subroutines and XCALL, which see for more information. 

A-Shell Reference 

Page 1127 

## **TERMINAL I/O STATEMENTS** 

_Added October 2024_ 

Terminal/keyboard input and output is actually just a variation of Sequential File I/O (e.g. INPUT, PRINT, ...) with the only difference being that the terminal channel is always 0. For terminal output statements, the channel parameter is optional; omitting it is the same as specifying a channel value of zero. For terminal input, the channel parameter must be omitted and optionally replaced by a prompt. For example: 

```
map1 name$,s,20
```

```
input "What's your name? ", name$    ! (channel replaced by prompt)
print #0, "hello"; name$             ! (explicit channel 0)
print "Goodbye"                      ! (implicit channel 0)
```

See Sequential File I/O for further details. 

A-Shell Reference 

Page 1128 

## **FILE I/O** 

ASB files divide into categories by both the type of access (sequential or stream, direct or "random", indexed, SQL) and the general file structure/organization (linked list, contiguous linear address space, index/data pairs, database). On the AMOS platform, sequential and direct access files are physically distinct at the OS level, whereas on all other platforms, there is no physical distinction; it's just a question of how they are accessed. AMOS used the somewhat misleading term "random" to refer to the ability to access any record in a file by its record number, i.e. as if randomly, to contrast it with sequential access. In the Unix and Windows world, all files can be accessed directly, so that "random access" loses its sense at multiple levels. Still the terminology persists. Under A-Shell, "sequential files" are equivalent to "streams", while "random files" consist of fixed length records accessed by record number, possibly with the aid of separate index. SQL database access is supported via a separate API (ASQL) and is not otherwise discussed here. 

## **File Access Methods** 

**Sequential** (aka stream) access is used for non-record-oriented data (binary or text). Sequential files are opened for either read or write access, but not both at the same time. And although it's possible to reposition the "cursor" to a specific byte offset within an existing file, access is normally sequential; see MX_FILEPOSXS. I/O operations can be byte oriented or logical line (terminated with LF or CRLF) oriented. In output mode, files grow automatically. In input mode, programs typically read bytes or lines at a time until the EOF status is returned. Typical uses are for programs, reports, documents, graphics, interface files, configuration files, structured text such as HTML, XML, JSON, CSV, etc. 

**Random** (aka direct) access is used for accessing sets of fixed-length records—i.e., flat files. Reads and writes may be intermixed within a single file open session, unless explicitly opened for read-only access. I/O operations are always one record at a time, with the record length specified in the open statement, and based on a record number. Record and file level locking is possible. There is no inherent indexing, but applications are free to construct indexes—possibly themselves random access files— to allow efficient access to individual records. Typical uses are for structured data, where the layout of a record is specified via a set of MAP Statements grouped under a MAP1 heading, or DEFSTRUCT). Random files must be pre-allocated to a specified size (see CREATE and ALLOCATE) which remains fixed unless manually expanded (see MX_EXPFIL). 

**ISAM** (Indexed Sequential Access Method) combines a random access data file with one or more index files, along with a set of special ISAM File Statements for performing the requisite operations, such as lookup by key, sequential access in key order, add and delete keys and records, etc. For those migrating from the AMOS platform, A-Shell's ISAM supports the original AMOS ISAM format, but also supports an extended format allowing for much more efficient organization of very large files both through 

A-Shell Reference 

Page 1129 

variable size index blocks and variable numbers of index levels. ISAM files automatically expand as needed unless disabled by the NOAUTOX option. 

**ISAM-A** is an alternate implementation of ISAM, based on the Informix C-ISAM standard, that offers some advantages over the original ISAM, such as automatic integration of the index and data operations, the ability to add/delete keys without completely rebuilding the file, keys combining several non-contiguous fields, multiple key types, variable length records, push/pop, transaction support, etc. ISAM-A files automatically expand as needed, and this feature cannot be disabled. 

**SQL** operations are supported via the ASQL module which currently supports MySQL/MariaDB and anything with an ODBC connector. Under Windows, ODBC drivers are typically included or available at no charge; under Linux, a third-party ODBC driver may be required. 

## **Comments** 

- Unlike in AMOS, there is really no such thing as a "contiguous" (aka RANDOM) file in Windows or Unix. The underlying files 

- are sequentially allocated; the random access feature is supported in a layer above that, partly in the OS, partly in A-Shell. 

- Because of that, A-Shell in some cases has to guess whether a file was intended to be RANDOM or not, based on whether it is 

- a multiple of 512 bytes as all AMOS RANDOM files would be. This mainly becomes an issue when using the LOOKUP statement, which returns a negative # for "random" files, and a positive # for "sequential" files. Some applications might actually depend on that and thus misbehave, for example, if a sequential file just happened to be a multiple of 512 bytes. In general, modern programs should not rely on the arbitrary unit of 512-byte blocks and instead should use the size in bytes (see SIZE.LIT, XCALL SIZE). Also see the system options ABSLOOKUP and EXTFIO. 

- For sequential files (aka "streams"), A-Shell supports the ability to seek directly to a byte position; see MX_FILEPOSXS. 

- For random files, A-Shell supports the ability to expand them incrementally in place, whether manually (see MX_EXPFILXS), or 

- automatically (see system options , and MX_GETOPTIONS, MX_SETOPTIONS GOP_AUTOX_RAN) 

- File expansion is always automatic for zequential and ISAM-A files. For ISAM files it is automatic unless the NOAUTOX option 

- is enabled. For random files, it can be enabled by setting the GOP2_AUTOX_RAN flag. You can also manually expand random files using MX_EXPFIL. 

## **See Also** 

- MX_FILEHOOK 

A-Shell Reference 

Page 1130 

- File-Related Functions 

- ISAM Performance 

## **Subtopics** 

- Generic Files 

- Sequential Files 

- Random Access Files 

- ISAM Files 

- ISAM-A Files 

A-Shell Reference 

Page 1131 

## **GENERIC FILES** 

These file statements work on all types of files. 

## u **CLOSE** 

## **CLOSE #ch** 

## **Parameters** 

_ch_ is the file channel associated with the file when it was opened. 

## **Comments** 

Closing a file releases any internal locks on it. It has no effect on external locking mechanisms such as XLOCK and FLOCK. 

All open files are automatically closed at the end of a program. 

Attempting to explicitly close a file channel which is not open generates ASB error #14 (I/O to unopened file). You can determine if a file channel is open by using the ERF() function. 

## u **KILL** 

_Updated July 2015; Comment added_ 

## **KILL fspec** 

KILL erases/deletes a file. 

## **Parameters** 

_fspec_ is filespec in native or DevPPN format. If no extension is specified, .DAT is assumed. Terminate the filespec with a dot to 

A-Shell Reference 

Page 1132 

erase a file with no extension. 

## **Comments** 

If the file does not exist, the statement behaves like a null operation—i.e., no error is triggered. So there is no particular need to do a LOOKUP prior to a KILL. 

## u **LOOKUP** 

## **LOOKUP fspec, blks** 

LOOKUP checks for size and existence of a file. 

## **Parameters** 

_fspec_ is a filespec in native or DevPPN format. Default extension is .DAT. 

_blks_ is a floating point variable which returns the size of the file in "blocks" (512 bytes). Adding further to the confusion of the archaic units, if the file is an exact multiple of 512 bytes, the number of blocks will be reported as a negative value, indicating a "random" file; otherwise it will be a positive number. See ABSLOOKUPSP to override that behavior. If the file does not exist, the return value is 0. If the file exists but has zero bytes, the return value is 0.5. 

## **See Also** 

- LOOKUP 

A-Shell Reference 

Page 1133 

## **SEQUENTIAL FILES** 

Sequential file (aka stream) notes: 

- Typically text-oriented, but may consist of raw binary data as well. 

- Byte, field, or line-oriented. 

- May contain variable length fields and lines, or simply be a stream of bytes. 

- Open for input or output, but not both at the same time, except for the terminal. 

- The terminal screen and keyboard are two special sequential files, implicitly opened for input and output, respectively, on 

- channel #0. 

- Record locking not supported. 

- Serial ports may be accessed as sequential files. 

- TCP sockets may be also be accessed as sequential files; see MX_FILESOCK. 

- Output files grow automatically via PRINT. 

- Access is by default sequential but 'cursor' can be repositioned using MX_FILEPOS 

## **Subtopics** 

- OPEN 

- INPUT 

- PRINT 

- WRITECD 

A-Shell Reference 

Page 1134 

## **OPEN** 

## **OPEN #ch, fspec, INPUT {,WAIT'FILE}** 

## **OPEN #ch, fspec, OUTPUT {,WAIT'FILE}** 

## **OPEN #ch, fspec, APPEND (,WAIT'FILE}** 

## **Parameters** 

_ch_ is an integer expression specifying the file channel which will be needed for subsequent I/O operations on the file. File channel 0 refers to the terminal, in which case the OPEN statement will have no effect. 

_fspec_ is a string expression specifying the file to open, using native or DevPPN. See the following topic _.NULL files_ 

_WAIT'FILE_ only applies when the LOKSER system option is active and causes the program to wait for exclusive access to the file. 

## **Comments** 

Opening a file for OUTPUT creates an empty file. If the file already existed, it is first deleted. 

APPEND is equivalent to OUTPUT except that if the file does exist, it is not first deleted. 

Sequential files can be connected to TCP sockets; MX_FILESOCK for details. 

## **See Also** 

- Search Paths - Data Files 

A-Shell Reference 

Page 1135 

## **.NULL FILES** 

_Added October 2015_ 

The special file name .NULL may be used with sequential files to open a file which is not connected to anything. For example: 

```
OPEN #1, .NULL, OUTPUT
```

```
OPEN #2, .NULL, INPUT
```

For output, .NULL is equivalent to the device /dev/null under Unix and NUL under Windows, i.e.any data output to the file is just discarded. For input, .NULL acts like an empty input file (returns EOF on the first input attempt). 

The ability to associate an output file channel with a null device adds to the flexiblity of the PRINT #CH statement, since depending on the value of CH and what file it is associated with, the statement can output to the screen (if CH=0), a disk file, or nothing at all. 

## **See Also** 

- MX_FILESOCK. 

- .NULL Dot Variable 

## **History** 

- 2016 September, A Shell 6.3.1524:  Function added to A-Shell. 

A-Shell Reference 

Page 1136 

## **INPUT** 

## **INPUT {#ch | prompt,} var {,var2 ... varn}** 

expects commas to delimit the input data into fields. If the data stream does not appear to satisfy the number of destination variables specified, it will prompt for more. The input stops when all the variables have been satisfied, which may be mid-line. 

## **INPUT LINE {#ch | prompt,} var** 

inputs up to a line terminator, assigning the entire result to the one var. 

## **INPUT RAW #ch, var** 

inputs a number of bytes of raw data equal to the physical size of the specified destination var. 

## **INPUT CSV #ch, var {,var2 ... varn}** 

similar to the standard INPUT but is better at tokenizing the input according to the common industry standards for comma separated values. 

## **Parameters** 

_ch_ is an integer expression specifying the file channel on which the file was opened. 

_prompt_ is a string expression specifying the prompt to display on the screen for the case of keyboard input. 

_var, var2, ... varn_ are numeric or string variables to receive the input. Except for INPUT RAW, you may use dynamic strings (s,0) which will be expanded as needed to contain the input data. 

## **Comments** 

If the file channel is not specified, or evaluates to zero, the operation inputs from the keyboard, in which case the optional prompt may be specified to instruct the operator what to input, e.g.: 

```
INPUT "Enter your name: ", NAME$
```

```
INPUT "", NAME$
```

A-Shell Reference 

Page 1137 

If no prompt is specified, a "?" will appear to prompt the user. You can specify a null prompt as in the second example above to eliminate the "?". 

## **See Also** 

- MX_SETCMDINP 

## **Subtopics** 

- INPUT CSV 

- INPUT CSV Into Array 

- INPUT CSV into Gridmap 

- INPUT RAW 

A-Shell Reference 

Page 1138 

## **INPUT CSV** 

_Updated November 2019; recognize pipe as delimiter_ 

## **INPUT CSV #ch, var1 {,var2 {,…varn}}}** 

## **INPUT CSV #ch, ary()** 

## **INPUT CSV #ch, $grid()** 

The first and second syntax options each read one line of from the CSV file and populate either an explicit list of individual variables, or an array.  The third syntax option reads the entire CSV file into a gridmap. See the subtopics INPUT CSV Into Array and INPUT CSV Into Gridmap for more details on those variations. This topic applies in general to all three variations. 

INPUT CSV acts much like INPUT (input from a file), except that it contains additional parsing logic designed to deal with various forms of CSV (Comma Separated Values) format, which can sometimes be troublesome for the standard INPUT #CH statement. 

Despite the name, CSV files sometimes use delimiters other than commas, such as tab, colon, semi-colon, or vertical bar (pipe). The INPUT CSV operation scans the first line of the file to identify the delimiter character, based on the most commonly appearing character not within pairs of quotes, from the set of: comma, tab, colon, semi-colon, and pipe. The standard INPUT #CH statement only supports comma delimiters. 

Another important difference between the two input statements is that INPUT CSV is line oriented rather the field oriented. Each INPUT CSV statement will process a single line of the input file, regardless of how many variables are listed in the INPUT CSV statement or how many fields appear in the actual data. If there are more variables than data fields, the extra variables are set to null. If there are more data fields than variables, the extra data fields are ignored. (Note that line breaks which occur within quoted fields are treated as mere data characters and do not terminate the INPUT CSV operation.) 

Unfortunately, there seems to be no universal standard for CSV files, particularly as it relates to the handling of quotes within fields. INPUT CSV uses various heuristics to attempt to determine whether each double-quote character is a merely a field delimiter or part of the data. For example, the quotes surrounding a field such as { "Smith, John" } would be treated as delimiters and removed from the data returned in the associated field. Without those quotes, the comma would probably be treated as a delimiter, such that the data would be considered as two fields. When a quote appears mid-field, such as { "6" bolt" }, with or without the quotes around the outside of the field, it will be treated as a raw data character; the associated 

A-Shell Reference 

Page 1139 

return variable would receive { 6" bolt }. Double double-quotes are generally treated as single double-quotes, as in BASIC strings, so { "7' 5"" center" } would be interpreted as { 7' 5" center }. 

## **Comments** 

You can disable all of the special quote handling logic by using the AS_CSVNOQUOTE flag in the ASFLAG subroutine. 

There is no specific limit to the number of fields or the overall length of a line. When using the first syntax option on lines containing an extremely large number of fields and/or when using variables with very long names, you could run up against the compiler's maximum source code line length though. See Limits and Capacities. 

**Warning:** the variables receiving the fields must each be long enough to hold the entire field as it appears in the data file, including outer quotes. Otherwise, fields which are quoted in the data may end up being returned with the leading quote character included in the returned variable, with a corresponding character truncated from the end. Dynamic string variables (s,0) are supported. 

## **Notes on Parsing** 

As it stands, the CSV extension on INPUT just affects the parsing of the line into individual fields. When it comes to converting/storing each individual field into a variable, we revert to the age-old INPUT rules, which, for numeric variables, _essentially_ consists of var = val(field$). In that context, the conversion from string format to number skips leading spaces and then stops at the first character that isn't a digit, a decimal point, or a plus or minus sign or E or e (for exponential notation). That has been the standard since way back when. 

Note that the determination of the decimal point character is based on the LDF, so comma could be interpreted as the decimal point. 

A-Shell's version of INPUT does however recognize one extension: you can prefix the number with "&h" or "&o" in which case it will interpret the string as hex or octal, respectively. 

## **See Also** 

- MX_CSVDELIM for a way to change the delimiter 

## **History** 

2023 March, A-Shell 6.5.1728:  Add _INPUT CSV Into Gridmap_ . 

A-Shell Reference 

Page 1140 

- 2019 November, A Shell 6.5.1671:  Recognize the pipe character "|" as a delimiter. 

- 2018 February, A Shell 6.5.1629: Add second syntax line `INPUT CSV #ch, ary().` 

- 2011 May, A Shell 5.1.1215: The auto-detection of the delimiter character has been expanded to support comma, tab, colon and semi-colon. The decision is based which of the four characters is the most common (outside of quoted fields) on the first line of the file. Previously, only comma and tab were supported, and the decision was based on which character appeared first in the file. 

- 2009 October, A Shell 5.1.1163: AF_CSVNOQUOTE flag now stifles the automatic removal of the outer quotes surrounding a field. 

- 2008 August, A Shell 5.1.1122:  Fields enclosed in quotes are now automatically de-quoted, even when AF_CSVNOQUOTE is set. AF_CSVNOQUOTE is still useful for eliminating all other quote-matching logic in files that have non-standard quoting. Also, AF_CSVSMARTQUOTE no longer does anything. Its logic is now automatic. Previously, it only served to prevent the improper concatenation of additional input lines in order to try to match up quotes that occur in the middle of a field (i.e. don't require matches). There doesn't seem to be any value in not doing that all the time. 

- 2008 February, A Shell 995.0.7: Fields with embedded line breaks are now supported. The total extended input line length is still limited to 4K. 

A-Shell Reference 

Page 1141 

## **INPUT CSV INTO ARRAY** 

_Updated May 2024_ 

## **INPUT CSV #ch, ary()** 

inputs the separated values from the next line of the input file channel into individual elements of the ary(), which must be allocated using DIMX, e.g. 

```
DIMX ary(0), S, 0, {,auto_extend}
```

The result is equivalent to: 

## **INPUT CSV #ch, ary(1), ary(2), ...** 

where the number of array elements specified is automatically adjusted at runtime to the number of fields on the line. 

## **Comments** 

- The ary() must be allocated with DIMX, and must be of type S or X. 

- The array element size doesn't have to be 0 (i.e. dynamically sized), but if not, individual fields may be truncated as needed. 

- For AUTO_EXTEND arrays (highly recommended), the extent will be set to the number of fields input, with 0 indicating none 

- (probably EOF). 

- In the case of a non auto_extend array, any fields on the input line beyond the fixed extent of the array will be discarded. 

See the fncsvutl.bsi in SOSLIB:[907,10] module for an example of using INPUT CSV into an array to convert each line of a CSV file into an ordmap. 

## **Example** 

Beginning with A-Shell 6.5.1697 (see History below), you can replicate a CSV file using the following: 

```
dimx ary(0), s, 0, auto_extend
```

```
open #1, "in.csv", input
```

A-Shell Reference 

Page 1142 

```
open #2, "out.csv", output
```

```
do
    input csv #1, ary()
    if eof(1) then
        exit
    else
```

```
            writecd #2, ary()
    endif
```

```
loop
close #1
close #2
```

Note that the explicit test for eof(1) prior to the writecd is only needed to prevent an extra blank line at the end of the output file resulting from the final writecd with a zero element ary(). If a blank line at the end isn't a bother, then you could simplify the loop to: 

```
do
```

```
    input csv #1, ary()
    writecd #2, ary()
loop until eof(1)
```

## **History** 

A-Shell Reference 

Page 1143 

- 2021 January, A Shell 6.5.1697: `INPUT CSV #ch, ary()` , where ary() is a DIMX array with the AUTO_EXTEND option, now updates the ary() extent based on the number of elements input. Previously it expanded the array extent as needed, but would not contract it. The new behavior matches the original intent and documentation. 

- 2018 June, A Shell 6.5.1637:  An empty element is now added to the end of the array if the input data ends with a comma. So for example, the data line { `one,two,` } will return ARY() with an extent of 3, with the last field empty. Note that it is still the case that an empty line will return an array with a zero extent. 

- 2018 February, A Shell 6.5.1629, compiler edit 854:  Function added to A-Shell. 

A-Shell Reference 

Page 1144 

## **INPUT CSV INTO GRIDMAP** 

An entire CSV file can be loaded into a gridmap in a single step using: 

```
input csv #ch, $gridmap()
```

For the `gridmap(int; int; varstr)` variation, the values will all be indexed by numeric row and column, each index starting from 1. The number of columns in each row may vary. 

For the `gridmap(int; varstr; varstr)` variation, the first row of the CSV is assumed to contain the column headers, which are used for indexing the columns by name. In that case the second physical row of the CSV will be treated as row one. The application can determine the column names by iterating across the first row, using the .key($$i,1) function to check when the row number changes. The following example copies the column names from row one into a separate array: 

```
dimx colnames$(0),s,40,auto_extend
```

```
dimx $csvmap, gridmap(int; varstr; varstr)
```

```
map1 col,i,2
```

```
...
```

```
input csv #ch, $csvmap()
```

```
foreach $$i in $csvmap()
    if .key($$i,1) = 1 then   ! if row 1
        col += 1
        colnames$(col) = .key($$i,2)
    else
        exit    ! quit when we hit the next row
    endif
next $$i
```

A-Shell Reference 

Page 1145 

## **History** 

- 2023 October, A Shell 7.0.1750: non-trailing empty cells are now included in the gridmap. Previously there were not, which might have created confusion, particularly in the gridmap(int;varstr;varstr) case where a column might have been listed on the header row the CSV but empty in the first data row. Note however, that even with this refinement, empty cells are included only if there are non-empty cells to the right of them (and trailing commas on the CSV lines do not count). 

2023 March, A-Shell 6.5.1728:  Add _INPUT CSV Into Gridmap_ . 

A-Shell Reference 

Page 1146 

## **INPUT RAW** 

## **INPUT RAW #ch, var** 

where _ch_ is the channel of a sequential file open for input, and _var_ is a variable of type X. The operation proceeds until _var_ is filled (with no filtering of binary characters, line terminators, etc.), or until EOF. 

## **Comments** 

Requires compilation with the /X:1 switch 

## **See also** 

- XCALL GET 

- XCALL GETBYT 

A-Shell Reference 

Page 1147 

## **PRINT** 

_Updated December 2020; added ? syntax_ 

## **PRINT {#ch} {TAB(...)} {USING mask}{delimiter} expr{delimiter expr delimiter...}** 

## **? {#ch} {TAB(...)} {USING mask}{delimiter} expr{delimiter expr delimiter...}** 

The two statements above are equivalent; a question mark ( ? ) may be used in place of "PRINT" in any ASB program. 

PRINT outputs the specified material to file or screen. 

_ch_ is an integer expression specifying the file channel on which the file was opened. If not specified, or zero, output is to the terminal. 

The optional _TAB_ (...) clause may to position the output or modify the display attributes, in which case they may be combined with subsequent expressions indicating what to print. Note that for file output, only single-dimension TABs (column positioning) make sense; for row/col positioning and attributes in printed output, see GDI Printing. The _TAB_ (...) clause may also be used to invoke client functions, in which case the subsequent expressions would either be omitted or used to supply parameters to the function rather than data to be printed. See Tab Functions for details. 

_USING mask_ may specify a format mask for the entire print operation, which must include format specifiers for each expression listed in the statement. 

Each expression is a numerical or string expression, which may include a USING mask clause for formatting that one expression. 

Each delimiter may be either a space, comma or semicolon. A space simply outputs a space. A semicolon outputs nothing beyond the preceding expression—i.e. stops the cursor just past the output of the expression. A comma adds several spaces following the preceding expression, unless a format mask was specified prior to the first expression, in which case commas are used simply to delineate the expressions so they can be matched up with the corresponding format specifiers in the mask. The last delimiter is optional. If omitted, a line terminator (CRLF or LF) is output. 

## **Comments** 

The statement token "PRINT" may be replaced by the equivalent "?" for brevity. 

A-Shell Reference 

Page 1148 

PRINT statements are somewhat unusual in that they take a variable number of expressions as arguments. A PRINT statement with multiple arguments can be broken up into multiple PRINT statements with the same overall result. Alternatively, instead of using the delimiters to separate multiple expression arguments, you can use string concatenation to combine them all into a single string expression. 

Three variations of PRINT are DPRINT, EPRINT and TPRINT (see Proportional Font Text Objects), all of which have the identical syntax but are only applicable for screen printing in a GUI environment. All three use the current default proportional font instead of the standard fixed-pitch text mode font. DPRINT adds a sunken panel effect and is typically used for displaying static data fields. EPRINT embeds the output fields in edit boxes, typically used for displaying editable data fields. For outputting to GUI screens you can also use AUI_CONTROL. 

## **Examples** 

```
PRINT "Hello world"
```

```
? #7, CITY$;", ";STATE$;" ";ZIP$
```

- `? #7, CITY$ + ", " + STATE$ + " " + ZIP$ ! same result as preceding statement` 

```
? #CHREP USING "###. /---description ---/ $###,###.##", QTY, DESCR$, QTY*PRICE
```

```
print tab(r,c);"Enter name: "'; tab(r,c+30);"Age: ";
```

```
Print (A using MASK1$) (B using MASK2$)
```

## **See Also** 

- TRACE.PRINT: output to debug window 

- DEBUG.PRINT: output to debug window if DEBUG mode 

- WRITECD (following topic): comma delimited file output 

- USING Mask 

- GDI Printing 

A-Shell Reference 

Page 1149 

- Tab Functions 

A-Shell Reference 

Page 1150 

## **WRITECD** 

_Updated September 2023_ 

## **WRITECD {#ch,} expr1{, …, exprN}** 

## **WRITECD {#ch,} ary()** 

## **WRITECD  {#ch,} $grid()** 

"Write Comma Delimited" is a variation of the PRINT statement which is useful for creating industry-standard* comma-delimited (or tab-delimited) files, normally called CSV files for "Comma Separated Values." 

Note: Although the default delimiter for WRITECD is the comma, it can be set to anything (see MX_CSVDELIM), making the WRITETD variation superfluous and now deprecated. 

## **Individual Elements (first syntax above)** 

Syntax and operation for the first variation shown above are identical to the PRINT statement, except that WRITECD performs three additional functions which are useful when more than one variable is being output on a line: 

- automatically inserts a comma between each variable being output 

- automatically quotes any string variable which itself contains any of the "likely" delimiter characters (comma, tab, semicolon, 

- colon, quote, apostrophe) or the custom delimiter character if applicable 

- strips leading and trailing blanks from any string variable unless accompanied by a formatting mask 

The maximum size of an individual field needing to be enclosed in quotes is 4092 bytes. 

## **Array (second syntax above)** 

The second  syntax variation allows you to output all of the elements in an entire array, without specifying them individually. 

This is equivalent to: 

```
WRITECD #ch, ary(1), ary(2), ...
```

A-Shell Reference 

Page 1151 

... up to the extent of the array. 

Note that the ary() must be created with DIMX (and not MAP), limited to a single dimension, and made up of standard types (X,S,B,F,I; not structures). 

## **Grid (third syntax above)** 

The third syntax variation outputs an entire grid (multiple rows and columns), starting from row 1; any rows below that are assumed to contain control information and are ignored. In the _gridmap(int;varstr;varstr)_ case, an additional starting row is output containing the column headers. In the caseof _gridmap(int;int;varstr)_ , there is no special treatment of column headers, although it is traditional for the first data row to contain the column names. 

## **Examples** 

```
WRITECD #1,5.2,"Nov 1, 2024","   abc  ","Robert ""Bob"" Scott"
```

## Outputs: 

```
5.2,"Nov 1,2024",abc,"Robert 'Bob' Scott"
```

Array: 

```
dimx ary(0), s, 20, auto_extend
ary(1) = "one" : ary(2) = "two" : ary(3) = "three"
writecd ary()
```

Outputs to the screen, as the #ch argument was omitted: 

## `one,two,three` 

This next example illustrates both inputting an entire CSV file into a gridmap and then outputting it again. 

```
dimx $grid, gridmap(int;varstr;varstr)
```

A-Shell Reference 

Page 1152 

```
open #1, csvin$, input
input csv #1, $grid()       ! input entire file into gridmap
close #1
```

```
open #2, csvout$, output
writecd #2, $grid()         ! write entire gridmap to file
close #2
```

## **Comments** 

WRITECD is essentially the inverse of INPUT CSV, which see. WRITECD will convert any embedded quotes (") within a field into apostrophes ('), to try to be more compatible with other CSV readers. 

Also note the procedure for breaking up a single line of CSV output into multiple WRITECD statements: 

```
WRITECD #CH, A, B, C,;
```

```
WRITECD #CH, D, E, F
```

This will output the six variables on one line. Note that that the comma after the C and before the semicolon is required. If you omit it, the D output will immediately follow C with no delimiter. If you omit the semicolon from the first line, then you will get two lines of output. 

The most extreme version of this technique occurs when outputting individual fields in a loop. For example: 

```
FOR %R = 1 TO MAXROW
```

```
    FOR %C = 1 TO MAXCOL-1
```

```
        WRITECD #CH, FIELD(%R,%C),;
```

A-Shell Reference 

Page 1153 

```
    NEXT %C
```

```
    WRITECD #CH, FIELD(%R,MAXCOL)   ! add last field, terminate line
```

```
NEXT %R
```

* Note that the term "industry standard" is used with a good deal of sarcasm and distaste in this context, since the notion of any such standard is farcical—which is why spreadsheet programs employ elaborate "wizards" to aid in the importing of CSV data, and which despite all kinds of fancy heuristics still have to rely on a complicated user interface for specifying all kinds of options, which if not specified properly, may reduce the results to mush. Readers are hereby advised that if they encounter a CSV file which doesn't read in properly using INPUT CSV, they might need to avail themselves of such a wizard to load the file into a spreadsheet and then re-save it, possibly with a different delimiter. This will hopefully result in a CSV file which has the same ideas about "standard" as does INPUT CSV. 

## **History** 

- 2023 September, A Shell 6.5.1742:  The WRITECD ARY() statement now supports numeric array types as well as gridmaps.. 

- 2023 February, A Shell 6.5.1724: Accept type S as well as type X for the array version. 

- 2021 February, A Shell 6.5.1697: Add WRITECD or WRITETD of an Entire Array. 

- 2011 May, A Shell 5.1.1216: Support new custom CSV delimiter per MX_CSVDELIM, expand the list of quoted characters. WRITETD is now deprecated, and should not be used; it remains a valid operator only to preserve operations by older code. 

A-Shell Reference 

Page 1154 

## **WRITETD** 

## **Deprecated** . See WRITECD. 

WRITETD is equivalent to to WRITECD except that, by default, it uses TAB as the delimiter.  However, since the introduction of MX_CSVDELIM, to override the default delimiter, the implied distinction between the two WRITEXD variations has become misleading, and consequently the use of WRITETD is deprecated. 

WRITETD will remain supported for compatibility reasons, but the recommended approach is first use MX_CSVDELIM to establish your preferred delimiter—if other than comma—and then stick with WRITECD. 

A-Shell Reference 

Page 1155 

## **RANDOM ACCESS FILES** 

ddd 

Random access files are: 

- fixed length records containing a mixture of field types 

- ISAM and ISAM-A files are special variants of random access files 

- files must be pre-allocated; see ALLOCATE, CREATE 

- file expansion typically not automatic, except for ISAM, ISAM-A; see MX_EXPFIL 

- file and record locking is available; see LOKSER 

- records may be "blocked" into 512 byte blocks; see OPEN statement 

See File Access Methods for an explanation / etymology of "Random Access". 

## **Subtopics** 

- ALLOCATE 

- FILEBASE 

- OPEN 

- XOPEN 

- READ 

- SET'RECNO 

- UNLOKR 

A-Shell Reference 

Page 1156 

## · WRITE 

- XREAD, XWRITE, XUNLOKR 

A-Shell Reference 

Page 1157 

## **ALLOCATE** 

## **ALLOCATE fspec, blks** 

ALLOCATE creates a random file. 

## **Parameters** 

_fspec_ is file specification in native or DevPPN format. If no extension is given, the default is .DAT. To create a file with no extension, terminate the filespec with a single period ("."). 

_blks_ specifies the size of the file in 512 byte "blocks". Modern disks typically have much larger physical blocks sizes, so the 512 byte unit used here is just a historical hold-over from AMOS. 

## **Comments** 

Random files must be created before they can be opened. In contrast, a sequential file is created automatically when it is opened for output. 

A-Shell Reference 

Page 1158 

## **FILEBASE** 

## **FILEBASE fbase** 

FILEBASE sets the record numbering basis. 

## **Parameters** 

_fbase_ is a literal value, typically 0 or 1, establishing the starting point for record numbering in all files opened subsequently. 0 is the default. 

A-Shell Reference 

Page 1159 

## **OPEN** 

_Rewritten June 2020_ 

## **OPEN #ch, fspec, mode, recsiz, recnovar {,WAIT'FILE} {,WAIT'RECORD} {,READ'ONLY} {,SPAN'BLOCKS}** 

## **Parameters** 

## _ch_ (Num)  [in] 

an integer expression (>0) specifying the file channel which will be needed for subsequent I/O operations on the file. 

## _fspec_ (String)  [in] 

string expression containing file specification, in native or DevPPN syntax. May contain embedded %env% variables, e.g. "%temp%\myfile.dat".  If no directory information is included, the search path consists of the current directory, followed by the [p,0] directory. 

## _mode_ (literal keyword)  [in] 

specifies the file access mode, and must be one of the following (case insensitive) compiler keywords: 

|**Symbol**|**Description**|
|---|---|
|RANDOM|WhenLOKSER<br>enabled, requests exclusive access; otherwise same as RANDOM'FORCED|
|RANDOM'FORCED|Shared access|



## _recsiz_ (Num)  [in] 

integer expression specifying the record size—i.e. the number of bytes transferred in each subsequent READ and WRITE operations. See _span'blocks_ below. 

_recnovar_ (F6)  [in] 

A-Shell Reference 

Page 1160 

holds the record number for record-level operations such as XREAD, XWRITE, XUNLOKR that require one. This variable must be F,6. It gets linked by address to the file's entry in the open file table, and thus must remain in scope for the duration of the open file channel. If this is not possible, for example, across function or SBX calls, you can manually reassign it to another variable using MX_FLSET. Or, to eliminate this limitation entirely, use XOPEN instead of OPEN. 

## _wait'file, wait'record_ and _read'only_ (literal keyword)  [in] 

have meaning only when LOKSER is enabled, otherwise they are ignored. _wait'file_ causes the statement to wait until access can be granted. If requesting exclusive access, no other process may have the file open except for _read'only_ . If requesting shared access, no other process can have the file open exclusively. Otherwise, if access cannot be granted, error 37 will be returned. _wait'record_ causes READ operations to wait if the requested record is locked, otherwise error 38 is returned. _read'only_ disables LOKSER—and WRITE operations—for this file access session, and is useful when you're just going to be reading from the file and it isn't critical that the file isn't modified during the read operations. Also see XCALL ASFLAG for a way to achieve this effect without using the BASIC _plus_ compiler extensions. See _History_ . 

## _span'blocks_ (literal keyword)  [in] 

disables 512-byte blocking. This is a historical hold-over, which performed random file access in 512 byte blocks and did not allow logical records to be split between two blocks. If the record size didn't divide evenly into 512, the remaining number of bytes would simply be unused at the end of each 512 byte block. In the worst case, a record size of 257 bytes would result in 255 out of every 512 bytes wasted. In _span'blocks_ mode, records are adjacent with no wasted space between them and no consideration for how they map onto physical disk "blocks". 512-byte blocking remains the default, for compatibility with existing files, but serves no useful purpose in the modern world and is therefore deprecated. _span'blocks_ is always recommended, except when compatibility with older file layouts is required. _span'blocks_ is automatic when the record size is greater than 512. 

## **See Also** 

- XOPEN 

## **History** 

- 2020 July, A Shell 6.5.1688: LOKSER _wait'file_ and _wait'record_ enhancement: when waiting for more than five seconds for access to a file or record, a status message will now display on the bottom unshifted status line of the main terminal window indicating the name of the file, access type, and elapsed wait time. 

A-Shell Reference 

Page 1161 

## **XOPEN** 

_Written June 2020_ 

## **XOPEN #ch, fspec$, mode, recsiz {, flags}** 

XOPEN is an alternative to the traditional OPEN statement, offering the following advantages: 

- Replacement of the literal compiler keywords (e.g. WAIT'RECORD) with a flexible flags parameter, allowing a single generic, 

- parameterized, XOPEN statement to be used for all variations. 

- Elimination of the requirement for the _recnovar_ to remain in scope, by eliminating it entirely. Instead, you can specify the 

- record number explicitly using the XREAD, XWRITE, XUNLOKR or SET'RECNO statements. 

## **Parameters** 

_ch_ (Num)  [in] 

an integer expression (>0) specifying the file channel which will be needed for subsequent I/O operations on the file. 

_fspec_ (String)  [in] 

string expression containing file specification, in native or DevPPN syntax. May contain embedded %env% variables, e.g. "%temp%\myfile.dat".  If no directory information is included, the search path consists of the current directory, followed by the [p,0] directory. 

## _mode_ (literal keyword)  [in] 

specifies the file access mode, and must be one of the following (case insensitive) compiler keywords: 

|**Symbol**|**Description**|
|---|---|
|RANDOM|WhenLOKSER<br>enabled, requests exclusive access; otherwise same as RANDOM'FORCED|
|RANDOM'FORCED|Shared access|



A-Shell Reference 

Page 1162 

Note that unlike with the traditional OPEN, here the you can specify RANDOM and then use the flags argument to change it to RANDOM'FORCED, thereby eliminating the need for two separate literal variations of the XOPEN statement in your code. 

_recsiz_ (Num)  [in] 

integer expression specifying the record size—i.e. the number of bytes transferred in each subsequent READ and WRITE operations. See SPAN'BLOCKS below. 

_flags_ (B,4 or numeric expression)  [in] 

flags optionally specifies zero or more of the following modifiers: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|FDVF_FORCED|&h0010|Convert RANDOM to RANDOM'FORCED (shared)|
|FDVF_EXCLUSIVE|&h0800|Convert INDEXED to INDEXED'EXCLUSIVE|
|FDVF_READONLY|&h1000|READONLY|
|FDVF_SPANBLOCKS|&h2000|SPAN'BLOCKS|
|FDVF_W_RECORD|&h4000|WAIT'RECORD|
|FDVF_W_FILE|&h8000|WAIT'FILE|
|**Definition file:**ashinc:addsfdv.def|||



A-Shell Reference 

Page 1163 

Note that if flags is expressed as a variable, it must be of type B,4. Since _flags_ occupies the same position as _recnovar_ in the traditional OPEN statement, requiring it to be of type B,4 here reduces the chance of accidentally confusing the two statements in your coding. 

## **Example** 

XOPEN makes it possible to create a generic function for opening random files, such as the following: 

```
call Fn'XOPEN'Random(ch=CH, fspec$="test.dat", recsiz=128, flags=FDVF_FORCED+FDVF_W_RECORD+FDVF_FILE)
```

```
XREAD #CH, 1    ! read rec # 1
```

```
...
```

```
Function Fn'XOPEN'Random(ch as b2:inputonly, fspec$ as s260:inputonly, recsiz as b2:inputonly, flags as
b4:inputonly) as i4
```

```
    XOPEN #ch, fspec$, RANDOM, recsiz, flags
```

```
EndFunction
```

The above function could easily be upgraded to trap errors and deal file locking conflicts, including logging, user interfacing, etc., allowing you to implement all of that logic in a single place with more modularity than would otherwise be possible with the traditional OPEN statement. 

## **See Also** 

- OPEN 

- XREAD, XWRITE, XUNLOKR 

- ASFLAGXS 

- SET'RECNO 

A-Shell Reference 

Page 1164 

- .RECNO() 

- Search Paths - Data Files 

A-Shell Reference 

Page 1165 

## **READ** 

_|Reviewed and revised July 2020; see History_ 

## **READ #ch, recvar** 

reads a record from a random file without locking. 

## **READL #ch, recvar** 

establishes an exclusive lock on the record before reading if LOKSER enabled. If the lock cannot be granted, the operation either waits or returns error 37, depending on whether the WAIT'RECORD clause was specified on the OPEN statement. To release the lock, you just either use a WRITE or UNLOKR statement. 

## **READ'READ'ONLY #ch, recvar** 

an unlocked read, with no option to subsequently write. 

## **READ var1{, var2...}** 

reads individual data fields from the DATA statement pool. 

## **Parameters** 

_ch_ (Num)  [in] 

specifies the previously-opened file channel. 

_recvar_ (X)  [out] 

variable to receive the entire record. Typically it is an unformatted MAP1 level variable or structure containing sub fields arranged to match the layout of the data record. See example below. It may also be a Dynamically Sized Variables (X,0), in which case you would subsequently need to copy it to a structure in order to break out the individual fields. See History. 

## **Comments** 

A-Shell Reference 

Page 1166 

The record number for the read operation is established by setting the record number variable specified in the OPEN statement. Since the OPEN statement and subsequent READ statements may be widely separated, care must be taken that the record number variable remains in scope. See MX_FLSET for details related to reading from a file within an SBX. See XREAD and XWRITE for variations of READ and WRITE which specify an explicit record number for the operation, eliminating the interdependence on the external record number variable. 

Record numbers start at 0 by default, but may be changed (typically to 1) using the FILEBASE statement. 

Typically the size of the recvar should match the record size specified in the OPEN statement. However, if not, the READ operation works in the same was as an assignment statement, with the data read from the disk acting as the source expression. Thus if recvar is too small, the data is simply truncated to fit. If recvar is too large, the extra bytes are either left alone, assuming recvar is an unformatted type, i.e. X variable, or set to null, if recvar is a string. 

## **Example** 

```
DEFSTRUCT ST_CUS        ! 64 byte customer record definition
```

```
    MAP2 ID,S,6
```

```
    MAP2 NAME,S,30
    MAP2 PHONES(2)
```

```
        MAP3 OFFICE,S,10
```

```
        MAP2 CELL,S,10
```

```
    MAP2 ZONE,B,2
```

```
    MAP2 BALANCE,F
```

```
ENDSTRUCT
```

```
MAP1 CUS,ST_CUS         ! customer record instance
```

```
MAP1 CUSRECNO,F         ! record #
```

```
    OPEN #1, "CUST.DAT", RANDOM'FORCED, 64, CUSRECNO
```

A-Shell Reference 

Page 1167 

```
    CUSRECNO = 9        ! rec # 9
    READL #1, CUS       ! lock and read rec
    CUS.BALANCE += 1    ! modify rec
    WRITE #1, CUS       ! write (and unlock) rec
```

## **See Also** 

- XREAD, XWRITE, XUNLOKR 

## **History** 

- 2020 June, A Shell 6.5.1684: READ, XREAD and ISAMA GET operations now work with dynamic X (X0) record variables, regardless of whether they are pre-initialized. Previously this only worked if the variable was pre-initialized to the size of the record. 

A-Shell Reference 

Page 1168 

## **SET'RECNO** 

_Added June 2020_ 

## **SET'RECNO #channel, expr** 

SET'RECNO sets the record number of a file. This would be equivalent to setting the _recnovar_ variable, associated with channel in the OPEN statement, to the value of _expr_ . 

## **History** 

- 2020 June, A Shell 6.5.1684:  Function added to A-Shell 

A-Shell Reference 

Page 1169 

## **UNLOKR** 

## **UNLOKR #ch** 

## **Parameters** 

_ch_ is an integer identifying the file; established by the OPEN statement. 

## **Comments** 

UNLOKR has no effect if LOKSER not enabled, or if the current record number is not locked. The record number to unlock is determined by the contents of the record-number variable specified in the OPEN statement. Records are locked by the READL statement, and if not unlocked by a subsequent WRITE, should be unlocked by UNLOKR. Closing the file also unlocks all locked records. 

## **See Also** 

- XREAD, XWRITE, XUNLOKR 

A-Shell Reference 

Page 1170 

## **WRITE** 

_Updated May 2024_ 

## **WRITE #ch, recexpr** 

## **WRITEL #ch, recexpr** 

## **WRITEN #ch, recexpr** 

## **WRITELN #ch, recexpr** 

The difference between WRITE and WRITEL has to do with record locking and only applies when LOKSER is enabled. WRITE writes a record and unlocks it afterwards so that it can be modified by another process. It assumes that the record was previously read with READL. WRITEL establishes a lock first and then writes. It is used for writing records that were not previously locked. 

WRITEN and WRITELN are identical to WRITE and WRITEL, respectively, except they don't release the lock after the write. 

## **Parameters** 

_recexpr_ is an expression containing the data to write. Typically it is the same record variable or structure used in the READ statement, but could technically be any expression, provided its length does not exceed the record size specified in the OPEN statement. If the length of _recexpr_ is less than the record size, the remaining bytes in the target record on disk will not be modified. 

## **Comments** 

See the READ statement topic for comments regarding the record number which apply here as they do for READ. 

## **Example** 

See READ. 

A-Shell Reference 

Page 1171 

## **See Also** 

- XREAD, XWRITE, XUNLOKR 

A-Shell Reference 

Page 1172 

## **XREAD, XWRITE, XUNLOKR** 

_Updated October 2019; see History_ 

## The "eXplicit" variations of READ, WRITE and UNLOKR take the following format: 

```
XREAD #CH, RECNO, VAR {,VAR2...,VARN}
```

```
XREADL #CH, RECNO, VAR {,VAR2...,VARN}
XREAD'READ'ONLY #CH, RECNO, VAR {,VAR2...,VARN}
```

```
XWRITE #CH, RECNO, VAR {,VAR2...,VARN}
XWRITEL #CH, RECNO, VAR {,VAR2...,VARN}
XWRITEN #CH, RECNO, VAR {,VAR2...,VARN}
XWRITELN #CH, RECNO, VAR {,VAR2...,VARN}
XUNLOKR #CH, RECNO
```

These are equivalent to the standard versions of these statements (without the "X" and without the RECNO variable), except that instead of getting the record number implicitly, from the variable specified in the OPEN statement, the record number is specified, eXplicitly, in the statement. 

While the "X" versions of the READ and WRITE file operations can be used in any context without penalty, there are two specific situations where they are extremely advantageous: 

• Within SBX routines, where they eliminate the need to use MX_FLSET to reset the address of the record number variable stored in the file's control structure. See Accessing Open Files for more information. 

• In parameterized/generic file operations where you don't know the record size at the time of writing the code. The standard variations of the WRITE statements will abort with a "record size overflow" error if the record variable specified in the WRITE is larger than the record size specified in the OPEN. The XWRITE variants avoid this limitation by automatically truncating the specified record variable to match the record size specified in the OPEN statement. 

A-Shell Reference 

Page 1173 

## **History** 

- 2019 October, A Shell 6.5.1669: Added XUNLOKR. Note that the appearance of XUNLOKR in a program will set the minimum version requirement in the RUN header to 1669. 

A-Shell Reference 

Page 1174 

## **ISAM FILES** 

See the following topics for the various statements used with ISAM files. 

## **Subtopics** 

- ISAM Statements 

- LOCK for ISAM 

- OPEN for ISAM 

- READ for ISAM 

- XOPEN for ISAM 

- WRITE for ISAM 

A-Shell Reference 

Page 1175 

## **ISAM STATEMENTS** 

## **ISAM #ch, code, key** 

## _ch_ (Num)  [in] 

Channel number specified in the OPEN statement for the file. Note that a single channel is used for the combination of the IDA and the primary IDX. Secondary IDX files have their own channels. 

## _key_ (String)  [in/out] 

## A symbolic key 

## _code_ (Num)  [in] 

A numeric code 1-8 indicating the operation to perform. 

|**Code**|**Operation**|**Description**|
|---|---|---|
|1|Lookup|Searches the IDX file associated with CH for the specified KEY. If not found, returns ERF(ch) = 33.<br>Else returns ERF(ch) = 0 and sets the relative record number variable (from the OPEN statement)<br>to match the found record.|
|2|Get Next|Performs a get-next operation based on index position left by the previous 1, 2, or 7 statement.<br>Sets the relative record number variable to match the fund record. Sets ERF(ch) to 38 if no more<br>keys in sequence. KEY is not used. Generally superseded by code 7.|
|3|Add Key|Adds the specified key to the index, associating it with the record number currently stored in the<br>record number variable.|



A-Shell Reference 

Page 1176 

|**Code**|**Operation**|**Description**|
|---|---|---|
|4|Delete Key|Deletes the specified key from the index.|
|5|Add Record|Allocates/assigns a new record in the IDA file, returning its relative record number in the record<br>number variable. Must be followed by a<br>`WRITE{L} #ch, rec`statement to actually write the<br>record data to the file.|
|6|Delete Record|Deletes the record specified by the relative record number variable from the IDA file (adding it<br>back to the deleted record chain so that it may be reused).|
|7|Get Next|Same as code 2 except returns the found next key in the KEY variable.|
|8|Get Previous|A-Shell extension, added in 6.1.1344.0. Reverse of code 7. Returns ERF(ch) = 38 if no more keys<br>(i.e. when you hit the start of the index).|



Each of the ISAM statements returns a status which you should check using the ERF() function. The range of values is given in the table below: 

|**ERF() value**|**Meaning**|
|---|---|
|32|Illegal ISAM statement code|
|33|Key not found during key lookup|
|34|Duplicate key during attempt to add key. Note that duplicate keys not supported by ISAM 1.x.|
|35|IDX is corrupted and must be recreated.|



A-Shell Reference 

Page 1177 

|**ERF() value**|**Meaning**|
|---|---|
|36|IDX file full. You've disabled the auto-expand feature (see NOAUTOX option), the disk is full, or you've reached<br>the maximum limit of 4 billion IDX blocks.|
|37|IDA file full. You've disabled the auto-expand feature (see NOAUTOX), the disk is full, or you've reached the<br>maximum limit of 4 billion records.)|
|38|End of file reached during get-next key operation, or start of file reached during get-previous key operation|
|39|Illegal ISAM sequence. See File Locking below.|



You must employ some kind of file locking system when allowing multi-user access to ISAM files (i.e. when the files are opened in INDEXED rather than INDEXED'EXCLUSIVE mode). Unlike ISAM-A, ISAM 1.x provides you the latitude (and responsibility) to implement the locking system. However, when LOKSER is enabled, it will be used and certain rules will be enforced with violations resulting in ERF(ch) returning error 39. The following table summarizes the ISAM / LOKSER behavior and rules: 

|**Stmt Code**|**Operation**|**Primary IDX**|**Secondary IDX**|
|---|---|---|---|
|1, 2, 7, 8|Locate record by key|Locked automatically and remains locked on return|Locked automatically during<br>operation but unlocked on<br>return|
|3|Add key|Must be locked initially (typically from a previous<br>locate record operation). Unlocked on return|Locked automatically during<br>operation; unlocked on return|
|4|Delete Key|Must be locked initially and remains locked on return|Locked automatically during<br>operation; unlocked on return|
|5|Add Data Rec|Must be locked initially; remains locked on return|Not applicable|
|6|Delete Data Rec|Must be locked initially; remains locked on return|Not applicable|
|READ|read data|Must be locked initially; unlocked on return|Not applicable|
|READL|read/lock (for update)|Must be locked initially; remains locked on return|Not applicable|
|WRITE|write/update data|Must be locked initially; unlocked on return.|Not applicable|



A-Shell Reference 

Page 1178 

|**Stmt Code**|**Operation**|**Primary IDX**|**Secondary IDX**|
|---|---|---|---|
|WRITEL|write new data|Must be locked initially; remains locked on return.<br>(Normally followed by Add Key which unlocks)|Not applicable|
|LOCK|Lock primary index|Locked by operation|Not applicable|
|UNLOKR|Unlock record and/or<br>index|Unlocked by operation (no harm if already unlocked)|Not applicable|



The following samples illustrate some typical operations on an ISAM file with a single primary IDX. For simplicity, all the examples use a generic routine called ISAM'ERROR for any unexpected errors. The routine should always start with an `UNLOKR #CH` to make sure the file isn't left in a locked state. 

## **Add Record:** 

```
ISAM #CH, 1, KEY                ! lookup key
```

```
IF ERF(CH) = 0 THEN
```

```
   ? "Record already exists"
```

```
   UNLOKR #CH
```

```
ELSEIF ERF(CH) # 33 THEN        ! any state other than not-found
```

```
   GOTO ISAM'ERROR
```

```
ELSE
```

```
   ISAM #CH, 5, KEY             ! add a data record
   IF ERF(CH) # 0 THEN
      GOTO ISAM'ERROR
```

```
   ELSE
```

A-Shell Reference 

Page 1179 

```
      WRITEL #CH, REC           ! write the data
      ISAM #CH, 3, KEY          ! add the key
```

```
      IF ERF(CH) # 0 THEN
         GOTO ISAM'ERROR
```

```
      ENDIF
```

```
   ENDIF
```

```
ENDIF
```

## **Delete Record:** 

```
ISAM #CH, 1, KEY                ! lookup key
```

```
IF ERF(CH) = 33 THEN
```

```
   ? "Record doesn't exist"
```

```
   UNLOKR #CH
```

```
ELSEIF ERF(CH) # 0 THEN
```

```
   GOTO ISAM'ERROR
```

```
ELSE
```

```
   READL #CH, REC               ! read/lock the record
   ISAM #CH, 4, KEY             ! delete key
   IF ERF(CH) # 0 THEN
      GOTO ISAM'ERROR
```

```
   ELSE
```

A-Shell Reference 

Page 1180 

```
      ISAM #CH, 6, KEY          ! delete the data record
```

```
      IF ERF(CH) # 0 THEN
         GOTO ISAM'ERROR
```

```
      ENDIF
```

```
   ENDIF
```

```
ENDIF
```

## **Read Record:** 

```
ISAM #CH, 1, KEY               ! lookup key
IF ERF(CH) = 0 THEN            ! if found ...
    READ #CH, REC              ! read rec (unlocks index)
ELSE                           ! else
    ? "Key ";KEY;" not found"  !
    UNLOKR #CH                 ! manually unlock index
```

```
ENDIF
```

## **Subtopics** 

- 

A-Shell Reference 

Page 1181 

## **LOCK FOR ISAM** 

_Added May 2024_ 

## **LOCK #ch** 

Applicable only when LOKSER enabled, LOCK is used to lock the primary index ( _ch_ ) after locating a record using a secondary index. This is automatic when the record is located via the primary index. 

## **Example** 

The following illustrates looking up a record in the secondary index and then deleting it. The LOCK statement is used to first lock the primary index before the delete operation. 

```
OPEN #PCH, "WIDGET", ISAM'INDEXED,  RECSIZ, RECNO    ! primary index & data
```

```
OPEN #SCH, "WIDGET2", ISAM'INDEXED, RECSIZ, RECNO    ! secondary index
```

```
...
ISAM #SCH , 1, KEY       ! lookup key in secondary index SCH
IF ERF(SCH) = 33 then
```

```
    ? "Record not found"
```

```
ELSEIF ERF(SCH) # 0 then
```

```
    GOTO ISAM'ERROR
```

```
ELSE
```

```
    LOCK #PCH            ! lock primary index
```

```
    READL #PCH, REC
```

```
    ISAM #SCH, 4, SKEY   ! delete secondary key
    IF ERF(SCH) # 0 GOTO ISAM'ERROR
```

A-Shell Reference 

Page 1182 

```
    ISAM #PCH, 4, PKEY   ! delete primary key
    IF ERF(PCH) # 0 GOTO ISAM'ERROR
    ISAM #PCH, 6, PKEY   ! delete data rec
    IF ERF(PCH) # 0 GOTO ISAM'ERROR
```

```
    WRITE #PCH, REC
```

```
ENDIF
```

## **See Also** 

- UNLOKR 

A-Shell Reference 

Page 1183 

## **OPEN FOR ISAM** 

_This is Rewritten June 2020_ 

## **OPEN #ch, fspec, mode, recsiz, recnovar {,WAIT'FILE} {,WAIT'RECORD} {,READ'ONLY} {,SPAN'BLOCKS}** 

The OPEN for ISAM syntax is identical to the OPEN for Random Access syntax except for the _mode_ options. However, note that in the ISAM case, one OPEN statement may actually open two files, the index or IDX file, and the data or IDA file; see the _fspec_ parameter for more details. 

## **Parameters** 

## _ch_ (Num)  [in] 

an integer expression (>0) specifying the file channel which will be needed for subsequent I/O operations on the file. 

## _fspec_ (String)  [in] 

string expression containing file specification, in native or DevPPN syntax. May contain embedded %env% variables, e.g. "%temp%\myfile.dat".  If no directory information is included, the search path consists of the current directory, followed by the [p,0] directory. 

In ISAM, the specification is of a primary or secondary index (IDX) file. In the case of a primary index, the associated data (IDA) file will also be opened at the same time and accessed via the same channel. To reduce confusion, the file extension (IDX) is normally omitted, since the operation will open both the IDX and IDA files. In the case of a secondary index, only the index file is opened. 

## _mode_ (literal keyword)  [in] 

specifies the file access mode, and must be one of the following (case insensitive) compiler keywords: 

|**Open Mode**|**Meaning**|
|---|---|
|ISAM'INDEXED|Same as INDEXED but forces operation to be interpreted as an ISAM open rather than an ISAM-<br>A open, regardless of the COMPIL mode. Otherwise the COMPIL mode will determine whether to|



A-Shell Reference 

Page 1184 

|**Open Mode**|**Meaning**|
|---|---|
||assume old ISAM or ISAM-A.|
|ISAM'INDEXED'EXCLUSIVE|Same as INDEXED'EXCLUSIVE but forces operation to be interpreted as an ISAM open rather<br>than an ISAM-A open, regardless of the COMPIL mode.|
|INDEXED|Normal shared open. If file is already open by another user exclusively, job will wait (if the<br>wait'record option specified) or receive ASB error 37 (file in use). See comment below this<br>table.|
|INDEXED'EXCLUSIVE|Open for exclusive use. If file is already open by another user in any mode, job will wait (if the<br>wait'record option specified) or receive ASB error 37 (file in use).|



Although the OPEN for ISAM syntax differs somewhat from the OPEN for ISAM-A syntax, there is enough overlap that they can be confused if the INDEXED or INDEXED'EXCLUSIVE mode is specified without the ISAM' (or ISAMP' for ISAM-A) prefix. In the absences of the disambiguating prefix, the compiler will assume ISAM if the /I switch is specified, else it will assume ISAM-A. 

## _recsiz_ (Num)  [in] 

integer expression specifying the record size—i.e. the number of bytes transferred in each subsequent READ and WRITE operations. See SPAN'BLOCKS below. 

## _recnovar_ (F6)  [in] 

holds the record number for record-level operations such as XREAD, XWRITE, XUNLOKR that require one. This variable must be F,6. It gets linked by address to the file's entry in the open file table, and thus must remain in scope for the duration of the open file channel. If this is not possible, for example, across function or SBX calls, you can manually reassign it to another variable using MX_FLSET. Or, to eliminate this limitation entirely, use XOPEN instead of OPEN. 

If opening a secondary index, specify the same record number variable as for the primary index. 

## _wait'file, wait'record_ and _read'only_ (literal keyword)  [in] 

have meaning only when LOKSER is enabled, otherwise they are ignored. _wait'file_ causes the statement to wait until access can be granted. If requesting exclusive access, no other process may have the file open except for _read'only_ . If requesting shared 

A-Shell Reference 

Page 1185 

access, no other process can have the file open exclusively. Otherwise, if access cannot be granted, error 37 will be returned. _wait'record_ causes READ operations to wait if the requested record is locked, otherwise error 38 is returned. _read'only_ disables LOKSER—and WRITE operations—for this file access session, and is useful when you're just going to be reading from the file and it isn't critical that the file isn't modified during the read operations. Also see XCALL ASFLAG for a way to achieve this effect without using the BASIC _plus_ compiler extensions. See _History_ . 

## _span'blocks_ (literal keyword)  [in] 

disables 512-byte blocking. This is a historical hold-over, which performed random file access in 512 byte blocks and did not allow logical records to be split between two blocks. If the record size didn't divide evenly into 512, the remaining number of bytes would simply be unused at the end of each 512 byte block. In the worst case, a record size of 257 bytes would result in 255 out of every 512 bytes wasted. In _span'blocks_ mode, records are adjacent with no wasted space between them and no consideration for how they map onto physical disk "blocks". 512-byte blocking remains the default, for compatibility with existing files, but serves no useful purpose in the modern world and is therefore deprecated. _span'blocks_ is always recommended, except when compatibility with older file layouts is required. _span'blocks_ is automatic when the record size is greater than 512. 

## **See Also** 

- XOPEN FOR ISAM 

- Search Paths - Data Files 

A-Shell Reference 

Page 1186 

## **READ FOR ISAM** 

_Doc added May 2021_ 

All of the READ for random access statement variations may be used with ISAM files. Note, however: 

- Each open ISAM file channel refers to both an index (IDX) and data (IDA) file. READ operations implicitly apply to only the 

- IDA. 

- Although you _can_ manually set the record number variable and read from IDA file independent of the index (as you would 

- with a random access file), typically you would use an ISAM File Statements (codes 1, 2, 7, or 8) to establish the record number. 

See ISAM File Statements for examples of ISAM operations involving READ statements. 

A-Shell Reference 

Page 1187 

## **XOPEN FOR ISAM** 

_Updated July 2021_ 

## **XOPEN #ch, fspec$, mode, recsiz {, flags}** 

XOPEN is an alternative to the traditional OPEN statement, offering the following advantages: 

- Replacement of the literal compiler keywords (e.g. WAIT'RECORD) with a flexible flags parameter, allowing a single generic, 

- parameterized, XOPEN statement to be used for all variations. 

- Elimination of the requirement for the _recnovar_ to remain in scope, by eliminating it entirely. Instead, you can specify the 

- record number explicitly using the XREAD, XWRITE, XUNLOKR or SET'RECNO statements. 

## **Parameters** 

_ch_ (Num)  [in] 

an integer expression (>0) specifying the file channel which will be needed for subsequent I/O operations on the file. 

## _fspec_ (String)  [in] 

string expression containing file specification, in native or DevPPN syntax. May contain embedded %env% variables, e.g. 

- "%temp%\myfile.dat".  If no directory information is included, the search path consists of the current directory, followed by the [p,0] directory. 

In ISAM, the specification is of a primary or secondary index (IDX) file. In the case of a primary index, the associated data (IDA) file will also be opened at the same time and accessed via the same channel. To reduce confusion, the file extension (IDX) is 

normally omitted, since the operation will open both the IDX and IDA files. In the case of a secondary index, only the index file is opened. 

_mode_ (literal keyword)  [in] 

specifies the file access mode, and must be one of the following (case insensitive) compiler keywords: 

A-Shell Reference 

Page 1188 

|**Open Mode**|**Meaning**|
|---|---|
|ISAM'INDEXED|Same as INDEXED but forces operation to be interpreted as an ISAM open<br>rather than an ISAM-A open, regardless of the COMPIL mode. Otherwise<br>the COMPIL mode will determine whether to assume old ISAM or ISAM-A.|
|ISAM'INDEXED'EXCLUSIVE|Same as INDEXED'EXCLUSIVE but forces operation to be interpreted as an<br>ISAM open rather than an ISAM-A open, regardless of the COMPIL mode.|
|INDEXED|Normal shared open. If file is already open by another user exclusively, job<br>will wait (if the wait'record option specified) or receive ASB error 37 (file in<br>use). See comment below this table.|
|INDEXED'EXCLUSIVE|Open for exclusive use. If file is already open by another user in any mode,<br>job will wait (if the wait'record option specified) or receive ASB error 37<br>(file in use).|



## _recsiz_ (Num)  [in] 

integer expression specifying the record size—i.e. the number of bytes transferred in each subsequent READ and WRITE operations. See SPAN'BLOCKS below. 

## flags  (B,4 or numeric expression)  [in] 

flags optionally specifies zero or more of the following modifiers: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|FDVF_FORCED|&h0010|Convert RANDOM to RANDOM'FORCED (shared)|
|FDVF_EXCLUSIVE|&h0800|Convert INDEXED to INDEXED'EXCLUSIVE|



A-Shell Reference 

Page 1189 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|FDVF_READONLY|&h1000|READONLY|
|FDVF_SPANBLOCKS|&h2000|SPAN'BLOCKS|
|FDVF_W_RECORD|&h4000|WAIT'RECORD|
|FDVF_W_FILE|&h8000|WAIT'FILE|
|**Definition file:**ashinc:addsfdv.def|||



Note that if flags is expressed as a variable, it must be of type B,4. Since _flags_ occupies the same position as _recnovar_ in the traditional OPEN statement, requiring it to be of type B,4 here reduces the chance of accidentally confusing the two statements in your coding. 

## **Example** 

```
if Fn'Open'ISAM(ch=1234, fspec$="MYFILE", recsiz=128, flags= FDVF_EXCLUSIVE+FDVF_W'FILE) > 0 then
```

```
    isam #ch, 1, mykey$
```

```
...
```

```
Function Fn'Open'ISAMA(ch as b2:inputonly, fspec$ as s260:inputonly, recsiz as b2:inputonly, flags as
b4:inputonly) as i4
```

```
    if ch # 0 then              ! if a non-zero channel specified
```

A-Shell Reference 

Page 1190 

```
       if eof(ch) = -1 then     ! and it's not already open
```

```
           xopen #ch, fspec$, ISAM'INDEXED, recsiz, flags
```

```
       endif
```

```
    endif
```

```
    .fn = ch
```

```
EndFunction
```

The above function could easily be upgraded to trap errors and deal file locking conflicts, including logging, user interfacing, etc., allowing you to implement all of that logic in a single place with more modularity than would otherwise be possible with the traditional OPEN statement. 

## **See Also** 

- OPEN FOR ISAM 

- XREAD, XWRITE, XUNLOKR 

- ASFLAGXS 

- SET'RECNO 

- .RECNO() 

A-Shell Reference 

Page 1191 

## **WRITE FOR ISAM** 

_Doc added May 2021_ 

All of the WRITE for random access statement variations may be used with ISAM files. Note, however: 

- Each open ISAM file channel refers to both an index (IDX) and data (IDA) file. WRITE operations implicitly apply to only the 

- IDA. 

- Although you _can_ manually set the record number variable and read from IDA file independent of the index (as you would 

- with a random access file), typically you would use an ISAM File Statements (codes 1, 2, 7, or 8) to establish the record number. 

See ISAM File Statements for examples of ISAM operations involving READ statements. 

A-Shell Reference 

Page 1192 

## **- ISAM A FILES** 

See the following topics for the various statements used with ISAM-A files. 

## **Subtopics** 

- OPEN for ISAM-A 

- XOPEN for ISAM-A 

- CLOSE 

- GET, GET’LOCKED, GET’READ’ONLY 

- GET'NEXT 

- GET'PREV 

- FIND 

- UPDATE’RECORD 

- DELETE’RECORD 

- CREATE’RECORD 

- SET'RECNO 

- RELEASE 

- ALLOCATE'INDEXED 

- INDEXED'STATS 

A-Shell Reference 

Page 1193 

- ISAM'PUSH and ISAM'POP 

- TRANSACTION'LOG 

- TRANSACTION 

- READ for ISAM-A 

A-Shell Reference 

Page 1194 

## **- OPEN FOR ISAM A** 

## **OPEN #channel, filespec, mode, recnovar, fstatvar {,END'FILE} {,WAIT'FILE} {,WAIT'RECORD}** 

## **{,READ'ONLY}** 

Opens the file. Note that while internally there may be multiple physical files, from BASIC, the combination of the data file and index is treated as a single file. Unlike old ISAM, there is no need or possibility of opening up additional index files. 

Also note that unlike the OPEN statements for random and ISAM files, there is no record size parameter. The actual data record size on disk is one byte larger (due to a control byte) than the logical record size specified in the file index. There is also no _span'blocks_ parameter, because it is effectively always on—i.e. the records are contiguous without regard to disk block size. 

## _ch_ (Num)  [in] 

an integer expression (>0) specifying the file channel which will be needed for subsequent I/O operations on the file. 

## _fspec_ (String)  [in] 

string expression containing file specification, in native or DevPPN syntax. May contain embedded %env% variables, e.g. "%temp%\myfile.dat".  If no directory information is included, the search path consists of the current directory, followed by the [p,0] directory. 

In ISAM-A, the specification is of a primary or secondary index (IDX) file. In the case of a primary index, the associated data (DAT) file will also be opened at the same time and accessed via the same channel. To reduce confusion, the file extension (IDX) is normally omitted, since the operation will open both the IDX and DAT files. 

## _mode_ (literal keyword)  [in] 

must be one of the following: 

|**Open Mode**|**Meaning**|
|---|---|
|ISAMP'<br>INDEXED|Same as INDEXED but forces operation to be interpreted as an ISAM-A open<br>rather than an ISAM open, regardless of the COMPIL mode. Otherwise the<br>COMPIL mode will determine whether to assume old ISAM or ISAM-A.|



A-Shell Reference 

Page 1195 

|**Open Mode**|**Meaning**|
|---|---|
|ISAMP'INDEXED<br>'<br>EXCLUSIVE|Same as INDEXED'EXCLUSIVE but forces operation to be interpreted as an<br>ISAM-A open rather than an ISAM open, regardless of the COMPIL mode.|
|INDEXED|Normal shared open. If file is already open by another user exclusively, job will<br>wait (if the wait'record option specified) or receive ASB error 37 (file in use).<br>See comment below this table.|
|INDEXED'<br>EXCLUSIVE|Open for exclusive use. If file is already open by another user in any mode, job<br>will wait (if the wait'record option specified) or receive ASB error 37 (file in<br>use).|



Although the OPEN for ISAM-A syntax differs somewhat from the OPEN for ISAM syntax, there is enough overlap that they can be confused if the INDEXED or INDEXED'EXCLUSIVE mode is specified without the ISAM' (or ISAMP' for ISAM-A) prefix. In the absences of the disambiguating prefix, the compiler will assume ISAM if the /I switch is specified, else it will assume ISAM-A. 

## _recnovar_ (F6)  [in] 

holds the current record number. Normally, you never need to do anything explicitly with this variable since all operations are based on the index, but it will be set to the data record number after each successful index operation and is used as input by some record-level operations such as UPDATE'RECORD. 

This variable must be F,6. It gets linked by address to the file's entry in the open file table, and thus must remain in scope for the duration of the open file channel. If this is not possible, for example, across function or SBX calls, you can manually reassign it to another variable using MX_FLSET. Or, to eliminate this limitation entirely, use XOPEN instead of OPEN. Also see .RECNO(). 

_fstatvar_ (F6)  [in] 

set to indicate the status of most operations, from the following table: 

|**Symbol**|**Value **|**Meaning**|
|---|---|---|
|ISAM_NF|-3|Not found|



A-Shell Reference 

Page 1196 

|**Symbol**|**Value **|**Meaning**|
|---|---|---|
|ISAM_NA|-2|Not available (record locked)|
|ISAM_LT|-1|Key found which is less than specified key|
|ISAM_EQ|0|Key found equal to specified key|
|ISAM_OK|0|OK|
|ISAM_GT|1|Key found greater than specified key|
|ISAM_DK|2|Duplicate key error inCREATE’RECORD<br>(if AF_ISAMNODUPERRS<br>set)|



The same limitations apply here as to _recnovar_ above. Also see the .FSTAT() function. 

The remaining parameters are all optional modifiers and may be specified in any order: 

|**Open**<br>**Modifier**|**Meaning**|
|---|---|
|end'file|Positions the internal index pointer at the end of the primary index, rather<br>than at the beginning (so that a GET'PREV or FIND'PREV will return the last<br>record in the index).|
|wait'record|If an attempt is made to read a locked record, the program will wait until<br>the record is freed.|
|wait'file|Causes the OPEN operation to wait until the file is available (instead of<br>returning error 37 if it is not).|
|read'only|Indicates that the file will only be accessed for read operations. Attempts<br>to perform updates will fail with an error.|



**See Also** 

A-Shell Reference 

Page 1197 

- XOPEN FOR ISAM-A 

- Search Paths - Data Files 

A-Shell Reference 

Page 1198 

## **- XOPEN FOR ISAM A** 

_Updated July 2021_ 

## **XOPEN #ch, fspec$, mode, {, flags}** 

This is equivalent to the traditional OPEN statement for ISAM files, except: 

- OPEN eliminates the implicit connection between the _fstatvar_ and _recnovar_ variables normally specified in the OPEN, and the 

- file access statements. The _recnovar_ and _fstatvar_ parameters are eliminated. 

- XOPEN allows for the various flags (WAIT'RECORD, WAIT'FILE, END'FILE,...) which must normally be specified as literals to 

- the compiler to instead be evaluated at runtime. 

## **Parameters** 

_ch_ (Num)  [in] 

an integer expression (>0) specifying the file channel which will be needed for subsequent I/O operations on the file. 

_fspec_ (String)  [in] 

string expression containing file specification, in native or DevPPN syntax. May contain embedded %env% variables, e.g. "%temp%\myfile.dat".  If no directory information is included, the search path consists of the current directory, followed by the [p,0] directory. 

In ISAM-A, the specification is of a primary or secondary index (IDX) file. In the case of a primary index, the associated data (DAT) file will also be opened at the same time and accessed via the same channel. To reduce confusion, the file extension (IDX) is normally omitted, since the operation will open both the IDX and DAT files. 

## _mode_ (literal keyword)  [in] 

specifies the file access mode, and must be one of the following (case insensitive) compiler keywords: 

|**Open Mode**|**Meaning**|
|---|---|
|ISAMP'|Same as INDEXED but forces operation to be interpreted as an ISAM-A open|



A-Shell Reference 

Page 1199 

|**Open Mode**|**Meaning**|
|---|---|
|INDEXED|rather than an ISAM open, regardless of the COMPIL mode. Otherwise the<br>COMPIL mode will determine whether to assume old ISAM or ISAM-A.|
|ISAMP'INDEXED<br>'<br>EXCLUSIVE|Same as INDEXED'EXCLUSIVE but forces operation to be interpreted as an<br>ISAM-A open rather than an ISAM open, regardless of the COMPIL mode.|
|INDEXED|Normal shared open. If file is already open by another user exclusively, job will<br>wait (if the wait'record option specified) or receive ASB error 37 (file in use).<br>See comment below this table.|
|INDEXED'<br>EXCLUSIVE|Open for exclusive use. If file is already open by another user in any mode, job<br>will wait (if the wait'record option specified) or receive ASB error 37 (file in<br>use).|



## _flags_ (B,4 or numeric expression)  [in] 

flags optionally specifies zero or more of the following modifiers: 

|**Symbol**|**Value**|**Modifiers***|
|---|---|---|
|FDVF_EXCLUSIVE|&h0800|Convert INDEXED to<br>INDEXED'EXCLUSIVE|
|FDVF_READONLY|&h1000|READ'ONLY|
|FDVF_END_FILE|&h2000|END'FILE|
|FDVF_W_RECORD|&h4000|WAIT'RECORD|



A-Shell Reference 

Page 1200 

|**Symbol**|**Value**|**Modifiers***|
|---|---|---|
||||
|FDVF_W_FILE|&h8000|WAIT'FILE|
|**Definition file:**ashinc:addsfdv.def|||



* These are the literal file OPEN modifiers that can be tacked on to the end of an ISAM-A OPEN statement. 

## **Example** 

This example illustrates a generic Open function for ISAM-A files. Note that the _mode_ parameter is hard-coded as ISAMP'INDEXED, but the _flags_ parameter allows the possibility of upgrading that to exclusive (via the FDVF_EXCLUSIVE flag). This function checks if the file channel is already open and does nothing if it is, assuming that the specified channel matches the fspec). 

```
Function Fn'Open'ISAMA(ch as b2:inputonly, fspec$ as s260:inputonly, recsiz as b2:inputonly, flags as
b4:inputonly) as i4
```

```
    if ch # 0 then              ! if a non-zero channel specified
```

```
       if eof(ch) = -1 then     ! and it's not already open
           xopen #ch, fspec$, ISAMP'INDEXED, recsiz, flags
```

```
       endif
```

```
    endif
```

A-Shell Reference 

Page 1201 

```
    .fn = ch
```

```
EndFunction
```

## A typical call might look like... 

```
if Fn'Open'ISAMA(ch=1234, fspec$="MYFILE", recsiz=128, flags= FDVF_EXCLUSIVE+FDVF_W'FILE) > 0 then
    get #ch, isam'key(0) = mykey$, myrec
```

## **See Also** 

- OPEN FOR ISAM-A 

## **History** 

- 2020 June, A Shell 6.5.1683:  Statement added to A-Shell 

A-Shell Reference 

Page 1202 

## **CLOSE** 

## **CLOSE #channel** 

## _channel_ 

an expression or variable matching that used to open the file. Files should be closed explicitly, although ASB will perform a forced closed on any file left open when the program ends. 

A-Shell Reference 

Page 1203 

## **GET, GET’LOCKED, GET’READ’ONLY** 

_Reviewed and revised October 2024_ 

## **GET #channel, {wait’record,} isam’key(knum) rel kval, varlist** 

## **GET'LOCKED #channel, {wait'record,} isam'key(knum) rel kval, varlist** 

## **GET'READ'ONLY #channel, {wait'record,} isam'key(knum) rel kval, varlist** 

The various forms of the GET statement are used to directly locate and read a record based on a key value. Logically this may be considered a combination of two operations: one to lookup the key and the other to read the record. 

## _channel_ 

the integer expression whose value matches that specified in the OPEN statement. 

The optional _wait’record_ clause causes the operation to wait until the record is available (just as if _wait'record_ was specified in the OPEN statement.) 

## _knum_ 

integer expression indicating which logical index to search in. The primary index is 0, the first secondary index is 1, etc. 

## _rel_ 

is one of the following logical comparison operators, relating the key to be found with the key specified: 

|**Relation **|**Meaning**|
|---|---|
|<|less than|
|<=|less than or equal|
|=|equal|
|>|greater than|



A-Shell Reference 

Page 1204 

**Relation Meaning** >= greater than or equal 

## _kval_ 

an expression indicating the key to start for in the specified index. 

## _varlist_ 

a list of variables to receive the data. Although it is technically legal to list several variables, the recommended approach is to specify a single unformatted record variable which is broken into fields by means of lower level MAP statements or an instance of DEFSTRUCT. It may also be a Dynamically Sized Variables (X,0), in which case you would subsequently need to copy it to a structure in order to break out the individual fields. See History. 

The _fstatvar_ variable, from the OPEN statement (if within the current scope) or from .FSTAT(), will be set according to the key found or not found. If the key is found, the _recnovar_ variable will also be set to the record number, although as mentioned before, you don't need to do anything with this information. 

For example: 

```
GET'LOCKED #CUS'CHANNEL, WAIT’RECORD, KEY(0) >= "BIG", CUS'REC
```

```
if .FSTAT(CUS'CHANNEL) # ISAM_OK and .FSTAT(CUS'CHANNEL) # ISAM_GT goto ISAM'ERROR
```

The above statements will search the primary index for the record whose key is greater than or equal to "BIG". On failure it jumps to the ISAM'ERROR label, where your code should respond appropriately. Otherwise, it will lock and return the record in the CUS'REC variable and set the fstatvar variable (from the OPEN statement) accordingly. Here we are using the .FSTAT() function to test the status; if in same scope, we could have alternately tested the fstatvar variable directly. To remove the record lock, you will need to perform a RELEASE'RECORD or DELETE'RECORD. If the record is found, but is currently locked, then WAIT'RECORD clause will cause the program to wait. 

## **Comments** 

A-Shell Reference 

Page 1205 

If you just want to read the current record (perhaps to lock it after a GET'NEXT'READ'ONLY), without having to re-locate it in the - index, you can use one of the READ for ISAM A variants. Do not, however, attempt to use a WRITE statement on an ISAM-A file! Always use UPDATE'RECORD instead. 

## **History** 

- 2020 June, A Shell 6.5.1684:  Support for dynamic X (X0) record variables added, whether pre-initialized or not. 

A-Shell Reference 

Page 1206 

## **GET'NEXT** 

## **GET'NEXT #channel, {wait’record,} varlist** 

## **GET'NEXT'LOCKED #channel, {wait’record,} varlist** 

## **GET'NEXT'READ'ONLY #channel, {wait’record,} varlist** 

These statements are similar to the corresponding GET, GET'LOCKED, and GET'READ'ONLY statements, except that instead of locating the record directly, by means of a specified key value, they simply get the next record based on the order of the index last specified in a GET or FIND statement. 

The _fstatvar_ variable, from the OPEN statement (if within the current scope) or from .FSTAT(), will be set to ISAM_NF if there are no more records in index order, or ISAM_NA if the found record is locked, or ISAM_EQ for success. 

A-Shell Reference 

Page 1207 

## **GET'PREV** 

## **GET'PREV #channel, {wait’record,} varlist** 

## **GET'PREV'LOCKED #channel, {wait’record,} varlist** 

## **GET'PREV'READ'ONLY #channel, {wait’record,} varlist** 

These statements are identical to the corresponding GET'NEXT statements except instead of getting the next (i.e. higher) record in the index, they get the previous (i.e. lower) record in the index. 

The _fstatvar_ variable, from the OPEN statement (if within the current scope) or from .FSTAT(), will be set to ISAM_NF if there are no more records in index order, or ISAM_NA if the found record is locked, or ISAM_EQ for success. 

A-Shell Reference 

Page 1208 

## **FIND** 

These statements are similar to GET and GET’NEXT statements except that they only operate on the index. They do not transfer any data. They are used to traverse or position the internal pointer into a specific index, after which you can use GET'NEXT or GET'PREV statements to access the data sequentially from that point. 

## **FIND #channel, isam’key(knum) rel kval, retkey** 

## **FIND’NEXT #channel, retkey** 

## **FIND’PREV #channel, retkey** 

_Retkey_ is a variable which will receive the located key (if the operation is successful). The variable should be of the correct size and type to match the specified index. 

For the FIND statement, the _fstatvar_ variable, from the OPEN statement (if within the current scope) or from .FSTAT(), can be set 

to any of the values listed in the table of status values with the OPEN statement, except for ISAM_NA. Since it doesn't try to read the data record, it cannot get a record-locked status. 

For the FIND'NEXT and FIND'PREV statements, the only possible values to be returned for _fstatvar_ are ISAM'NF (meaning you hit the end of the index) or ISAM'EQ (found). 

Examples: 

```
FIND #CUS'CH, ISAM’KEY(1) >= "BIG", RET’KEY
```

```
FIND’NEXT #CUS'CH, RET'KEY
```

```
FIND’PREV #CUS'CH, RET'KEY
```

A-Shell Reference 

Page 1209 

## **UPDATE’RECORD** 

## **UPDATE’RECORD #channel, varlist** 

This statement rewrites a previously locked record and updates all indexes accordingly. 

The _recnovar_ variable (from the OPEN statement) determines which record will be updated. Normally it is set automatically by a GET operation with the LOCKED option. However, it could also be set manually, or via an ISAM'POP statement. 

Because failed GET and NEXT operations do not update the _recnovar_ variable, you should always check the value of the status variable after these operations to avoid inadvertently updating the wrong record. 

If the record specified by the _recnovar_ value is not currently locked, the attempted UPDATE'RECORD will generate ASB error 42 (record not locked). 

UPDATE'RECORD does not release the lock on the record. So normally you would follow it with a RELEASE'RECORD operation. 

The UPDATE'RECORD operation performs all necessary index operations so that the indexes match the updated data. 

Except as noted below, all errors are trapped as ASB errors. 

## **Comments** 

The most likely error during UPDATE'RECORD would be an attempt to add a record with a duplicate key, assuming duplicates not allowed. Normally this will trigger ASB error 208, but you can stifle the ASB error and instead get back the status value 2 (in the _fstatvar_ parameter specified in the OPEN statement) by setting the AF_ISAMNODUPERRS flag in XCALL ASFLAG. 

A-Shell Reference 

Page 1210 

## **DELETE’RECORD** 

_Rewritten March 2019_ 

## **DELETE’RECORD #file-channel** 

DELETE'RECORD deletes the last accessed record and all associated keys. Like UPDATE'RECORD, it relies on the record being previously locked, but unlike UPDATE'RECORD, it ignores the value of the _recnovar_ variable and instead always deletes the last accessed record. Also unlike UPDATE'RECORD, it removes the lock on completion of the operation. 

All errors trap as ASB errors. 

## **Examples** 

The typical delete scenario consists of a GET'LOCKED (or GET'NEXT'LOCKED) to read and lock the record to be deleted, followed by the DELETE'RECORD, e.g. 

```
OPEN #ch, filespec, ISAMP'INDEXED, recnovar, fstatvar , wait'record
```

```
...
```

```
GET'LOCKED #ch, ISAM'KEY(0) = key$, rec
```

```
if fstatvar = ISAM_EQ then
    DELETE'RECORD #ch
```

```
endif
```

In a more complex scenario, you may want to lock several records, and then—perhaps based on user input or other logic—decide to delete just one of them. This requires re-accessing the record to be deleted, presumably by its unique key, prior to the delete. Note that as long as the record is locked by the first access, the second access will not affect that lock; i.e. it doesn't matter whether the second access uses the 'LOCKED option or not. In this example we lock a group of "items" using GET'NEXT'LOCKED operations, then allow the user to select one to be deleted: 

```
defstruct ST_ITEM            ! record def
```

A-Shell Reference 

Page 1211 

```
    map2 key,s,10            ! item key
    map2 description,s,30
    map2 price,f
endstruct
```

```
map1 item, ST_ITEM
dimx items(0), ST_ITEM, auto_extend
```

```
open #ch, filespec, ISAMP'INDEXED, recnovar, fstatvar , wait'record
```

```
...
? "Locking n items..."
```

```
for i = 1 to n
    GET'NEXT'LOCKED #ch, item
    if fstatvar # ISAM_NF then
        ? "item #";i;" ";item.key;" ";item.description
        items(i) = item      ! save items in array for future reference
    else
        exit
    endif
next i
```

A-Shell Reference 

Page 1212 

```
input "Enter item # to delete (or 0 for none): ",i
```

```
if i > 0 then
```

```
    GET #ch, ISAM'KEY(0) = items(i).key, item   ! re-access to set context
    if fstatvar = ISAM_EQ then
          DELETE'RECORD #ch
```

```
    endif
```

```
endif
```

```
RELEASE'ALL #ch               ! release all the remaining locked recs
```

Note the critical step in the above example of doing another GET on the target record prior to the DELETE'RECORD, and that it doesn't matter if it was GET or GET'LOCKED since the record was already locked. 

See the sample program ISPDEL.BP in EXLIB:[908,033] for a more complete working version of the above scenario. 

A-Shell Reference 

Page 1213 

## **CREATE’RECORD** 

_Updated July 2014; added Comments and History_ 

## **CREATE’RECORD #channel, varlist** 

CREATE'RECORD adds a new record to the file and updates the indexes accordingly. Except as noted below, all errors are trapped as ASB errors. 

## **Comments** 

The most likely error during CREATE'RECORD would be an attempt to add a record with a duplicate key, assuming duplicates not allowed. Normally this will trigger ASB error 208, but you can stifle the ASB error and instead get back the status value 2 (in the _fstatvar_ parameter specified in the OPEN statement) by setting the AF_ISAMNODUPERRS flag in XCALL ASFLAG 

## **History** 

- 2012 October, A Shell 6.1.1313: Add support for AF_ISAMNODUPERRS 

A-Shell Reference 

Page 1214 

## **SET'RECNO** 

_Added June 2020_ 

## **SET'RECNO #channel, expr** 

SET'RECNO sets the record number of a file. This would be equivalent to setting the _recnovar_ variable, associated with channel in the OPEN statement, to the value of expr. 

## **History** 

- 2020 June, A Shell 6.5.1684:  Function added to A-Shell 

A-Shell Reference 

Page 1215 

## **RELEASE** 

## **RELEASE’RECORD #channel {,recordnumber}** 

## **RELEASE’ALL #channel** 

RELEASE'RECORD releases the lock on the previously accessed record, or the record number specified. 

Note that you need to use RELEASE'RECORD after an UPDATE'RECORD, since the latter does not release the lock itself. 

A-Shell Reference 

Page 1216 

## **ALLOCATE'INDEXED** 

## **ALLOCATE'INDEXED fspec, allocate'map** 

ALLOCATE'INDEXED creates a new ISAM-A file (as an alternate to using ISMUTL.LIT). The _allocate'map_ structure contains the configuration details needed to create the file, and must be customized, based on the following: 

```
MAP1 ALLOCATE'MAP
```

```
MAP2 ERROR'OFFSET,B,2,-1              ! Offset if error
```

```
MAP2 MAX'RECS,B,4                     ! (ignored)
MAP2 REC'SIZE,B,2                     ! total record size
MAP2 EXTRA'PCT,B,2                    ! extra IDX blocks (ignored)
MAP2 LOADING'FACTOR,B,1,100           ! loading factor (ignored)
MAP2 RESERVED0,X,11                   ! reserved for future
MAP2 VARIABLE'REC'SIZE,B,2            ! size of variable portion of rec
MAP2 PRIMARY'KEY                      ! primary key definition
<see key definition structures below>
```

```
MAP2 SECONDARY'KEY                    ! zero or more secondary key definitions
<see key definition structures below>
MAP2 ALLOCATE'END,B,2,0               ! marks end of key definitions
```

The layout of the PRIMARY'KEY and SECONDARY'KEY sub-structures should be mapped according to one of the following models, based on the key type: 

## **Alphanumeric Key Definition** 

```
MAP2 KEY'ALPHANUMERIC
```

A-Shell Reference 

Page 1217 

```
MAP3 KEY'TYPE,B,1,1               ! 1=alphanumeric
MAP3 KEY'RESV(3),B,1              ! reserved for expansion
MAP3 KEY'NAME,S,20                ! name of key (ignored)
MAP3 KEY'NULL1,B,2,0              ! null terminator for name
MAP3 KEY'DUP,B,1                  ! sum of 1=duplicates allowed,
                                  ! 2=compress dupes, 4=leading, 8=trailing
MAP3 KEY'CHG,B,1                  ! key change permitted (ignored)
MAP3 KEY'SIZE,B,2                 ! size of key in chars
MAP3 KEY'POS,B,2                  ! key pos (1=first byte)
```

## **Signed Integer Key Definition** 

```
MAP2 KEY'INTEGER
```

```
MAP3 KEY'TYPE,B,1,2               ! 2=integer
MAP3 KEY'RESV(3),B,1              ! reserved for expansion
MAP3 KEY'NAME,S,20                ! name of key (ignored)
MAP3 KEY'NULL1,B,2,0              ! null terminator for name
MAP3 KEY'DUP,B,1                  ! 1=duplicates allowed
MAP3 KEY'CHG,B,1                  ! key change permitted (ignored)
MAP3 KEY'SIZE,B,2                 ! size of key in bytes (2 or 4)
MAP3 KEY'POS,B,2                  ! key pos (1=first byte)
```

## **Unsigned Binary Key Definition** 

```
MAP2 KEY'BINARY
```

A-Shell Reference 

Page 1218 

```
MAP3 KEY'TYPE,B,1,4               ! 4=binary
MAP3 KEY'RESV(3),B,1              ! reserved for expansion
MAP3 KEY'NAME,S,20                ! name of key (ignored)
MAP3 KEY'NULL1,B,2,0              ! null terminator for name
MAP3 KEY'DUP,B,1                  ! 1=duplicates allowed
MAP3 KEY'CHG,B,1                  ! key change permitted (ignored)
MAP3 KEY'SIZE,B,2                 ! size of key in bytes (1-5)
```

```
MAP3 KEY'POS,B,2                  ! key pos (1=first byte)
```

## **Concatenated Key Definition** 

```
MAP2 KEY'CONCAT
```

```
MAP3 KEY'TYPE,B,1,3               ! 3=concatenated
MAP3 KEY'RESV(3),B,1              ! reserved for expansion
MAP3 KEY'NAME,S,20                ! name of key (ignored)
MAP3 KEY'NULL1,B,2,0              ! null terminator for name
```

```
MAP3 KEY'DUP,B,1                  ! 1=duplicates allowed
MAP3 KEY'CHG,B,1                  ! key change permitted (ignored)
```

```
MAP3 SUBKEY(?)                    ! 1 or more subkeys
```

```
  MAP4 SUBKEY'SIZE,B,2            ! size of subkey in chars
  MAP4 SUBKEY'POS,B,2             ! subkey pos (1=first byte)
MAP3 KEY'END,B,2                  ! terminate list of subkeys
```

A-Shell Reference 

Page 1219 

## **INDEXED'STATS** 

## **INDEXED'STATS #channel, stats'map** 

## **INDEXED'STATS fspec, stats'map** 

INDEXED'STATS retrieves information about an existing file, either based on its open channel number or its filespec. The layout of the _stats'map_ variable depends on the number of type of indexes, which you must therefore know in advance. (If you don't know, you can always use ISMUTL.LIT to retrieve statistical information.) 

The _stats'map_ layout is as follows: 

```
MAP1 ISAM'STATS'MAP
```

```
MAP2 IS'DATA'DEVICE,B,2,0            ! RAD50 device name of DAT
MAP2 IS'DATA'UNIT,B,2,0              ! Device unit number of DAT
MAP2 IS'REC'SIZE,B,2                 ! total record size
MAP2 IS'FREE'RECS,I,4                ! free rec count (100 million)
MAP2 IS'FREE'IDX,I,4                 ! free IDX flock count
MAP2 IS'TOT'RECS,I,4                 ! total allocated records (100 million)
MAP2 IS'TOT'IDX,I,4                  ! total allocated idx blocks
MAP2 IS'TOT'LOADED,I,4               ! # records loaded
MAP2 IS'MIN'FREE'IDX,B,2             ! minimum free idx blocks
MAP2 IS'EXTRA'PCT,B,2                ! extra % idx blocks to allocate
MAP2 IS'CREATE'DATA                  ! creation date
MAP3 IS'CREATE'MONTH,B,1
MAP3 IS'CREATE'DAY,B,1
```

A-Shell Reference 

Page 1220 

```
MAP3 IS'CREATE'YEAR,B,1
MAP3 IS'CREATE'DOW,B,1
```

```
MAP2 IS'SECOND'IDX,B,1               ! number of secondary indices
```

```
MAP2 IS'REBUILD'DATA                 ! rebuild date (not used)
```

```
MAP3 IS'REBUILD'MONTH,B,1
MAP3 IS'REBUILD'DAY,B,1
```

```
MAP3 IS'REBUILD'YEAR,B,1
MAP3 IS'REBUILD'DOW,B,1
```

```
MAP2 IS'RESERVED(8),B,1              ! reserved for expansion
MAP2 IS'PRIMARY'KEY'STATS            ! primary key stats
```

```
     <use same key structures as for ALLOCATE'INDEXED above>
```

```
MAP2 IS'SECONDARY'KEY'STATS          ! 0 or more secondary keys
```

```
     <use same key structures as for ALLOCATE'INDEXED above>
MAP2 IS'END,B,2,0                    ! marks end of key definitions
```

**Note:** When compiling without the /X:# switch, the I,4 variables shown above will have to be changed to B,4. This is an unfortunate side effect of retaining compatibility with the AlphaBASIC and BASIC _plus_ variations of indexed'status under AMOS. Under A-BASIC (OCMPIL and COMPIL), the four-byte fields in the above structure were type B, while under BASIC _Plus_ (COMPLP), they were type I. This remains true under A-Shell, but seems even more confusing because A-Shell makes less of a distinction between the two variations of BASIC. (They use the same RUN.LIT and COMPIL.LIT, with the only difference being whether the COMPIL switch /X:# was specified.) Unfortunately, the format of B and I variables is not the same (the low and high words are swapped), so a common bug when migrating older code to use BASIC Extensions is to forget to remap these B,4 variables to I,4, leading to wildly incorrect values. Programmer beware! 

A-Shell Reference 

Page 1221 

## **ISAM'PUSH AND ISAM'POP** 

## **ISAM'PUSH #channel** 

## **ISAM'POP #channel** 

ISAM'PUSH and ISAM'POP are extensions only available in A-Shell (and which require the COMPIL /X:2 switch). They allow you to save, and later restore, the current index cursor context. This is particularly handy when, while traversing an index which includes duplicate keys, you need to make a detour involving some other index operations on the same file, before continuing from where you were. Without these operations, you would instead have to manually reposition yourself within the index, which, if duplicates are involved, would require scanning through the duplicates until you hit the record where you were, based on the record number. (There is no other way to go directly to a particular key among a group of duplicate keys.) 

Specifically, the context attributes that are saved and restored are: 

- The index number (if there are multiple indexes for the file) 

- The cursor position within the index 

- The value of the _recnovar_ variable. 

Note that ISAM'PUSH and ISAM'POP do not affect record locks. Thus, if you lock a record before using ISAM'PUSH, it remains locked, and will still be locked when you use ISAM'POP. However, the contents of the record data variable (aka _varlist_ ) is not saved or restored, so you must take care to either save your own copy, or to make sure that your record data variable contains the desired contents before you update the record. 

Note also that ISAM'PUSH uses the current record number according to the record number variable in the open statement, as opposed to the one last saved inside the ISAM library. The problem with the superceded method was if the ISAM'PUSH did not immediately follow another operation on the same file, some intervening ISAM operations to other files could disrupt the state information within the ISAM library, causing the ISAM'PUSH to not push the proper location. 

## Example: 

```
GET'NEXT'LOCKED #AROPEN'CH, WAIT'RECORD, AROPEN'REC
```

```
SAVE'AROPEN'REC = AROPEN'REC             ! save copy of locked rec
```

A-Shell Reference 

Page 1222 

```
ISAM'PUSH #AROPEN'CH
```

```
CALL SCAN'FOR'OTHER'AROPEN'RECS          ! (unknown processing)
```

```
ISAM'POP #AROPEN'CH                      ! restore our index context
```

```
AROPEN'REC = SAVE'AROPEN'REC             ! restore our saved data rec
```

```
AROPEN'UPDATED = 1                       ! change some data
UPDATE'RECORD #AROPEN'CH, AROPEN'REC     ! update the rec
RELEASE'RECORD #AROPEN'CH                ! and release the lock
```

A-Shell Reference 

Page 1223 

## **TRANSACTION'LOG** 

## **TRANSACTION'LOG'OPEN logspec** 

## **TRANSACTION'LOG'CLOSE** 

These are extensions only available in A-Shell (and which require the COMPIL /X:2 switch). TRANSACTION'LOG'OPEN opens a log file of the specified name (native or DevPPN syntax, default extension is ITL for ISAM Transaction Log). Any file opened after the log file is opened in the current program will automatically have all its update operations logged to the file. This is a prerequisite for the TRANSACTION'BEGIN, TRANSACTION'COMMIT, and TRANSACTION'ROLLBACK operations. 

TRANSACTION'LOG'CLOSE closes the current log file. If not done explicitly, it will be done implicitly at the end of the program. 

See the discussion on Transactions and Logging for more details. 

A-Shell Reference 

Page 1224 

## **TRANSACTION** 

## **TRANSACTION'BEGIN** 

## **TRANSACTION'COMMIT** 

## **TRANSACTION'ROLLBACK** 

These are extensions only available in A-Shell (and which require the COMPIL /X:2 switch). Together they allow you to implement "transactions" (which are logical operations involving multiple physical operations on one or more files which should be done as a logical unit, i.e. either all or nothing). 

TRANSACTION'BEGIN marks the beginning of the transaction. 

TRANSACTION'COMMIT marks the successful end of the transaction. 

TRANSACTION'ROLLBACK aborts the transaction, discarding all changes since the TRANSACTION'BEGIN operation. 

Note that while you may operate on any number of files between the TRANSACTION'BEGIN and either the TRANSACTION'COMMIT or TRANSACTION'ROLLBACK, only those ISAM-A files which were opened after the 

TRANSACTION'LOG'OPEN will be affected by the transaction statements. Any operations to other files will take place normally and immediately, just as they would in the absence of the transaction statements. 

See the discussion on Transactions and Logging for more details. 

A-Shell Reference 

Page 1225 

## **- READ FOR ISAM A** 

## **READ #ch, recvar** 

## **READL #ch, recvar** 

## **READ'READ'ONLY #ch, recvar** 

The READ statement variants listed above, normally reserved for random files, may also be used with ISAM-A files. 

One reason why you might want to use READ instead of one of the GET statement variants would be in a situation where you have previously read a record with GET'NEXT and now want to lock it so that it can be deleted or updated. Normally you would use GET'LOCKED; but if all the indexes allow duplicate keys, there may not be any easy and efficient way to re-locate the current record. In that case, READL would work. 

For example, the following code illustrates scanning a file looking for records with specific attributes to be deleted. If the file is large, and the number of records to be deleted is small, and the index accepts duplicates, then it might be more efficient to scan the file with GET'NEXT'READ'ONLY, using an extra READL for the few records to be deleted, than to scan the entire file using GET'NEXT'LOCKED followed by a RELEASE'RECORD for all of the records we aren't going to delete. 

```
do
```

```
    get'next'read'only #ch, rec
    if fstat = ISAM_EQ
then
```

```
        if <rec data meets some condition> then
```

```
            readl #ch, rec     ! re-read the record with the lock set
```

```
            delete'record #ch
```

```
        endif
```

A-Shell Reference 

Page 1226 

```
    else
```

```
        exit
```

```
    endif
```

```
loop
```

See READ (for Random files) for more details on READ statements. 

A-Shell Reference 

Page 1227 

## **TRACE STATEMENTS** 

_Updated October 2025; see History_ 

## **TRACE.OPEN {title}** 

## **TRACE.PRINT {(level {,tags})} expr1{,expr2,...,exprN}** 

## **TRACE.PRINT {(level {,tags})} expr1{,expr2,...,exprN}** 

## **TRACE.CLOSE** 

This group of statements is useful for outputting tracing or debugging messages without interfering with the existing screen display or program logic. By default, the messages go to the System Messages Window; see Opening the Message Window. Also see Debug Settings for other output options: disk file, main window, SBX, etc. 

Typically only the TRACE.PRINT statement is needed.  The optional (level,tags) arguments allow the statement to be enabled/disabled at runtime via SET DEBUG statements.  The exprN arguments operate similarly to those in the standard PRINT statement, except that variables will expand out to "variable=[value]" (rather than just outputting the value), and the first expression may contain macros (see below). 

TRACE.OPEN is optional, since the TRACE.PRINT and TRACE.PAUSE statements will perform the open operation automatically if necessary.  The only point would be the ability to set the message window title (assuming that is the output option); otherwise it defaults to "A-Shell System Messages".  And TRACE.CLOSE is unnecessary because in the message window case, the user can close it with the mouse, and in the other cases, closing is irrelevant or automatic. 

TRACE.PAUSE is equivalent to TRACE.PRINT except that (assuming trace output is to the System Message window), it causes the application to pause with a message prompting the operator: 

```
<Application paused - Double-click here to resume>
```

As suggested by the message, the application is then suspended while waiting for the user to double-click the message window. This is intended as alternative to the usual practice of display message boxes which require a click on the OK button to proceed (or the venerable and primitive STOP statement). Note: Ctrl+C will abort the pause and pass the Ctrl+C to the program. 

A-Shell Reference 

Page 1228 

The actual wording of that message and the acknowledgement message when the double-click is received may be customized via the strings 005,002 and 005,003 in sys:sysmsg.xxx. 

The optional ( _level_ , _tags_ ) arguments(s) provide two overlapping mechanisms for activating specific TRACE statements at run time. _Level_ sets the minimum DEBUG level to activate the trace, while the _tags_ (one or more string tokens, comma-delimited) provide additional specificity. Both can be set via the SET DEBUG system command. 

The list of expressions  ( _expr1, ... exprN_ ) may be either string expressions or variables.  In the latter case, the output will be expanded to show both the variable name and its value (see the examples below). 

A special form of the first expression can be used to enable/disable the Show System Traces option in the System Message window: 

```
TRACE.PRINT "SYSTRACE ON"           ! or "SYSTRACE OFF"
```

The manual way to do this is to right-click on the message window, click Properties, and then check the System Trace option.) Being able to do this from within a program is sometimes useful when you want to activate certain verbose traces but only for a short time, or starting at the beginning of a session, before you would have a chance to manually open the message window and turn on the traces automatically. 

The first expression may also optionally contain any of the following macros: 

|**Macro**|**Expands To**|
|---|---|
|$#|Displays the running message count as a message id number. This applies only when the<br>destination is $WIN, i.e. the System Message Window, otherwise it is ignored.|
|$T|Displays the time in hh:mm:ss format, except when destination is a log file that applies its<br>own automatic date/time stamp.|
|$P|Displays the program name in brackets, e.g. <MYPROG>. If the current context is an SBX,<br>it will be appended to the program name, e.g. <MYPROG:MYSBX>.|



A-Shell Reference 

Page 1229 

|**Macro**|**Expands To**|
|---|---|
|$L|Displays the current location counter as a six digit hex number, matching the format used<br>in the LSX file.|
|$D|Displays the date in dd-mm-yy format, except when destination is a log file that applies its<br>own automatic date/time stamp.|
|$I|Displays the process ID number.|
|%env%|Environment variable definition.|



Macros, when present, must precede any other output expressions. Typically they are space delimited, in which case the first token that does not start with a $ or % cancels the macro processing for the remainder of the arguments. Alternatively, the macros can be comma delimited, which may be useful when outputting to a custom log file in CSV format.  In that case the first comma-delimited argument that doesn't start with $ or % cancels macro processing. 

## **Examples** 

```
trace.print "Price Calc: " + price, factor1, factor2
```

```
trace.print (1) var1,var2
```

```
debug.print (1,"beta,i/o,2.0") var3,var4
```

```
trace.pause (27,"alpha"),"total="+totx
```

A-Shell Reference 

Page 1230 

The first example demonstrates the original syntax and the fact that the new clauses are entirely optional. 

The second example uses the new clause to specify a debug level of 1, which makes the TRACE.PRINT equivalent to DEBUG.PRINT —illustrating that the only difference between TRACE.XXX and DEBUG.XXX is the default debug level. It also illustrates that you can specify just the level without the tags argument. 

The third example illustrates the use of a tags list. Note that you must include the level argument if you using the tags list; 1 is the standard level for debug statements. It also illustrates the use of multiple values—i.e. a comma delimited list of values, as allowed in a normal PRINT statement. 

The last example shows a variation using trace.pause, but note that since the level is set to 27, it won't be executed unless the runtime debug level is 27 or higher and one of the tags enabled. Also note that the totx in the expression list will not get an automatic label because it is already part of a string expression. 

## **Comments** 

When the TRACE.XXX statements are executed on a server whose client is ATE, the message is forwarded to the ATE client to display. If the client is not ATE, the message is output to the standard ashlog.log. 

## **See Also** 

- The description of the DEBUG system variable in the A-Shell Extensions table. 

- TRACE_BEGIN and _END 

- SET.LIT…DEBUG to set the runtime debug level, tags, and tracing destination. 

- Debugging Techniques 

## **History** 

- 2025 October, A Shell 7.0.1779: Add macros $D and $I and the comma delimited option. 

A-Shell Reference 

Page 1231 

- 2019 November, A Shell 6.5.1671, compiler edit 921:  Optimizes the runtime code generated by trace statements of the forms: 

```
DEBUG.PRINT <args>
```

```
TRACE.PRINT (level,tags) <args>
```

The optimization adds a few bytes to the RUN code for each statement, but eliminates nearly all of the overhead associated with runtime evaluation in the caes where where no DEBUG level or tags have been set, as would be typical for most production environments. Previously, the overhead, while small, was enough to become significant when such statements were embedded in code executed in tight loops. This partially undermined the advantage of being able to insert many such traces into code so that they could be activated selectively for debugging purposes. 

Note while the optimization requires runtime version 6.5.1671.0+ to be effective, it will containue to run with older runtimes but without the benefit of the optimization. 

- 2018 July, A Shell 6.5.1639, compiler edit 861:  Expanded xxxxxx.PRINT and xxxxxx.PAUSE statements 

- 2018 July, A Shell 6.5.1639: Add $L macro 

A-Shell Reference 

Page 1232 

## **DEBUG STATEMENTS** 

## **DEBUG.OPEN expr1{,expr2,...,exprN}** 

## **DEBUG.PRINT expr1{,expr2,...,exprN}** 

## **DEBUG.CLOSE** 

The DEBUG.xxx statements are equivalent to the corresponding TRACE Statements except that they are only triggered via the system DEBUG Settings. Originally this was a useful distinction but since the debug level option was added to the TRACE statements, the DEBUG statements became redundant and deprecated. 

A-Shell Reference 

Page 1233 

## **ARRAY STATEMENTS** 

_Added January 2022_ 

|**Statement**|**Description**|
|---|---|
|DIMX|Create a dynamic array|
|.CLEAR|Remove all elements of the array.|
|REDIMX|Re-dimension an array originally created withDIMX.|



## **See Also** 

- Multi-level List MLIST 

A-Shell Reference 

Page 1234 

## **CLEAR** 

_Modified January 2022_ 

## **.CLEAR ary() ! clear a dimx or fixed array** 

## **.CLEAR $ary()** 

## **! clear a collection** 

The "dot clear" statement clears or removes all the elements of an array or collection. 

For traditional MAP arrays, as well as for DIMX arrays without the AUTO_EXTEND attribute, .CLEAR ARY() simply clears the contents of the array without affecting its structure. This applies to both single and multi-dimensioned arrays. The end result is exactly equivalent to iterating through all of the array elements and setting each to null, except that it is easier to code and faster to execute. 

For DIMX arrays with the AUTO_EXTEND attribute, the extent of the first dimension of the array is reset to 0. This is similar to resizing the array to 0 using REDIMX except that the array remains defined and ready to receive new elements (via autoextension). Note that for multi-dimensional arrays, dimensions beyond the first retain their original extents; this is necessary for re-using the array since only the first dimension is subject to auto-extension. 

## **Examples** 

This illustrates the case with an ordered map (collection). 

```
dimx $capitals,ordmap(varstr;varstr)   ! declare array
print .extent($capitals())             ! initial extent is 0
```

```
$capitals(“california”) = “sacramento” ! add an element
```

```
$capitals(“nevada”) = “carson city”    ! add another element
print .extent($capitals())             ! extent is now 2
```

```
.clear $capitals()                     ! clear all elements
```

A-Shell Reference 

Page 1235 

```
print .extent($capitals())             ! extent is now 0
```

This illustrates the use of .CLEAR to clear regular arrays created with MAP or DIMX: 

```
map1 ary1(25),b,4
```

```
map1 ary2(10,5),f,6
```

```
dimx ary3(75),s,32
```

```
dimx ary4(0),x,0,auto_extend
```

```
...
```

```
.clear ary1()     ! all 25 elements cleared; array allocation unaffected
```

```
.clear ary2()     ! all 10x5 (50) elements cleared; allocation unaffected
.clear ary3()     ! all 75 elements cleared; allocation unaffected
.clear ary4()     ! array extent set back to 0; memory freed
```

## **History** 

- January 2018, A Shell build 6.5.1624, compiler edit 846: .CLEAR enhancement:  .CLEAR ARY() now supported for all types of arrays; previously it only applied to collections. The details of the clearing operation depend on the nature of the array being cleared. **Warning** : using .CLEAR with any array type other than a collection (e.g. ORDMAP) requires that runtime version 6.5.1624 or above. Otherwise it will generate an Unsupported Function error. 

- June 2013, A Shell build 6.1.1354, compiler edit 638:  .CLEAR $ARY() introduced. 

A-Shell Reference 

Page 1236 

## **REDIMX** 

This statement will re-dimension an array originally created with DIMX. 

## **DIMX varnam(sub1,...,subn),<type>,<size>** 

**...** 

## **REDIMX varname(sub1,...subn)** 

where sub1 thru subn are the desired extents of each dimension. 

It can also be used to deallocate an array by setting the extents to zero. For example: 

```
DIMX ARY(50,100),X,25          ! allocate the array
```

```
...
```

```
REDIMX ARY(0,0)                ! deallocate it
```

You can also use REDIMX to deallocate an ordered map, except in that case instead of specifing an explicit extent of zero, you leave the parentheses empty: 

```
DIMX $ARY, ORDMAP(VARSTR;VARSTR)    ! allocate the ordered map
```

```
...
```

```
REDIMX $ARY()                       ! deallocate it
```

## **Notes** 

A-Shell Reference 

Page 1237 

- The REDIMX statement must occur after the corresponding DIMX (both during compilation and at runtime). If the compiler 

- sees the REDIMX first, it will report an unmapped variable. If the runtime sees the REDIMX first (except for the exception noted below), it will report error 30 (re-dimensioned array - same error as you get when attempting to use DIMX a second time). 

- The one exception to this rule is that a runtime attempt to REDIMX an array to a size of 0 will not complain if the array has 

- not yet been allocated. This allows you to add a REDIMX VARNAME(0,…,0) to free up an array in an error recovery routine, without having to check whether the array had actually been allocated yet. 

- You cannot change the number of subscripts; you can only change the maximum value(s) of the subscript(s). 

- The REDIMX statement can not specify a variable type or size; thus you cannot change the original type or size. 

- The original contents of the array will be preserved ONLY if all dimensions beyond the first (for multi-dimensional arrays) are 

- preserved. For example, if you start with `DIMX A(P,Q,R)` , and then re-dimension using `REDIMX A(X,Y,Z)` , the contents will be preserved only if Y=Q and Z=R (i.e., only the first dimension was changed). 

- The MALLOC trace option will trace DIMX and REDIMX memory allocations (along with most other memory allocations/de- 

- allocations), making it a useful debugging tool. 

## **See Also** 

- DIMX 

A-Shell Reference 

Page 1238 

## **MISCELLANEOUS STATEMENTS** 

See the following topics for descriptions of the statements that don't fit into any of the other categories. 

## **Subtopics** 

- SIGNIFICANCE 

- X-ARGs 

- DATA, READ, RESTORE 

- SCALE 

- SLEEP 

- .BINDSTRUCT 

- DIVIDE'BY'0 

- Comments 

- Line Continuation 

- STOP 

A-Shell Reference 

Page 1239 

## **SIGNIFICANCE** 

_Written August 2020_ 

## **SIGNIFICANCE digits** 

This statement establishes the maximum number of significant digits to be displayed when printing floating point values (without a USING mask) to the screen or a file . _digits_ is an integer, the default is 6. If the value being printed requires more than the specified number of digits for the integer part of the value, exponential notation will be used instead. Digits to the right of the decimal point that exceed the significance value will be rounded off. 

## **Example** 

```
MAP1 VALUE,F,8,12345678.98765
```

- `? "Default Significance (6): ";VALUE    ! 1.23456e+07` 

## `SIGNIFICANCE 10` 

- `? "Significance 10 ";VALUE              ! 12345678.99` 

## `SIGNIFICANCE 12` 

- `? "Significance 12 ";VALUE              ! 12345678.98765` 

## `SIGNIFICANCE 16` 

- `? "Significance 16 ";VALUE              ! 12345678.98765564` 

**Notes** 

A-Shell Reference 

Page 1240 

The last example above illustrates the problem of the inherent limitations of binary floating point representation for decimal fractional values, resulting in unwanted extra digits beyond those contained in the original value. When the SIGNIFICANCE limit exceeds the number of digits in the original value, these rounding errors (in the conversion from binary to decimal fractions) will show up. The best way to avoid that problem is to rely on USING masks when displaying fractional values like currency amounts. 

Note that SIGNIFICANCE only affects the display formatting of numeric values; it does not affect the internal precision of calculations. Nowadays, the standard internal precision is 64 bit (approximately 16 decimal digits), but in order to maintain compatibility with the original 48 bit floating point hardware, from whence the F,6 variable type arose, most intermediate calculations are down-scaled to 48 bit precision. So even when using F,8 variables, you may not be experiencing the full effect of 64 bit precision from end to end. 

## **See Also:** 

- MX_ROUND 

A-Shell Reference 

Page 1241 

## **- X ARGS** 

_Revised June 2017_ 

The peculiar term "X-ARGS" is used to apply to the family of statements listed below. 

See History at the bottom of this topic. 

These statements may be used (in place of the MX_XCBDATAX calls) to retrieve and return values within an SBX routine: 

## **XGETARGS var1{,var2,... varN}** 

## **XGETARG <argno>, var** 

**XPUTARG <argno>, <expr>** 

## **XPUTARG @var {=<expr>)** 

## **XGETARGSBX <argno>, var** 

## **XPUTARGSBX <argno>, <expr>** 

## **XPUTARGSBX @var {=<expr>)** 

These statements transfer arguments between callers and SBX modules, functions, and procedures. The XGET* variations receive arguments from the caller into local variables within the called routine, while the XPUT* variations send values back to the caller. XGETARGS is equivalent to a series of individual XGETARG statements referencing the variables in order, i.e. the nth argument passed by the caller is returned in the nth argument in the XGETARGS statement. Any additional arguments passed by the caller are ignored, as are any additional variables on the XGETARGS statement beyond the number passed by the caller. Likewise, any PUT operation for a parameter beyond the number of parameters passed by the caller will be ignored. The GET operations are non-destructive to the original argument list, allowing you to later retrieve (or re-retrieve) the same parameters with other XGETARG* statements. 

A-Shell Reference 

Page 1242 

The *SBX variations are specific to SBX parameters, eliminating confusion when an SBX also contains function/procedure calls. The non-*SBX variations always refer to the current function/procedure/SBX, whereas the *SBX variations only refer to the current SBX, so they could be used within a function within an SBX. 

`XGETARG argno,var` performs the same function as XGETARGS except that it retrieves only the one argument, whose number is specified in `argno` . 

`XPUTARG argno,var` is the reverse of XGETARG. It returns the value of the argument var into the caller's argument number `ARGNO` . 

Note that in the case of XPUTARG, the second argument (value to return) can be a variable or an expression, whereas in the case of XGETARGS or XGETARG, the second argument must be a variable. You can't retrieve an argument into an expression, but you can use an expression to return an argument. 

`XPUTARG @var{=<expr>}` is a newer convenience form (see History below) which eliminates the possibility of a mismatch between the argument number and the value by having the compiler automatically determine the argument number which matches the specified var, based on a prior XGETARG{S} statement referencing the same var. In the absence of the `=<expr>` clause, `XPUTARG @var` returns the current value of var. Otherwise it returns the value of the expression, using @var only to determine which parameter the expression is returned to (without modifying the value of var itself). For example: 

```
XGETARGS vx,vy,vz
```

```
vy = 77
```

```
XPUTARG @vy       ! same as XPUTARG 2,vy
```

```
XPUTARG @vz=vx+88 ! same as XPUTARG 3,vx+88s
```

Type conversions will be made as appropriate if the variable types do not match the types passed to the routine, although it behooves you to use "appropriate" data types for the circumstances. 

## **See Also** 

- .ARGTYP() and .ARGSIZ() 

A-Shell Reference 

Page 1243 

- MX_XCBDATAX Replacement 

## **History** 

- 2017 June, A Shell 6.5.160?, compiler edit 825: `XPUTARG{SBX} @var{=<expr>}` added. Note that it is purely handled by the compiler and requires no update to the run-time. 

## **Subtopics** 

- MX_XCBDATAX Replacement 

A-Shell Reference 

Page 1244 

## **MX_XCBDATAX REPLACEMENT** 

When SBX calls were first implemented, a special MIAMEX function, MX_XCBDATAX, was added to facilitate passing parameters between the caller and the SBX. Since A-Shell 5.0, these have been deprecated and superseded by X???ARG* statements, which, in addition to handling SBX parameters, also handle function and procedure parameters. Although the MX_XCBDATAX statements continue to operate, we recommend converting them whenever possible. 

The following examples may clarify the equivalencies between the new statements and the old MX_XCBDATAX calls: 

```
XGETARGS P1,P2,P3,P4
```

## is equivalent to: 

```
xcall MIAMEX, MX_XCBDATAX, XCBADR, XCBGET,1,P1
```

```
xcall MIAMEX, MX_XCBDATAX, XCBADR, XCBGET,2,P2
xcall MIAMEX, MX_XCBDATAX, XCBADR, XCBGET,3,P3
xcall MIAMEX, MX_XCBDATAX, XCBADR, XCBGET,4,P4
```

and is also equivalent to: 

```
XGETARG 1,P1
```

```
XGETARG 2,P2
XGETARG 3,P3
```

```
XGETARG 4,P4
```

## For returning arguments, 

```
xcall MIAMEX, MX_XCBDATAX, XCBADR, XCBPUT,1,A+B/C
```

is equivalent to: 

A-Shell Reference 

Page 1245 

```
XPUTARG 1,A+B/C
```

The main advantage of the new statements is just efficiency, both for the programmer and for the computer. This is especially true if you use XGETARGS to retrieve all arguments in one statement. 

Note that these new statements do not require XCBADR or any of the other variables set up by ASHINC:XCALL.BSI. However, you may still want to continue including xcall.bsi at the start of your SBX modules since it does set the variable XCBCNT to the number of parameters passed, and the XCBSTRUCT() array to the types and sizes, and this information can be useful in determining how to interpret the passed parameters. XGETARGS and XGETARG do not give you any obvious indication when fewer parameters were passed to the subroutine than the subroutine is expecting, so a well-written subroutine should, at a minimum, check XCBCNT to see how many parameters were passed. 

All of the X???ARG* statements require the compiler /X:2 switch. 

A-Shell Reference 

Page 1246 

## **DATA, READ, RESTORE** 

## **DATA item1{, item2, ..., itemN}** 

## **READ var1{, var2, ..., varN}** 

## **RESTORE** 

DATA statements allow data to be stored directly within a program.  Each statement may contain one or more items, each of which may be a string or numeric literal.  The order of the DATA statements is significant, but their position is not, since all of them, regardless of where they appear, are pooled together and indexed in the header of the RUN file. READ statements encountered at run time will process the data items in the physical order in which they appear in the source. 

For example, these DATA statements contain two and three items, respectively, creating a single data pool of five items: `DATA 25, 53.1` 

```
DATA .007,  Louis XIV, "1,2"
```

Note that in the second statement above, the literal string "Louis XIV" doesn't need to be quoted (although it wouldn't change anything). But the third item, "1,2" depends on the quotes, without which the comma would be interpreted as an item delimiter, resulting in two separate data items. 

Since the DATA items are all combined into a single pool (independent of how many items were in each DATA statement), the number of variables specified in each READ statement does not have to correspond in any way. Each variable is simply associated with the next item in the pool. The exact interpretation of each data item however will depend on the type of variable that it is read into. 

For example, we could read the five data values from the example above using the following: 

```
MAP1 QTY,F
```

A-Shell Reference 

Page 1247 

```
MAP1 WT,B,2
```

```
MAP1 PRICE'PER'OZ,F
```

```
MAP1 KING$,S,30
```

```
MAP1 RATING,F
```

```
READ QTY, WT, PRICE'PER'OZ, KING$, RATING
```

Because WT is mapped in this example as a two byte binary, it cannot hold the fractional part of the data item 53.1 and thus will be truncated to 53. Similarly, because RATING is a floating point, the string item "1,2" will be truncated at the first illegal character, i.e. the comma, resulting in just 1. (Unless the LDF for the current language specifies the comma as the decimal separator, in which case it will receive the value one point two.) If we changed RATING to a string variable, then it would receive "1,2". 

If there are no more DATA items to process, the next READ statement will generate ASB error 4 (out of data). 

The RESTORE statement resets the internal data cursor back to the first DATA statement, allowing the data to be read again. 

A-Shell Reference 

Page 1248 

## **SCALE** 

## **SCALE factor** 

The SCALE statement effectively shifts the significant digit window on floating point values by the specified factor—i.e. the specified number of digits—with the goal of reducing the rounding/precision problems inherent in floating point representation. The most common factor to use is 2, which shifts the window 2 decimals to the right, effectively multiplying by 100, causing values like 123.45 to be stored as 12345 instead. This can be a useful technique when using floating point values to store currency figures. But for most systems, it is an all-or-nothing affair because it affects the way floating point values are stored in files. If you access the same file from programs with different SCALE factors, you will end up with a mixture of values off by the differing factors of ten. Plus, for what you gain at one edge of the range, you lose at the other. For example, if you use `SCALE 2` to reduce rounding problems with dollars and cents, you effectively also reduce, by the same two decimal places, the maximum dollar values you can reliably store without introducing the same kinds of rounding problems on the high end—i.e. reducing the maximum value you can reliably store in the eleven significant digits of F6 format from a hundred billion to one billion. 

Because of the complications, risks and side effects, and because there are other better methods of dealing with rounding and precision, the use of SCALE is not recommended. But it remains supported for backwards compatibility with legacy applications. See the links below for other approaches to rounding and precision. 

Note while SCALE is primarily a run-time mechanism, it also affects the way literal constants are stored within compiled programs. Also note that the position of the SCALE statement is critical; it should almost always appear before any other statement defining or using variables. 

## **See Also:** 

- Rounding of Floating Point Variables 

- USING MASK 

- ABC_SCALE 

## **History** 

A-Shell Reference 

Page 1249 

- 2018 February, A Shell 6.5.1628: SCALE is now inherited by SBX routines from the caller. Previously it was essential that the SBX specify the same SCALE factor in order to avoid problems with values getting shifted up or down by the SCALE factor. 

A-Shell Reference 

Page 1250 

## **SLEEP** 

## **SLEEP seconds** 

SLEEP puts the job to sleep for the specified amount of time. _Seconds_ may be fractional, down to a theoretical precision of .0001 seconds. There is no maximum. 

The SLEEP statement is exactly equivalent to Xcall SLEEP. However, unlike the subroutine, it requires the /X:1 switch or higher. 

## **See Also** 

- SLEEP.LIT 

- SLEEP (subroutine) to sleep until a specified time. 

- Xcall WAKNO to wake up a sleeping job. 

- SLEEPR.LIT to sleep until a specified time. 

A-Shell Reference 

Page 1251 

## **.BINDSTRUCT** 

_Updated August 2022_ 

## **.BINDSTRUCT ds, st** 

## **Parameters** 

_ds_ 

an instance of a DYNSTRUCT 

_st_ 

## an instance of a DEFSTRUCT 

The .BINDSTRUCT statement binds the specified DYNSTRUCT variable (ds) to the structure definition corresponding to the specified DEFSTRUCT instance variable (st). Then it copies the data from the DEFSTRUCT instance to the DYNSTRUCT. This would be equivalent to the following... 

```
xcall MIAMEX, MX_DYNSTRUCT, DYNOP_DEF, status, src$, fields, stsize, dsname$
```

```
xcall MIAMEX, MX_DYNSTRUCT, DYNOP_BIND, status, dsname$, ds
```

```
ds = st
```

... except that the structure name (dsname$) is determined implicitly from the structure variable instance (st), and the src$ parameter is set to "" to extract the structure definition from the current RUN file directly. 

Note that DEFSTRUCTs are embedded in the RUN file only under certain conditions. If not embedded by the compiler, you can embed them at run time using MX_DYNSTRUCT. See the links before for more details. 

Also note that the second argument (the _defstruct_ instance) may be a base array reference. For example: 

```
.BINDSTRUCT ds, st()
```

A-Shell Reference 

Page 1252 

In this case, the structure is bound to the DYNSTRUCT instance (ds), but no data is copied. However, once bound, you can then manually copy elements from the array, using the same binding, e.g. 

```
.bindstruct ds, st()      ! bind w/o copy
```

```
for i = .extent(st())
```

```
    ds = st(i)            ! copy, preserving prior binding
```

- `? ds,@fldname$        ! dynstruct deferred indirect ref` 

```
next i
```

## **See Also** 

- Structure Definition Embedding 

- MX_DYNSTRUCT 

## **History** 

- 2022 August , A Shell 6.5.1718: Add option, as described above, allowing _st_ to be a base array reference. 

- 2022 February, A Shell 6.5.1711: Function added to A-Shell 

A-Shell Reference 

Page 1253 

## **DIVIDE'BY'0** 

## **DIVIDE’BY’0** 

## **DIVIDE'BY'0** 

## **NO'DIVIDE'BY'0** 

These statements determine how an attempt to divide by zero is handled from that point forward in the program. In the default case (NO’DIVIDE’BY’0) such an attempt causes an error #10. After DIVIDE’BY’0 has been executed, such an attempt will return a quotient of 0. 

## **STOP** 

## **STOP** 

The STOP statement is a legacy holdover from early BASIC. It simply prints the following message and waits for the user to hit carriage return (CR) to proceed: 

```
Program stop at location counter <location> of <program>
```

```
Enter CR to continue:
```

A-Shell Reference 

Page 1254 

## **COMMENTS** 

_Added March 2025_ 

Comments can be inserted into ASB programs in the following ways. 

The **!** character (exclamation point), anywhere in the line except within a literal quoted string, marks the beginning of a comment. For example: 

```
!--------------------------------------------------------------
```

```
writecd #ch, name, rank, serialno     ! output comma delimited
```

Comments can be inserted into the middle of a logical statement that is broken up into multiple physical lines using the & continuation character, provided that each comment is the last thing on the physical line (after the & character), for example: 

```
query$ = "INSERT INTO LineUp (first, second, third) " &    ! SQL infield positions
```

```
              + VALUES (" + fn'quote$("Who") &             ! Who's on first
              +   fn'quote$("What") &                      ! What's on second
              +   fn'quote$("I don't know") &              ! I don't know is on third
              + ")"
```

The one exception to the rule that comments auto-terminate at the end of the physical line is if the comment itself ends with the & continuation character, in which case, the following line is treated as part of the comment. This is legacy quirk and is not recommended because it make it far too easy to overlook when viewing your code. In the following example, the assignment statement on the second line may appear to be executable code, but it is actually a continuation of the comment from the previous line due to it ending with the & continuation character: 

```
! this commented line can extend to the next if it ends with &
```

```
a = b + c
```

A-Shell Reference 

Page 1255 

The statement code **REM** acts the same as the ! character, and is another legacy method of indicating comments, e.g. 

```
REM This is a comment
```

```
print "Hello World"   REM and so is this
```

Yet another option is **@@@** , which acts the same as REM or !. For example: . 

```
@@@ This is a comment
```

```
print "Hello World"   @@@ and so is this
```

And finally, a single **@** also serves as a start-of-comment indicator, but only if it is the first non-blank character on the line, e.g. 

```
@ this is a comment
```

```
map1 var1, x, 10, @var2   ! the @ in this line is not a comment indicator
```

## **See also:** 

- Program Structure 

## **History** 

- 2025 February, A Shell 7.0.1768: Add "@" and "@@@" as comment characters. 

A-Shell Reference 

Page 1256 

## **LINE CONTINUATION** 

_Added March 2025_ 

By default, ASB statements terminate at the end of the physical source line. However, to make the code easier to read and edit, you can continue a logical statement on to the next physical line by appending the **&** character(ampersand) to the end of the line. For example: 

```
xcall MSGBOX, "La cigale, ayant chanté tout l'été," &
```

```
    + "se trouva fort dépourvue quand la bise fut venu...", &
```

```
    "La Cigale et La Fourmi", &             ! title
```

```
    MBTN_OK, MBICON_STOP, MBMISC_TOPMOST
```

Note that the **&** may be followed by spaces and optionally by a comment as shown (" ! title") above. 

## **See also:** 

- Comments 

- Program Structure 

A-Shell Reference 

Page 1257 

## **STOP** 

## **DIVIDE’BY’0** 

## **DIVIDE'BY'0** 

## **NO'DIVIDE'BY'0** 

These statements determine how an attempt to divide by zero is handled from that point forward in the program. In the default case (NO’DIVIDE’BY’0) such an attempt causes an error #10. After DIVIDE’BY’0 has been executed, such an attempt will return a quotient of 0. 

## **STOP** 

## **STOP** 

The STOP statement is a legacy holdover from early BASIC. It simply prints the following message and waits for the user to hit carriage return (CR) to proceed: 

```
Program stop at location counter <location> of <program>
```

```
Enter CR to continue:
```

A-Shell Reference 

Page 1258 

## **COMPILER DIRECTIVES** 

Compiler directives are another category of statements, except that they are consumed entirely by the compiler, with the result of affecting the compiler's behavior, rather than generating tokens in the RUN module to be processed at runtime. They include + +EXTERN and the subtopics listed below. 

## **Subtopics** 

- SCALE Directive 

- DEFALIAS 

- DEFINE 

- UNDEF 

- DEFTYPE 

- ++INCLUDE 

- ++PRAGMAs 

- Conditional Compilation 

- STRSIZ 

- ++MESSAGE 

- ++ERROR 

- DEFSTRUCT 

A-Shell Reference 

Page 1259 

## **SCALE DIRECTIVE** 

_Added January 2022_ 

## **SCALE factor** 

This is both a runtime statement and a compiler directive. In its guise as a compiler directive, once seen by the compiler, it it affects the way literal values are stored in the RUN file. See the SCALE statement for more details. 

A-Shell Reference 

Page 1260 

## **DEFALIAS** 

_Resived October 2021; see History_ 

## **DEFALIAS <routine-alias>() = <real-routine>()** 

DEFALIAS (define alias) allows aliases to be defined for the names of functions and procedures. 

This can be a useful code management technique for isolating lower level changes or variations in routines—due to differences in versions, implementation, etc.—from the higher level application. For example, an application may have many different discount calculation routines based on the type of discount, some of which might be effectively the same. Rather than forcing the higher level code to know which discounts are effectively the same, or forcing you to maintain redundant routines which differ only by name, you can use DEFALIAS to create aliases. For example, the following statement would cause any subsequent references to the function Fn'Senior'Discount(qty,gender) to be converted into references to the function Fn'AARP'Discount(qty,gender): 

```
DEFALIAS Fn'Senior'Discount() = Fn'AARP'Discount()
```

## **Notes** 

- Currently this applies only to functions and procedures and not subroutines 

- The empty set of parentheses is mandatory for both the alias and the real routine name. Currently the alias only affects the 

- name; the arguments are passed through without change. 

- This is purely a compiler-level mechanism and does not require any runtime support—i.e. it is backward compatible to all 

- runtimes. 

## **See Also** 

- UNDEF 

## **History** 

- 2021 October, A Shell 6.5.1708, compiler edit 957: DEFALIAS now updates the effective type (string or numeric) of the function, making it possible to alias a numeric function call to a string function or vice versa, e.g.: `DEFALIAS Fn'Foo()  = Fn'Foo$()` and `DEFALIAS Fn'Bar$() = Fn'Bar()` 

A-Shell Reference 

Page 1261 

- 2017 November, A Shell 6.5.1620, Compiler edit 838: Statement added to A-Shell 

A-Shell Reference 

Page 1262 

## **DEFINE** 

## **DEFINE symbol = value** 

This statement defines the constant <symbol> to be equal to <value>. 

## **Examples** 

```
DEFINE TCRT'REVON = 32
```

```
DEFINE XTF'CTRLC = &h01000000
```

```
DEFINE MY'NAME$ = "JACK"
```

The names following the DEFINE must conform to the normal rules for variable names (start with an alphabetic character and contain alphabetic, numeric and apostrophe or underline characters plus an optional $ or % suffix). 

The definition must either be a literal numeric value (as in the first two examples above), or a quoted string value. 

These definitions act like macros, substituting the definition into the source code before each line of the program is compiled. Because of this, compiler error messages will usually display the line after macro expansions (which may look strange at first, but since the error messages also show the line number, it allows you to compare your source code to the result after the macro replacements.) 

From a logic standpoint, the result is equivalent to using MAP statements, i.e.: 

```
MAP1 TCRT'REVON,B,1,32
```

```
MAP1 XTF'CTRLC,B,4,&h01000000
```

```
MAP1 MY'NAME$,S,4,"JACK"
```

## The main advantages of DEFINE over MAP statements are: 

- You cannot assign a value to a DEFINEd symbol; thus, they act like true constants. 

A-Shell Reference 

Page 1263 

- DEFINEd constants take up no space in the RUN file unless they are used. Thus it is practical to create ++INCLUDE files which 

- define constants for virtually every situation, without worrying about the overhead. (They do create some compiler overhead, but is that really something we need to worry about?) 

• Even for constants that are referenced in the program, constants generally save space in the RUN file. A non-subscripted MAP statement with an initial value takes 16 bytes, and then it takes another 2 or 3 bytes to reference it in the code. A constant takes zero bytes to define, and generally only 2 bytes to reference. (Depending on the number of significant binary digits in the constant, it may take 4 or 6 bytes to represent. But in the vast majority of cases, DEFINEd constants are small integers or powers of 2 and can be represented in only 2 bytes. Strings require 2 bytes plus their length to reference as constants, so in that case, the use of constants may actually increase the size of the RUN, assuming they are referenced multiple times.) 

- Because of the above, converting MAP statements to DEFINEd constants (assuming they are never assigned more than one 

- value) will result in smaller RUN files, with a very slight bonus in performance, at the cost of a slight increase in compile times. But the main advantage comes in programming clarity when you use meaningful symbolic names for constant values in place of literal number or mapped variables. 

Including a file containing an unknown set of DEFINEs is generally safe and should have no side effect on an existing program (unless you deliberately use the defined constants). There are, however, some scenarios to be aware of: 

- If a DEFINE precedes a MAP statement for the same identifier, the MAP statement will generate a syntax error, because the 

- MAP statement identifier will be replaced by the value of the DEFINEd symbol before it gets compiled. For example: `DEFINE CTLOP'ADD = 1` 

```
MAP1 CTLOP'ADD,B,2,1
```

Since the CTLOP'ADD in the MAP statement will be replaced by 1, it will be compiled (and a syntax error generated) as if it were: `MAP1 1,B,2,1` 

- If a DEFINE conflicts with an unmapped variable, a similar thing will happen when you try to assign a value to the variable: 

- `DEFINE CANADA'VAT = .15` 

A-Shell Reference 

Page 1264 

```
CANADA'VAT = .16
```

```
! assignment to unmapped variable
```

This will also cause a syntax error, because it will look to the compiler as if it were: 

```
.15 = .16
```

(If the unmapped variable is never referenced, you won't get a syntax error, but then again it won't matter to your program operation either.) 

• The one case where you might have a problem is if you reference an unmapped (and unassigned) variable in an IF statement, i.e.: 

```
IF CANADA'VAT = .16 THEN ...
```

This will compile as if it were: 

```
IF .15 = .16 THEN ...
```

That is a perfectly legal statement, and won't be what you expected (although your test of an unmapped/unassigned variable probably won't be what you wanted either, unless you were counting on it being zero). To eliminate this possibility, compile your programs with /M !!! 

• If you attempt to DEFINE a symbol that has already been MAPPED, you will get a duplicate label error. So it doesn't really matter whether you DEFINE all your symbols first or do all your MAPs first, or mix them together; any conflict between the two will generate a compilation error. 

## **See Also** 

- UNDEF 

A-Shell Reference 

Page 1265 

- Passing symbol definitions into compiler 

A-Shell Reference 

Page 1266 

## **- AUTO DEFINED SYMBOLS** 

_Added November 2016_ 

|**Symbol**|**Description**|
|---|---|
|COMPILER_VERSION|See link at left.|
|ABC_CURRENT_ROUTINE$|These equate to the current function/procedure name (or "" if none),<br>and the current module filename (file.ext). Both may be useful in<br>standardized error reporting.|
|ABC_CURRENT_MODULE$||
|ABC_NAMED_PARAMS|Is defined (=1) automatically when the /P compiler switch is used, i.e.<br>indicates that there is support for named parameters|
|ABC_SCALE|Current SCALE value, zero if no SCALE statement yet encountered|



## **History** 

- 2016 September, A Shell 6.3.1528, compiler edit 778: Add ABC_CURRENT_ROUTINE$ and ABC_CURRENT_MODULE$. 

- 2014 October, A Shell 6.1.1392, compiler edit 711: Add COMPILER_VERSION. 

- 2014 January, A Shell 6.1.1373, , compiler edit 650: Add ABC_NAMED_PARAMS. 

A-Shell Reference 

Page 1267 

## **COMPILER_VERSION MACRO** 

_Added February 2015_ 

The compiler internally defines a macro symbol COMPILER_VERSION to the compiler edit number, allowing you use it in a conditional compilation statement to avoid or warn about code that requires a minimum compiler version. For example: 

```
++IFNDEF COMPILER_VERSION
```

```
    ++ERROR Compiler version too old (pre 711)
```

```
++ENDIF
```

```
++IF COMPILER_VERSION >= 710
    DEFTYPE BOOLEAN I,2
++ENDIF
```

```
++IF COMPILER_VERSION < 728
? "Error ";err(0);
++IFDEF ABC_CURRENT_ROUTINE$
     ? " in routine ";ABC_CURRENT_ROUTINE$
++ELSE
    ? " at line #";err(1)
++ENDIF
++IFDEF COMPILER_VERSION
```

```
    ++IF COMPILER_VERSION >= 792            ! .LOCATION introduced in
```

A-Shell Reference 

Page 1268 

```
        ? " location counter = "+.LOCATION  !   compiler edit 792
```

```
    ++ENDIF
```

```
++ENDIF
```

## **Comments** 

Unfortunately, since the COMPILER_VERSION macro was introduced in edit 711, an attempt to reference its value in a prior version will generate a "conditional expression not constant" error, so that will only be useful going forward. However, you can use ++IFDEF to test if it's defined—and if not, you will know that it is prior to version 711. 

Independent of, but related to, the concept of the minimum compiler version needed to compile a section of source code, is the minimum runtime version needed to execute it. This is not something you can test for or specify at compile time, but as of compiler version 896 (released with A-Shell 6.5.1657), the compiler automatically indicates the minimum runtime version needed (if it exceeds 6.5.1657) in the RUN header, based on the features used in the program. You can use VERSYS.LIT to display the minimum version, if applicable, for any RUN, LIT, or SBX program. 

## **History** 

- 2014 October, A Shell 6.1.1392, compiler edit 711: added to A-Shell 

A-Shell Reference 

Page 1269 

## **ABC_SCALE** 

_Added February 2022_ 

The auto-defined macro ABC_SCALE is set to the current SCALE value, zero if no SCALE statement yet encountered. In environments that depend on SCALE, this allows you to insert conditionals into ++INCLUDE files to make sure that SCALE hasn't accidentally been omitted from the main program, e.g.: 

```
++ifdef ABC_SCALE                                ! does this compiler version support ABC_SCALE?
    ++if ABC_SCALE <> 2                          ! if so, is SCALE set to 2?
```

```
        ++error You forgot to set SCALE 2!!!
```

```
    ++endif
```

```
++endif
```

## **History** 

- 2021 October, A Shell 6.5.1708, compiler edit 959: Macro added to A-Shell 

A-Shell Reference 

Page 1270 

## **RESERVED SYMBOLS** 

_Written Feburary 2025_ 

## **_MIN_RUN_VER** 

This special symbol may be defined to override the minimum runtime version field placed into the RUN file header, which is normally based purely on the range of language constructs referenced in the source code.  For example, if your program contains a system function that normally requires a runtime version of 7.0.1767, but you want to be able to run the program in older versions  6.4.1580+, using runtime logic to avoid hitting the unsupported code, you can either add the following definition to the program: 

```
DEFINE _MIN_RUN_VER = 1580
```

or compile the program with definition on the command line, e.g.: 

```
.COMPIL myprog/C:_MIN_RUN_VER=1580
```

## **Background** 

Normally the compiler will automatically plug in the minimum run version value based on the language features used in the program. The RUN interpreter will compare that value to the current runtime version, and if not sufficient, will abort with an explicit complaint -- "Program requires minimum A-Shell level ####". This is deemed preferable to getting some cryptic error, such as #34 (Invalid Syntax Code) when the intepreter encounters the unrecognized code. However, there may be times where you know better than the compiler. For example, your program may check the version at runtime and avoid code that requires a later version, in which case you might want to override the minimum version in the header to allow it to run on earlier versions anyway. Or, in the case of embedded defstructs, if you distribute RUN programs across older 64 bit A-Shell versions, you may want to force the minimum run version to 1767, to avoid wasting time later trying to figure out why embedded defstructs aren't working. 

## **History** 

- 2025 January, A Shell 7.0.1767, compiler edit 1053: Function added to A-Shell. 

A-Shell Reference 

Page 1271 

## **_NO_MIN_1767** 

This special symbol may be defined (as 1) to prevent the compiler from setting the minimum runtime version field in the RUN file header to 1767 for any program containing embedded DEFSTRUCTs. This is safe and only makes sense when compiling and running under the same (32 vs 64 bit) architecture, allowing programs compiled under compiler edit 1057+ to be run under A- Shell versions prior to 7.0.1767. For example: 

```
DEFINE _NO_MIN_1767 = 1
```

or: 

```
.COMPIL myprog/C:_NO_MIN_1767=1
```

## **History** 

- 2025 January, A Shell 7.0.1768, compiler edit 1057: Function added to A-Shell. 

A-Shell Reference 

Page 1272 

## **UNDEF** 

## **UNDEF <symbol>** 

The UNDEF directive cancels (undefines) a symbol created by a prior DEFINE, DEFALIAS or DEFTYPE directive. 

For example: `++IFDEF Flavor_of_the_Month$ ++MESSAGE Out with the old flavor (Flavor_of_the_Month$) UNDEF Flavor_of_the_Month$ DEFINE Flavor_of_the_Month$ = "Marmite" ++ELSE ++MESSAGE Flavor of the month program not currently active ++ENDIF` 

Note that in the above case, without the UNDEF, the DEFINE statement would generate a "redefined symbol" error unless the new definition was the same as the prior one. On the other hand, an UNDEF of a symbol that hasn't yet been defined is **not** considered an error, so the above ++IFDEF would only be necessary or sensible if the objective was to change the flavor of the month only if a flavor of the month had already been established, and otherwise to leave it undefined. 

## **History** 

- 2022 June, A Shell 6.5.1717, compiler edit 994: UNDEF extended to work on DEFALIAS definitions. It previously worked only for DEFINEs. 

A-Shell Reference 

Page 1273 

## **DEFTYPE** 

_Added November 2014_ 

## **DEFTYPE <typename> = <standard type>{,<size>}** 

## **DEFTYPE <typename> = <defstruct type>** 

DEFTYPE may be used to define an alias for a data type, with optional size, that can then be used in MAP statements and in Function and Procedure declarations. This can be useful in assuring consistency of logical data types through an application. For example: 

```
DEFTYPE Boolean = I,2
deftype PRICE = F,8
deftype phone = ST_PHONE
```

```
map1 ready,Boolean        ! equivalent to map1 ready,I,2
dimx total(10),PRICE      ! equivalent to dimx total(10),F,8
map1 cellnum,phone        ! equivalent to m1p cellnum,ST_PHONE
```

```
Function Fn'PiePrice(ala'mode as Boolean) as PRICE
```

```
! equivalent to: Function Fn'PiePrice(ala'mode as I,2) as F,8
```

Note that while DEFTYPE itself is case INsensitive, following the normal rule for keywords, the defined macro symbols are case sensitive—i.e., are the same as those created by DEFINE or DEFSTRUCT. You can compile with the case-insensitive option (/CI or -ci) if you prefer case insensitivity throughout. 

## **History** 

A-Shell Reference 

Page 1274 

- 2014 October, A Shell 6.1.1391: Function added to A-Shell 

A-Shell Reference 

Page 1275 

## **++INCLUDE** 

_Updated June 2023; see History_ 

## **++INCLUDE <fspec>** 

## **++INCLUDE'ONCE <fspec>** 

## **++INCLUDE'IF'EXISTS <fspec>** 

## **++INCLUDE'ONCE'IF'EXISTS <fspec>** 

The ++INCLUDE compiler directives cause the file specified by _fspec_ to be processed as if it were part of the file being compiled. The technique is useful for sharing common code, map statements, and definitions between programs. The _fspec_ may be in either AMOS or native format. If no explicit location specified the file is expected to be in the current directory, or in the BAS: account. If not found in either location, the A-Shell compiler—unlike the AMOS counterpart—will also search in the same directory as the main source file being compiled, assuming that is different from the current directory. 

All variations of ++INCLUDE also support a "transclude" mechanism via two optional parameters which are omitted from the syntax shown above. See the subtopics listed below for details on this and other ASB extensions to the standard include operation. 

## **See Also** 

- COMPIL/LI (Local Include) 

## **History** 

- 2023 June, A Shell 6.5.1732:  Transclude function added. 

- 2017 March, A Shell 6.4.1546, compiler enhancement (797): maximum nesting levels for ++INCLUDE and ++IF conditions increased from 20 to 40. Improve messaging/recovery for the overflow condition. 

A-Shell Reference 

Page 1276 

2013 July, A-Shell 6.1.1358: Compiler enhancement (642): new variations of ++INCLUDE: `++INCLUDE'IF'EXISTS <filespec>` and `++INCLUDE'ONCE'IF'EXISTS <filespec>` . As the name implies, these operate just like ++INCLUDE and ++INCLUDE'ONCE except that if the file is not found in the normal search path, it is just skipped. 

## **Subtopics** 

- Nested ++INCLUDEs 

- One Time ++INCLUDEs 

- Transclude 

A-Shell Reference 

Page 1277 

## **NESTED ++INCLUDES** 

A-Shell supports thirteen levels of nested ++INCLUDEs. This is primarily useful to allow modular include files to themselves include all of the necessary modules they require, thus relieving the programmer from having to include the entire network of dependent modules in the main source file. Nesting does introduce two complications worth further discussion: how to avoid including the same module twice (see One Time ++INCLUDE), and how to keep track of the hierarchy of nested includes, particularly when it comes to locating the module containing an error flagged by the compiler. 

To help you visualize the hierarchy of ++INCLUDE processing, the compiler normally (absent the /S switch) lists the included file names as it processes them, indenting to indicate the level, e.g.: 

```
.compil sqltest4/x:2
```

```
Phase 1 - Initial work memory is 16944 bytes
```

```
        Copying from ASHELL.DEF[907,16]
        Copying from FNSQLSTATE.BSI
          Copying from FNEXTCH.BSI[907,10]
?Syntax error (++40) - this is an error
        Copying from FNSQLATR.BSI
```

```
...
```

The above example illustrates two levels of ++INCLUDE processing. The files SOSLIB:ashell.def and fnsqlstate.bsi are included directly from the main program at the first level, and the file fnextch.bsi is included from within fnsqlstate.bsi at the second level, which we can tell based on the fact that it is indented. The standard error message does not directly indicate which file the error occurred in, but it outputs a "+" in front of the line number for each level of ++INCLUDE nesting. Thus, the "(++40)" tells us that the error was in a module nested two levels below the main program, which could only be fnextch.bsi in this example. 

Another option would be to use the COMPIL Background switch, which causes the compiler to output a <prog>.lst file containing details for each error, including the module file name. 

A-Shell Reference 

Page 1278 

Another useful function is offered by the COMPIL List File (LF) switch, which creates a consolidated List File containing all of the + +INCLUDEd modules. The file is designed mainly to use as a cross reference for linking runtime errors to the original source code, but could be used as an aid to studying all the parts of the program in one listing. 

Yet another option would be to use The A-Shell Editor, a multi-file program editor capable of identifying all of the included modules associated with the main source and jumping between them as needed. 

## **See Also** 

- The A-Shell forum discussion " Managing nested ++INCLUDEs." 

A-Shell Reference 

Page 1279 

## **ONE TIME ++INCLUDES** 

## **++INCLUDE'ONCE <fspec>** 

This directive acts just like the regular ++INCLUDE, except that if the specified file has already been included in the current compilation, then it is skipped. This largely solves the problem—introduced by nesting—of accidentally including the same file twice. In fact, in most cases you may want to just use ++INCLUDE'ONCE all the time. It is somewhat unlikely that you would deliberately want to include the same file twice, but one possibility would be a set of map statements that you want to use locally within multiple functions. 

To help you visually confirm the operation of skipping redundant ++INCLUDEs, the compiler will indicate them as in this example: `Phase 1 - Initial work memory is 16944 bytes` 

```
        Copying from ASHELL.DEF[907,16]
        Copying from SQL.DEF
        Copying from FNSQLCON.BSI
        Copying from FNSQLSTATE.BSI
        Skipping sql.def (already included)
          Copying from FNEXTCH.BSI[907,10]
        Copying from FNSQLATR.BSI
        ...
```

++INCLUDE'ONCE is useful for allowing individual modules to explicitly include their own dependent modules without having to know whether other modules in the program have already done so. But, it depends on using the option everywhere. An alternative or additional technique for avoiding including a module more than once, which does not rely on the consistent use of ++INCLUDE'ONCE, is to enclose each module inside a conditional compilation statement as follows: 

```
! foo.bsi
```

A-Shell Reference 

Page 1280 

```
++ifndef INC_FOO_BSI_
    define INC_FOO_BSI_ = 1
```

```
    <contents of the module>
```

```
++endif
```

In the above example, the module is only included if the specified symbol is not yet defined. Since it gets defined immediately after the test, we can be sure that the contents of the module will only be included once. Although there is no enforced standard for the symbol names, to be practical, they need to be unique. Thus it is wise to form the symbol by appending some prefix and/or suffix to the module name. 

## **See Also** 

- Avoiding Duplicate INCLUDES 

A-Shell Reference 

Page 1281 

## **TRANSCLUDE** 

_Written June 2023_ 

"Transclude" (aka "transcopy") is built on the same framework as MX_TRANSCOPY. It can be integrated into any of the existing + +INCLUDE variants by adding one or two additional comma-delimited parameters: 

## **++INCLUDE includespec {,tcfspec {,section}}** 

If the _tcfspec_ parameter is specified, it must identify a Transcopy Configuration File (TCF) that follows the rules described for MX_TRANSCOPY above. 

If the _section_ parameter is not included, then only the common section of the TCF (at the top, before any [section] headers) is processed. Otherwise, the common section plus the specified section is processed. Specifying a section that does not exist is considered an error, but a TCF file with no relevant search/replace patterns simply reverts back to an ordinary ++INCLUDE operation. 

The concept here is to allow the use of generalized (or quasi-template) include files that can be customized at compile time for different uses, rather than having to maintain multiple separate include file variations. 

To debug the operation, you can either consult the LSX file, which will contain the result of each transclude operation, or use the MX_TRANSCOPY function. 

Note that ++INCLUDE'ONCE takes into account the TCF and _section_ , allowing the same original include file to be included multiple times, each with different TCF. But, if the include file contains a compiler directive to prevent multiple inclusions (e.g. ++IFNDEF, ++IFNLBL, etc.), then the parent program would need to take additional action to override it—for example, with an explicit + +UNDEF prior to the additional ++INCLUDE directives. 

Also note that in APN, using the Goto Definition function to locate the definition of a function or other symbol will take you to the original version of the include file. For example, if you have a function Fn'Foo() in an include file FOO.BSI, and you use the transclude feature to include a variation of the function called Fn'Foo2(), using the Goto Definition function on a reference to Fn'Foo2() will take you to the definition of Fn'Foo() in FOO.BSI. Fn'Foo2() only exists virtually so there is no practical way to jump to its source code. 

## **History** 

A-Shell Reference 

Page 1282 

- 2023 June, A Shell 6.5.1732:  Transclude function added. 

A-Shell Reference 

Page 1283 

## **++PRAGMAS** 

_Updated February 2013 (see PRIVATE_...)_ 

## **++PRAGMA <pragma> {options}** 

PRAGMAs are commands to the compiler to specify compilation options or otherwise modify its behavior. The general syntax is: 

```
++PRAGMA FORCE_EXT "LIT"
```

where the available pragmas and associated options are listed in the tables below. 

## **- A Shell PRAGMAs** 

The following PRAGMAs are supported only when A-Shell Extensions are enabled (X:2 compiler switch). 

|**A-Shell PRAGMA**|**Description**|
|---|---|
|ALIGN2|Align MAP1 variables on 2 byte boundaries (default).<br>See Alignment below.|
|ALIGN4|Align MAP1 variables on 4 byte boundaries. See<br>Alignment below.|
|ALIGN8|Align MAP1 variables on 8 byte boundaries. See<br>Alignment below.|
|EXTERN_BEGIN, EXTERN_END|Bracket MAP statements used to declare<br>Global/External Variables<br>.|
|SBX|Same as /X:3 (create an SBX instead of RUN).|



A-Shell Reference 

Page 1284 

|**A-Shell PRAGMA**|**Description**|
|---|---|
|TRACK_LAST_ROUTINE <boolean>|Updates .LAST_ROUTINE (seeDot Variables<br>)each time<br>a function or procedure is called.|
|TRACK_LAST_LABEL <boolean>|Updates .LAST_LABEL (seeDot Variables<br>) each time<br>execution passes a label in the program.|
|AUTO_EXTERN<br> <boolean>|Used withinUser-Defined Functions<br>or Procedures<br> to<br>allow the use of global variables within the local<br>routine. Also seeGlobal/External Variables<br>.|
|PRIVATE_BEGIN and _END|Used within++INCLUDEfiles to ensure that the<br>module's private variables (MAPandDIMX) are<br>initialized once and only once before they are used.|
|GLOBAL_BEGIN and _END|Similar to PRIVATE_BEGIN and PRIVATE_END, except<br>that they declare a block of variables intended to be<br>visible to any other module in the program.|
|TRACE_BEGIN and _END|Enable and disable automatic tracing of all enclosed<br>statements|
|ASHELL_EXTENSIONS <boolean>|Enables/disables the switches /X:2, /P, and /PX<br>respectively. The <boolean> argument is optional and<br>defaults to "TRUE". Must be placed before any other<br>code, except for comments, ++pragmas,++IFXXX<br>conditionals, and the PROGRAM statement.|
|PRE_PROCESS <boolean>||
|EXTENDED_PRE_PROCESS||



A-Shell Reference 

Page 1285 

|**A-Shell PRAGMA**|**Description**|
|---|---|
|<boolean>||
|INCLUDE_GLOBAL_ONCE_ONLY<br><boolean>|When enabled,++INCLUDEis treated as +<br>+INCLUDE'ONCE, except when it occurs inside a<br>function or procedure. In such cases, it is likely that<br>you are intentionally including an extra copy of some<br>map statements.|
|AUTO_LARGE_CONSTANTS|Causes the compiler to automatically supply the "L"<br>suffix to any integer constant, as appropriate.|
|LSX_FSPEC|Provides a way to assign a name to theLSX file<br>that<br>includes the vedit field of the program version.|
|FORCE_F1_HDR <boolean>|Forces a toggle of the /F1 switch.|
|EMBED_DEFSTRUCT|See Structure Definition Embedding<br>.|
|EMBED_DEFSTRUCTS_BEGIN and<br>EMBED_DEFSTRUCTS_END|See Structure Definition Embedding<br>.|
|OVERRIDE_OUTPUTONLY|Causes parameters with the :OUTPUTONLY qualifier<br>and a default value to revert to input/output.|



**BASIC** _**plus**_ **PRAGMAs** 

A-Shell Reference 

Page 1286 

## The following PRAGMAs are supported in BASIC _plus_ mode (X:1 compiler switch). 

|**BASIC****_plus_ PRAGMA**|**Description**|
|---|---|
|NO_LINE_NUMBERS <boolean>|Same as /O|
|ERROR_IF_NOT_MAPPED <boolean>|Same as /M|
|FORCE_24_BIT <boolean>|Same as /A|
|FORCE_EXT "ext"|Force compiler output to use "ext" extension instead<br>of .RUN.|
|FORCE_FSPEC|Allows you to change the name of the output file.|
|FORCE_IEEE <boolean>|Forces a floating point variable which does not have an<br>explicit size to be treated as F,8 (rather than F,6). Also<br>requires /X:1 or higher.|
|FORCE_OLD_ISAM <boolean>|This is the equivalent of /I, causing the compiler to<br>assume ISAM 1.x for OPEN statements that are<br>otherwise ambiguous. Unlike /I, it can be turned on and<br>off for different sections of the source code.|



Valid replacements for the "boolean" argument are (not case sensitive): "YES", "TRUE", 1 or "NO", "FALSE", 0. Beginning with A- Shell 6.3.1528, the default for all pragmas accepting a <boolean> argument is "TRUE". Previously some of them required an explicit argument while others did not. For example, the following two are equivalent, though previously, the first one would have triggered an invalid argument error: 

```
++pragma ERROR_IF_NOT_MAPPED
```

```
++pragma ERROR_IF_NOT_MAPPED "TRUE"
```

## **AlphaBASIC PRAGMAs** 

The following PRAGMAs from BASIC _plus_ are recognized but ignored by A-Shell because the associated function is not important or relevant under A-Shell. The important point is that by being recognized, they do not generate compile errors, thereby keeping your code (more) source-compatible with AMOS. 

A-Shell Reference 

Page 1287 

- FORCE_SBR_EXT (see FORCE_EXT and SBX) 

- LIFESIGNS (hardly needed when compilation time is measured in milliseconds) 

- ADD_EXTRA_STRWRK (A-Shell's string work area can use the entire memory partition) 

- EXTRA_STRWRK 

- SET_SETWRK 

## **Alignment** 

MAP1 variables are 2-byte aligned (ALIGN2) by default. Variables at all other MAP levels are always single-byte aligned. The ALIGN4 and ALIGN8 pragmas (for 4 and 8 byte alignment) may be more efficient on some modern processors, and can be useful for matching data layouts originating in other languages (such as C). But beware of the effect this can have when using map overlays. For example: 

```
MAP1 A1,S,5
```

```
MAP1 A2,S,5
```

```
MAP1 AX,S,16,@A1
```

Under the normal 2-byte alignment, A2 will start in the 6th position of the AX overlay. But with 4 byte alignment, it would start in the 8 position. 

## **See Also** 

- ++ERROR 

- ++MESSAGE 

## **History** 

- 2025 January, A Shell 7.0.1767, compiler edit 1054: Added ++PRAGMA OVERRIDE_OUTPUTONLY 

- 2020 June, A Shell 6.5.1683, compiler edit 929:  Added ++PRAGMA FORCE_F1_HDR <boolean> 

A-Shell Reference 

Page 1288 

- 2019 February, A Shell 6.5.1654, compiler edit 891:  Added ++PRAGMA AUTO_LARGE_CONSTANTS 

- 2014 July, A Shell 6.1.1387, compiler edit 679:  ++PRAGMA ERROR_IF_NOT_MAPPED "FALSE" may now be used to override /M or a previous "TRUE". Previously it was only possible to enable the /M switch, not disable it. Note that you can now turn the option on and off multiple times within a program, allowing you to get the benefit of the for new sections of code without being forced to clean up the unmapped variables in all of your code—i.e. in all of your include modules. 

A-Shell Reference 

Page 1289 

## **FORCE_FSPEC** 

## **++PRAGMA FORCE_FSPEC <file specification>** 

Similar to FORCE_EXT <ext>, this pragma allows you to change the name of the output file generated by the compilation. The name you specify may optionally contain an extension (in which case it overrides the extension previously established by default or by prior pragmas), and it may be in native or DevPPN format. It may also contain "%s" to indicate the simple name of the current source file. (This allows you to use a common pragma, perhaps via a ++INCLUDE, which specifies an alternate location for the run file.) Note that in all cases the filespec should be quoted. Examples: 

```
++PRAGMA FORCE_FSPEC "fred"
```

```
++PRAGMA FORCE_FSPEC "BAS:MYNAME.RRR"
```

```
++PRAGMA FORCE_FSPEC "/vm/miame/run/abcdef"
```

```
++PRAGMA FORCE_FSPEC "NEWRUN:%s"
```

## **History** 

- 2026 April, A Shell 7.0.1785:  ++PRAGMA FORCE_FSPEC now  sets the default base name for the LSX if there is no explicit + +PRAGMA LSX_FSPEC. 

A-Shell Reference 

Page 1290 

## **PRIVATE_BEGIN AND _END** 

_Updated August 2018; see History_ 

## **++PRAGMA PRIVATE_BEGIN** 

## **<map and dimx statements>** 

## **++PRAGMA PRIVATE_END** 

This set of pragmas may be used within ++INCLUDE files to ensure that the module's private variables (MAP and DIMX) are initialized once and only once before they are used, regardless of the position of the ++INCLUDE in the main program. Previously, without the benefit of the new pragmas, it was left to the programmer to make sure that any such MAP statements containing initializers, and any DIMX statements, got executed, just once, before being used. Typically that required that the ++INCLUDE be at the top of the main program, so that execution fell through the MAP and DIMX statements before the main program started executing, or it required a static control variable and some conditional logic within the ++INCLUDE module to keep track of whether the initializations had occurred. 

Using these pragmas, the compiler takes care of the problem, making sure that the enclosed MAP and DIMX statements are initialized before any of the functions or procedures within the module are executed. 

Secondarily, as a syntactic convenience, the keyword PRIVATE will be automatically added to any MAP or DIMX statement enclosed by the pragmas if not already explicitly specified. Thus, if you really do want to specify global variables within such a + +INCLUDE module, you must keep then outside the set of pragmas lest they be turned into module private variables. 

## **Notes** 

- Each ++INCLUDE module can have only a single pair of these pragmas 

- The feature is entirely implemented in the compiler, so there is no requirement for a corresponding update of the runtime 

- system. 

A-Shell Reference 

Page 1291 

- Other kinds of statements may be included within the PRIVATE_BEGIN and _END pragmas, such as assignments or function 

- calls related to initializing the private variables. As with the MAP and DIMX statements, they would be guaranteed to execute prior to any of the functions or procedures within the module, and only once. 

## **Example** 

```
! (main program)
```

```
...
if Fn'GetTableItem$(X) = "" then
    call SetTableItem(X, "Behold!")
```

```
endif
```

```
...
++include table.bsi
```

```
- - - - - - - - -
```

```
! (table.bsi)
```

```
++pragma private_begin
map1 table'max,f,6,5000
dimx table(table'max),s,100
++pragma private_end
```

```
...
```

```
Function Fn'GetTableItem$(idx as f) as s100
```

A-Shell Reference 

Page 1292 

```
   if (idx <= table'max) then Fn'GetTableItem$ = table(idx)
```

```
EndFunction
```

```
Procedure SetTableItem(idx as f, item$ as s100)
```

```
   if (idx <= table'max) then table(idx) = item$
```

```
EndProcedure
```

In the above example, the module table.bsi contains a private DIMX array table() which is shared by the function and procedure in the module. Because the module is included at the bottom of the main program, without the ++PRAGMA PRIVATE_BEGIN, the array would still be uninitialized at the point it was referenced in the Fn'GetTableItem$() function, leading to an error. To correct for that, the ++INCLUDE statement would have to be moved to the top of the main program, but that is an undesirable 

dependency which the programmer creating the table.bsi would rather not have to depend on. And it is otherwise not easy to code around the problem. But with the ++PRAGMA PRIVATE_BEGIN, the problem disappears. 

## **History** 

- 2018 August, A Shell 6.5.1641, compiler edit 868:  Language enhancement: PRIVATE variables and ++PRAGMA PRIVATE_BEGIN / _END blocks may now be used in the main source module to limit the scope of those variables to just that source file. Note that this enhancement entirely handled by the compiler; there is no issue with backwards or forwards runtime compatibility, even under AMOS. 

- 2016 November, A Shell 6.3.1534, compiler edit 790:  use of .ARGCNT within a PRIVATE_BEGIN / PRIVATE_END block now generates a compile error. Although the expression wouldn't technically be illegal, because the PRIVATE block is essentially called for initialization by whatever function or procedure in the module gets called first, there is really no good way to predict in advance what the .ARGCNT value will represent, and thus it is almost certain to create a discrepancy between the expected and actual behavior. 

- 2013 February, A Shell 6.1.1338: Pragmas added to A-Shell, compiler edit 624. 

A-Shell Reference 

Page 1293 

## **GLOBAL_BEGIN AND _END** 

_Updated July 2019; see History_ 

## **++PRAGMA GLOBAL_BEGIN** 

## **<map and dimx statements>** 

## **++PRAGMA GLOBAL_END** 

These are similar in concept to the pragmas PRIVATE_BEGIN and PRIVATE_END, except that they declare a block of variables— and possibly some instructions related to initializing those variables—intended to be visible to any other module in the program. 

Although non-PRIVATE variables defined outside of functions and procedures are already global, the difference here is that the section of variables and code gets effectively moved to the start of the program (see clarification below) so that the variables are all defined and initialized before any other code that may reference them. This feature is intended to help programmers modernize old-style ++INCLUDE modules which suffer from the use of un-mapped variables, and/or which are sensitive to the order in which they are included in the main program. 

Clarification: by default, the GLOBAL_BEGIN/END code is moved to the start of the program. But in some cases that may not be quite ideal, for example where the MAP statements or code require definitions from, say, SOSLIB:ashell.def. To give you that flexibility, you can specify the location where you want the global code to be inserted via a special ++INCLUDE statement: 

```
++include $GLOBALS      ! insert GLOBAL_BEGIN/END blocks here
```

This acts like a normal ++INCLUDE except that instead of referencing a static file, it collects up all the code in the GLOBAL_BEGIN / END blocks and creates a virtual include file on the fly. Technical note: the global blocks will actually be copied to a temporary file cmpglobals.tmp, which you can examine for debugging purposes. 

For include modules with unmapped variables, the recommendation would be to add a GLOBAL_BEGIN/END block to explicitly map the variables used in the module. For example, to take an extremely simple case, imagine an include module containing a routine to close a file: 

```
CLOSE'FILE:     ! caller sets CH
```

```
    CLOSE #CH
```

A-Shell Reference 

Page 1294 

```
    RETURN
```

The problem with this module is that it references a variable, CH, which is not mapped or initialized here, thus requiring the calling programs to compile without the /M switch, or to figure out how and where to map/init it. It probably should be converted to a function, passing the channel explicitly, but that would definitely require changing all of the code that uses this function, which we're trying to avoid. Without the new pragmas, to fix the unmapped variable problem, you could insert a map statement into the module, but unless the module was included at the top of the program, it is likely that code that calls the module would not yet have seen the MAP statement, and thus would still get an unmapped variable reference. And if you did include it at the top of the program, you would also have to insert a GOTO statement and label to jump over the CLOSE'FILE routine, lest it get executed during the program startup. And even then, if the routine was referenced by other included modules, you could easily get into "include sequence hell", where you endlessly shuffle the sequence of ++INCLUDEs trying to come up with an order that manages to have all the variable definitions occur before they are referenced. 

Another approach to solving that problem would be to split the module into two parts: a .map to be included at the top of the program, and a .bsi to be included at the bottom. That works, but introduces module clutter, which tends to encourage combining the .MAP modules, but that leads to variable definition bloat and general confusion. 

With the new pragma, we can insert the following at the top of the module: 

```
++PRAGMA GLOBAL_BEGIN
```

```
MAP1 CH,B,2
```

```
++PRAGMA GLOBAL_END
```

Now, when we compile it, the definition of CH will get moved to the top of the program (or to a specified location, see above), thereby eliminating the forward-reference problem. Existing programs can just be recompiled without any other changes, unless they actually did map the CH variable, in which case that map would have to be removed. But it is likely that any such map statement would be in a common include, so you can probably just add a `++IFNMAP CH` conditional to that to fix it in all cases. 

Of course this is an extremely simplistic example. In a more realistic case, you may have many variables used within a BSI, some of which are truly local and should be declared PRIVATE, and others which may require some explicit initialization code. 

A-Shell Reference 

Page 1295 

But the principle remains the same: whatever you put between the GLOBAL_BEGIN and GLOBAL_END pragmas will be made globally available to the rest of the program without you having to make any other adjustments to external code, other than recompiling the programs that use this module. 

Note: the feature requires the /P (or -p) compile switch, but does not require any particular run-time version. The RUN files can even be AMOS compatible, if you stick with the /RC option. 

## **History** 

- 2019 July, A Shell 6.5.1664, compiler edit 911:  The temporary file used to hold a GLOBAL_BEGIN/END block now uses a source-file-specific name <source>.glbi instead of the fixed name cmpglobals.inc. This resolves a conflict with running multiple simultaneous compilations in the same directory. 

- 2014 October, A Shell 6.1.1392: Add to A-Shell 

A-Shell Reference 

Page 1296 

## **TRACE_BEGIN AND _END** 

_Revised November 2018_ 

## **++PRAGMA TRACE_BEGIN   {optionlist}** 

## **++PRAGMA TRACE_END** 

## **++PRAGMA TRACE_OPTIONS {optionlist}** 

TRACE_BEGIN and TRACE_END may be used to bracket a section of code for which automatic TRACE.PRINT statements will be generated after each program statement. Each auto-generated trace will consist of two lines: first the source code, then the trace of the variables in that statement. Note that not all statements will be traced; primarily it is limited to those statements which operate on variables. Also note that the trace generally occurs after the statement execution, which means that function and procedure call statements show up in the trace output after the routine returns. IF statements are an exception in that they get traced prior to execution (so you can see the IF statement regardless of whether the condition is true or false). 

The TRACE_OPTIONS pragma only establishes default options for subsequent manually typed xxxxx.PRINT and xxxxx.PAUSE statements, except for those which already include their own explicit options. Note that the _optionlist_ on the TRACE_BEGIN statement also establishes the default options, in addition to activating the auto tracing. 

The _optionlist_ consists of the following four fields. Each field is itself optional, although in order to specify a subsequent field, you must specify the prior ones. The parentheses are optional if only the _dbglvl_ field is specified; otherwise they are mandatory. 

## _dbglvl_ 

Sets the debug level for the statement; the higher the level, the higher the corresponding DEBUG system variable must be in order to activate the statement. See SET.LIT DEBUG <options> for details on setting the runtime _dbglvl_ . The default _dbglvl_ is 1, and requiring `SET DEBUG {1}` to enable. 

## _tags_ 

A quoted literal string consisting of comma-delimited symbols to be associated with each xxxxx.PRINT or xxxxx.PAUSE statement. Use the SET.LIT DEBUG <options> command at runtime to specify tags to filter the trace output by. Note that the current program and SBX names are implicitly added to the _tags_ list. 

A-Shell Reference 

Page 1297 

## _prefix_ 

A quoted literal string which, if specified, is inserted at the start of each xxxxx.PRINT / xxxxx.PAUSE statement, typically used to specify macros like $#, $T, $P, $L, etc. It comes in handy in situations where you already have a lot of xxxxx.PRINT statement in the program, but are having trouble identifying them in the trace output. Rather than manually modifying each statement to include additional contextual identifiers, you could simply specify `++PRAGMA TRACE_OPTIONS (0,"","$L")` to insert the location counter into each trace. See TRACE Statements for a reference to the available macros. 

## _tokens_ 

— A quoted list of tokens—typically variables to be traced. If specified, only lines containing one of those tokens/variables will be auto-traced. 

## **Example** 

```
++PRAGMA TRACE_BEGIN (5,"tag1","$#","qty,TOTAL,sku")
```

Following the above pragma, only lines containing "qty", "TOTAL", or "sku" will be set up by the compiler for auto-tracing. Whether the tracing will actually occur at runtime will be dependent on options established at runtime via the SET.LIT DEBUG <options> command. The debug level will need to be set to at least 5, and/or the tag value "tag1" will need to be set. 

## **Comments** 

- The token matching is case sensitive, and 'whole word' oriented. So the above would not match the line "qty_1 = QTY / 

- TOTAL2". However, the token XXX in the pragma list will match XXX$, XXX(Y), and XXX.Y. 

- Tokens will also match anywhere in the source line—i.e. within string literals and even comments. 

- The trace token filtering is handled entirely by the compiler. 

- TRACE_BEGIN / END blocks can be nested to 38 levels. Any unterminated TRACE_BEGIN block will be automatically 

- terminated at the end of each source file module ro function. Consequently, to trace an entire include module, you could insert just the ++PRAGMA TRACE_BEGIN at the top. 

- Unlike the TRACE.PRINT statement, if no _optionlist_ is specified, the default _dbglvl_ is 1, meaning that the traces are disabled by 

- default, requiring some form of SET DEBUG to enable. 

A-Shell Reference 

Page 1298 

## **See Also** 

- SET.LIT DEBUG <options> 

## **History** 

- 2018 August, A Shell 6.5.1644:  • Specify a list of tokens to be traced. • TRACE_BEGIN / END blocks can now be nested to 38 levels. Any unterminated TRACE_BEGIN block will be automatically terminated at the end of each source file module. Consequently, to trace an entire include module, you could insert just the ++PRAGMA TRACE_BEGIN at the top. 

- 2018 July, A Shell 6.5.1639: Added to A-Shell. 

A-Shell Reference 

Page 1299 

## **AUTO_LARGE_CONSTANTS** 

_Added February 2019_ 

## **++PRAGMA AUTO_LARGE_CONSTANTS <boolean>** 

Beginning with A-Shell 6.5.1655, compiler edit 891, ++PRAGMAs are available to support large constants. 

As with most other ++PRAGMAs, the <boolean> argument is optional, defaulting to TRUE if not specified. 

This pragma causes the compiler to automatically supply the "L" suffix to any integer constant (in any DEFINE or other statement), as appropriate. By "appropriate", we mean whenever the constant is too large to be perfectly represented as an F,6 without possible loss of significant digits, and not too large to be stored as a 48 bit integer. 

For background, ASB normally stores constants in either 2, 4, or 6 byte floating point representation, as needed for accuracy (and for compatibility with AlphaBASIC). But the F6 format can only handle 11 significant digits before you start to risk losing precision. For example, the constant 9999999999999 (13 9's) may well get approximated as something like 

10000000000000.00000001 and get treated as 10000000000000 for printing and other purposes. To avoid this, for integer constants with between 12 and 14 digits, you would be better off storing them in the 48 bit integer format. 

A-Shell since 6.3.1516 and compiler edit 763 has allowed explicit specification of the 48 bit integer format for literal contants by specifying the "L" suffix, or in a DEFINE statement using &h or &o notation. And that remains the recommended approach, for clarity. But in cases where you aren't sure if you have such constants, the ++PRAGMA AUTO_LARGE_CONSTANTS will use the 48 bit format for those cases where it will improve precision. 

Note that this does not apply to literal values with explicit decimal points, or to those too large to fit in the 48 bit integer format. (In that case, it's better to approximate the value as a floating point, possibly resulting in a +1/-1 rounding error, than to have the value wrap around, resulting in apparent garbage. 

Also note that for positive values, the compiler assumes you intend to use it or store it as an unsigned value, so it sets the upper limit at 2**48-1. For negative values, the limit is 2**47-1. If you have positive literal values between 2**47-1 and 2**48-1 which may end up getting stored in the I6 format, you may want to explicitly specify a trailing decimal point to force the value to be stored as a floating point, rather than risk the wraparound problem. 

## **History** 

A-Shell Reference 

Page 1300 

- 2019 February, A Shell 6.5.1655: Added to A-Shell. 

A-Shell Reference 

Page 1301 

## **LSX_FSPEC** 

_Added July 2019_ 

## **++PRAGMA LSX_FSPEC "filespec"** 

where "filespec" can be an A-Shell-style or native filespec, optionally including the following special macros: 

%s program source name (without directory or extension) 

%v the vedit field of the PROGRAM statement (or zero if not avail) 

Beginning with A-Shell 6.5.1663, compiler edit 910, this ++PRAGMA provides a way to assign a name to the LSX file that includes the vedit field of the program version. 

For example: 

```
PROGRAM FOO,1.0(245)
```

```
...
```

```
++PRAGMA LSX_FSPEC "LSXARC:%s-%v.LSX"
```

If the program above is compiled with the /LF switch, the LSX file will be named lsxarc:foo-245.lsx. 

## **Notes** 

- The ++PRAGMA does not by itself activate the /LF switch. 

- The ++PRAGMA may appear before or after the PROGRAM statement. 

- The ++PRAGMA has no effect if compiling an LSX file, in which case the list file will have the same name as the LSX source file 

- except with an LSY extension. 

- If the filespec in the ++PRAGMA statement does not specify an extension, LSX is assumed. 

A-Shell Reference 

Page 1302 

## **See Also** 

- COMPIL switch List File (LF) 

## **History** 

- 2019 July, A Shell 6.5.1663, compiler edit 910:  Pragma added to A-Shell. 

A-Shell Reference 

Page 1303 

## **OVERRIDE_OUTPUTONLY** 

_Added February 2025_ 

## **++PRAGMA OVERRIDE_OUTPUTONLY** 

This pragma causes parameters with the :OUTPUTONLY qualifier and a default value to revert to input/output. This is intended to be transitional feature to support programs that were counting on the behavior prior to compiler edit 1047 (A-Shell 7.0.1765.6) until they can be corrected. After that edit, and without this pragma, the :OUTPUTONLY qualifier was taken seriously, meaning that any value passed in to that parameter would be ignored, and as of compiler edit 1049, attempting to set a default value for an :OUTPUTONLY parameter (other than 0 or "") generates an error. 

Note that this option can also be set by passing the new COMPIL_OOO flag (&h400000000, defined in compil.def) to the MX_COMPIL function. 

## **History** 

- 2025 January, A Shell 1767, compiler edit 1054: Option added to A-Shell. 

A-Shell Reference 

Page 1304 

## **CONDITIONAL COMPILATION** 

The following directives may be used to mark sections of code to be conditionally compiled, based on whether a symbol, variable or label has been defined, or whether a constant expression is true or false. They are analogous to the IF/ELSEIF/ELSE/ENDIF statements except that they affect the operation of the compiler—determining which statements are compiled and which are ignored—rather than the runtime interpreter. The feature requires compiler switch /RC or /X:1 or higher. 

|**Directive**|**Description**|
|---|---|
|++IF, ++ELIF|Conditionals based on evaluating a constant expression.|
|++IFDEF, ++IFNDEF, ++ELIFDEF|Conditionals based on whether the specified symbol or structure has been previously defined.|
|++IFLBL, ++INFLBL, ++ELIFLBL|Conditionals based on whether specified label has been defined.|
|++IFMAP, ++IFNMAP, ++ELIFMAP|Conditionals based on whether specified variable has been mapped.|
|++ELSE|Used as an optional final clause preceded by any other type of ++IFxxx and ++ELIFxxx<br>statements. The lines following the ++ELSE up to the ++ENDIF are compiled only if all of the<br>preceding clauses were false.|
|++ENDIF|Marks the end of the conditional construct.|



## **Example 1** 

```
++IFDEF GUI
```

```
PROGRAM MYPROG,1.0G(100)
```

```
<source code implementing GUI version here>
```

```
++ELSE
```

```
PROGRAM MYPROG,1.0(100)
```

```
<source code implementing text version here>
```

```
++ENDIF
```

A-Shell Reference 

Page 1305 

The above illustrates one way to use conditional compilation to conditionally create either a GUI or text version of your RUN file, starting from the same source file. Previously you could only do the same thing with runtime conditions (which may still be a better option in most cases), but in some cases, you may prefer to have two separate versions of the RUN (perhaps to keep the size down, or to simplify runtime debugging.) Note that the symbol GUI would have had to have been defined somewhere prior to the compiler seeing these statements; see below for how to define symbols on the command line. 

Also note that we used two different versions of the PROGRAM statement in the above example, so that you can easily tell which RUN version you have by displaying it with `DIR/V` . 

## **Example 2** 

```
++IF APPVER = 1
```

```
   ++MESSAGE Compiling Version 1
   ++ver1.bsi
```

```
++ELIF APPVER = 2
```

```
   ++MESSAGE Compiling Version 2
   ++ver2.bsi
```

```
++ELSE
```

```
   ++ERROR No APPVER defined!
```

```
++ENDIF
```

This illustrates the IF/ELIF/ELSE/ENDIF construct, used to select which ++INCLUDE file to use based on the defined APPVER. See + +ERROR statement. 

## **Example 3** 

```
++IFDEF SBX
```

A-Shell Reference 

Page 1306 

```
   ++PRAGMA SBX
```

```
   <retrieve parameters, SBX setup, etc.>
```

```
++ENDIF
```

This illustrates a simple way to allow a single source file to be compiled as either an SBX or a RUN file. The SBX symbol would need to be defined on the compiler command line, e.g. COMPIL MYPROG/X:2/C:SBX=1. 

## **Example 4** 

```
++IFDEF MODE_SBX
```

```
   ++PRAGMA SBX
```

```
   <retrieve parameters, SBX setup, etc.>
```

```
++ELIFDEF MODE_LIT
```

```
   ++PRAGMA FORCE_FSPEC SYS:MYPROG.LIT
```

```
   <command line parsing>
```

```
++ELSE
```

```
   <standard RUN setup>
```

```
++ENDIF
```

This illustrates an approach to generating either an SBX, LIT, or RUN from the same source file. The MODE_SBX or MODE_LIT symbols would need to be defined on the compiler command line, e.g. COMPIL MYPROG/X:2/C:MODE_SBX=1. 

## **See Also** 

- Avoiding Duplicate INCLUDES 

- COMPILER_VERSION Macro 

A-Shell Reference 

Page 1307 

## **History** 

- 2013 March, A Shell 6.1.1346:  Add ++ELIFDEF and ++ELIFMAP 

- 2011 November, A Shell 6.0.1240:  Increase maximum nesting levels for conditional compilation statements from 5 to 13. 

A-Shell Reference 

Page 1308 

## **++IF, ++ELIF** 

_Updated March 2017; see History_ 

## **++IF <constant expression>** 

**...** 

## **{++ELIF <constant expression>** 

## **...{++ELSE** 

**...** 

## **++ENDIF** 

The statement `++IF <constant expression>` evaluates the specified expression and compiles the following statements if the expression is equivalent to TRUE. Constant expressions are a subset of regular BASIC expressions, made up only of defined symbols (constants) and literals (i.e. no variables), and a limited set of pre-defined functions and operators: 

- All arithmetic operators (+, -, /, *, **, ^, MOD) 

- All logical operators (AND, OR, NOT) 

- Comparison operators (<, >, <=, >=, ==, <>, #) 

- All bitwise operators (AND, OR, NOT, NOR, XOR) 

- Arithmetic functions: INT(), FIX(), ABS(), MIN, MAX 

- Scientific functions: EXP(), SGN(), SQR(), FACT(), SIN(), COS(), TAN(), ATN(), ASN(), ACS(), DATN() 

- String functions: +, LEFT(), MID(), RIGHT(), [a, b], LEN(), INSTR(), ASC(), CHR(),  STR(), VAL(), RTRIM(), EDIT(), STRIP(), 

- PAD() 

A-Shell Reference 

Page 1309 

- File functions: lookup() 

`++ELIF <constant expression>` is equivalent to `++IF <constant expression>` except is only evaluated if the preceding ++IF or ++ELIF expression(s) were false. See example below. 

## **Examples** 

```
++IF APPVER > 3
    <statements>
++ENDIF
```

```
++IF SITE_NAME$ = "MARS"
    <statements>
++ELIF SITE_NAME$ = "JUPITER"
    <statements>
++ELIF SITE_NAME$ # LOCAL_PLANET$
    <statements>
++ENDIF
```

```
++IF (APPVER > 3) AND (LOOKUP("xyz.bsi") # 0)
    <statements>
++ELSE
    <statements>
```

A-Shell Reference 

Page 1310 

```
++ENDIF
```

Note that the above examples are only valid if APPVER, SITE_NAME$, and LOCAL_PLANET$ are DEFINE'd symbols. Variables would not be acceptable because their values are not constant from the compiler's perspective. The LOOKUP expression is acceptable as long as the filename is constant, i.e. a literal string as in the example, or a DEFINEd symbol. 

## **History** 

- 2017 March, A Shell 6.4.1546, compiler enhancement (797): maximum nesting levels for ++INCLUDE and ++IF conditions increased from 20 to 40. Improve messaging/recovery for the overflow condition. 

A-Shell Reference 

Page 1311 

## **++IFDEF, ++IFNDEF, ++ELIFDEF** 

_Updated October 2020_ 

## **++IFDEF <symbol>** 

**...** 

## **{++ELIFDEF <symbol>** 

**...}** 

## **++ENDIF** 

or 

## **++IFNDEF <symbol>** 

**...** 

## **{++ELIFDEF <symbol>** 

**...}** 

## **++ENDIF** 

These directives may be used to conditionally compile sections of code based on whether a specified symbol or structure name has been defined, via DEFINE , DEFTYPE, Compiler Symbol Definitions, DEFSTRUCT or DEFALIAS 

One typical use is to compile separate bits of code based on a prior symbol definition, for example: 

```
++ifdef VER_WIN
```

```
   MAP1 TEMPDIR,"c:\temp"
```

A-Shell Reference 

Page 1312 

```
++elifdef VER_Unix
```

```
   MAP1 TEMPDIR,"/tmp"
```

```
++else
```

```
   MAP TEMPDIR,"%TEMP%"
```

```
++endif
```

In the above example, the symbols VER_WIN or VER_Unix might have been defined via a DEFINE statement or via the /C switch passed to the compiler. 

Another typical use is to avoid redundantly processing a ++INCLUDE module that may have already been compiled. See Avoiding Duplicate INCLUDES. 

In the case where the symbol being tested is a DEFALIAS, the ++IFDEF directives test whether the symbol itself exists—i.e. the DEFALIAS was seen by the compiler—not whether the target label or function exists. For example: 

```
defalias fn'bonjour() = fn'hello()
```

```
++ifdef fn'bonjour()
```

```
    ++message fn'bonjour() alias was defined
```

```
++eliflbl fn'bonjour()
```

```
    ++message fn'hello() function (aliased to  fn'bonjour()) exists
```

```
++endif
```

A-Shell Reference 

Page 1313 

In other words, the ++IFDEF directives treat symbols created by DEFALIAS exactly like those created by DEFINE (without regard to the value of the definition), while the ++IFLBL directives treat DEFALIAS symbols based on the existence of the actual label referenced by the alias. 

A _++ifdef ... ++endif_ statement can be contained in a single source line, for example: 

```
++ifdef TEST_MODE : ? "Running in test mode" :  ++endif
```

Note however that this is intended to be an accommodation to simplify injection of test or debugging code into source code, and not as an embrace of the generalized concept of jamming multiple statements—especially not pragmas—onto one source line. Developers are encouraged to use the TRACE Statements for messaging that can be enabled at run time rather than compile time. 

## **History** 

- 2022 June, A Shell 6.5.1717, compiler edit 994:  ++IFDEF / ++IFNDEF now treat DEFALIAS definitions as they would symbols defined via DEFINE statements. 

- 2020 October, A Shell 6.5.1690, compiler edit 938: Add single-line support for testing and debugging. 

A-Shell Reference 

Page 1314 

## **++IFLBL, ++INFLBL, ++ELIFLBL** 

_Added April 2014_ 

## **++IFLBL <label>** 

**...** 

## **{++ELIFLBL <label>** 

**...}** 

## **++ENDIF** 

or 

## **++IFNLBL <label>** 

**...** 

## **{++ELIFLBL <label>** 

**...}** 

## **++ENDIF** 

These are analogous to the existing ++IFDEF, ++IFNDEF, and ++ELIFDEF statements, as well as ++IFMAP, ++IFNMAP and + +ELIFMAP, except that instead of referring to defined symbols or mapped variables, they refer to labels—used by GOTO and GOSUB—as well as procedure and function names. Note however that when the specified label is meant to refer to a function or procedure name, it must be terminated by an empty pair of parentheses. For example: 

## `++IFLBL MAIN` 

```
    ++MESSAGE The label MAIN is defined
```

A-Shell Reference 

Page 1315 

```
++ELIFLBL MAIN()
```

```
    ++MESSAGE The procedure MAIN() is defined
```

```
++ELIF fn'main()
```

```
    ++MESSAGE The function fn'main() is defined
```

```
++ENDIF
```

If the label referenced is actually an alias defined with DEFALIAS, then the alias is evaluated first—i.e. converted to the actual target label—before the ++IFLBL expression is evaluated. 

As with the ++IFDEF and ++IFMAP directives, the ++IFLBL directives operate on whether the referenced label has been seen yet by the compiler _in the current pass_ . Advance knowledge of function definitions gleaned from the preliminary (/p or /px) compilation pass does not affect ++IFLBL evaluation. 

Also note that labels, like variable names, are case sensitive, unless you compile with the /CI switch. 

## **See Also** 

- ++IFDEF, ++IFNDEF, ++ELIFDEF for notes on how DEFALIAS definitions are handled by both types of directives. 

## **History** 

- 2022 June, A Shell 6.4.1717, compiler edit 994:  ++IFLBL / ++IFNLBL now recognize DEFALIAS'd function and procedure labels, acting based on the existence of the target function / procedure and not the existence of the DEFALIAS definition. 

- 2014 April, A Shell 6.1.1382, compiler edit 655: add all three statements to A-Shell 

A-Shell Reference 

Page 1316 

## **++IFMAP, ++IFNMAP, ++ELIFMAP** 

## **++IFMAP <variable>** 

**...** 

## **{++ELIFMAP <label>** 

**...}** 

## **++ENDIF** 

or 

## **++IFNMAP <variable>** 

**...** 

## **{++ELIFMAP <variable>** 

**...}** 

## **++ENDIF** 

These conditionals may be used to conditionally compile sections of code based on whether a specified variable has been mapped. For example: 

```
++IFMAP WORK'VARS
```

```
    <work statements>
```

```
++ELIFMAP PLAY'VARS
```

```
    <play statements>
```

A-Shell Reference 

Page 1317 

```
++ELSE
```

```
    MAP1 WORK'VARS
        MAP2 JOB$,S,10
    MAP1 PLAY'VARS
        MAP2 GAME$,S,10
```

```
++ENDIF
```

Note that even when used within a ++INCLUDE file, or a procedure/function, the variable name evaluated by the conditional is treated as global, and thus will not work as expected if the variable you are referring to was defined privately or locally. For example, both of the following conditions will act based on whether the specified variable has been previously mapped globally, even though you may be expecting otherwise: 

```
++IFNMAP Module_Private_Var
```

```
    PRIVATE MAP1 Module_Private_Var,B,1
```

```
++ENDIF
```

```
Procedure Test()
```

```
    ++IFNMAP FLAG
```

```
        MAP1 FLAG,B,1
```

```
    ++ENDIF
```

```
...
```

```
EndProcedure
```

A-Shell Reference 

Page 1318 

This is because private variables (and local variables) are defined in separate areas relative to their scope, but the conditional statements have no good way of knowing which context you are referring to, and checking multiple contexts would introduce another layer of confusion, so they always refer to the global context. 

A-Shell Reference 

Page 1319 

## **AVOIDING DUPLICATE INCLUDES** 

One common use for conditional compilation statement is to prevent a common include file—which may be referenced by - multiple modules—from being processed more than once. You can also use ++INCLUDE'ONCE (see One Time ++INCLUDES) but that depends on consistent use through all the code which may reference an include file. Or you can use ++PRAGMA INCLUDE_GLOBAL_ONCE_ONLY, or the compiler switch /IGOO, either of which can eliminate the duplicate inclusion problem globally. 

Addressing the issue via conditionals within the include file itself may require more code but has the advantage of eliminating any dependencies on the calling modules or the compilation environment. A common approach is to define a special symbol whose purpose is to indicate that the module has already been included, and then add a conditional testing that symbol to control whether the rest of the module will be compiled.  For example: 

```
! MYMODULE.BSI
```

```
++IFNDEF INC_MYMODULE_BSI_
```

```
DEFINE INC_MYMODULE_BSI_ 1
```

```
    <contents of the module>
```

```
++ENDIF
```

In the above example, the first time the compiler sees the code, the symbol INC_MYMODULE_BSI_ will not have been defined, so it proceeds to process the module (including defining the symbol). On subsequent passes through this module, the symbol will have been defined, so the conditional will cause the module contents to be skipped. 

For modules that define symbols or structures, you may avoid the need to define an artificial symbol just to track whether the module has been compiled, by referencing one of the DEFINE or DEFSTRUCT symbols in the file, i.e 

A-Shell Reference 

Page 1320 

```
++IFNDEF ST_CUSTOMER
    ...
    DEFSTRUCT ST_CUSTOMER
        MAP2 ...
    ...
    ENDSTRUCT
    ...
++ENDIF
```

Similarly, if the module maps variables or defines any labels or functions/procedures, you can use `++IFNMAP <variable>` or `+ +INFNLBL <label>` , for example: 

```
++IFNMAP MYMODULE'VARS
    ...
    MAP1 MYMODULE'VARS
        MAP2 ...
    ...
++ENDIF
```

Note that in the above case, the variable referenced in the ++IFNMAP must have global (not private or local) scope. See + +IFMAP, ++IFNMAP, ++ELIFMAP . 

Or, to use the same idea but with a label or procedure name instead of a variable: 

```
++IFNLBL MyProc()
```

A-Shell Reference 

Page 1321 

```
    ...
```

```
Procedure MyProc()
```

```
   EndProcedure
```

```
    ...
```

```
++ENDIF
```

## **See Also** 

- COMPILER_VERSION Macro 

## **History** 

- 2014 March, A Shell 6.1.1382 (Compiler edit 655): Add ++IFLBL, ++ELIFLBL, ++IFNLBL 

A-Shell Reference 

Page 1322 

## **STRSIZ** 

## **STRSIZ <numeric constant>** 

The STRSIZ statement establishes the default length of string variables, applicable to any non-mapped string seen by the compiler from that point forward. The default STRSIZ value is 10. For example: 

## `STRSIZ 100` 

Traditionally it also set the limit on the length of SWITCH and CASE statement arguments, as well as any string arguments to functions and procedures that were not explicitly declared with an "as" clause. These rules were relaxed somewhat in A-Shell version 6.5; see History below for details. 

## **History** 

- 2018 January, A Shell 6.5.1624, compiler edit 845: 

- In the absence of an explicit "as s#" clause, string arguments to functions and procedures, as well as the return value of a 

- string function, now defaults to s0 (i.e. dynamic, unlimited) instead of the current STRSIZ. 

- STRSIZ 0 now sets the default string size to dynamic, as would be expected. Previously it set the default string size to a fixed 

- length of zero, i.e.  making it impossible for any unmapped string variable to hold a value. 

- SWITCH and CASE arguments are no longer limited by the current STRSIZ. Previously the compiler would complain about it 

- you were forced to actually change the STRSIZ to accommodate them, which was not very programmer-friendly. 

Note that all of the above are purely compiler adjustments, i.e. they change the resulting RUN programs, which are backward compatible as least as far back as 6.0. 

A-Shell Reference 

Page 1323 

## **++MESSAGE** 

## **++MESSAGE** _**message**_ 

The compiler directive ++MESSAGE message simply outputs a literal text message to the screen during compilation. This is generally useful in conjunction with Conditional Compilation (in which see Example 2) to give the programmer visual confirmation that the conditions are being interpreted as intended, or to warn of unusual or questionable environmental conditions. The remainder of the line following the keyword ++MESSAGE is output literally, as-is, to the screen, without any regard to punctuation or delimiters. Example: 

```
++MESSAGE This is an example of a compiler message
```

A-Shell Reference 

Page 1324 

## **++ERROR** 

## **++ERROR** _**message**_ 

This directive outputs a message (as with ++MESSAGE) but also generates a compiler error. Like ++MESSAGE, it is mainly used in conjunction with Conditional Compilation (in which see Example 2) to make sure that the programmer doesn't overlook and important problem. Example: 

```
++IF TARGET_PLATFORM = 1
```

```
   ++MESSAGE Compiling for platform Windows
```

## `++ELSE` 

```
   ++ERROR This program only supports Windows - must use /C:TARGET_PLATFORM=1
```

```
++ENDIF
```

A-Shell Reference 

Page 1325 

## **DEFSTRUCT** 

_Updated October 2017_ 

## **DEFSTRUCT <structname>** 

## **{optional MAP1 <varname1>}** 

## **MAP2 <fieldname1>** 

**...** 

## **MAPn <fieldnameN>** 

## **ENDSTRUCT** 

A DEFSTRUCT ... ENDSTRUCT block may be used to assign a type name to a set of MAP statements and then use that as if it was a standard variable type. This is similar to the combination of typedef and struct in the C language and is useful for many data standardization and encapsulation scenarios, including handling multiple copies of a record layout, or passing complex data as parameters. 

To define a structure, use the DEFSTRUCT and ENDSTRUCT keywords to enclose a set of MAP statements. For example: 

```
DEFSTRUCT ST'PHONE
```

```
    MAP2 DESCR,S,20     ! e.g. Front Office, Accounts Payable, etc.
```

```
    MAP2 TYPE,S,6       ! e.g. cell, bus, home, pager
```

```
    MAP2 XNUM
```

```
        MAP3 COUNTRYCODE,S,3
```

```
        MAP3 AREA,S,3
```

A-Shell Reference 

Page 1326 

```
        MAP3 NUMBER,S,10
```

```
ENDSTRUCT
```

```
DEFSTRUCT ST_CUS
MAP1 CUSTREC
    MAP2 ID,S,6
    MAP2 NAME,S,30
    MAP2 PHNUM(5), ST'PHONE     ! array of ST'PHONE structures
    MAP2 BALANCE,F
```

```
ENDSTRUCT
```

`MAP1 SALE, ST_CUS               ! SALE is an instance of structure ST_CUS MAP1 PROSPECT(10), ST_CUS       ! PROSPECT() is an array of struct ST_CUS DIMX CLIENTS(N),ST_CUS          !` Dynamic array of structures `MAP1 PH$, ST'PHONE              ! PH$ is an instance of struct ST'PHONE` 

```
...
```

```
PH$ = FN'GETPHONENUM$(SALE,"cell")  ! retrieve cell # from customer SALE
```

```
FUNCTION FN'GETPHONENUM$(cus as ST_CUS, type$ as S6) as ST'PHONE
```

```
    map1 locals
```

A-Shell Reference 

Page 1327 

```
        map2 i,f
```

```
    ! locate phone number by matching type
    for i = 1 to 5
        if cus.PHNUM.TYPE(i) = type$ then
            FN'GETPHONENUM$ = cus.PHNUM(i)
        endif
    next i
```

```
ENDIF
```

The above example illustrates defining two structures, ST_PHONE and ST_CUS. (Structures have the same naming flexibility as other variables, but it seems like a useful convention to prefix their formal names with ST_ to avoid confusion with variable names.) The ST_CUS structure contains an array of ST_PHONE structures, illustrating that they can be nested. The example then defines an instance of the ST_CUS structure called SALE, a fixed array of instances call PROSPECT(), a dynamic array called CLIENTS(), and an instance of the ST_PHONE structure called PH$. 

Note that the MAP1 CUSTREC line within the DEFSTRUCT ST_CUS definition is not exactly a field within the structure, but instead creates an additional set of traditional (non-structure) map statements for the contents of the structure. In other words, without even declaring an instance of the ST_CUS structure, the map statements within it can still be accessed in the traditional way. This makes it easy to convert traditional sets of MAP statements used for record layouts into structures, without requiring any changes to existing code. Without the MAP1 element, the structure can only be used by declaring a mapped instance of it. 

The following shows the equivalent (fully expanded) form of MAP1 SALE, ST_CUS : 

```
MAP1 SALE
```

```
    MAP2 SALE.ID,S,6
    MAP2 SALE.NAME,S,30
    MAP2 SALE.PHNUM(5)
```

A-Shell Reference 

Page 1328 

```
        MAP3 SALE.PHNUM.DESCR,S,20
        MAP3 SALE.PHNUM.TYPE,S,6
        MAP3 SALE.PHNUM.XNUM
```

```
            MAP4 SALE.PHNUM.COUNTRYCODE,S,3
```

```
            MAP4 SALE.PHNUM.AREA,S,3
            MAP4 SALE.PHNUM.NUMBER,S,10
```

Note the use of the period to separate the names of structure instances from the fields in the structure. 

Also note that the syntax for accessing individual members of dynamic arrays of structures is different; see Dynamic Array of Structures for details. 

**Warning:** initial values for individual mapped fields within a structure definition are allowed for mapped instances of the structure, but not for DIMX; see Dynamic Array of Structures. Prior to compiler edit 521, such initial values led to runtime errors; - " " after that the compiler just ignored the initial values. See the A Shell forum discussion MAP initializers in DEFSTRUCT. 

So, for example, you might read the structure from a disk file and then print out the ID field as follows: 

```
READ #CH, SALE
```

```
PRINT "Customer ID = ";SALE.ID
```

Defined structure names may be used similarly to the unformatted type X, and passed to functions and procedures. In the example above, the function FN'GETPHONENUM$() takes a ST_CUS structure as an argument, and returns a ST'PHONE structure. 

Defined structure names may end in $, but the $ is dropped when referencing the individual fields.  For example: 

```
defstruct ST_CUS
```

```
    map2 id,s,10
```

A-Shell Reference 

Page 1329 

```
    map2 name$,s,30
```

```
endstruct
```

```
map1 cus$,ST_CUS         ! structure names may end in $
map1 tmpcus,ST_CUS       ! (or not)
```

```
! use the $ when referring to the structure as a whole
tmpcus = cus$
```

```
! drop the $ from structure name when referring to individual fields
cus.id = "A12345"
```

```
! field names may end in $, just like any other variable
```

```
cus.name$ = "Agamemnon"
```

(Note that because function names must contain a $ suffix if the function returns an S or X value, and since structures are essentially a special variation of the X type, any function returning a structure must have a $ on the end of the name.) 

The formal parameter "cus as ST_CUS" essentially creates a set of local map statements which are identical to the ones shown above for SALE, except with "SALE." replaced by "cus." Otherwise, in terms of parameter passing, the "cus as ST_CUS" parameter is equivalent to "cus as X246". (Previously, this is how you had to pass the structure, and then you had to repeat the MAP2-MAP9 levels of the structure map statements within the Function. So the new method doesn't exactly add any new capability, but it makes using structures and especially passing them between routines much cleaner and easier. 

A-Shell Reference 

Page 1330 

One way to help clarify the effect of structure definitions is to compile with the /L switch, in which case the expanded forms of the structures will display in the LSX file. 

## **See Also** 

- Dynamic Array of Structures 

- A-Shell forum discussion "DEFSTRUCT newbie question." 

## **History** 

- 2017 July, A Shell 6.4.1552/6.5.1603, compiler edit 828:  add ability to include an initial MAP1 within the DEFSTRUCT; see comments. 

- 2010 July, A Shell 5.1.1187, Compiler edit 456: reserved words are now allowed for field names within a DEFSTRUCT. For example: 

```
DEFSTRUCT ST_TIMEDATE
```

```
   MAP2 TIME,B,4
```

```
   MAP2 DATE,B,4
```

```
ENDSTRUCT
```

Normally TIME and DATE would be disallowed since they are reserved words, but since they get appended to the structure instance name before really being used, there is no conflict here. 

2008 September, A-Shell 5.1.1124:  Initial values and overlays are now supported within DEFSTRUCT / ENDSTRUCT. 

- 2008 September, A Shell 5.1.1123: DEFSTRUCT now allows upper and lower case (or mixed case) formal structure names, and STATIC and PRIVATE instances of structures now allowed. Note that DIMX does not support structures. 

A-Shell Reference 

Page 1331 

## **FUNCTIONS** 

See the topics listed below. 

## **Subtopics** 

- System-Defined Functions 

- User-Defined Functions 

- Tab Functions 

- SOSFUNC Library Functions 

A-Shell Reference 

Page 1332 

## **- SYSTEM DEFINED FUNCTIONS** 

The following sections of the documentation show A-Shell's various functions grouped by category—String Functions, Trig Functions, etc. Below is a table showing all of the functions in alphabetical order. 

Note that although all functions require a parenthesized argument list (even if empty), the function names themselves are effectively ASB Keywords in that they cannot be used as variable names. 

|**Name**|**Description**|**Type/Category**|
|---|---|---|
|ABS(x)|Returns absolute value of x.|Numeric|
|ACS(x)|Arccosine of x.|Trigonometric|
|.ARG_PASSED()|Indicates whether the specified argument was passed to the current SBX, function, or<br>procedure.|Other / Misc|
|.ARGSIZ()|Returns the size of the specified argument passed to the current SBX, function, or procedure.|Other / Misc|
|.ARGTYP()|Returns the type of the specified argument passed to the current SBX, function, or procedure.|Other / Misc|
|.ARGTYP_READONL<br>Y()|Indicates whether the specified argument is read-only.|Other / Misc|
|ASC(a$)|Returns the numeric value of the first character of a$.|String|



A-Shell Reference 

Page 1333 

|ell Reference||Page 1333|
|---|---|---|
|ASN(x)|Arcsine of x.|Trigonometric|
|ATN(x)|Arctangent of x.|Trigonometric|
|AUTOCAP$(a$)|Intelligently capitalizes a specified string.|String|
|.BEFORE()|Specify insertion position inMLIST<br>.||
|CHR$(x)|Returns the OEM or Latin1 character of specified character.|String|
|COS(x)|Cosine of x.|Trigonometric|
|DATN(y,x)|Double arctangent.|Trigonometric|
|.DYNOFFSET()|Indirect deferred version.|Dynamic Structure|
|.DYNOFFSIZ()|Dynamic structure version of .OFFSIZ$().|Dynamic Structure|
|EDIT$()|Returns a modified version of a string based on specified options.|String|
|EOF()|Returns end-of-file status for a file channel.|File|
|ERF()|Returns error/status information about the last operation on an ISAM file.|File|



A-Shell Reference 

Page 1334 

|ell Reference||Page 1334|
|---|---|---|
|ERR()|Used within an error trap to return information relating to a ASB error that has occurred.|Other / Misc|
|ERRMSG()|Returns the message associated with ASB error x.|Other / Misc|
|EXP(x)|Returns the constant e raised to the power x.|Numeric|
|.EXTENT()|Returns the "extent" of the specified array or collection.|Other / Misc|
|FACT(x)|Returns the factorial of x.|Numeric|
|FILL$()|Returns a string consisting of a string repeated until it reaches specified length.|String|
|FIX(x)|Returns the integer part of the floating point value x.|Numeric|
|.FSTAT()|Returns the file status for the last ISAM-A operation on a specified channel.|File|
|GETKEY()|Inputs and returns the ASCII decimal value of a single character.|Input|
|IFE(), IFE$()|Ternary function; returns one of two parameters based on value of first.|String / Numeric|
|IFELSE(), IFELSE$()|Ternary function; returns one of two parameters based on condition.|String / Numeric|
|INSTR()|Returns position of first occurrence of a specified string.|String|



A-Shell Reference 

Page 1335 

|ell Reference||Page 1335|
|---|---|---|
|.INSTRR()|Same as INSTR() but works in reverse direction.|String|
|INT(x)|Returns the largest integer less than or equal to x.|Numeric|
|.ISBOUND()|Returns TRUE if the specified variable is a DYNSTRUCT that has been bound to a defined<br>structure.|Dynamic Structure|
|.ISDEF()|Indirect deferred version.|Dynamic Structure|
|.ISEMPTY()|Returns yes/no if the string or unformatted expression is "empty.|String|
|.ISNULL()|Tests for the .NULL condition.|Other|
|.KEY()|Returns the key associated with the element currently indexed by the iterator.|Other|
|LCS$(a$)|Returns string a$ folded to lower case.|String|
|LEFT$()|Returns leftmost x characters of string a$.|String|
|LEN()|Returns length of string a$.|String / Numeric|
|.LINENO()|Returns current line number for sequential output files.|File|
|LOG(x)|Returns the natural (base e) log of x.|Numeric|



A-Shell Reference 

Page 1336 

|ell Reference||Page 1336|
|---|---|---|
|LOG10(x)|Returns the decimal logarithm of x.|Numeric|
|LOOKUP()|Returns the size of the specified file in blocks.|File|
|LSTRIP$(a$)|Returns the string a$ with the leading blanks and TABs removed. .|String|
|MEM()|Returns information about available memory and resources.|Other|
|MID$(a$,x,y)|Returns substring of a$, starting in position x and extending y characters or until end.|String|
|NUMEXPR()|Treats expression as numeric.|String / Numeric|
|.NEXT()|Advances the iterator, returning the associated key or .null if no more.|Other|
|ODTIM$()|Outputs the specified date and/or time according to the formatting flags.|String|
|.OFFSET()|Returns the offset to the specified member variable within the specified structure.|Compiler|
|.OFFSIZ$()|Returns the combination of the specified structure member's offset and size.|Compiler|
|PAD$()|Returns string truncated, or padded with trailing blanks, to the specified length.|String|
|.PAGENO()|Returns current page number for sequential output files.|File|



A-Shell Reference 

Page 1337 

|ell Reference||Page 1337|
|---|---|---|
|PYFUNC()|Provides a means to call an external function written in Python version 3.|Other / Misc|
|.RECNO()|Returns the current record number for the specified random, ISAM, or ISAM-A file channel.|File|
|.RECSIZ()|Returns the record size for the specified open file channel.|File|
|.REF()|Return a reference to iterator location inMLIST<br>.||
|RIGHT$(a$,x)|Returns the rightmost x characters of string a$. Equivalent to a$[-x,-1].|String|
|RND(x)|Returns a random number.|Numeric|
|RND2()|Enhanced version of RND(x).|Numeric|
|RTRIM$(a$)|Returns string a$ with trailing spaces removed.|String|
|SGN(x)|Returns the sign of x: -1 if x < 0, 0 if x = 0, 1 if x > 0.|Numeric|
|SIN(x)|Sine of x.|Trigonometric|
|.SIZEOF()|Evaluates at compile-time to the size in bytes of the specified variable or defined structure.|Compiler|
|SPACE$(x)|Returns a string of x spaces.|String|



A-Shell Reference 

Page 1338 

|ell Reference||Page 1338|
|---|---|---|
|SQR(x)|Returns the square root of x.|Numeric|
|SRND2()|Initializes the RND2() random number generator.|Numeric|
|STR$()|Converts a numeric value or expression to string. .|String|
|STREXPR$()|Treats the expression argument as a string.|String|
|STRIP$(a$)|Returns the string a$ with the trailing spaces and tabs removed.|String|
|TAN(x)|Tangent of x.|Trigonometric|
|TRIM$(a$)|Returns the string a$ with the leading spaces and tabs removed.|String|
|UCS$(a$)|Returns string a$ folded to upper case.|String|
|VAL()<br>, VAL$()|Returns the decimal value of a string.|String / Numeric|
|.VALX()|Extended version of VAL.|String|
|XFUNC(), XFUNC$()|Executes an external SBX routine.|Other / Misc|



A-Shell Reference 

Page 1339 

## **COMPILER FUNCTIONS** 

A-Shell Reference 

Page 1340 

## **.OFFSIZ$()** 

_Added April 2013_ 

## **.OFFSIZ$(struct.member)** 

This is a variation of the ..OFFSET() function which returns the combination of the specified structure member's offset and size, as a string formatted as "offset~size". While the combination of the two values in a string may seem unusual, since the offset and size are often used together, the combined format eliminates the need to specify the struct.member name twice, which invites discrepancy, and lends itself to use in runtime functions that may parse out the two values and combine them with other information. 

Here are some examples using the structure given: 

- `? "Offset~size of FLD1 in ST_1: "; .OFFSIZ$(ST_1.FLD1)   ! "1~10"` 

- `? "Offset~size of FLD2 in VAR : "; .OFFSIZ$(VAR.FLD2)    ! "11~13"` 

- `? "Offset~size of FLD3 in VX(): "; .OFFSIZ$(VX().FLD3()) ! "24~6"` 

.OFFSIZ$() is particularly handy in building XTREE coldefs, e.g.: 

```
coldef$ += .OFFSIZ$(ST_1.FLD1) + "~Field~S~~"   ! 1~10~Field 1~S~~
```

or, using a hypothetical function to build the entire definition for an XTREE column: 

```
coldef$ += Fn'Coldef$(.OFFSIZ$(ST_1.FLD1), title$, cformat$, option$)
```

## **History** 

- 2013 April, A Shell 6.1.1350:  Function added to A-Shell 

A-Shell Reference 

Page 1341 

## **.OFFSET()** 

_Added April 2013_ 

## **.OFFSET(struct.member)** 

Similar to .SIZEOF() except that it returns the offset to the specified member variable within the specified structure, starting from 1, rather than the size of the variable, and it only works on fields within structures. Also, in the case of arrays, .OFFSET() only returns the offset to the base of the array, and doesn't actually allow the use of subscripts. The specified structure name can either be a defined structure name, or a MAP'd or DIMX'd instance of it. For example: 

## `DEFSTRUCT ST_1` 

```
    MAP2 FLD1,S,10
```

```
    MAP2 FLD2,S,13
    MAP3 FLD3(4),F
```

## `ENDSTRUCT` 

```
MAP1 VAR,ST_1
```

```
DIMX VX(10),ST_1
```

For example: 

- `? "Offset of FLD1 in ST_1: "; .OFFSET(ST_1.FLD1)   ! 1` 

- `? "Offset of FLD2 in VAR : "; .OFFSET(VAR.FLD2)    ! 11` 

- `? "Offset of FLD3 in VX(): "; .OFFSET(VX().FLD3()) ! 24` 

Note the empty parentheses () in the third example. 

## **History** 

A-Shell Reference 

Page 1342 

- 2013 April, A Shell 6.1.1350:  Function added to A-Shell 

A-Shell Reference 

Page 1343 

## **.SIZEOF()** 

_Updated May 2019; see History_ 

## **.SIZEOF(variable)** 

.SIZEOF() evaluates at compile-time to the size in bytes of the specified variable or defined structure, which must have been previously defined with a MAP or DEFSTRUCT statement. For example: 

```
defstruct ST_REC
```

```
    map2 field1,s,10
```

```
    map2 field2,f
```

```
endstruct
```

```
map1 price,f,8
```

```
map1 vs$,s,0
```

```
map1 rec, ST_REC
```

```
map1 rec'copy, x, sizeof(ST_REC) ! rec'copy, x, 16
```

```
dimx xary(5), x, .sizeof(rec)    ! xary(5), x, 16
map1 fbytes(.sizeof(price)),b,1  ! fbytes(8),b,1
```

```
map1 ary(10)
```

```
    map2 foo,f
    map2 bar,i,2
print .sizeof(ST_REC)         ! 16
print .sizeof(rec)            ! 16
print .sizeof(rec'copy)       ! 16
```

A-Shell Reference 

Page 1344 

```
print .sizeof(ST_REC.field2)  ! 6
print .sizeof(rec.field1)     ! 10
print .sizeof(vs$)            ! 16 (see comments)
print .sizeof(ary(1))         ! 8
print .sizeof(foo(1))         ! 6
```

## **Comments** 

Although most of the examples above show use of the .SIZEOF() compiler function in a PRINT statement, where it might be confused with a run-time function, in all cases, the function is evaluated by the compiler. It is converted to a fixed integer at the point it is first encountered, and thus may be used anywhere a literal integer is otherwise required, such as when declaring the size of a variable or the number of elements in an array. 

The .SIZEOF() function may take as an argument the name of a defined structure (ST_REC), the name of a field within the defined structure (ST_REC.field2), the name of an ordinary mapped variable (price), an instance of a structure (rec), a field within an instance of a structure (rec.field1), or an array element (ary(1) or foo(1)). 

Variable length S and X variables, such as vs$ in the example above, always return a size of 16; this is the internal size of the descriptor for the variable, not the size of the data held by the variable, which changes at runtime and which can be accessed via the run-time LEN() function. 

Use of .SIZEOF() when defining related variables is a good technique for avoiding inadvertent errors that arise when you later change the size of one of the variables and forget to change the other. Another way to reduce that risk is to use the ST_REC and ary(1) in the example above. 

Because of the commonality of the .SIZEOF() compiler function across many languages, SIZEOF() (without the dot) is treated as equivalent to .SIZEOF() (with the dot). That is not normally the case with Dot Functions, where the dot was used to avoid conflicts with user array variables or procedures of the same name. 

## **History** 

A-Shell Reference 

Page 1345 

- 2019 May, A Shell 6.5.1661: .SIZEOF() now supports DEFTYPE names, e.g. `.SIZEOF(BOOLEAN)` . 

A-Shell Reference 

Page 1346 

## **NUMERIC FUNCTIONS** 

_Updated February 2023; see History_ 

## These functions all return numeric values, although some may operate on string arguments. 

|**Function**|**Description**|
|---|---|
|ABS(x)|Returns absolute value of_x_.|
|EXP(x)|Returns the constant e (2.718218285) raised to the power_x_.|
|FACT(x)|Returns the factorial of_x_.|
|FIX(x)|Returns the integer part of the floating point value_x_. See_History_.|
|IFE()|Ternary function; returns one of two parameters based on value of first.|
|IFELSE()|Ternary function; returns one of two parameters based on condition.|
|INT(x)|Returns the largest integer less than or equal to_x_.FIX()andINT()are same for positive numbers, but<br>differ for negative numbers. See_History_.|
|LEN(a$)|Returns the length of a$. See inString Functions<br>.|
|LOG(x)|Returns the natural (base e) log of_x_.|
|LOG10(x)|Returns the decimal logarithm of_x_.|



A-Shell Reference 

Page 1347 

|ell Reference||
|---|---|
|NUMEXPR()|See inString Functions<br>.|
|RND(x)|Returns a random number.|
|RND2()|Enhanced version ofRND(X).|
|SRND2()|Initializes theRND(X)generator.|
|SGN(x)|Returns the sign of_x_: -1 if_x_< 0, 0 if_x_= 0, 1 if_x_> 0.|
|SQR(x)|Returns the square root of_x_.|
|VAL()|Returns the decimal value of a string.|



## **History** 

- 2025 January, A Shell 7.0.1767.0:  The fudge factor described above for INT() and FIX() may now be completely disabled by calling  MX_ROUND with a factor of -1. 

- 2023 February, A Shell 6.5.1724: INT() and FIX() update. When FPROUND is not set, these functions now apply a fudge factor of .0000005 (one tenth of the standard FPROUND factor). This minimizes the problem illustrated whereby an expression like INT(140.4*100) might result in 14039 rather than 14040. The discrepancy is caused by the inherent imprecision of binary floating point representation of decimal fractions—e.g., 14039.999999975 instead of 14040.0). 

There are various other ways to deal with this issue, including setting the FPROUND option, but the issue continues to catch programmers by surprise; this automatic adjustment should minimize that problem. But note that it only works for numbers up to about 8 significant digits, after which the tiny fudge factor becomes too small to matter. If you regularly work with larger 

A-Shell Reference 

Page 1348 

numbers and aren't explicitly dealing with rounding within the application, you may want to set your rounding factor somewhat higher. See "Rounding of Floating Point Variables" in the A-Shell reference for more details.. 

- 2016 July, A Shell 6.3.1517: Add second random number generator, RND2 and SRND2. 

## **Subtopics** 

- Random Number Generators 

A-Shell Reference 

Page 1349 

## **RANDOM NUMBER GENERATORS** 

A-Shell supports two pseudorandom number generation algorithms, exposed via the following three functions: 

## **RND(seedop)** 

## **RND2()** 

## **SRND2(seed {,ubound, lbound {,stream}})** 

RND() has been included in A-Shell since version 1.0, and is semantically compatible with the AMOS function of the same name. That is to say, it is source and run time compatible, but doesn't generate the same sequence of output values as the AMOS version. Based on the standard C library functions _rand()_ and _srand()_ , which are in turn based on different underlying algorithms on different operating system platforms, its output varies across platforms and possibly even versions of the same platform. Depending on the _seedop_ parameter, RND() either initializes the generator or returns the next value. The values returned are always in the range of 0 to 1. 

RND2() was introduced in A-Shell version 6.3.1517, and is not in any way compatible with the AMOS version. However, because it is implemented directly within A-Shell, it is guaranteed to be stable and compatible across all A-Shell platforms and versions going forward, which is important for certain encryption and testing applications. It is also offers some other advantages, described below. RND2() takes no parameters; it only returns the next value, based on the initialization/state. The values returned may be fractional in the range of 0 to 1, or they may be integers in an arbitrarily specified range, depending on the initialization parameters. 

SRND2() initializes the RND2() generator. 

## **Parameters** 

_seedop_ (32 bit integer value) 

If >= 0, causes the function to return the next value in the sequence. If < 0, acts as the _seed_ to initialize the RND() generator. You can also establish a randomly selected _seed_ by executing the RANDOMIZE statement. 

_seed_ (32 bit integer value) 

A-Shell Reference 

Page 1350 

establishes the initial state of the RND2() generator. A _seed_ value of 0, combined with a _stream_ value of -1, results in a randomly selected _seed_ —equivalent to executing the RANDOMIZE statement. 

_ubound, lbound_ (32 bit signed integer value) 

optionally determine the range of returned values. If omitted or equal to each other, the range of returned values will be from 0 to 1 (fractional) as with the traditional RND(x). Otherwise, the returned values will be integers, uniformly distributed across the range specified by _lbound_ and _ubound_ , inclusive. 

_stream_ (32 bit signed integer value) 

optionally selects one of 2^32 “streams” or sequences within a given _seed_ . Combining 2^32 streams with 2^32 seeds increases the universe of possible sets/sequences of random values dramatically. Note that for a given _seed_ , different streams are guaranteed never to overlap each other. The default _stream_ is 0, which, unlike the case with _seed_ , does **not** result in a randomly selected stream. A _stream_ value of -1 is used in conjunction with _seed_ = 0 to set a random seed. 

## **Comments** 

Even though SRND2() doesn't return any value, because it is a function, it needs to be used in an expression, typically a dummy assignment statement, e.g. 

```
x = SRND2(seed,ubound,lbound)   ! use a dummy assignment to invoke SRND2()
```

If RND2() is called without first initializing the generator with SRND2(), it will be automatically initialized as if `SRND2(0,0,1,-1)` had been called, i.e. a random _seed_ will be selected and the range of returned values will be from 0 to 1 (fractional). Note that random seed initialization is relative to the A-Shell session, not just to the current program; so a program that fails to initialize the generator is somewhat at the mercy of whatever state previous programs left the generator in. 

The RANDOMIZE statement initializes both generators to a non-deterministically selected psuedorandom _seed_ and, in the case of RND2(), _stream_ . It does not affect previously established _lbound_ and _ubound_ values. 

Aside from stability and uniformity, the RND2() generator offers some additional benefits: 

• The _lbound,ubound_ feature makes it much easier and faster to generate integers in a particular range, which is probably the most common usage. It also eliminates the floating point rounding problem which might otherwise result in a fractional value 

A-Shell Reference 

Page 1351 

very close to 1 acting as equivalent to 1 in an expression, which in turn could cause program logic intending to generate values in a range of 1 to N—e.g. `INT(RND(1)*N)+1` —to generate a value N+1, leading to application errors. 

- RND2() is much less predictable than RND(), making it superior for cryptographic uses. 

- RND2() has a wider, more granular range of output values, especially compared to the Windows implementation of RND() 

- which is limited to 16 bits. 

- Splitting it into two functions, one to initialize and one to generate, reduces the confusion inherent in the multiple operations 

- of RND(). 

- RND2() is based on the PCG family of random number generators; see www.pcg random.org for more information. 

## **History** 

- 2016 July, A Shell 6.3.1517: RND2 and SRND2 functions added to A-Shell. Note that in earlier versions of A-Shell 

A-Shell Reference 

Page 1352 

## **TRIGONOMETRIC FUNCTIONS** 

_Updated December 2023, see History_ 

|**Function**|**Description**|
|---|---|
|SIN(x)|Sine of_x_|
|COS(x)|Cosine of_x_|
|TAN(x)|Tangent of_x_|
|ATN(x)|Arctangent of_x_|
|ASN(x)|Arcsine of_x_|
|ACS(x)|Arccosine of_x_|
|DATN(y,x)|Double arctangent|



## **History** 

- 2023 December, A Shell 7.0.1752: DATN (double arctangent function) is no longer treated as a keyword if it appears in a MAP statement first. 

A-Shell Reference 

Page 1353 

- 2023 February, A Shell 6.5.1725: add support for the DATN function ("double arctangent", aka "four-quadrant inverse tangent") which was somehow overlooked during the original implementation of the other trigonometric functions supported in AlphaBASIC, and whose absence was creating a nuisance for a very select set of mathematically-inclined A-Shell developers. 

Note that although DATN(y,x) may seem like a typo, it actually makes more sense than DATN(x,y) as it matches the geometric interpretation, i.e. DATN(y,x) is the angle between the x-axis and the line passing through the origin (0,0) and the point (x,y). Thanks to Bob Fowler for pointing this out. 

Also note that for full backwards compatibility with AlphaBASIC, the function is recognized in all variations of the compiler (OCMPIL, COMPIL, COMPLP). However, since it requires A-Shell runtime 6.5.1725.0+, by default the compiler will set the minimum runtime version in the RUN header, which in the case of OCMPIL changes the header signature from &hF002 to &hF202 (use VERSYS to display), making the RUN file incompatible with AMOS. If, for some reason you need to create an AMOScompatible RUN file containing the DATN(x,y) function, add the /F1 switch to the compilation to disable the minimum version information in the RUN header. 

A-Shell Reference 

Page 1354 

## **STRING FUNCTIONS** 

_Updated May 2023_ 

"True string functions" are those that return string values. Such functions can usually be specified with or without a trailing $ (i.e., CHR(x) or CHR$(x); we use the trailing $ below to emphasize that the function acts like a string expression. Also included here are functions that return numeric values (and thus are really numeric functions) but whose purpose is closely tied to string handling, such as LEN(). 

Note that for the functions below without links to further description, _a$_ is used to indicate a string, while _x_ and _y_ are used for numeric arguments; in all cases those arguments could be either variables or expressions. For the linked functions, follow the links for details on the argument lists. 

|**Function**|**Description**|
|---|---|
|ASC(a$)|Returns the numeric value of the first character of a$.|
|AUTOCAP$ (a$)|Intelligently capitalizes a$. The A-Shell implementation of this is rather minimal; users in need of more<br>"intelligent" capitalization should refer toXcall XFOLD<br>.|
|CHR$(x)|Returns the OEM or Latin1 character—depending on the current character set—corresponding to the<br>value x.|
|EDIT$()|Returns a modified version of a string based on specified options.|
|FILL$()|Returns a string consisting of a string repeated until it reaches specified length.|
|IFE$()|Ternary function; returns one of two parameters based on value of first.|



A-Shell Reference 

Page 1355 

|ell Reference|Pag|
|---|---|
|IFELSE$()|Ternary function; returns one of two parameters based on condition.|
|INSTR()|Returns position of first occurrence of a specified string.|
|.INSTRR()|Same as INSTR() but works in reverse direction.|
|.ISEMPTY()|Returns yes/no if the string or unformatted expression is "empty.|
|LCS$(a$)|Returns string a$ folded to lower case.|
|LEFT$(a$,x)|Returns leftmost x characters of string a$. Equivalent to a$[1,x].|
|LEN(a$)|Returns length of string a$, as determined by the first null byte or the physical mapped length, whichever<br>is smaller. For type X, it is always the physical mapped length, since null bytes do not act as terminators<br>for type X. For numeric types, the returned length will be based on the string representation of the<br>numeric value.|
|LSTRIP$(a$)|Returns the string a$ with the leading blanks and TABs removed. Also see TRIM$().|
|MID$(a$,x,y)|Returns substring of a$, starting in position x and extending y characters or until end. Equivalent to<br>substring syntax a$[x;y].|
|NUMEXPR()|Treats expression as numeric.|
|ODTIM$()|Outputs the specified date and/or time according to the formatting flags.|



A-Shell Reference 

Page 1356 

|ell Reference|Pag|
|---|---|
|||
|PAD$()|Returns string truncated, or padded with trailing blanks, to the specified length.|
|RIGHT$ (a$,x)|Returns the rightmost x characters of string a$. Equivalent to a$[-x,-1].|
|RTRIM$(a$)|Returns string a$ with trailing spaces removed. Also seeSTRIP$()andTRIM$()below.|
|SPACE$(x)|Returns a string of x spaces. Also seeFILL$()<br>.|
|STREXPR$()|Treats the expression argument as a string.|
|STRIP$(a$)|Returns the string a$ with the trailing spaces and tabs removed.|
|STR$()|Convert a numeric value or expression to string. Also see RTRIM$(a$) above andSTRIP<br>.|
|TRIM$(a$)|Returns the string a$ with the leading spaces and tabs removed; equivalent to the combination of STRIP$ (a$) and LSTRIP$(a$). Also see the subroutineTRIM<br>.|
|UCS$(a$)|Returns string a$ folded to upper case.|
|VAL$()|Returns the decimal value of a string.|



A-Shell Reference 

Page 1357 

.VALX() Extended version of VAL. 

## **History** 

- 2024 May, A Shell 7.0.1757: Refinement to the SPACE() function: remove the 64K limitation on the length of the returned string. SPACE(n) now maps to FILL$(chr(32),n); its theoretical maximum length is 2GB. 

- 2022 March, A Shell 6.5.1713, compiler edit 977:  Add TRIM. 

- 2022 March, A Shell 6.5.1712, compiler edit 971:  Add LSTRIP. 

- 2021 June, A Shell 6.5.1704, compiler edit 947:  all standard string functions now support the optional $ suffix on the name (e.g. STR(x) or STR$(x).) The following functions did not previously support the optional $ suffix: AUTOCAP$(a$), LCS$(a$), ODTIM$(), RTRIM$(a$), UCS$(a$) 

A-Shell Reference 

Page 1358 

## **EDIT$()** 

_Updated February 2019; see History_ 

## **EDIT$(expr$, flags)** 

The EDIT$() function modifies the specified string expression _expr_ according to one or more of the following _flags_ as defined in ASHINC:ASHELL.DEF. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|EDITF_SPTB|&h0002|remove spaces and tabs|
|EDITF_CTLS|&h0004|remove chr(127) & chr(0)-chr(31) except TAB|
|EDITF_SPTBL|&h0008|remove leading spaces and tabs|
|EDITF_SPTB1|&h0010|shrink spaces & tabs to one space|
|EDITF_SPTBR|&h0020|remove trailing spaces and tabs|
|EDITF_UNQT|&h0040|unquote (and reduce "" to "). EDITF_UNQT performs two operations: 1) if the<br>first and last character, after any other processing (such as removal of<br>leading/trailing spaces and tabs) are both quotes ("), then are removed.  2) Any<br>remaining double quotes ("") which are not preceded by a regular quotes are<br>reduced to regular quotes ("), unless the string has been reduced to a single pair<br>of quotes ("").|



A-Shell Reference 

Page 1359 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|EDITF_EXQT|&h0080|limits action to outside matched quotes. Exemption for quoted strings allows for<br>multiple quoted subsections. This works well with JSON documents, which may<br>contain many individually quoted strings, yet it may be convenient to remove all<br>the whitespace not within those quoted strings.|
|EDITF_Z|&h0100|applied after any other flags, and converts a string containing just "0" to "".|
|EDITF_SPTBZ|&h0128|EDITF_SPTBZ is a combination of EDITF_SPTBR, EDITF_SPTBL and EDITF_Z; it<br>first removes leading and trailing spaces and tabs, and if the result is just "0",<br>then removes it too, returning "".|



## **Examples** 

```
S$                       After EDIT$(S$,EDITF_SPTB+EDITF_EXQT)
```

```
---------------------    ------------------------------------------
```

```
"name" : "v1 v2"         "name":"v1 v2"
"name" : v1 v2           "name":v1v2
"name : v1 v2" ]         "name : v1 v2"]
"6"" ruler"              "6"" ruler"
S$                       After EDIT$(S$,EDITF_UNQT)
```

```
---------------------    ------------------------------------------
```

A-Shell Reference 

Page 1360 

```
"6"" ruler"              6" ruler
"6"" ruler":$1.99        "6"" ruler":$1.99
```

In the last example above, the outer quotes were not removed because they didn't completely enclose the string, and the "" was not reduced to " because it followed a " character. 

## **History** 

- 2019 February, A Shell 6.5.1656: Add flags EDITF_Z and EDOTF_SPTBZ. These are mainly useful in mixed number/string situations where the distinction between a null strings, strings containing just blanks, strings containing just "0", or some combination, are all to be treated equivalently. 

- 2016 October, A Shell 6.3.1534: Add flags EDITF_UNQT and EDITF_EXQT 

A-Shell Reference 

Page 1361 

## **FILL$()** 

## **FILL$(expr,length)** 

The FILL$() function returns a string expression made by repeating the source expression until it reaches the specified overall length (in bytes). 

For example: 

```
PRINT FILL$("ab-",10)     ! displays "ab-ab-ab-a"
```

Note that the source expression may contain nulls, which generally only makes sense if assigning the output of the function to an unformatted variable. For example, the statement `REC = FILL$(chr(0),sizeof(REC))` would fill the REC variable or structure with nulls. 

FILL$ requires COMPIL switch /X:1 or higher. 

## **History** 

- 2024 May, A Shell 7.0.1757: Optimize the FILL$() function, achieve a 10x improvement when used with single-character patterns (not that anyone will notice!) 

A-Shell Reference 

Page 1362 

## **IFE() AND IFE$()** 

_Revised December 2019_ 

## **IFE(expr1,expr2{,flags})** 

## **IFE$(expr1$,expr2${,flags})** 

The IFE() and IFE$() functions provide a shorthand way to select one of two values without having to resort to an IF/THEN/ELSE statement. Each returns the value of either the first or second expression argument, depending on the value of the first expression and the _flags_ . IFE returns a numeric value, while IFE$ returns a string value. 

Without the _flags_ parameter, these act as follows: 

```
IFE(expr1,expr2)     ! if expr1 then expr1 else expr2
IFE$(expr1$,expr2$)  ! if expr1$ # "" and # .NULL then expr1$ else expr2$
```

In other words, if the first expression is non-zero (for the numeric version) or non-blank and non-null (for the string version), then the return value of the function is the first expression; else it is the second expression. 

The optional _flags_ are defined in ashell.def and may be used to alter the type of test performed on the first expression: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|IFE_NB|0|IFE$() default (test if_expr1$_"Not Blank")|
|IFE_NZB|1|Treat "0" same as blanks|
|IFE_TRUE|0|IFE() default (test if_expr1_TRUE)|



A-Shell Reference 

Page 1363 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|IFE_FALSE|2|Test if_expr_FALSE (zero) instead of TRUE|



## For example: 

```
IFE(expr1,expr2,IFE_FALSE)   ! if expr1 = 0 then expr1 else expr2
IFE$(expr1$,expr2$,IFE_NZB)  ! if .ISEMPTY(expr1$) then expr1$ else expr2$
```

Note that consistent with the way ASB tests for string equality, trailing blanks are not significant. Also note that .NULL here is treated the same as "" for IFE$() and as 0 for IFE; see _History_ below. 

IFE() and IFE$() are similar to the IFELSE() and IFELSE$() functions, except: 

- Whereas IFELSE()/IFELSE$() uses a separate relative expression argument to decide which of the two possibilities to return, 

- IFE()/IFE$() uses the first expression both as the test expression and as a return value (if the test passes). 

- Unlike IFELSE() and IFELSE$(), which always evaluates each of the arguments, IFE() and IFE$() do not evaluate the second 

- expression unless the test on first expression fails (i.e. unless the second expression is to be returned.) This is particulary useful when the second expression is a function call or other complex expression with significant overhead and/or side effects.) 

## **Additional Examples** 

```
sale'price = IFE(special'price,standard'price)
```

## The above is equivalent to: 

```
if special'price <> 0 then       ! if there is a special going
```

```
    sale'price = special'price   ! use the special price
```

```
else
```

A-Shell Reference 

Page 1364 

```
    sale'price = standard'price  ! else use the regular price
```

```
endif
```

The following example uses sets salutation$ to "Dear <firstname>" if the we know the first name, otherwise it uses the more generic "Dear Customer." 

```
salutation$ = "Dear " + IFE$(firstname$,"Customer")
```

The expression arguments can be anything that could appear on the right side of an assignment, such as a function call, provided they are numeric expressions in the case of IFE, and string expressions in the case of IFE$(). 

In the next example, we attempt to email the receipt but if the return status is not zero, indicating failure, we print it instead. The return value of the IFE function will be the return value of the Fn'Email'Receipt() function (if 0), else the return value of the Fn'Print'Receipt() function. Note that since this is backwards from the default mode—where the second expression is only evaluated if the first one is 0, FALSE, or blank—we add the IFE_FALSE flag. 

```
status = IFE(Fn'Email(receipt), Fn'Print(receipt), IFE_FALSE)
```

Perhaps the place where the IFE() functions—along with the related IFELSE() functions—are most useful is in argument lists with conditional dependencies where you would otherwise have to use temporary variables, as in this example where we want to use the employee's from address if she has one, else use the company return address: 

```
status = Fn'Email(to=toaddr$, from=IFE$(emp.addr$,"sinkhole@acme.com"), body=msg$)
```

## **See Also** 

- IFELSE() and IFELSE$() 

- ISEMPTY() 

- Dot Variables (.TRUE, .FALSE, .NULL) 

## **History** 

- 2023 March, A Shell 6.5.1728: IFE$() now treats .NULL the same as "". 

A-Shell Reference 

Page 1365 

- 2019 March, A Shell 6.5.1657: IFE() and IFE$() added to A-Shell. 

A-Shell Reference 

Page 1366 

## **IFELSE() AND IFELSE$()** 

_Added October 2016_ 

## **IFELSE(cond, expr1, expr2)** 

## **IFELSE$(cond, expr1, expr2)** 

These functions allow IF/THEN/ELSE logic to be embedded within a larger statement, eliminating the need for a temporary variable or additional/duplicated statements to deal with an either/or bifurcation. 

Each takes a conditional expression ( _cond_ ) and two value expressions ( _expr1_ and _expr2_ ). If the conditional expression evaluates to true, then the function returns the value of _expr1_ , else it returns the value of _expr2_ . IFELSE() returns a numeric value and IFELSE$() returns a string value. 

Note that although _cond_ is normally provided in the form of a relational (boolean) expression evaluating to true (-1) or false (0), the compiler is more lenient, allowing a string expression, variable or literal value—even though ill-advised.  See _History_ below and Logical vs. Arithmetic Operators for details. 

## **Examples** 

Consider the case where you want to print a value with one of two masks depending on whether the value is less than 1. You might code it like this: 

```
if VALUE >= 1 then
```

```
    PRINT VALUE USING "#####"
```

```
else
```

```
    PRINT VALUE USING "#.###"
```

```
endif
```

With the IFELSE$() function, you can eliminate the IF statement and reduce the two PRINT statements to one: 

A-Shell Reference 

Page 1367 

```
PRINT VALUE USING IFELSE$(VALUE>=1,"#####","#.###")
```

Or, in the case of larger statements where you are more likely to introduce temporary variables than to repeat variations of the statement, IFELSE() can eliminate the need for a temporary variable, e.g. 

```
if flag'disable then
```

```
    CSTATE = MBST_DISABLE
```

```
else
```

```
    CSTATE = MBST_ENABLE
```

```
endif
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, CTLID$, CTEXT$, CSTATE, CTYPE$, CMD$, FUNC$, ...
```

The above can be reduced to a single statement using IFELSE: 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, CTLID$, CTEXT$, ifelse(flag'disable,MBST_DISABLE,MBST_ENABLE), CTYPE$,
CMD$, FUNC$, ...
```

## **See Also** 

- IFE() and IFE$() 

## **History** 

- 2026 May, A Shell 7.0.1786.2, compiler edit 1083:  String _cond_ expressions are now explicitly converted to numeric values using the VAL() function. Previously, the interpretation of such a string expression as a boolean was ambiguous, depending on the prior state of the numeric expression stack. 

- 2016 September, A Shell 6.3.1526, compiler edit 773: Function added to A-Shell. 

A-Shell Reference 

Page 1368 

## **ODTIM()** 

## **ODTIM (date, time , flags)** 

## **ODTIM$ (date, time , flags)** 

ODTIM() and ODTIM$() output the specified date and/or time according to the formatting flags. If date and/or time is zero, the current date/time is used. The flags are the same as those used by XCALL ODTIM, which see for flag definitions and additional information. 

## **History** 

2021 June, A-Shell 6.5.1704, compiler edit 947:  Add support for the optional trailing $. 

A-Shell Reference 

Page 1369 

## **PAD()** 

## **PAD (var, size)** 

## **PAD$ (var, size)** 

PAD() and PAD$() return a string equal to the input string _var_ (which must be string format) padded with trailing spaces out to the length specified by _size_ . In other words, this is the opposite of STRIP(). If size is less than the current length of var then it functions just like the LEFT() function. 

## **History** 

- 2013 May, A Shell 6.1.1351: Removed limits on input and output size. Previously, the input expression was limited to 255 bytes, and the output expression to 4095. The new effective limit is the available space in the memory partition 

A-Shell Reference 

Page 1370 

## **INSTR()** 

_Updated December 2023_ 

## **INSTR (spos, subject, pattern, {flags})** 

INSTR() returns position of first occurrence of _pattern_ in _source._ 

Searches the subject string for the specified pattern, starting at position spos. Returns the position (base 1) of the first match, or 0 if no match is found. Negative values indicate Regex errors; see comments. 

The A-Shell version of INSTR() is equivalent to the original AlphaBASIC version except for the optional flags argument, which, if specified, causes the pattern to be treated as a regular expression (see below). 

## **Parameters** 

_spos_ (Num)  [in] 

Position within the subject string to begin search. 1 is the first position. 0 and negative values are invalid and will return 0 as the result. 

_subject_ (String)  [in] 

String to be searched 

_pattern_ (String)  [in] 

Substring or pattern to search for. Treated as case-sensitive literal text unless flags specified. Note that a single character ASCII value may be interpreted as a precompiled pattern index rather than a literal pattern. See Using Precompiled Patterns under Comments below. 

_flags_ (Num)  [in] 

If specified (even if 0), causes pattern to be treated as a Perl-compatible regular expression. The values for flags are the same as those for the XCALL REGEX options flags plus these two additional flags: 

A-Shell Reference 

Page 1371 

|**Flag**|**Value**|**Description**|
|---|---|---|
|INSTRF_ANY|&h0100000<br>0|Treat pattern as set of characters; match first one<br>that appears in subject.|
|INSTRF_ANY<br>QT|&h0200000<br>0|Same as INSTRF_ANY but ignores characters in<br>subject between matching quotes.|



## These are based on the standard C function _strpbrk()_ . For example: 

```
PRINT INSTR(1, "DSK0:ABC.RUN /X", ";/ ", INSTRF_ANY)
```

Of the three characters in the pattern (";/ "), the first to occur in the subject is the space at position 13. 

The above is equivalent to the REGEX character set pattern "[;/ ]"; it simply eliminates any doubts about REGEX syntax for special characters. But the INSTRF_ANYQT version is much harder to implement using REGEX. 

## **Comments** 

**Error Conditions:** Any of the following conditions are considered invalid and will return 0 (no match): 

- null pattern 

- null subject 

- spos < 0 

- spos > length of string 

Errors relating to regular expressions will be returned as negative values, matching those returned by XCALL REGEX. See REGEX's Pattern Complilation Errors and Matching Errors. 

A-Shell Reference 

Page 1372 

**Case Sensitivity** : For a case-insensitive search, you can either use the regular expression mode with PCRE_CASELESS (&h0001) flag, or you can just apply the String Functions LCS$() or UCS$() to the subject and pattern strings. 

**Matching whole words only** : to avoid matches on substrings within words (e.g. to match "old" but not "golden"), surround the pattern string with "\b" (e.g. "\bold\b") and add the flags parameter to activate REGEX matching, which treats "\b" as a zerolength word break. 

**INSTR() versus REGE[XS] :** The function and subroutine version reference the same internal logic, and have the same parameter semantics. The INSTR() version has less overhead and is easier to use, while REGEX[XS] offers additional power—mainly in the advanced area of sub-expression matching, although it also returns the actual matched substring, which is often handy and not obvious. 

**Precompiling Patterns:** Five numbered precompiled patterns (1-5) may be shared between REGEX[XS] and INSTR(), and thus you could use REGEX[XS] to pre-compile patterns later used with INSTR(), if you prefer to use INSTR()itself to pre-compile patterns, set the PCREX_PRECOMPILE (&h80000000) bit in the flags parameter and set _spos_ to the pattern number, like _patno_ in REGEX. The subject string will be ignored (can be ""). On success, the return value of the function will equal _spos_ ; else refer to the status codes listed under XCALL REGEX. 

**Using Precompiled Patterns:** As with REGEX, you can specify a precompiled pattern by setting _pattern_ = CHR$(n) where n is the pattern number (1-5). Whenever the same pattern is used in consecutive calls, the previously compiled version is automatically used, making pre-compilation unnecessary except when alternating between multiple patterns. To prevent a single-character pattern from being accidentally misinterpreted as a precompiled pattern number, specify the PCREX_NOT_PRECOMPILED (&h08000000) bit in _flags_ . See History below for evolution of this feature and OPTIONS=NOINSTRX_PCP for a way to disable it globally. 

## **See Also** 

- EXLIB:[908,46] for sample programs. 

- .INSTRR() 

- XCALL NFIND 

A-Shell Reference 

Page 1373 

• The A-Shell forum topic "Substring search right-to-left" for a discussion on how to implement a last-match (or right-to-left) version of INSTR(). As of 6.3.1527, the doc function .INSTRR() is available right-to-left searching. A general form search on the term "INSTR" will also turn up many threads which might be of related interest 

## **History** 

- 2023 December, A Shell 7.0.1752.4:  PCREX_NOT_PRECOMPILED flag introduced and maximum precompiled pattern number reduced from 127 to 5 to minimize accidental misinterpretation. 

- 2023 June, A Shell 6.5.1732:  Maximum precompiled pattern number increased from 20 to 127. 

- 2016 October: A Shell 6.3.1530: Add two non-REGEX flags as shown above. 

A-Shell Reference 

Page 1374 

## **STR$()** 

_Added February 2019_ 

The STR$(x) function, the logical inverse of the VAL() function, returns the string decimal representation of the value (or expression) x, with no leading or trailing blanks. Typically the function is superfluous, since the compiler will automatically insert it whenever it detects the need to convert a numeric value or expression to a string. 

Note that when explicitly applied to an expression rather than just a variable or literal, it causes the compiler to expect the expression to be numeric—since the point of the STR$() function is to convert the numeric x to string. This can have counterintuitive side effects, including converting any string operands within the expression to number, and treating the "+" operator as addition rather than concatenation. For example: 

```
map1 a$,s,10
```

```
map1 b,f,6,2
```

```
map1 c,f,6,3
```

```
a$ = b + c               ! =
23
```

```
a$ = str$(b) + str$(c)   ! = 23
a$ = str$(b + c)         ! = 5
a$ = str$(a$ + b)        ! = 7
a$ = strexpr$(b + c)     ! = 23
```

The first two statements are equivalent, i.e. the compiler effectively converts the first expression into the second. The reasoning is that since the target of the assignment is a string (a$), the expression on the right side of the equals sign should be a string expression. When the compiler encounters the numeric variables b and c, it therefore inserts implicit STR$() functions to convert them to string, and interprets the plus operator as concatenation, i.e. STR$(2) + STR$(3) = "2" + "3" = "23" 

A-Shell Reference 

Page 1375 

In the third statement, the explicit STR$() enclosing the expression causes the compiler to expect the expression to be numeric, which causes it to interpret the plus operator as addition, i.e. 2 + 3 = 5; STR$("5") = 5. 

The fourth statement is just like the third, except that when the compiler sees the a$ operand within STR$(a$ + b), it perhaps counter-intuitively converts it to a number, since it expects the argument of the STR$() function to be numeric. So even though we have an explicit STR$() function, and a string argument a$, we still treat the plus operator as addition rather than concatenation. 

The final statement illustrates the STREXPR$() alternative to the STR$() function. Added in A-Shell 6.5 (compiler 890), it tells the compiler to expect a string expression, which in turn causes it to convert the operands b and c to strings, and to treat the plus operator as concatenation, which is probably a more intuitive approach when dealing with expressions rather than simple values. 

## **See Also** 

- Overloaded Plus Operator 

- STREXPR$() 

A-Shell Reference 

Page 1376 

## **.INSTRR()** 

## **.INSTRR (spos, string, pattern)** 

.INSTRR() is similar to INSTR() except it searches in reverse—e.g. it searches the string for the pattern, starting at the specified _spos_ and working backwards towards the beginning of the string. The return value is the position of the last match—i.e. first match working backwards, with 1 indicating the first character of the string and 0 indicating no match. 

Unlike INSTR(), .INSTRR() supports both positive and negative starting positions, with negative values counting from the end of the string—e.g. -1 starts the search at the end of the string. However the return value is always >= 0—i.e. position starting from the beginning of the string. 

Also unlike INSTR(), ..INSTRR() does not support the 4th argument used for regular expression searches. 

## **See Also** 

- INSTR() 

- NFIND[XS] 

## **History** 

- 2016 September, A Shell 6.3.1527:  Function added to A-Shell. 

A-Shell Reference 

Page 1377 

## **VAL() AND VAL$()** 

The VAL(a$) function returns the decimal value represented by the string argument a$. While it is the logical inverse of the STR$() function, there are some additional features and considerations. For one, it supports the "hexadecade" date notation enabled by OPTIONS=HEXDEC (which see for more information). It also supports the decimal point and thousands separate character definitions in the Language Definition File (-> LANGUAGE). 

VAL$(a$) ignores leading spaces, and stops at the first character which is not a legal character in a decimal value representation. So for example, `VAL("123.4X")` returns 123.4, and `VAL("   012  34")` returns 12. See VALX() for an alternative that is more tolerant of non-numeric characters mixed up with the number being evaluated, such as prefixes, currency symbols, thousands separators, etc. 

As in the case with the STR$() function, the compiler will often insert the VAL() function implicitly into a statement or expression when needed to convert a string argument to obtain a numeric result. So its use is optional in cases like: 

```
map1 x,f
```

```
map1 a$,s,10,"123"
```

```
x = a$     ! same as x = VAL(a$)
```

Note that when explicitly applied to an expression (rather than just a variable or literal), it causes the compiler to expect the expression to be of type string, since the point of the VAL(A$) function is to convert the string a$ to a numeric value. This can have counter-intuitive side effects, including converting any numeric operands within the expression to string, and treating the "+" operator as concatenation rather than addition. For example: 

```
map1 x,f,6
```

```
map1 a$,s,10,"2"
```

```
map1 b$,s,10,"3"
```

A-Shell Reference 

Page 1378 

**==> picture [212 x 83] intentionally omitted <==**

```
x = numexpr(a$ + b$)     ! = 5
```

The first two statements are equivalent, i.e. the compiler effectively converts the first expression into the second. The reasoning is that since the target of the assignment is a numeric variable (x), the expression on the right side of the equals sign should be a numeric expression. When the compiler encounters the string variables a$ and b$, it therefore inserts implicit VAL() functions to convert them to numbers, and interprets the plus operator as addition, i.e. VAL("2") + VAL("3") = 5 

In the third statement, the explicit VAL() enclosing the expression causes the compiler to expect the expression to be string, which causes it to interpret the plus operator as concatenation, i.e. "2" + "3" = "23". 

The fourth statement is just like the third, except that when the compiler sees the numeric x operand within VAL(x + a$), it perhaps counter-intuitively converts it to a string, since it expects the argument of the VAL() function to be string. So even though we have an explicit VAL() function, and a numeric argument x, we still treat the plus operator as concatenation rather than addition. 

The final statement illustrates the NUMEXPR() alternative to the VAL() function. Added in 6.5 (compiler 890), it tells the compiler to expect a numeric expression, which in turn causes it to convert the operands a$ and b$ to numbers, and to treat the plus operator as addition, which is probably a more intuitive approach when dealing with expressions rather than simple values. 

## **See Also** 

- Overloaded Plus Operator 

- STREXPR$() 

- VALX() 

A-Shell Reference 

Page 1379 

## **.VALX()** 

_Updated May 2024_ 

The .VALX(A$) function is an extended version of the traditional VAL(). It supports all of the same behavior, plus it automatically skips over any amount of non-numeric text preceding the number, and also recognizes common types of numeric formatting such as thousands separators, currency symbols, and parentheses for negatives. This makes it particularly handy for importing values from spreadsheets and reading numeric cells in XTREE. 

## **Examples** 

|**Expression**|**val(expr**<br>**)**|**.valx(expr)**|**Notes**|
|---|---|---|---|
|"123"|123|123||
|"  123"|123|123|leading spaces|
|" -123 US"|-123|-123|leading minus and spaces|
|"$123"|0|123|leading non-digits|
|"-$123.45"|0|-123.45|leading -$|
|"123,456.78"|123|123456.78|thousands separators|
|"($1,234.56)"|0|-1234.56|parentheses for neg|



A-Shell Reference 

Page 1380 

|**Expression**|**val(expr**<br>**)**|**.valx(expr)**|**Notes**|
|---|---|---|---|
|"price: (USD) 0.99"|0|0.99|(USD) ignored (non-numeric)|
|"&h0200"|512|512|&h for hex|
|"&O0200"|128|128|&o for octal|
|"hex flags: &h0200"|0|512|leading text|
|"hex flags: 0x0200"|0|512|0x for hex|
|"octal flags: o0200"|0|128|0o for octal|
|"binary flags: 0b10110"|0|22|0b for binary|
|"&b1010101010101010"|0|43690|&b for binary|



## **History** 

- 2021 April, A Shell 6.5.1702:  Add function to A-Shell. 

A-Shell Reference 

Page 1381 

## **NUMEXPR()** 

_ADDED February 2019_ 

NUMEXPR(expr) is the mirror image of STREXPR$(expr). It tells the compiler to expect and treat the argument expression as a numeric expression. This may seem similar to the VAL() function but differs in important ways. 

VAL() is designed to convert a string value (variable or expression) to a number. If given an expression for an argument, it expects the expression to be a string expression, which means that it will intepret any + operator as concatenation, and will convert any numeric operands to string. Only after the expression argument is fully evaluated (as a string) does it get converted to a numeric value. 

NUMEXPR(expr) expects the argument to be a numeric expression, which means that it will interpret any + operator as addition, and will convert any string operands to numbers. Since the resulting expression will be a numeric value, there is no need for a final conversion. Examples: 

```
map1 x,f,6
```

```
map1 y,b,2
```

```
map1 z,f,6
```

```
map1 a$,s,10
```

```
map1 b$,s,10
```

```
x = y + z                ! addition
```

```
x = numexpr(y + z)       ! same; numexpr() has no effect here
```

```
a$ = y + z               ! concatenation (due to string target)
```

```
a$ = numexpr(y + z)      ! addition
```

```
x = a$ + b$              ! addition; same as val(a$) + val(b$)
```

```
x = numexpr(a$ + b$)     ! addition; same as above
```

A-Shell Reference 

Page 1382 

```
x = val(a$ + b$)         ! concatenation; (val expects a string argument)
```

```
x = str$(a$ + b$)        ! addition(!); same as val(a$) + val(b$)
fn'foo(a$ + b$)          ! concatenation; (a$ sets string mode here)
```

```
fn'foo(numexpr(a$ + b$)) ! addition
```

NUMEXPR() is particularly useful when working with DYNSTRUCT members, since they are always treated by the compiler as strings, possibly causing intended addition operations to be compiled as concatenation. In fact, the compiler will treat any expression involving a dynstruct.member and the + operator as an error, unless one of the casting functions NUMEXPR() or STREXPR$() is used. 

## **See Also** 

- Overloaded Plus Operator 

- STREXPR$() 

- Explicit Plus Operators 

## **History** 

- 2019 February, A Shell 6.5.1654, compiler edit 890:  Added to A-Shell. 

A-Shell Reference 

Page 1383 

## **STREXPR$()** 

_Added February 2019_ 

STREXPR$(expr) is the mirror image of NUMEXPR(expr). It tells the tells the compiler to expect and treat the expression argument as a string expression. This may seem similar to the STR$() function but differs in important ways. 

STR$() is designed to convert a numeric value (variable or expression) to a string. If given an expression for an argument, it expects the expression to be a numeric expression, which means that it will intepret any + operator as addition, and will convert any string operands to numeric. Only after the expression argument is fully evaluated (as a number) does it get converted to a string value. 

STREXPR$(expr) expects the argument to be a string expression, which means that it will interpret any + operator as concatenation, and will convert any numeric operands to strings. Since the resulting expression will be a string value, there is no need for a final conversion. Examples: 

```
map1 x,f,6
```

```
map1 y,b,2
```

```
map1 z,f,6
```

```
map1 a$,s,10
```

```
map1 b$,s,10
```

```
x = y + z                ! addition
```

```
x = strexpr$(y + z)      ! concatenation; same as str$(y) + str$(z) (sum then converted to string)
```

```
a$ = y + z               ! concatenation (due to string target)
```

```
a$ = strexpr$(y + z)     ! same; strexpr$() here has no effect
```

```
x = a$ + b$              ! addition; same as val(a$) + val(b$)
```

```
x = strexpr(a$ + b$)     ! concatenation; result then converted to string
```

A-Shell Reference 

Page 1384 

```
x = val(a$ + b$)         ! concatenation; (val expects a string argument)
```

```
x = str$(a$ + b$)        ! addition(!); same as val(a$) + val(b$)
fn'foo(x + y)            ! concatenation; (a$ sets string mode here)
fn'foo(strexpr$(x + y))  ! concatenation
```

STREXPR$(expr) is particularly useful when working with DYNSTRUCT members where the compiler is unable to determine at compile time the ultimate type of the member when it is bound at run time. Use of the casting functions eliminates the possible confusion and resulting logical errors of mistaking addition for concatenation or vice versa. 

## **See Also** 

- Overloaded Plus Operator 

- .VALX() 

## **History** 

- 2019 February, A Shell 6.5.1654, compiler edit 890:  Added to A-Shell. 

A-Shell Reference 

Page 1385 

## **.ISEMPTY()** 

## **.ISEMPTY(expr$)** 

The .ISEMPTY() function returns a boolean value (.TRUE or .FALSE) depending on whether the string or unformatted expression is empty, where "empty" is defined as meeting one of the following conditions: 

- If the expression is .NULL, i.e. if .ISNULL(expr$) returns .TRUE 

- In the case of a string expression, if expr$ = "", i.e. if it contains zero or more blanks up to the first null, and nothing more. 

- In the case of an unformatted variable or expression, if it contains only null bytes. 

## **Also See** 

- IFE() 

- IFELSE() 

- .ISNULL() 

## **History** 

## - 2023 August, A Shell 6.5.1742:  Function added to A-Shell. 

A-Shell Reference 

Page 1386 

## **FILE FUNCTIONS** 

_Reviewed and revised August 2020_ 

|**Function**|**Description**|
|---|---|
|EOF()|EOF(x)returns end-of-file status for file channel X: -1 if no file is open on channel X; 0 if file is open but end-of-file has<br>not been reached; 1 if end-of-file has been reached (after some form of INPUT statement on a sequential file).|
|ERF()|ERF(x)returns error/status information about the last operation on an ISAM file (see table below for details). In the<br>case of ISAM-A files, it simply returns the value of the_fstatvar_(status) variable associated with the file in the ISAM-A<br>OPEN statement. As with theEOF()function, it returns -1 for channels that are not open. Note that -1 is also a valid<br>ISAM-A status (ISAM_LT, key found less than specified key), but the usage context should usually make that<br>distinction clear.|
|LOOKUP()|LOOKUP (fspec$)Returns the size of the specified file in blocks (0 for non-existing, 0.5 for a file with zero bytes). Note<br>that the returned block count for files which appear to be contiguous (are an even multiple of 512 bytes) will be<br>negative, unless you set<br>`OPTIONS=`<br>`ABSLOOKUP`<br>inmiame.ini. If you don't have control over that option, you may<br>want to use theABS()function on the result in order to confusion with files that happen to be a multiple of 512 bytes<br>with, e.g.<br>`ABS(LOOKUP(FSPEC$))`.|
|.LINENO()|LINENO()returns current line number for sequential output files.|
|.FSTAT()|.FSTAT(channel)returns the file status for the last ISAM-A operation on the specified channel; equivalent to reading the<br>value of the_fstatvar_variable specified on the OPEN statement, but more flexible in that it can be used regardless of<br>whether the_fstat_variable is in scope, or even exists. In the case ofXOPEN, it is the only way to retrieve the status.<br>For details about the relation between various ISAM-A file operations and the status codes, see the relevant ISAM-A<br>statement topics.|
|.PAGENO()|PAGENO(channel)returns current page number for sequential output files.|
|.RECNO()|.RECNO(channel)returns the current record number for the specified random, ISAM, or ISAM-A file channel; equivalent<br>to reading the value of the recnovar variable specified on the OPEN statement, but more flexible in that it can be used<br>regardless of whether the recnovar variable is in scope, or even exists. SeeXOPENandSET'RECNO.|
|.RECSIZ()|.RECSIZ(channel)returns the record size for the specified open file channel based on the OPEN (orXOPEN) statement. If|



A-Shell Reference 

Page 1387 

the channel does not specify an open RANDOM, ISAM or ISAMA file, a negative value is returned. 

## **ERF(X) Values for ISAM files** 

|**Function**|**Description**|
|---|---|
|14|Illegal record number|
|32|Illegal ISAM statement code|
|33|(after ISAM 1) indicates the key was not found|
|34|(after ISAM 3) duplicate key found during add key|
|35|link structure smashed|
|36|(after ISAM 3) index file full (and auto-expansion disabled; see<br>`OPTIONS=NOAUTOX`<br>.|
|37|(after ISAM 5) data file full (and auto-expansion disabled).|
|38|(after ISAM 2 or 7) already at end of index|
|39|Illegal ISAM sequence (violatesLOKSER<br>rules; if program was not designed to work with LOKSER, you can turn<br>LOKSER off with SET NOLOKSER or LOKSER=OFF inmiame.ini)|



A-Shell Reference 

Page 1388 

## **.LINENO(), .PAGENO()** 

_Added November 2014_ 

## **.LINENO(channel)** 

## **.PAGENO(channel)** 

These return the (a) current line number within the current page, or (b) the current page number, respectively, for sequential output files. Both counters start at 1. 

These are intended to simplify traditional report coding, particularly for those working with legacy or unfamiliar report programs, by eliminating the need to keep your own line and page counts synchronized with the file contents. Note however that the counting mechanism is based on a hook that covers only the most typical cases. In particular: 

- For PRINT statements, the .LINENO(ch) value is only incremented by the absence of a trailing semicolon. Line feed characters 

- which are output as data will not be counted. 

```
PRINT #CH, PLINE                ! counts as 1 line
```

```
PRINT #CH, PLINE;               ! does not count (semicolon)
PRINT #CH, PLINE;chr(10);       ! does not count
```

- Form feed characters, i.e. chr(12), will be detected anywhere, causing the .PAGENO(ch) value to be incremented, exept in the 

- first position of the output file. The assumption there is that you are using the STRIPFF feature in the printer initialization file to ignore a leading form feed. 

- PRINT[xs] is supported, although the feature is probably not useful there. 

- PUTBYT[xs] is also supported; line and form feed will be detected anywhere. 

- Any other method of outputting to a sequential file will probably bypass the counter hook. 

## **History** 

A-Shell Reference 

Page 1389 

- 2014 October, A Shell 6.1.1396: Functions added to A-Shell 

A-Shell Reference 

Page 1390 

## **TAB FUNCTIONS** 

Tab "functions" conform to standard function syntax, but they are not real functions in that they don't return any value. Instead, they perform some kind of terminal / file / client output or control operation. For this reason and because there are so many of them, especially in the sub-category of ATE Functions, they are covered in their own Tab Functions section of the documentation. 

A-Shell Reference 

Page 1391 

## **DYNAMIC STRUCTURE FUNCTIONS** 

_Updated March 2025; see History_ 

## These functions relate to Dynamic Structures, which see for more information. 

|**Function**|**Description**|
|---|---|
|.BINDSTRUCT|Bind the structure definition to the DYNSTRUCT variable|
|.DYNOFFSET()|Indirect deferred version.|
|.DYNOFFSIZ()|Dynamic structure version of.OFFSIZ$()<br>.|
|.ISBOUND(DS)|Returns TRUE if the specified variable is a DYNSTRUCT that has been bound to a defined structure.|
|.ISDEF()|Indirect deferred version; seeDynamic Structures<br>.|



## **See Also** 

- Dynamic Structures 

## **History** 

- 2025 March, A Shell 7.0.1770, compiler edit 1062:  .ISBOUND added to A-Shell. 

A-Shell Reference 

Page 1392 

## **.ISDEF()** 

_Added February 2022_ 

## **.ISDEF(ds.member)** 

## **.ISDEF(ds.@member$)** 

.ISDEF() returns true (-1) or false (0) depending on whether the specified DYNSTRUCT member exists—i.e., whether the DYNSTRUCT is bound to a structure that contains the specified member. 

In both variations, _ds_ should be either an mapped instance of a structure, or the structure definition name from the defstruct. The difference between the two variations is that in the first case, _member_ must be an actual reference to a member of the specified structure, whereas in the second case _member$_ should be a string variable whose value matches a member of the structure. See Dynamic Structure Reference / Usage for more details. 

## **Example** 

```
map1 ds,DYNSTRUCT
map1 field$,s,30
```

```
...
```

```
if .ISDEF(ds.foo) then
    ? "ds.foo exists; value = ";ds.foo
```

```
endif
```

```
...
```

```
field$ = "foo"
```

```
if .ISDEF(ds.@field$) then
    ? "ds.@";field$;" exists; value = ";ds.@field$
```

```
endif
```

A-Shell Reference 

Page 1393 

## **See Also** 

- Dynamic Structures 

- MX_DYNSTRUCT (DYNOP_INFO) for an alternate approach to determining the details of the current binding for a specified 

- DYNSTRUCT. 

## **History** 

- 2022 February, A Shell 6.5.1711: Function added to A-Shell 

A-Shell Reference 

Page 1394 

## **.DYNOFFSET()** 

_Added February 2022_ 

## **.DYNOFFSET(ds.member)** 

## **.DYNOFFSET(ds.@member$)** 

.DYNOFFSET() returns the offset to the specified DYNSTRUCT member from the base of the structure, starting at 1. Equivalent to .OFFSET() except applies only to DYNSTRUCTs, and is evaluated at run time instead of compile time. 

In both variations, _ds_ should be either an mapped instance of a structure, or the structure definition name from the defstruct. The difference between the two variations is that in the first case, _member_ must be an actual reference to a member of the specified structure, whereas in the second case _member$_ should be a string variable whose value matches a member of the structure. See Dynamic Structure Reference / Usage for more details. 

Note that the offset to a DYNSTRUCT member can also be retrieved in the pos member of the ST_FLDDEF structure returned by MX_DYNSTRUCT (DYNOP_INFO), except that it starts at zero whereas .DYNOFFSET() starts at 1. 

## **See Also** 

- .OFFSET() 

- Dynamic Structures 

- MX_DYNSTRUCT 

## **History** 

- 2022 February, A Shell 6.5.1711: Function added to A-Shell 

A-Shell Reference 

Page 1395 

## **.DYNOFFSIZ()** 

_Added February 2022_ 

## **.DYNOFFSIZ$(ds.member)** 

## **.DYNOFFSIZ$(ds.@member$)** 

.DYNOFFSIZ() is equivalent to .OFFSIZ$() except that it operates at run time instead of compile time and works exclusively for DYNSTRUCT members. 

In both variations, ds should be either an mapped instance of a structure, or the structure definition name from the defstruct. The difference between the two variations is that in the first case, _member_ must be an actual reference to a member of the specified structure, whereas in the second case _member$_ should be a string variable whose value matches a member of the structure. See Dynamic Structure Reference / Usage for more details. 

The return value is a string of the form "x~y" where x is the offset from the based of the ds DYNSTRUCT to the specified 

member (base 1), and y is the size of the member in bytes. As with .OFFSIZ$(), the function is mainly useful in conjunction with XTREE. 

## **See Also** 

- .OFFSIZ$() 

- Introduction to Dynamic Structures 

- MX_DYNSTRUCT 

## **History** 

- 2022 February, A Shell 6.5.1711: Function added to A-Shell 

A-Shell Reference 

Page 1396 

## **OTHER FUNCTIONS** 

All of the functions listed in the table below except MEM() require COMPIL /X:2 or higher. 

|**Function**|**Description**|
|---|---|
|.ARGTYP()|Returns the type of the specified argument passed to the current SBX, function, or procedure.|
|.ARGSIZ()|Returns the size of the specified argument passed to the current SBX, function, or procedure.|
|.ARGTYP_READONLY<br>()|Indicates whether the specified argument is read-only.|
|.ARG_PASSED()|Indicates whether the specified argument was passed to the current SBX, function, or procedure.|
|ERR()|ERR() is used within an error trap to return information relating to an ASB error that has occurred.|
|ERRMSG()|ERRMSG(X) returns the message associated with ASB error X, based on contents of sys:errmsg.xxx.|
|.EXTENT()|Returns the "extent" of the specified array or collection.SeeSpecial ORDMAP Functions.|
|GETKEY()|This function inputs a single keyboard character and returns its numeric (ASCII or Latin1) character<br>value.|
|.ISNULL()|Tests for the .NULL condition. SeeSpecial ORDMAP Functions.|



A-Shell Reference 

Page 1397 

|ell Reference|Page 1397|
|---|---|
|.KEY()|Returns the key associated with the element currently indexed by the iterator. SeeSpecial ORDMAP Functions.|
|MEM()|MEM(X) returns information about available memory and resources. See table of MEM(X) Values<br>below.|
|.NEXT()|Advances the iterator, returning the associated key or .null if no more. SeeSpecial ORDMAP Functions.|
|PYFUNC()|Provides a means to call an external function written in Python version 3.|
|XFUNC(), XFUNC$()|XFUNC and XFUNC$ execute an external SBX routine, returning a numeric or string value.|



## **MEM(X) Values** 

|**Function **|**Description**|
|---|---|
|MEM(0)|returns the number of bytes of free space remaining in the "partition," which is used mostly for variable storage,<br>expression evaluation, stack, and possibly SBX loading.|
|MEM(1)|returns total size of "partition." SeeMEMORY.LIT<br>,MX_MEMORY<br>XS, andMEMORY<br>SPfor further discussion and<br>methods of configuring partition size.|
|MEM(5)|size of compiled object code area|
|MEM(6)|size of DATA pool|



A-Shell Reference 

Page 1398 

|ell Reference|Page 1398|
|---|---|
|MEM(7)|size of array storage area|
|MEM(8)|size of variable storage area (excluding arrays)|



## **See Also** 

- Constants ... Compiler Functions 

A-Shell Reference 

Page 1399 

## **.ARGTYP() AND .ARGSIZ()** 

_Reviewed and revised April 2024_ 

Syntax one: 

## or **.ARGTYP(argno) .ARGTYP(@arg)** 

Syntax two: 

## or **.ARGSIZ(argno) .ARGSIZ(@arg)** 

These two dot functions return the type and size, respectively, of the specified source argument as passed to the current SBX, function, or procedure. Note that the original source argument types and sizes may be completely different from those received by the SBX or function; see Parameter Types. These functions allow the called routine to see the original passed types and sizes before they were converted by the calling operation. 

**Warning** : It is easy to accidentally specify _arg_ when you meant _@arg_ , both of which are syntactically correct (assuming _arg_ is the name of an argument in the current context) but have vastly different meaning. To help avoid this mistake, the compiler (as of edit 1065) will treat _arg_ as an error if it matches a current argument name; if you really meant to reference the argument by number, use a literal number or a variable that isn't a current argument. 

## **Parameters** 

Note that these parameters apply to all of the .ARG... functions. 

_argno_ (Unsigned int)  [in] 

The ordinal number of the argument being queried, starting from 1. Note that in the case of Named Parameters, the parameter numbers are determined by the function declaration or subroutine DEFXCALL directive, not necessarily by the order specified in the calling statement. If the _argno_ passed is invalid, the return value of the function will be -1. 

## _@arg_ (Literal parameter name)  [in] 

This syntax provides an alternate way to reference the parameter of interest by its name rather than its ordinal number. The concept is similar to that used for XPUTARG _@arg_ : _@arg_ is treated by the compiler as a macro for the argument number corresponding to the argument _arg_ as defined in the function/procedure definition or as retrieved in an SBX using XGETARG(S). 

A-Shell Reference 

Page 1400 

## The return value for .ARGSIZ() is the size of the original argument in bytes. 

The return value for .ARGTYP() is a 16-bit bitmap value based on the following tables: one bit from the first table, zero or more bits from the second table. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|ARGTYP_MASK|&h000f|mask for types X,S,F,B,I|
|ARGTYP_X|&h0000|X type (mutually exclusive)|
|ARGTYP_S|&h0002|S type ("  "   ")|
|ARGTYP_F|&h0004|F type ("  "   ")|
|ARGTYP_B|&h0006|B type ("  "   ")|
|ARGTYP_I|&h0008|I type ("  "   ")|



|**Symbol**|**Value**|**Description**|
|---|---|---|
|ARGTYP_ARRAY|&h0010|Array|
|ARGTYP_NOSURR|&h0020|No surrogate|



A-Shell Reference 

Page 1401 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|ARGTYP_DYN|&h0040|Dynamic variable|
|ARGTYP_LOCAL|&h0080|Local dynamic variable|
|ARGTYP_SBR|&h0100|Variable within SBX orXCALL ASHELL|
|ARGTYP_DIMX|&h0200|Base ofDIMXarray passed by reference|
|ARGTYP_READONLY|&h0400|See ARGTYP_READONLY section below|
|ARGTYP_COLL|&h0800|Collection (e.g. ordered map, etc.)|
|ARGTYP_DYNSTRUCT|&h1000|Parameter is a dynstruct|
|ARGTYP_DEFVAL|&h2000|Parameter is not actually passed, is set per =defval logic|



## u **ARGTYP_READONLY Details** 

This flag will be set if the passed argument is a literal value, expression, or otherwise incapable of receiving an updated value. This provides a good way for routines to be able to decide whether it is worth generating and returning values for output parameters. For example: 

A-Shell Reference 

Page 1402 

```
Function Fn'Foo(arg1=0 as b2, arg2="" as s0, arg3=-1 as f6)
```

```
    ...
```

```
    ! calc and return arg3 if not readonly
```

```
    if not (.ARGTYP(@arg3) and ARGTYP_READONLY) then
```

```
        <calculate updated arg3 value>
```

```
        .xputarg @arg3
```

```
    endif
```

```
    ...
```

The ARGTYP_READONLY flag is set by the runtime system and is independent of the compiler version. Runtime versions prior to its implementation (see History below) will never set the flag and thus logic like that above would always calculate and output the parameter—i.e. dependability over optimization. Also note that in the above example, the use of default values in the function declaration will guarantee that the function receives three parameters, so the .ARGCNT dot variable will not help identify un-passed parameters. Instead, you may want to use the .ARG_PASSED() function to avoid wasting time, however harmlessly, generating return values for parameters that were not passed. 

## **Example: SBX** 

```
xgetargs color, rvalue, gvalue, bvalue
```

```
xgetarg 5, name
```

```
...
```

```
if .argtyp(@gvalue) and ARGTYP_B then ...  ! if gvalue arg binary
```

```
if .argtyp(3) and ARGTYP_B then ...        ! if 3rd arg binary (same as above)
```

A-Shell Reference 

Page 1403 

```
if .argtyp(@name) and ARGTYP_S then ...    ! if name arg string
```

The above example illustrates that in the case of an SBX, the _@arg_ reference is based on the order that the referenced variable appears in the XGETARGS statement, or the argument number associated with it in a preceding XGETARG statement. Usually the _@arg_ syntax is preferred, since it self-adjusts if you alter the parameter list, but in some cases it might be preferable to stick with the numeric argument numbering. 

Note that .ARGTYP() returns the type of the argument that was passed in the XCALL, not the type of the variable receiving it in the SBX. 

For example, if the `gvalue` variable inside the SBX was mapped as B,1, but the SBX was called via... 

```
xcall RGB, &h0080ff,  "255", "128", 0, "orange"
```

then `.argtyp(@gvalue)` would return &h0422 (ARGTYP_READONLY, ARGTYP_NOSURR, ARGTYP_S), not ARGTYP_B. 

## **Example: Function** 

```
map1 lastname$,s,35,"Ryan"
```

```
call Fn'MilitaryID(serial=123456789, name=lastname$)
```

```
...
```

```
Function Fn'MilitaryID(name="" as s20, rank="Private" as s15, serial="" as s10)
```

```
   map1 ix,i,2
```

```
   for ix = 1 to .argcnt
```

```
      ? "&h";Fn'Dec2Hex$(.argtyp(ix), .argsiz(ix)
```

```
   next ix
```

```
EndFunction
```

A-Shell Reference 

Page 1404 

The above should print out: 

```
&h22     35
```

```
&h422    7
```

```
&h424    8
```

The .argcnt is 3 even though only two parameters were listed in the call; this is because the default values in the function declaration caused the compiler to add the missing parameter and default value (rank="Private") to the call. 

All three of the arguments have the ARGTYP_NOSURR bit set, indicating that the arguments were passed directly without the use of an intermediate surrogate; that typically only affects internal subroutines passing F6 parameters with an IEEE F8 surrogate. The last two have the ARGTYP_READONLY bit set since they were passed as expressions rather than variables and therefore can't be updated. 

The first line/argument in the display refers to the name parameter (#1 in the declaration) even though it is passed second in the call. Again, the named parameter mechanism causes the calling statement to be rearranged to match up with the expectation of the target function. Note that its size is 35 (the size of the source variable lastname$) rather than 20 (the size of the local variable name receiving it.) It can be updated via XPUTARG since a real variable was passed. 

The second line refers to the rank parameter (#2 in the declaration); its size is 7 because it is effectively a literal string "Private". 

The third line refers to the serial parameter (#3 in the declaration); its size is 8 because the value 12345678 passed in the call was converted to a numeric (F8) expression before being converted to a string during the parameter passing. 

## **See Also** 

- .ARGCNT 

- Named Parameters 

- XGETARG(S) and XPUTARG 

A-Shell Reference 

Page 1405 

- .ARGTYP_READONLY() and .ARG_PASSED() 

## **History** 

- 2024 December, A Shell 7.0.1767, compiler edit 1051: ARGTYP_DYNSTRUCT and ARGTYP_DEFVAL defined 

2017 September, A-shell 6.5.1616, compiler edit 834: Add support for .ARGTYP() and .ARGSIZ(). 

- 2017 July, A Shell 6.4.1553: ARGTYP_READONLY added to A-Shell. 

- 2014 September, A Shell 6.1.1373:  Functions added to A-Shell. **Warning:** These functions are not recognized by prior runtime versions, and will simply return the value of the _argno_ passed. You could use this fact to test if the feature is supported at runtime by passing an illegal _argno_ , such as 999 or -2, to .ARGTYP(). If supported, the return value will be -1 (error); else if will match the _argno_ passed. If developing code that might possibly have to run on such an old version, use MX_GETVER or the wrapper function Fn'MinAshVer() in fnminsasver.bsi in SOSLIB:[907,10] to check the version first. 

A-Shell Reference 

Page 1406 

## **.ARG_PASSED()** 

_Ororganized August 2025_ 

## **.ARG_PASSED(argno)    or    .ARG_PASSED(@arg)** 

Indicates whether the specified argument was actually passed to the current SBX, function or procedure. 

**Warning** : It is easy to accidentally specify _arg_ when you meant _@arg_ , both of which are syntactically correct (assuming _arg_ is the name of an argument in the current context) but have vastly different meaning. To help avoid this mistake, the compiler (as of edit 1065) will treat _arg_ as an error if it matches a current argument name; if you really meant to reference the argument by number, use a literal number or a variable that isn't a current argument. 

## **Parameters** 

Note that these parameters apply to all of the .ARG... functions. 

_argno_ (Unsigned int)  [in] 

The ordinal number of the argument being queried, starting from 1. Note that in the case of Named Parameters, the parameter numbers are determined by the function declaration or subroutine DEFXCALL directive, not necessarily by the order specified in the calling statement. If the _argno_ passed is invalid, the return value of the function will be -1. 

## _@arg_ (Literal parameter name)  [in] 

This syntax provides an alternate way to reference the parameter of interest by its name rather than its ordinal number. The concept is similar to that used for XPUTARG _@arg_ : _@arg_ is treated by the compiler as a macro for the argument number corresponding to the argument _arg_ as defined in the function/procedure definition or as retrieved in an SBX using XGETARG(S). 

## **Comments** 

The return value is a BOOLEAN, .TRUE if the argument was explicitly passed by the caller, rather than auto-set via the default value specification in the function declaration. Note that although this function is fully resolved by the compiler, making it at least nominally backwards compatible on runtime versions prior to 7.0.1767, it acts as the inverse of .ARGTYP_READONLY(). An argument that is only supplied by default is necessarily read-only, since there is no variable to pass an updated value back to. 

## **Example 1** 

A-Shell Reference 

Page 1407 

```
call fn'foo(arg=9)
```

```
...
```

```
function fn'foo(arg=1 as b2)
```

```
    ? .ARGTYP_READONLY(@arg)  ! .TRUE in all cases
```

```
    ? .ARG_PASSED(@arg)       ! .TRUE if > 7.0.1766, else FALSE
endfunction
```

The argument is readonly because it was passed as a literal value. The function could try to update it using `XPUTARG(@arg1)` but it would have no effect, since the value is on the stack. 

But readonly or not, it was actually passed, which might be meaningful to the called function. However, prior to 7.0.1767, the runtime is unable to determine that, so it will the readonly status instead. From 1767 forward, the two flags are independent. 

## **Example 2** 

```
call fn'foo()   ! no arg passed
```

```
end
```

```
function fn'foo(argx=0 as b2:outputonly)
```

```
    ? "argx=";argx;  .ifelse$(not .ARG_PASSED(@argx),"NOT ",""); "passed"
```

```
    call fn'nested'foo(argy=argx)
```

```
endfunction
```

```
function fn'nested'foo(argy=1 as b2:outputonly)
```

A-Shell Reference 

Page 1408 

- `? "argy=";argy;  .ifelse$(not .ARG_PASSED(@argy),"NOT ",""); "passed"` 

```
endfunction
```

The above program will display... 

```
argx= 0 NOT passed
```

```
argy= 1 NOT passed
```

... even though the call from fn'foo() to fn'foo'nested() actually does specify the argy=argx parameter, since the inheritance of the argument passed status carries down to the nested function. The fn'foo'nested() function could still pass an updated argument back to its immediate parent fn'foo(), but that value would not ever make it back to the top level since it wasn't passed from there.  (If fn'foo() really wanted the value passed back from fn'foo'nested(), it might want to use a different variable to eliminate the potential ambiguity over whether fn'foo'nested() needed to update that argument.) 

Note that this applies to both normal static function calls and dynamic (DYNFUNC) calls. 

## **See Also** 

- .ARGTYP() 

- .ARGSIZ() 

- .ARGTYP_READONLY() 

## **History** 

- 2025 March, A Shell 7.0.1770, compiler edit 1065:  ARG_PASSED() status now inherited. 

- 2025 January, A Shell 7.0.1767, compiler edit 1051: Add support for .ARGTYP_READONLY() and .ARGTYP_PASSED(). 

A-Shell Reference 

Page 1409 

## **.ARGTYP_READONLY()** 

_Reorganized August 2025_ 

## **.ARGTYP_READONLY(argno)    or    .ARGTYP_READONLY(@arg)** 

Indicates whether the specified argument was passed in the form of a variable that can actually receive an updated value. 

**Warning** : It is easy to accidentally specify _arg_ when you meant _@arg_ , both of which are syntactically correct (assuming _arg_ is the name of an argument in the current context) but have vastly different meaning. To help avoid this mistake, the compiler (as of edit 1065) will treat _arg_ as an error if it matches a current argument name; if you really meant to reference the argument by number, use a literal number or a variable that isn't a current argument. 

## **Parameters** 

Note that these parameters apply to all of the .ARG... functions. 

_argno_ (Unsigned int)  [in] 

The ordinal number of the argument being queried, starting from 1. Note that in the case of Named Parameters, the parameter numbers are determined by the function declaration or subroutine DEFXCALL directive, not necessarily by the order specified in the calling statement. If the _argno_ passed is invalid, the return value of the function will be -1. 

## _@arg_ (Literal parameter name)  [in] 

This syntax provides an alternate way to reference the parameter of interest by its name rather than its ordinal number. The concept is similar to that used for XPUTARG _@arg_ : _@arg_ is treated by the compiler as a macro for the argument number corresponding to the argument _arg_ as defined in the function/procedure definition or as retrieved in an SBX using XGETARG(S). 

## **Comments** 

The return value is a BOOLEAN.  It is logically equivalent to testing the ARGTYP_READONLY bit in the flags returned by .ARGTYP(). 

Note that attempting to update a read-only parameter (or one that wasn't even passed), using XPUTARG, is not an error; It just has no effect. 

A-Shell Reference 

Page 1410 

## **See Also** 

- .ARG_PASSED(), particularly the examples which include .ARGTYP_READONLY. 

A-Shell Reference 

Page 1411 

## **ERR()** 

The ERR(#) function was part of the original AlphaBASIC, to which A-Shell adds the new sub-functions, ERR(7,8,9). For completeness, all the sub-functions are documented in the following table: 

|**Sub-**<br>**Function**|**Description**|
|---|---|
|ERR(0)|Returns the last ASB error code. Seesys:errmsg.xxxfor the description of all the ASB<br>error codes. Also seeERRMSG<br> for info on displaying and/or logging the error text under<br>application control, as well as.LINENO<br>.|
|ERR(1)|Returns the last line number processed. Note that since ASB doesn't require line numbers<br>on every line, the last line number processed might be a long way from where the error<br>occurred (or it may be 0 if the program has no line numbers). See ERR(8) to get the<br>precise location of the error.|
|ERR(2)|Returns the last file channel processed. SeeFILNAM<br>for info on retrieving the name of the<br>file associated with the channel.|
|ERR(7)|(A-Shell Extension) Reports the location of the last error within the current stack<br>frame/scope. This would differ from ERR(8) if the error occurred within a function or<br>procedure and was allowed to percolate up to a higher level, where ERR(7) would indicate<br>the line that called the function or procedure. Also see.LOCATION in the Dot Variables table<br>to retrieve the current location counter outside the context of an ASB error.|
|ERR(8)|(A-Shell Extension) Returns the internal location counter where the error occurred. Note<br>that by convention, location counter values are usually displayed in hex, but the Basic<br>PRINT statement has no way to know (or support) this. So if you are going to print the<br>value of err(8), you may want to use MIAMEX, MX_OCVT, or the Fn'Dec2Hex$() function<br>(in theSOSLIB<br>). To match the location with a line of source code, you will need to<br>compile your program with the /L switch to create anLSX file<br>, which lists the location<br>counter (in hex) for each statement. Also see.LOCATION in the Dot Variables table<br>to retrieve<br>the current location counter outside the context of an ASB error.|
|ERR(9)|(A-Shell Extension) Returns the function or procedure nesting level at the time of the<br>error (equivalent to the dot variable .NEST_LEVEL). This might be helpful in debugging.|



A-Shell Reference 

Page 1412 

If you add TRACE=BASERR to miame.ini (highly recommended), then all ASB errors will be logged to the ashlog.log file, including most of the above information, and indicating whether the error was trapped. Also see Call Stack Tracing. 

- Errors occurring within User Defined Functions or Procedures will appear to the calling routine to have occurred on the line in which the Function or Procedure was invoked, unless the Function/Procedure performs its own local error trapping. 

## **History** 

- 2012 December, A Shell 6.1.1329:  ERR(7) added, meaning of ERR(8) restored to original (as documented above) 

A-Shell Reference 

Page 1413 

## **.EXTENT()** 

_Rewritten March 2025_ 

## **.EXTENT(ary(){,subno})** 

This function returns the "extent" of the specified array or collection, i.e. the number of elements in it. The first syntax applies to arrays; the optional subno parameter specifies the subscript or dimension number, defaulting to 1 for single-dimension array. It works for both static and DIMX arrays and is especially useful for those with the AUTO_EXTEND attribute.  For example: 

```
DIMX ary(p,q,r),s,25,AUTO_EXTEND
```

```
...
```

- `? .EXTENT(ary())    ! prints maximum current value of the first subscript, i.e. p in ary(p,q,r)` 

- `? .EXTENT(ary(),2)  ! prints maximum current value of the second subscript, i.e. q in ary(p,q,r)` 

The second syntax applies to ordered maps or Gridmaps.  For example: 

```
DIMX $zipcodes, ORDMAP(varstr;varstr)
```

```
$zipcodes("00000") = "North Pole" ! add an element
```

```
? .EXTENT($zipcodes())            ! displays 1 (one name-value pair)
```

```
$zipcodes("00000") = .NULL        ! delete the element
```

```
? .EXTENT($zipcodes())            ! displays 0
```

```
DIMX $table(int, int, varstr)
```

```
? .EXTENT($table())               ! displays 0 (map initialized but empty)
REDIMX $table()
```

A-Shell Reference 

Page 1414 

```
? .EXTENT($table())               ! displays -1 (map uninitialized)
```

## **Comments** 

In all the variations involving DIMX, if the array or map has not yet been initialized (i.e. the compiler has seen the DIMX statement but it was not yet executed at runtime), or it was executed and then freed with REDIMX (as in the last example above), .EXTENT() will return -1. 

As illustrated above, deleting elements from an ordered map or gridmap (by setting the value to .NULL) reduces the extent.  For standard arrays, there is no equivalent to deleting an element, and there is no way to add an element (x) without automatically adding any previously missing elements from (1) to (x-1).  So for those arrays, .EXTENT() effectively returns the highest element number previously assigned to that subscript (unless the array has been redimensioned with REDIMX), for example: 

```
DIMX a(0),b, 2, AUTO_EXTEND
```

```
a(9) = 1
```

```
? .EXTENT(a())    ! prints 9 (elements 1-8 were auto-filled with zeros)
```

```
REDIMX a(5)
```

```
? .EXTENT(a())    ! prints 5 (redimensioned size)
```

Also note that when a standard array is auto-extended, even though as an efficiency measure it typically allocates room for more than just the latest element, .EXTENT() only reports the highest element number actually assigned. 

## **See Also** 

- Sample programs in EXLIB:[908,61] 

A-Shell Reference 

Page 1415 

## **GETKEY()** 

## **GETKEY(X {,xltname})** 

This function inputs and returns the ASCII decimal value of a single character. The parameter _X_ must be one of the following: 

|**Value**|**Description**|
|---|---|
|0|Don't wait for input. If no characters are available, returns -1. This is similar toXCALL TINKEY.|
|-1|Wait until a character is entered. This is similar toACCEPTXS.|
|-2|Check if a character is available, but don't input it. Returns -1 if no character is available. (Some versions have returned 0<br>to indicate that a character is available, and others have returned the actual character value. For maximum compatibility,<br>you should treat anything other than -1 as indicating that a character is available, but then input it using one of the other<br>modes to determine its actual value.)|



The optional _xltname_ argument may be used to specify a function key translation table to process the character through if it is a function key. 

Note that the return value of 999 indicates an invalid value of X. A common mistake is to use 1 or 2 instead of -1 or -2. 

## **See Also** 

- ACCEPT, ACCEPNXS 

- GETXS  (keyboard or file input) 

- GETXXS 

- TINKEYXS 

A-Shell Reference 

Page 1416 

## **PYFUNC()** 

_Written August 2025_ 

PYFUNC() provides a means to call an external function written in Python version 3. 

## **PYFUNC (module, funcname {, arg1, ... argn})    ! (numeric return value) PYFUNC$ (module, funcname{, arg1 ... argn})    ! (string return value)** 

where: 

_module_ (String)  [in] 

filespec (native format) of the module containing the function; (default extension py) 

_funcname_ (String)  [in] 

name of the function to call 

_arg1 ... argn_ (any scalar type)  [in] 

zero or more arguments to the function 

PYFUNC uses the Python C interface API to initialize the Python environment. If necessary, certain Python environment variables can be set via the file %MIAME%/pyconfig.ini, formatted as follows: 

```
[Python]
```

```
;Base directory for Python installation (executable)
```

```
HOME=C:\Program Files (x86)\Python312-32
```

```
;PLATLIBDIR=
```

The pyconfig.ini file can be eliminated if Python is set up to run from the command or shell prompt without explicit settings. 

A-Shell Reference 

Page 1417 

Unlike other A-Shell function interfaces, the parameters here are all read-only, so if the function is to return anything to caller, it must be done through the return value of the function, either a scalar or an auto-extend array.  Examples: 

```
city$ = pyfunc$("./geo.py", "capital_of", "California")
```

```
median = pyfunc(".math.py", "median", 5, 23, 15, 100, 44, 11)
dimx ary(0), b, 2, auto_extend
```

```
...
ary() = pyfunc("./mymod.py", "myfunc", 10, 20, 30)
```

Warning: this interface is still in the experimental stage. We're not yet sure if there's really any application for it, and there are a number of complexities that will need to be sorted out. Developers are advised to provide feedback to us before investing too much effort into it. 

A-Shell Reference 

Page 1418 

## **XFUNC() AND XFUNC$()** 

_Updated June 2025_ 

## **XFUNC (sbxname, arg1,...,argn)** 

## **XFUNC$ (sbxname, arg1,...,argn)** 

XFUNC and XFUNC$ execute an external SBX routine, returning a numeric or string value. They are nearly identical to XCALL in that they load and call an SBX, except that they are expressions (which return values) rather than statements (which do not). The only special requirement for the SBX routine is that it return a value— numeric for XFUNC or string for XFUNC$—via a special form of the RETURN statement. The return value will be ignored if the SBX is called via XCALL, allowing a single SBX to work with both XFUNC/XFUNC$ and XCALL. 

## **Parameters** 

_sbxname_ (String)  [in] 

name (without path or extension) of the SBX subroutine which implements the function 

_arg1,...,argn_ (any data types)  [in/out] 

arguments passed to the SBX routine 

## **Examples** 

Here is an example of an SBX to concatenate two strings that can be called via XCALL (returning the result in the 3rd parameter), or via XFUNC$ (returning the result as the value of the function): `map1 var1$,s,30,"  abra   " map1 result$,s,50` 

```
    xcall CONCAT2,var1$,"  cadabra  ",result$
```

A-Shell Reference 

Page 1419 

```
    ? "xcall result:  "; result$
```

```
    ? "xfunc$ result: "; xfunc$("CONCAT2", var1$,"  cadabra  ")
```

```
    end
```

Both the XCALL and the XFUNC$ statements above invoke the same CONCAT2.SBX routine, which, if written to handle both calling methods, will result in the same output for the two print statements above, i.e. 

```
.RUN TSTCONCAT2
```

```
xcall result:  abracadabra
```

```
xfunc$ result: abracadabra
```

This sample program illustrates the use of the XPUTARG and RETURN (expr) statements to support both calling interfaces. 

```
program CONCAT2, 1.0(100)  ! sbx to strip spaces and concatenate 2 strings
```

```
!------------------------------------------------------------------------
```

```
!NOTES
!   xcall CONCAT, arg1$, arg2$, result$
!or
```

```
!   xfunc$("CONCAT", arg1$, arg2$)  - returns result as value of function
!------------------------------------------------------------------------
```

```
++pragma SBX
```

A-Shell Reference 

Page 1420 

```
map1 params
```

```
    map2 arg1$,s,0
    map2 arg2$,s,0
    map2 result$,s,0
```

```
xgetargs arg1$, arg2$
xcall TRIM, arg1$
xcall TRIM, arg2$
result$ = trim$(arg1$) + trim$(arg2$)
```

```
xputarg 3,result$           ! return result in 3rd param (if XCALL)
return (result$)            ! in case called via XFUNC$
```

```
end
```

## **Comments** 

As with subroutines, any of the arguments passed to XFUNC/XFUNC$ can be updated by the SBX routine, although any such updates will only have an effect if the argument was passed as a variable. 

As with other system-defined functions, XFUNC and XFUNC$ are expressions—not labels—and thus cannot be invoked with the CALL statement. 

## **See Also** 

- Call SBX as a Function 

A-Shell Reference 

Page 1421 

- AG_XFUNC 

A-Shell Reference 

Page 1422 

## **- USER DEFINED FUNCTIONS** 

_Updated October 2016; see History_ 

## **{PRIVATE} {DYNAMIC} FUNCTION FN'name{$}(p1{=defval} {as typsiz{:mod}},...pN...) {as typsiz}** 

<optional local MAP statements, with optional STATIC prefix> 

<optional XGETARGS> 

<nearly any kind of statements> 

## **FN'name = <expression>** ! set return value 

## **<optional XPUTARGs>** 

## **ENDFUNCTION** 

The function definition, as shown above, starts with the zero or one of the optional keywords "PRIVATE" / "DYNAMIC" (see Private Functions and Procedures and Dynamic Functions for details), followed by the keyword "FUNCTION" followed by the function name, the list of formal parameters, and the function return type. The function name by convention starts with **FN'** , **Fn'** , or **fn'** so that references embedded in expressions can easily be identified as function calls rather than arrays; see Function Name and Type for clarification. The function name must end with **$** if the function returns a string or unformatted or defined structure type. If the final { _as typsiz_ } clause (which defines the return type of the function) is omitted, the default type is **F6** . 

The _typsiz_ (data type and size) specification is similar to that used in MAP statements, except without a comma between the type code and the size. For example: 

```
FUNCTION Fn'Test(p1 as S10, p2 as f6, p3 as B2, p4 As x256) AS i2
```

```
Function fn'display'name$(cus as ST_CUS_REC, bold as BOOLEAN) as s MAX_NAME
```

A-Shell Reference 

Page 1423 

```
function fn'test(p1 as s20:inputonly, p2 as ST_PHONE:outputonly)
```

The first example above illustrates that, as with virtually all keywords, the FUNCTION keyword and _AS typsiz_ clauses are **not** case sensitive. However, as with all other variables and labels, the function name and the formal parameter names **are** case sensitive, unless compiled with the /ci option. 

The optional {= _defval_ } clause assigns a default value to the parameter; see Named Parameters. 

The optional : _mod_ clause may be used to declare certain modifying attributes for the parameter, such as _inputonly_ or _outputonly_ ; see Parameter Type and Size. 

## **See Also** 

- XFUNC() 

- Procedures 

- SOSLIB:[907,10] also known as SOSFUNC 

## **History** 

- 2016 August, A Shell 6.3.1523, compiler edit 770:  Add private attribute for functions and procedures. 

- 2014 October, A Shell 6.1.1391: Function name does not need to begin with FN'; see History note in Function Name and Type 

- 2014 September, A Shell 6.1.1389:  A-Shell now supports Passing DIMX Arrays to functions/procedures by reference. 

- 2014 January, A Shell 6.1.1373: Named parameters implemented in A-Shell. 

## **Subtopics** 

- Function Name and Type 

- Parameter Type and Size 

- Named Parameters 

A-Shell Reference 

Page 1424 

- Parameter Passing 

- Return Expression 

- Local Variables 

- Global/External Variables 

## · Exit Label $EXIT 

- Error Trapping in Functions 

- Invoking A Function 

- Private Functions and Procedures 

- Dynamic Functions 

- Ellipsis Function Arguments 

- Indirect Function Calls 

- User-Defined Function Examples 

- Implicit Function Return Value Capture 

A-Shell Reference 

Page 1425 

## **FUNCTION NAME AND TYPE** 

_Updated June 2026_ 

The function name must begin with FN' and is case insensitive. (Changed; see History, below). A side effect of this rule is that you may not define an array with a name starting with FN'. 

Like other ASB expressions, functions fall into two fundamental types: numeric and string / unformatted. So that the compiler can immediately recognize the type of the function when it is referenced before being defined (without requiring forward declarations), the following naming convention is required: 

- Functions that return string (or unformatted or structure) values must have names that end in $, such as Fn'Format$(...) 

- Functions that return numeric values must have names that do not end in $, such as Fn'Average(...) 

The return type can be further refined by appending the " `as <typsiz>` " clause to the end of the Function declaration, as in the Examples below. Note, however, that you cannot override the rule just stated regarding the requirement that the names of functions returning string or unformatted values must end in $, while those returning numeric values must not end in $. If no " `as <typsiz>` " clause is specified, the standard defaults for implicit mapping of variables will determine the return type (i.e. F,6 for numeric functions, and S,# where # is 10 or the current STRSIZ for string functions. 

## **Examples** 

```
Function Fn'Foo()              ! returns F,6 (default for numeric function)
```

```
Function Fn'Foo$()             ! returns S,<strsiz>
```

```
Function Fn'Foo() as i2
```

```
Function Fn'Foo() as BOOLEAN   ! see below
Function Fn'Foo$() as ST_BAR   ! see below
```

The fourth example above would only be legal if BOOLEAN is defined (via DEFTYPE) as a numeric type.  Similarly, the fifth example would only be legal if ST_BAR was either defined via DEFTYPE as a string type, or via DEFSTRUCT. All structures are effectively type X, which is treated as variant of string rather then number. 

A-Shell Reference 

Page 1426 

## **History** 

- 2014 October, A Shell 6.1.1391: Compiler enhancement (edit 708): when the /P (or -p) switch is used, it is no longer required that function names start with fn'. The main downside of taking advantage of this option is that it could make your source code harder to understand, since it wouldn't be immediately clear whether a subscripted identifier appearing in an expression, e.g. 

```
something = WhatIsThis(idx)
```

is an array reference or a function reference. The compiler can tell the difference though. The upside is mainly aesthetic, allowing you to syntactically simplify your functions. This could be particularly helpful in cases where you have class-like collections of related functions and procedures. These can all share a common prefix, allowing you to adopt a simpler but more object-oriented syntax scheme, i.e. object.verb(params). 

**Warning:** This feature is somewhat non-standard, and may not be recognized by the APN Goto Definition mechanism. 

A-Shell Reference 

Page 1427 

## **PARAMETER TYPE AND SIZE** 

_Revised June 2026_ 

Parameters in function and procedure definitions have an optional "as <typsiz>{:<mod>)" clause to declare the type, size, and modifiers for the parameter. This also applies to the return type of the Function. If no clause is specified, the default type and size follows the normal rules for ASB. The fact that you probably aren't 100% certain what those rules are should reinforce the importance of always defining the type and size explicitly. The following examples will help clarify the syntax: 

## **Example 1** 

```
FUNCTION Fn'Test(p1 as S10, p2 as f6, p3 as B2, p4 As x256) AS i2
```

This illustrates the fact that although the _<typsiz>_ clause uses the same fundamental data types as in MAP statements, here there is no comma between the type and size (e.g. " `var2 as f6` " instead of " `map2 var2,f,6` "). It also illustrates the case insensitivity of the native type codes (F, S, B, X, I) and the AS keyword. 

## **Example 2** 

```
Function fn'display'name$(cus as ST_CUS_REC, bold as BOOLEAN) as s MAX_NAME
```

This shows the possibilities for using symbolic types and sizes rather than just the fundamental types and hard-coded sizes. One possibility is to use a DEFSTRUCT (i.e. "as ST_CUS_REC"). Another is to use a symbol defined via a DEFTYPE statement(i.e. "bold as BOOLEAN"). Syntactically, it's impossible to tell the difference between a defined structure name and DEFTYPE name, but the assumption here is that BOOLEAN was defined via `DEFTYPE BOOLEAN = I,2` . 

A third possibility is to replace just the size with a symbol, e.g. " `as s MAX_NAME` "). In this case, a single space is required between the native variable type ("s") and the symbol name (MAX_NAME). Using a symbol rather than a hard-coded number is useful for avoiding a common bug that may happen when passing string arguments to functions, where you decide to increase the size of the string field elsewhere in the application but forget about the function, resulting in the value being truncated within the function. But the technique has largely been superseded by the DEFTYPE method, which eliminates such discrepancies both in the parameter size and its type. 

For string and X parameters, another way to avoid the truncation bug just described is to use Dynamically Sized Variables within the function. 

A-Shell Reference 

Page 1428 

## **Example 3** 

```
function fn'test(p1 as s20:inputonly, p2 as ST_PHONE:outputonly)
```

This illustrates the use of the optional _:<mod>_ clause to specify a modifier affecting the way the parameter is to be used. The available modifiers are _inputonly_ and _outputonly._ 

The _inputonly_ modifiier serves primarily as an aid to self-documenting code, but will also cause the compiler to generate an error if you explicitly reference the parameter in an XPUTARG statement. _Note, however, that there is no run-time aspect of this feature_ , so you won't be stopped from outputting to the parameter using a variable to specify the parameter number in the XPUTARG statement. 

The _outputonly_ modifier also aids in self-documenting your code, but in addition it skips the input parameter binding operation (which, for very large parameters could save a lot of CPU cycles). 

In the absence of an _inputonly_ or _outputonly_ modifier, the parameter is consider input/output. Note however, that since parameter passing is, in almost all cases, by value (as opposed to by reference), there is no automatic updating of the variables passed by the caller, unless you use explicit XPUTARG statements. 

## **Example 4** 

```
function Fn'Get'Date'Time$(dt=-1 as b4:outputonly, tm=-1 as b4:outputonly) as s40
```

This illustrates the use of default values (=-1) and outputonly clauses.  Without the default value, any parameter not explicitly passed by the caller,  and all outputonly parameters, would be initialized to zero or null, just like mapped variables.  Specifying a default value also has the less obvious effect of allowing the caller to ignore (i.e.not specify) particular parameters, and/or vary the parameter order, e.g. 

```
call Fn'Get'Date'Time$(tm=TIME'NOW)
```

Without the default value for the _dt_ parameter in the function declaration, the compiler would complain about the above statement missing the mandatory _dt_ parameter. See the  Named Parameters and Parameter Passing (In) topics for more about that. 

**Warning** : the treatment of the outputonly modifier has changed over time; see the _History_ notes below for details. 

## **History** 

A-Shell Reference 

Page 1429 

- March 2025, A Shell 7.0.1770.2, compiler edit 1065:  The .ARG_PASSED(@parm) status is now inherited even for outputonly parameters.  (Technically, while the caller may specify an outputonly parameter,  they aren't passed.  The intent of the .ARG_PASSED() function, despite its name,  was to allow the function to decide whether it was necessary to go to any extra effort to pass the parameter back.) 

January 2025, A-Shell 7.0.1767.0, compiler edit 1054:  Introduce ++PRAGMA OVERRIDE_OUTPUTONLY (causing outputonly to revert to the behavior prior to compiler edit 1047) 

- November 2024, A Shell 7.0.1756.6, compiler edit 1047:  Prior to this update, specifying a default value causing the outputonly modifier to be ignored, which also meant that the value of the parameter passed by the caller would override the default value clause.  The outputonly clause was also interfering with the ability to reference the parameter in a DYNFUNC() call. 

A-Shell Reference 

Page 1430 

## **NAMED PARAMETERS** 

_Revised and reviewed April 2020_ 

Named parameters, also called "keyword arguments," may be used in place of, or in conjunction with, the traditional ordered parameters for all function and procedure calls. (For related information as it applies to subroutines, see Named Parameters in Subroutines.) Although this feature is really just a syntactic nicety rather than a fundamental capability, it nevertheless offers a variety of benefits: 

- makes code more self-documenting 

- reduces errors relating to omitting or mis-ordering parameters 

- allows functions to specify default parameter values besides 0 or "" 

- allows functions to specify mandatory parameters 

- allows caller to specify just the parameters of interest, omitting the defaults 

- allows the compiler to detect badly formed function calls 

The ASB implementation of named parameters is similar to that found in other modern languages such as Python, in which the parameter names are extracted from the existing function and procedure definitions without requiring any syntactic changes to existing definitions. In addition, function and procedure definitions may specify default values for one or more parameters. Parameters with specified defaults are considered optional parameters, whereas those without defaults are considered mandatory. 

However, there is one important exception to this rule, required for backward compatibility. Since ASB has traditionally treated ALL function, procedure and subroutine parameters as optional, it will continue to do so unless a function/procedure definition is modified to specify at least one default value. 

This will become clear with a few examples, but first let's note the following points: 

- Named parameters are resolved entirely by the compiler. Thus programs using named parameters are backwards compatible 

- back to the 5.0 runtime, and the runtime system has no way of detecting if a particular call used named or traditional ordered parameters. 

A-Shell Reference 

Page 1431 

• The semantics regarding optional and mandatory parameters are entirely determined by the function/procedure definitions, and not affected by whether the routine is called with named or ordered parameters. 

• Since the compiler needs to see the function/procedure definition before any calls which use named parameters, it requires a new preliminary pass of the entire source to build a table of the definitions. Although this pre-pass is very fast, to avoid inflicting any performance penalty or risk of side effects on programmers not using named parameters, the preliminary pass and thus the named parameter feature requires a new switch: /P or /PX. The latter also activates logic in the pre-pass to identify functions and procedures which are not actually called, eliminating them from the compiled output. 

• In order to create common utility functions and procedures that might need to be compiled by older versions of the compiler, the /P switch will define a symbol ABC_NAMED_PARAMS=1 which you can use in conditional compilation statements to specify alternate versions of your function/procedure definitions. See example below. 

• Ambiguity/Compatibility Warning: Expressions of the form A=B have always been legal where expressions are legal, and thus Fn'X(A=B) is legal with any version of the compiler, provided that A and B are mapped variables or that (the horror!) you are compiling without the /M switch. The expression evaluates to true (-1) if A equals B, and or false (0) otherwise. Use of the /P switch disables that dubious feature within subroutine and function/procedure calls, and instead interprets the expression as a request to set the named parameter A to the value B. However, there is possibility that calls with named parameters might be compiled under an older compiler or without the /P switch, resulting in a syntactically correct but semantically confused RUN file. To avoid this possibility, in programs that use named parameters, you should include a conditional compilation test to detect an attempt at compilation without /P and to report it as an error, e.g.: 

```
++ifndef ABC_NAMED_PARAMS
```

```
    ++error This program requires compiler 653+ (and /P)
```

```
++endif
```

Now for the examples. Consider the following function which takes the names of players at the first, second and third base positions and displays them as a sentence, as in the famous Abbott & Costello routine, i.e. "Who's on first, What's on second, and I Don't Know's on third". 

```
function fn'lineup$(first$ as s0, second$ as s0, third$ as s0) as s0
```

Traditionally, any of the following would be legal invocations of the function, at least from the compiler's perspective: 

A-Shell Reference 

Page 1432 

```
? fn'lineup$()
```

```
? fn'lineup$("Who")
```

```
? fn'lineup$("Manny","Moe")
```

- `? fn'lineup$(spam$,spam$,spam$,spam$)` 

The first three examples specify fewer than the three expected parameters, but since there is no enforcement of minimum parameter counts, the compiler is happy. The routine itself can test .ARGCNT to see how many were actually passed. The fourth example specifies an extra parameter, which the compiler is happy to pass, and the routine may simply ignore, although it also has the ability to retrieve such additional parameters using explicit XGETARG statements. 

Using named parameters, any of the following are also legal: 

- `? fn'lineup$(first$="Who", second$="What", third$="I don't know")` 

- `? fn'lineup$(second$="Jack", first$="Manny")` 

- `? fn'lineup$("Eenie", "Meenie", third$="Mo")` 

The first simply adds the names of the parameters, making the code a bit more self-documenting. The second illustrates that you can rearrange the parameters since the compiler can match the names up to their proper positions, and you can also omit trailing parameters, in this case third$, provided it doesn't create a gap. The third example illustrates that you can combine ordered and named parameters, as long as the ordered ones ("Eenie" and "Meenie" in this case) come first. 

These, however, are illegal: 

- `? fn'lineup$(first$="Who", shortstop$="Curly")` 

- `! no such parameter: shortstop$` 

- `? fn'lineup$(first$="Manny", "Mo", "Jack")` 

A-Shell Reference 

Page 1433 

```
        ! ordered parameters cannot follow named parameters
```

```
? fn'lineup$(first$="Tiny", second$="Fats", first$="Tiny")
```

```
        ! parameter first$ specified twice
```

```
? fn'lineup$(second$="What", third$="Nobody")
```

- `! missing mandatory first$ parameter` 

The last example above deserves clarification. Although traditionally all parameters were optional, it was never possible with ordered parameters to omit one, other than at the trailing end of the parameter list. Consequently, to preserve runtime compatibility, we don't want to allow that to happen with named parameters either, at least by default. 

However, by adding default values for one or more parameters in the function/procedure definition, we can effectively instruct the compiler regarding which parameters are mandatory and thereby have it do more of the work of error checking and standardizing function and procedure calls. To accommodate default values, a default value may be specified for any parameter in the function declaration, using the following syntax: 

## **<paramname>{=defvalue} as <type>{:modifier}** 

For example: 

```
function fn'lineup$(first$="Who" as s0, second$ as s0, third$="I don't know" as s0) as s0
```

Or, if we want to make it clear that these are all inputonly parameters, we can add the :inputonly modifier: 

```
function fn'lineup$(first$="Who" as s0:inputonly, second$ as s0:inputonly, third$="I don't know" as
s0:inputonly) as s0
```

With the updated function definition, we can reevaluate how the compiler would treat the example calls: 

```
? fn'lineup$()
```

A-Shell Reference 

Page 1434 

```
        ! illegal (missing mandatory second$ parameter)
```

```
? fn'lineup$("Who")
```

```
        ! illegal ("    "   ")
```

```
? fn'lineup$("Manny","Moe")
```

```
        ! ok (missing third$ defaults to "I don't know")
```

```
? fn'lineup$(spam$,spam$,spam$,spam$)
```

```
        ! ok
```

```
? fn'lineup$(first$="Who", second$="What", third$="I don't know")
```

```
        ! ok
```

```
? fn'lineup$(second$="Jack")
```

```
        ! ok (first$ defaults to "Who" and third$ to "I don't know")
```

```
? fn'lineup$("Eenie", "Meenie", third$="Mo")
```

```
        ! ok
```

Finally, if we want to make our fn'lineup$() function available in a library where it might be compiled with an older version of the compiler, we can use conditional compilation to specify two versions of the function definition—one traditional (ordered parameters only) and one modern (with named parameters and default values): 

```
++ifdef ABC_NAMED_PARAMS                ! if /P (named parameter supported)
```

```
    function fn'lineup$(first$="Who" as s0, second$ as s0, third$="I don't know" as s0) as s0
```

```
++else                                  ! traditional version
```

A-Shell Reference 

Page 1435 

```
    function fn'lineup$(first$ as s0, second$ as s0, third$ as s0) as s0
```

```
++endif
```

```
    fn'lineup$ = first$ + "'s on first, " + second$ + ",s on second, and " + third$ + ",s on third."
    endfunction
```

Note: in the case of the outputonly modifier, the default value is effectively the initial value regardless of whether the parameter was specified in the calling statement. See History. 

## **History** 

- 2024 November, A Shell 7.0.1765, compiler edit 1047:  Default value no longer overrides outputonly modifier when argument passed by caller. 

- 2017 June, A Shell 6.3.1514, compiler edit 762:  /PX switch added. 

- 2014 January, A Shell 6.1.1373:  Named parameters implemented in A-Shell. 

A-Shell Reference 

Page 1436 

## **PARAMETER PASSING** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- By Value 

- By Reference 

- Parameter Passing (In) 

- Parameter Passing (Out) 

A-Shell Reference 

Page 1437 

## **BY VALUE** 

_Written July 2023_ 

By default, parameters are passed to functions and SBX subroutines "by value", meaning that the value of the source (calling) parameter is passed to the variable within the target function or subroutine. This is essentially equivalent to an assignment statement, with automatic type conversions taking place as necessary. In order for an updated value to be passed back, the function or subroutine must explicitly use an XPUTARG statement to perform the reverse assignment—i.e., to copy the updated value back to the calling parameter (again, with type conversions as needed). Note that parameter passing by value can be limited to one direction by adding the inputonly or outputonly (User-Defined Functions) modifiers on the function parameter declaration. 

## **Example** 

```
map1 brownbag, ST_LUNCH
    ...
```

```
    call Fn'School(brownbag)
    ...
```

```
Function Fn'School(lunch as ST_LUNCH)
    ...
   xputarg @lunch
EndFunction
```

In the above example, the local variable lunch receives a copy of the value of the variable brownbag. Any changes to the the lunch variable within the function have no effect on the brownbag variable until the (optional) XPUTARG @lunch statement copies the updated value back. 

A-Shell Reference 

Page 1438 

## **BY REFERENCE** 

_Written July 2023_ 

While the standard method of passing parameters By Value is sensible for individual scalar parameters, it isn't practical for entire arrays and collections. Instead, these are passed "by reference", meaning that rather than copying the value from the source to the target, a reference is passed instead. The effect is make the array or collection within the called routine essentially an alias of the array or collection in the calling routine. In this case, the inputonly or outputonly modifiers wouldn't make any sense. 

Note that passing parameters by reference, there is no opportunity for data type conversions to take place. In general it is left to the programmer to make sure that the source and destination types are compatible, but in the case of collections, to avoid hardto-debug or otherwise catastrophic mismatches, the compiler does enforce certain rules.  See Mismatched Collection Arrays for details. 

```
dimx kindergarden(0), ST_STUDENTS, auto_extend
```

```
    ...
```

```
call Fn'Field'Trip(kindergarten())
```

```
    ...
```

```
Function Fn'Field'Trip(class() as ST_STUDENTS)
```

```
    ...
```

```
EndFunction
```

In the above example, the entire dynamic array kindergarden() is passed by reference to the function, where it is referenced by the local name class().  Any changes made to class() within the function, including extending (or otherwise redimensioning the array) will be directly reflected in the source array kindergarten(). The use of XPUTARG does not apply. 

## **History** 

A-Shell Reference 

Page 1439 

- 2023 August, A Shell 6.5.1740: DIMX arrays of type S or X are now treated as compatible with each other when passed by reference to a function. Previously this triggered an incompatible parameter error. 

## **Subtopics** 

- Passing DIMX Arrays 

- Passing Collections I 

A-Shell Reference 

Page 1440 

## **PASSING DIMX ARRAYS** 

_Modified (Example 3) August 2015_ 

Arrays can be passed as parameters to functions/procedures/subroutines, but the techniques vary depending on whether the array is static or dynamically mapped. For static mapped arrays, the only available technique is to map an X variable as an overlay over the array, e.g. 

```
map1 blob
```

```
   map2 array(200)
      map3 field1,s,4
      map3 field2,f,6
...
call Proc(blob)      ! pass the array by means of the overlay
```

Passing DIMX arrays, by contrast, requires one of the following special methods: 

- Using Dynamic Overlays to pass a copy of the array as a blob. 

- Using pass-by-reference; see following discussion 

Unlike the normal pass-by-value method for parameter passing, in which the called routine receives a copy of the parameter, pass-by-reference provides the called routine an alias—essentially a pointer—to the original parameter/array. This is much more efficient than making a copy of the entire array and then having to transfer that copy back to the original on return. Both the alias array and the original array refer to the same set of elements; the only difference between them is the name. Any changes made to the alias array (including resizing or auto-extending it) are directly made to the original array (since they are the same array). 

Passing an array by-reference is architecturally nearly the same as just accessing it globally—i.e., using ++EXTERN or ++PRAGMA AUTO_EXTERN within the called routine to bring the global array into scope. The main advantages are that it makes the code (on 

A-Shell Reference 

Page 1441 

the calling side) somewhat more explicit/self-documenting, and it provides the called routine the flexibility to act on different source arrays (determined by the caller). 

The syntax for indicating an array to be passed or received by reference is to use an empty set of parentheses, e.g. ARY(), as in the following examples. 

## **Example 1: Pass DIMX array of structures to function / procedure** 

```
dimx CUST(0), ST_CUST, auto_extend
```

```
...
call Add'Items'To'Array( CUST(), 5 )  ! pass CUST() by reference to function
```

```
...
procedure Add'Items'To'Array( ary() as ST_CUST, count as b2)    ! rcv array by reference
```

```
   map1 p,i,2
   map1 i,i,2
   p = .extent( ary() )
   for i = p+1 to p+count
      ary(i).field = <data>    ! ary() is effectively alias for passed CUST()
   next i
endprocedure
```

In the above example, the array ary() within the procedure becomes an alias to the array CUST() in the calling routine, and any changes made to ary() within the procedure are reflected in CUST() immediately. 

Neither the compiler nor runtime system (currently) can verify that the passed and received structure types are the same; the runtime system can only verify that the structure sizes are the same. This could allow for a kind of polymorphism—or more 

A-Shell Reference 

Page 1442 

likely, subtle bugs—if you do not take care to make sure that the structure types are in fact the same. In the above example, both the source array CUST() and the received array ary() are explicitly declared as the same structure type, ST_CUST. 

Note: Do not attempt to use XPUTARG to copy the array back to the caller; this would make no sense. 

## **Example 2: Pass DIMX array of dynamic blobs to function / procedure** 

The syntax and other logic for passing a DIMX array of X,0 elements is essentially the same as in the example above, e.g. 

```
dimx XRY(0),X,0,auto_extend   ! declare DIMX array of variable length blobs
```

```
...
```

```
call Add'Items'To'Array( XRY() )  ! pass XRY() by reference to procedure
```

```
...
procedure Add'Items'To'Array( xry() as x0)    ! rcv array by reference
map1 i,f
do while <some condition>
    xry(i) = <some variable length string or binary data>
loop
```

```
endprocedure
```

The source array must be defined at the global or module-scope—i.e., PRIVATE DIMX—level, rather than locally within a function. This is to ensure that the contents remain valid when referenced within another scope. 

Currently this only works for X,0 (and not S,0) variables. The restriction may be lifted, but there is no particular need since dynamic X variables are practically interchangeable with dynamic S variables anyway.  The main distinction between X and S has to do with the whether bytes past the first null are considered significant, but this isn't really a factor when loading string data into dynamic X variables, since the variable size would be trimmed to eliminate any bytes after the null terminator anyway. 

A-Shell Reference 

Page 1443 

## **Example 3: Pass DIMX array of structures to XCALL SBX** 

Passing a DIMX array of structures to a subroutine (SBX) is similar to passing one to a function or procedure, at least from the calling side, e.g. 

```
dimx myary(0),ST_MYSTRUCT,auto_extend   ! define source array
```

```
...
```

```
xcall MYSBX,myary(),...                 ! specify in arg list with empty ()
```

On the receiving side (within the SBX), because there is no equivalent of the formal parameter declaration like there is in Functions and Procedures, the SBX has to declare a surrogate array using a special form of the DIMX statement with the BYREF modifier, and the initial subscript value set to -1, e.g.: .: 

```
dimx locary(-1), ST_MYSTRUCT, byref       ! define surrogate local array
```

The surrogate local array will not work correctly unless the subscript in the dimx statement is -1, and the BYREF clause is specified. Prior to 6.1.1415 (compiler edit 744), the compiler failed to complain about invalid subscript values such as 0 or 1. 

To receive the array passed by reference, use the normal xgetargs syntax, but with an empty set of parentheses for the local surrogate array, e.g. 

```
xgetargs locary(), ...
```

Note that as with the function / procedure examples, there is no need for any XPUTARG statement to send the updated array back to the caller, since the called routine effectively shares the same copy of the array with the caller. 

## **History** 

- 2025 August, A Shell 7.0.1762:  Added capability, and documentation, for  passing un-DIMXed arrays. 

- 2023 January, A Shell 6.5.1724: DIMX arrays of type S may now be passed by reference to functions; previously, only type X was allowed. Also, DIMX arrays of type B, F and I may now be passed by reference to functions. 

A-Shell Reference 

Page 1444 

- 2014 November, A Shell 6.1.1398:  Pass-by-reference extended to XCALL (SBX) 

- 2014 November, A Shell 6.1.1398:  Pass-by-reference extended to XCALL (SBX) 

- 2014 October, A Shell 6.1.1391: Pass-by-reference feature introduced for functions and procedures (not XCALLs) 

PASSING UNDIMXED ARRAYS 

_Written August 2024_ 

Beginning with A-Shell 7.0.1762 of August 2024, it is  possible to pass an un-DIMXed array received via a .NULL initialization within a function to another function. To illustrate, the following code calls a function without passing the expected array parameter. But the function declaration defaults the array to .NULL, which effectively treats the array as if un-DIMXed. 

It then passes it to fn'two(), which also treats it as un-DIMXed. 

Previously the call from fn'one() to fn'two() would have generated an error. 

Note that this technique is only useful if you test the extent of the received array before attempting to access it, since any such access will generate an undimensioned array error. 

```
call fn'one()
```

```
...
```

```
function fn'one(ary1()=.NULL as ST_1)
```

```
    ? "Extent of ary1() = "; .extent(ary1())   ! -1
    call fn'two(ary2()=ary1())
```

```
endfunction
```

```
function fn'two(ary2()=.NULL as ST_1)
```

```
    ? "Extent of ary2() = "; .extent(ary2())   ! -1
```

A-Shell Reference 

Page 1445 

```
endfunction
```

## **History** 

- 2025 August, A Shell 7.0.1762:  Added capability, and documentation, for  passing un-DIMXed arrays. 

A-Shell Reference 

Page 1446 

## **PASSING COLLECTIONS I** 

_Updated June 2023; see History_ 

An entire ordered map may be passed by reference to functions, procedures, and subroutines. Conceptually and syntactically this is very similar to passing other kinds of DIMX arrays by reference. On the calling side, you specify the array in the parameter list using an empty set of parentheses, for example... 

```
dimx $mymap, ordmap(varstr;varstr)
```

```
...
```

```
call MyProc($mymap())         ! pass $mymap() ordered map by reference to procedure
```

```
xcall MYSBX, $mymap(), ...    ! pass $mymap() ordered map by reference to SBX
```

On the receiving side, the syntax is somewhat different between functions/procedures, on the one hand, and SBX routines on the other. In the case of functions and procedures, you declare the local name for the array in the parameter definition also with an empty set of parentheses, with the "as clause" specifying the ordered map type, e.g. 

```
Procedure MyProc($m() as ordmap(varstr;varstr))
```

```
   $m("foo") = "bar"      ! updating m$() updates $mymap() directly
```

In the case of an SBX, you must use a special variation of the DIMX statement, with the BYREF clause, to declare the local copy of the map, and then use XGETARG{S} to set up the connection to the calling map: 

```
dimx $m ordmap(varstr;varstr), byref    ! declare surrogate local version of map
```

```
...
```

```
xgetargs $m(), ...
```

A-Shell Reference 

Page 1447 

or 

```
xgetarg 1, $m()
```

See the following subtopic for information on Mismatched Collection Arrays. 

Note that once the ordered map passed by the caller is linked to the local surrogate ordered map using one of the above schemes, from that point on, the local and remote arrays are the same, i.e. their names are aliases for the same ordered map, and any changes made within the function or SBX will directly affect the caller's copy of the map. 

Do not use XPUTARG to try to pass back the updated local array, as this is both superfluous and senseless. 

In addition to passing ordered maps by reference to any SBX written to receive them, there may be specific built-in subroutines which are capable of handling ordered maps passed by reference in very specific cases, in which case it will be explicitly so noted in the documentation for that subroutine. For example, see the CGIUTL opcode CGIOP_GETPARRAY. 

## **See Also** 

- MAPDIR.BP (SBX) and the corresponding TSTMAPDIR in SOSLIB:[907,45] which illustrate passing an ordmap to an SBX by 

- reference. 

## **History** 

- 2023 June, A Shell 6.5.1731, compiler edit 1022:  Compiler now complains about mismatched collection arrays passed by reference to functions. 

- 2017 December, A Shell 6.5.1623:  Add ability to pass ordered maps by reference to functions and procedures. 

- 2016 August, A Shell 6.3.1520:  Add capability to A-Shell. 

## **Subtopics** 

- Passing Collection Elements 

A-Shell Reference 

Page 1448 

- Passing Collections II 

- Mismatched Collection Arrays 

## PASSING COLLECTION ELEMENTS 

Ordered map element values, being variable length strings or unformatted blobs, may be passed as parameters to functions, procedures and subroutines just as you would an ordinary S,0 (dynamic string) or X,0 (dynamic unformatted blob) variable or expression. But note that since references to ordered map elements are essentially expressions, they're effectively read-only and thus attempts to update them via XPUTARG will have no effect. For example: 

```
call FoldUpper($capitals("california")) ! passes "sacramento"
print $capitals("california")           ! (unchanged by procedure)
```

```
...
```

```
Procedure FoldUpper(name$ as s0)
```

```
    name$ = ucs(name$)
    xputarg 1,name$   ! this doesn’t change calling param
                      ! (if it was an ordered map value)
```

```
EndProcedure
```

## PASSING COLLECTIONS II 

_Added February 2018_ 

Beginning with A-Shell 6.5.1623 and compiler edit 844 of December 2017, collections can be passed by reference in a subroutine to an SBX. On the calling side, the syntax is the same as for passing a DIMX array of structures, i.e. just specify the collection name with an empty set of parentheses, e.g.: 

```
dimx $coll, ordmap(varstr;varstr)
```

```
...
```

A-Shell Reference 

Page 1449 

```
xcall MYSBX, $coll(), ...
```

The receiving side is also similar to that for receiving a DIMX array of structures, i.e. you must first declare the receiving array with a variation of the DIMX statement including the BYREF clause, e.g. 

```
dimx $locoll, ordmap(varstr;varstr), byref
```

Then use XGETARG or XGETARGS to receive the collection... 

```
xgetargs $locoll(), ...
```

or 

```
xgetarg 2,$locoll()
```

See MAPDIR.SBX and associated TSTMAPDIR in SOSLIB:[907,45] for a useful working example. 

Ordered map parameters are passed by reference, allowing the called routine to operate directly on the caller's copy of the ordered map (inputting and/or outputting, clearing or extending). As there are multiple variations of ordered maps, it is usually necessary that the variation passed matches the expectation of the receiving routine—which hopefully spells out the requirements in its documentation. 

## **History** 

- 2017 December, A Shell 6.5.1623:  Add capability to A-Shell. 

## MISMATCHED COLLECTION ARRAYS 

_Added June 2023_ 

The compiler will complain about mismatched collection arrays passed by reference to functions. For example, passing an ORDMAP to an ORDMAPM, or an `ordmap(varstr;varx)` to an `ordmap(varstr;varstr)` . 

A-Shell Reference 

Page 1450 

Since there may be situations where it makes sense to take advantage of the compatibility overlap between different kinds of collections, you can  signal to the compiler that you want to allow such mismatches, by appending an asterisk to the collection name in the function declaration. For example, the "*" in this function declaration... 

```
Function Fn'Foo($m as ordmap*(varstr;varx))
```

... causes the compiler to allow essentially any kind of ordmap to be passed to the function. 

An example where this might make sense would be if you had an auxiliary function that traced the contents of a collection by iterating through it. A single copy of such a function could handle both ORDMAP and ORDMAPM, and quite possibly other collection types, as long as they supported iteration. 

## **Notes** 

- Since collections (as opposed to individual values within a collection) are passed by reference, the called function actually 

- operates directly on the passed copy of the collection. So for example, even if the function was declared as receiving an ordmap, if the caller passes an ordmapm, then the function will operate on that ordmapm —i.e. it will support duplicate keys. That could lend useful flexibility, or introduce subtle bugs, which is why the default is to treat it as a compilation error unless you explicitly request the flexibility with the asterisk. 

- There is no problem (and no need for the asterisk) when passing a collection with an _varstr_ value type to a function 

- receiving it as a collection with a _varx_ value type. _Varx_ can faithfully represent any _varstr_ value. But the reverse is not true, and requires the asterisk feature if you want to allow it. 

## **History** 

- 2023 June, A Shell 6.5.1731, compiler edit 1022:  Compiler now complains about mismatched collection arrays passed by reference to functions. 

A-Shell Reference 

Page 1451 

## **PARAMETER PASSING (IN)** 

_Rewritten July 2022_ 

The process of passing parameters in to a function or procedure actually has two separate parts: matching and passing. 

## **Matching** 

At compile time, the compiler has to match the calling parameters to the receiving parameters, using one or both of the following: 

- Match by order: If the caller simply lists the parameters in the calling statement without naming them, then they are matched 

- to the receiving parameter by order, i.e. the first parameter in the function call is matched to the first parameter in the function definition, etc. 

- Match by name: If the calling statement identifies the parameters by name, then they are matched to the receiving 

- parameters by name. 

## **Example** 

```
call fn'produce("apple", 0.97, 4.5, "extra")
```

```
call fn'produce(itemname$="peach", lbs=9)
```

```
call fn'produce("surprise")
```

```
...
```

```
function fn'produce(itemname$ as s20:inputonly, price=0 as f6:inputonly, lbs as f6:inputonly) as f6
```

```
   if price = 0 then
```

```
      price = fn'price(itemname$)
```

```
   endif
```

```
   ...
```

In the above example, the first call specifies four parameters without any names, so they will have to match to the receiving parmeters by order, i.e. _itemname$_ receives "apple", _price_ receives 0.97, _lbs_ receives 4.5. The fourth parameter, _extra_ , is 

A-Shell Reference 

Page 1452 

passed to the function but not automatically matched to any receiving parameters; the function could detect it using .ARGCNT and retrieve it manually into a variable using XGETARG. 

The second call specifies names, so the second parameter ( `lbs=9` ) is properly matched to the third parameter on the receiving end. Nothing is passed to the _price_ parameter, which is only allowed since the function definition specifies a default value ( `price=0` ). 

The third call also lacks names, and only specifies one parameter, which will be matched to _itemname$_ . The other two parameters will default on the receiving end, either based on an explicitly set default (price=0), or else to 0 or "" depending on the receiving data type. 

Note that although it is possible for the caller to specify some parameters by order and some by name, the named parameters must all follow the ordered ones. Skipping over parameters is only allowed when the parameter has a specified default value. 

## **Passing** 

At run-time, the values of the parameters specified in the calling statement are passed to the receiving parameters by one of the following methods: 

- Pass by Value: This applies to most situations, and involves making a separate copy of the source value into the received 

- parameter. If the parameter types are not the same, conversions will be performed just like they would in an assignment statement. Changes to the received variable do not affect the calling variable unless XPUTARG is used to copy the value back. 

- Pass by Reference: This applies only to the passing of entire arrays or collections, and consists of linking the receiving 

- parameter to the calling parameter so that they share the same memory. Any changes update both the the calling and received parameters simultaneously, and XPUTARG is not used. 

## **Detecting Optional Parameters** 

As noted above in the description of parameter matching, trailing parameters are always optional. Beyond that, in order to make a parameter optional, it needs to have a default value in the function definition. In the fn'produce() function, the first parameter _itemname$_ is mandatory except when the caller specifies no parameters at all. The _price_ parameter is optional because of the default value, and _lbs_ is optional because it's a trailing parameter. 

The following methods can be used within the function to determine whether an optional parameter was actually passed: 

A-Shell Reference 

Page 1453 

The .ARGCNT dot variable indicates the total number of parameters. Since this will include any non-trailing optional parameters, it is only good for identifying the number of trailing parameters that were not specified by the caller—or conversely, the number of additional parameters that were specified beyond those defined int he function declaration. 

Any non-trailing optional parameters that were not passed by the caller will be set to the default value. So, depending on the default value set, you may be able to determine whether the parameter was passed. 

For arrays and collections passed by reference (see the related topics listed below), you can set the default value to .NULL to make them optional, and then you can test if they were passed by checking the .EXTENT() of the received array or collection. -1 indicates nothing was passed, while zero or more indicates the extent of the actual array of collection passed. 

## **See Also** 

- Sample programs in EXLIB:[908,61] demonstrate array passing by reference. 

## **History** 

- 2018 May, A Shell 6.5.1635: When passing expressions to/from functions and SBX subroutines, if the target is type X, use a physical rather than logical transfer. This matches the behavior of assignments, and closes a loophole that previously occurred when the source expression was of the form VAR[x;y] or VAR[x,y] where VAR was of type X. Previously the transfer was being terminated at the first null even when the target variable was of type X. 

Note that this change affects all variations of XGETARG and XPUTARG, as well as implicit parameter passing to 

functions/procedures, potentially changing the runtime behavior of existing compiled programs, but only in cases where a string or non-numeric expression is passed to an X type variable. Given the narrow range of situations affected, and our belief that the new behavior is more in line with how programmers thought that it had been working all along, not to mention the fact that it is now consistent with the assignment statement logic, we feel that the upside of the change overwhelms the downside. Nevertheless, at least for now, we are not treating it as a bug fix and therefore not planning to retrofit into the stable 6.4 release. Programmers concerned about whether this might affect them are advised to do a global source code search for occurrences of "[" within a subroutine or func/proc call parameter list, as well as within any "PUTARG" statement and then check to see whether the receiving variable is of type X and whether you are counting on the expression being terminated by the first null. 

- 2014 September, A Shell 6.1.1389:  A-Shell now supports Passing DIMX Arrays to functions/procedures by reference. 

## **Subtopics** 

A-Shell Reference 

Page 1454 

· 

A-Shell Reference 

Page 1455 

## **PARAMETER PASSING (OUT)** 

In addition to the Return Expression of a function, both functions and procedures can pass updated values of the parameters they received back to the calling routine, by using XPUTARG. 

## **See Also** 

- The discussion on Parameter Type and Size. 

A-Shell Reference 

Page 1456 

## **RETURN EXPRESSION** 

The default return value is 0 for numeric functions and "" (null) for string functions. To set another return value, assign it to the variable matching the function name (e.g. FN'name = -1). Note that this is similar in concept to the RETURN(<EXPRESSION>) statement in an SBX, except that it doesn't end the function. 

The return variable otherwise functions as a standard variable and can be used in expressions and be assigned a value multiple times (only the last one will matter at the time the function returns). As an example of one possibility, in the Fn'Dec2Hex$ sample function above, the return variable Fn'Dec'Hex$ receives its value by being passed as a parameter to a subroutine: 

```
xcall MIAMEX, MX_OCVT, decval, width, OT_MEM or flags, Fn'Dec2Hex$
```

A special case occurs when the function returns a defined structure. In this case, in order to obey the naming rules, the function name must end with a $. But the $ is dropped when referencing members of the structure. Consider this example of a function which returns an item structure when passed an item ID. 

```
defstruct ST_ITEM
```

```
   map2 id,s,10
```

```
   map2 descr,s,30
```

```
   map2 price,f
```

```
endstruct
```

```
map1 item,ST_ITEM
```

```
item = Fn'Item$("A12345")
```

```
end
```

```
Function Fn'Item$(itemid as s10) as ST_ITEM
```

A-Shell Reference 

Page 1457 

```
   Fn'Item.id = itemid
```

```
   Fn'Item.descr = "some description"
   Fn'Item.price = 7.99
```

```
End Function
```

Note that the name of the function has a $ on the end (Fn'Item$), but when referring to the individual fields within the structure, the $ is dropped (Fn'Item.id = itemid). 

Also note that the return value of the function is a copy of the entire ST_ITEM structure as it exists at the end of the function, even though there is no explicit reference to the structure as a whole. Any members of the structure which are not assigned would simply default to zeros or nulls, just as they would for a traditional unformatted MAP1/MAP2 structure.+ 

The alias .fn (or .FN or .Fn, i.e. case insensitive) may be used in place of the actual function name for the return value variable. This typically makes for easier-to-read code, and simplifies the process of changing the name of a function. Note that the alias does not take a $ suffix, regardless of whether the function returns a number, string, or structure.  For example: 

```
function Fn'Bracket$(arg1 as f6) as s20
```

```
    .fn = "[" + arg1 + "]"    ! equivalent to Fn'Bracket$ = ...
```

```
endfunction
```

## **History** 

2018 September, A-Shell 6.5.1647:  FN alias introduced 

A-Shell Reference 

Page 1458 

## **LOCAL VARIABLES** 

Any MAP statements defined between FUNCTION and ENDFUNCTION are considered local stack variables, which are allocated and initialized for each instance of the function. 

You may also prefix MAP statements within the function definition with STATIC (e.g. STATIC MAP1 S'COUNT,F) to make the local variable persistent across instances of the function. Such a variable will only be initialized once, the first time the function is called. 

## **Subtopics** 

- Auto-Mapped %Var Variables 

A-Shell Reference 

Page 1459 

## **- AUTO MAPPED %VAR VARIABLES** 

_Added September 2021_ 

Variables whose names begin with "%" will be exempted from the normal variable mapping rules, i.e. will be auto-mapped, in the following cases: 

- FOR...NEXT loop counter - if the loop counter variable name is of the form %name, it will be auto-mapped as F,6 but it's 

- scope will be limited to the loop. 

- Within a function or procedure - any variable of the form %name within a function or procedure will be auto-mapped as F,6 

- and variables of the form %name$ will be auto-mapped as S,0 (dynamic strings). In either case, like variables explicitly mapped within the routine, they are initialized at the start of the routine and freed at the end of it. For example: 

```
Function Fn'Foo3(seed as i4:inputonly)
```

```
   %x = rnd(seed)                      ! auto map1 %x,f,6
   %ran$ = "Random number sequence: "  ! auto map1 %ran$,s,0
   for %i = 1 to 10                    ! auto map1 %i,f,6
       %x = rnd(0)
       %ran$ += str(%x) + ","
   next %i
   ? %ran$;"..."
```

```
EndFunction
```

Note that the ability to auto-map variables within a function should not be taken as a blanket invitation to stop mapping local variables! The idea is mainly to use them for incidental, intermediate or temporary values with such limited scope that having to having to map them is more of a distraction than an aid to code readability. 

## **See Also** 

A-Shell Reference 

Page 1460 

- FOR … NEXT 

- Implicit Variable Declarations 

## **History** 

- 2021 September, A Shell 6.5.1706:  Feature added to A-Shell 

A-Shell Reference 

Page 1461 

## **GLOBAL/EXTERNAL VARIABLES** 

By default, only variables defined within the function or procedure (i.e. Local Variables) are accessible within that routine. This is generally a good thing, as it helps prevent inadvertent references to the wrong variables, as well as unintended side-effects from calling a function or procedure. But the ability to access variables defined outside the routine can be enabled, by any of the following methods: 

- **Private Map:** You can share variables between a group of related functions or procedures by grouping them all within a 

- single file and declaring the shared variables at the top of the file using PRIVATE MAP statements. See MAP Statement Extensions. 

- AUTO_EXTERN may be used to expose all global variables. 

- **EXTERN_BEGIN, END:** You can expose a list or block of global variables by repeating the original MAP statements for those 

- variables within the function or procedure, enclosed by ++PRAGMA EXTERN_BEGIN and ++PRAGMA EXTERN_END, e.g. 

```
++PRAGMA EXTERN_BEGIN
```

```
MAP1 SOME'VAR,F,6
```

```
MAP1 ANOTHER'VAR,S,20
```

```
++INCLUDE MOREVARS.MAP
```

```
++PRAGMA EXTERN_END
```

- EXTERN may be used to expose individual global variables. 

## **Subtopics** 

- AUTO_EXTERN 

- EXTERN 

- .EXTERN() 

A-Shell Reference 

Page 1462 

## **AUTO_EXTERN** 

## **++PRAGMA AUTO_EXTERN {"<boolean>"}** 

Enables or disables the visibility (with the local function or procedure) of variables defined globally—i.e. with standard MAP statements outside any function or procedure. The argument defaults to "TRUE", so the following are equivalent: 

```
++PRAGMA AUTO_EXTERN "TRUE"
```

```
++PRAGMA AUTO_EXTERN
```

```
++pragma auto_extern          ! pragmas are case insensitive
```

The setting is reset to FALSE at the start of each function or procedure, so must be specified whenever you want to reference global variables within a routine. The only point of specifying an argument of "FALSE" would be if you first enabled it, then later in the function didn't have any further need to reference global variables and wanted to protect against accidentally doing so. 

## **Example** 

```
PROCEDURE MYPROC(p1 as f)
```

```
++PRAGMA AUTO_EXTERN           ! expose all global vars to this procedure
   ...
```

```
   SOME'VAR = SOME'VAR + p1    ! add parameter p1 to global variable SOME'VAR
```

```
   ...
```

```
ENDPROCEDURE
```

The above technique, while undermining one of the benefits of using PROCEDURE as opposed to old-style GOSUBs, does provide a convenient way to migrate from unstructured GOSUBs to structured PROCEDURES. Essentially all you need to do to convert a 

A-Shell Reference 

Page 1463 

reasonably well-designed GOSUB into a proper PROCEDURE is to add the PROCEDURE keyword, an empty parameter list, the AUTO_EXTERN pragma, remove the RETURN, and add the ENDPROCEDURE, e.g. 

The following GOSUB ... 

```
MYPROC:
```

```
   ...
```

```
   RETURN
```

can be converted to a PROCEDURE as follows: 

```
PROCEDURE MYPROC()
```

```
++PRAGMA AUTO_EXTERN
```

```
   ...
```

```
   ! RETURN    ! (RETURN may also be converted to EXITPROCEDURE)
```

```
ENDPROCEDURE
```

Note that the above illustration ignores certain issues that may complicate such conversions. If the GOSUB has RETURN statements other than at the physical end, these can be converted to EXITPROCEDURE statements. But a PROCEDURE may not contain GOSUB (or CALL) statements to other old-style GOSUB routines, so they would have to be converted as well. Also, any `GOSUB MYPROC` (or `CALL MYPROC` ) statements referencing the original routine would have to be converted to `CALL MYPROC` . These are all fairly mechanical steps though, after which you would be in position to incrementally access the modularization/isolation/encapsulation advantages of proper procedures with local variables and true parameter passing. 

## **See Also** 

- EXTERN 

A-Shell Reference 

Page 1464 

## **EXTERN** 

As an alternative to exposing all global variables to a function or procedure with AUTO_EXTERN, you can instead expose individual global variables via ++EXTERN statements: 

## **++EXTERN SOME'VAR,F,6** 

## **++EXTERN SOME'ARRAY()** 

There are few subtleties and disclaimers to consider when using either of the above methods to declare specific global variables as being visible within a local procedure: 

- Declaring a variable with ++EXTERN or ++PRAGMA EXTERN_BEGIN does not have any effect on the original global variable 

- definition, although it does allow the code within the procedure or function to modify the global variable at runtime. 

- The type and size may be omitted in the local extern declaration. Also, for arrays, the array dimensions may be omitted by 

- just using (). However, if you do specify a type, size, or array dimensions, then they must match those in the original global definition of the variable. For example: 

```
!(main program)
```

```
MAP1 GFLAGS(5),B,1
```

```
MAP1 SFLAG$,S,1
```

```
...
```

```
PROCEDURE TEST()
```

```
++EXTERN GFLAGS(5),B,1     ! valid
++EXTERN GFLAGS(5),F       ! invalid (types don't match)
++EXTERN GFLAGS(5),B,2     ! invalid (sizes don't match)
++EXTERN GFLAGS(4),B,1     ! invalid (subscripts don't match)
++EXTERN GFLAGS()          ! valid (equivalent to GFLAGS(5),B,1)
```

A-Shell Reference 

Page 1465 

```
++EXTERN SFLAG$            ! valid (equivalent to SFLAG$,S,1)
```

• The MAP level does not need to match; it doesn't even get specified for the ++EXTERN statements. But to the extent that there is any discrepancy between the local and global definitions, it is the global one that actually matters. The local one simply allows the local routine to access the global variable. 

Another alternative to individual ++EXTERN statements is to use ++PRAGMA EXTERN_BEGIN and ++PRAGMA EXTERN_END to bracket some ordinary MAP statements (or a ++INCLUDE referencing more MAP statements), for example: 

```
++PRAGMA EXTERN_BEGIN
```

```
MAP1 SOME'VAR,F,6
MAP1 ANOTHER'VAR,S,20
```

```
++INCLUDE MOREVARS.MAP
```

```
++PRAGMA EXTERN_END
```

A-Shell Reference 

Page 1466 

## **.EXTERN()** 

_Added May 2019_ 

The functional directive .EXTERN(EXPR), when used within a function or procedure, changes the normal scope search rules (first local, then module, then global) for all of the variables within the enclosed expression, to consider only global variables. For example: 

```
map1 state$,S,20,"Ignorance"
...
Function Fn'Foo() as i4
    map1 state$,S,.sizeof(.extern(state$))  ! S,20
    state$ = "Bliss"                        ! assign local state$
    print .extern(state$);" is ";state$     ! Ignorance is Bliss
EndFunction
```

In the above function, there are references to two variables named state$: one local to the function and one global. Normally, the scope rules would give the local variable precedence, even if ++PRAGMA AUTO_EXTERN or an explicit ++EXTERN state$ directive was specified. The use of the .EXTERN() functional directive allows the function to selectively and explicitly refer to the global version of the variable. 

## **Example** 

The following illustrates and emphasizes that the .EXTERN() might encompass multiple variables, all of which will refer to the global instance. 

```
map1 seccao,b,1
```

```
map1 array$(2),s,0
```

A-Shell Reference 

Page 1467 

```
array$(1) = "element 1"
array$(2) = "element 2"
seccao = 2
call FN'teste(1)
end
```

```
function FN'teste(seccao as b1) as b1
++extern array$()
```

```
        ? array$(seccao)            ! array$() is global but seccao is local ("element 1")
```

```
        ? .extern(array$(seccao))   ! both array$ and seccao global ("element 2")
```

```
endfunction
```

## **History** 

- 2019 May, A Shell 6.5.1551: Feature added to A-Shell 

A-Shell Reference 

Page 1468 

## **EXIT LABEL $EXIT** 

_Rewritten August 2016_ 

If the special label $EXIT: is included in a function or procedure, the EXITFUNCTION statement will transfer to that label, rather than to the physical end of the function—i.e. the ENDFUNCTION statement. This allows you to consolidate cleanup code and/or assignment of the function return value in a single place, and eliminates the common bug of forgetting to assign the return value prior to an EXITFUNCTION statement. For example: 

```
FUNCTION FN'TEST() AS I4
    open #999, "TEST.LOG", output
    ...
    IF <some condition) EXITFUNCTION
    ...
    ...
```

```
$EXIT:
```

```
    if eof(999)>=0 close #999
    FN'TEST = <expr>  ! assign return value
ENDFUNCTION
```

In the example above, execution hits the $EXIT label either as the result of the EXITFUNCTION statement, or by just falling into it. This assures that the file is closed and the return value assigned, regardless of which logical path is taken. The one exception would be in the case of an ASB error, which in the above example, would bypass the $EXIT label. To cover that case, error trapping logic could be added as follows: 

```
FUNCTION FN'TEST() AS I4
```

```
    on error goto TRAP
```

A-Shell Reference 

Page 1469 

```
    open #999, "TEST.LOG", output
    ...
    IF <some condition) EXITFUNCTION
    ...
    ...
    EXITFUNCTION   ! skip over error trap
TRAP:
    ...
    RESUME $EXIT
$EXIT:
    if eof(999)>=0 close #999
    FN'TEST = <expr>  ! assign return value
ENDFUNCTION
```

In the modified example above, we added a second EXITFUNCTION to avoid falling into the error trap. The error trap code has the option of resuming explicitly to the $EXIT label, (as in the case above), just like it could resume to any other label within the function. Or it could bypass the $EXIT code with RESUME ENDFUNCTION {WITH_ERROR {N}). See Error Trappingfor more details. 

## **Notes** 

- The $EXIT label functions the same way in procedures as in functions, except substituting EXITPROCEDURE and 

- ENDPROCEDURE for EXITFUNCTION and ENDFUNCTION 

- All of the keywords and labels discussed here are case insensitive, including the $EXIT label. 

A-Shell Reference 

Page 1470 

- Be careful not to include an EXITFUNCTION or EXITPROCEDURE statement within the $EXIT: code, lest you create an infinite 

- loop. 

## **History** 

- 2011 July, A Shell 5.1.1223: RESUME behavior changed to skip the code following the $EXIT, so as to reduce chance of infinite error trapping loops if an error occurred within that code. Previously, RESUME ENDFUNCTION resumed to the $EXIT label, if present. 

A-Shell Reference 

Page 1471 

## **ERROR TRAPPING IN FUNCTIONS** 

_Updated and November 2016_ 

Although this topic explicitly discusses Functions, it applies equally to Procedures—which are, after all, just functions without return values. Every occurrence of the word “Function” in this topic (and nearly all others), either in the text or in syntax or examples, regardless of case, and including compound keywords like ENDFUNCTION, may be taken to apply to procedures (e.g. ENDPROCEDURE) as well. 

By default, ASB errors within functions are internally filtered in such a way that the error appears to the caller to have occurred on the line that called the function. This allows the stack to be properly unwound rather than doing an unstructured ON ERROR GOTO out of the function. You may, however, create a local error trap inside the function, using the regular ON ERROR GOTO statement. The local error trap may resume back to locations within the function, or it may resume back to the caller, or even to a global error trap, including optionally forwarding an error code, using one of the following syntaxes: 

## **RESUME {label}** 

## **RESUME ENDFUNCTION {WITH_ERROR {errno}}** 

## **RESUME EXITPROGRAM {WITH_ERROR {errno}}** 

The first syntax is used to clear the error and resume to the specified label within the function, including the special label $EXIT, or to the line which triggered the error if the $EXIT label is not present. Note that this variation works outside of functions as well.. 

The second syntax (ENDFUNCTION) terminates the current function, bypassing the local $EXIT label if present, resuming to the line that called the function. 

The third syntax (EXITPROGRAM) is like the ENDFUNCTION option, except that it keeps going—terminating the current function and returning to its caller—until it gets back to the top level main program, after which it resumes to the special label $EXITPROGRAM. 

Without the optional WITH_ERROR clause, the error condition is cleared. A common way to use this feature would be: 

```
FN'name = err(0)    ! assign ASB error # to function value
```

A-Shell Reference 

Page 1472 

```
RESUME ENDFUNCTION  ! return to caller (with error cleared)
```

This would clear the error condition, so it doesn't trigger the caller's ON ERROR GOTO, but it would still return to the caller the error number via the function's return value. This would enable the caller to  take action in a more structured manner, as opposed to via an error trap. 

If the `WITH_ERROR {errno}` clause is specified, then the function returns with the error number set—i.e. triggering the error handling process in the caller. Omitting _errno_ , or setting it to 0 or err(0), preserves the current error, while specifying an _errno_ value allows you to change the error code passed back. 

## **Comments** 

The EXITPROGRAM option is useful in situations where the only sensible response to the error (besides logging it) is to terminate the program, perhaps returning to a main menu or support screen. Being able to go there directly relieves the burden on the calling functions to handle passing the status back up the chain. 

Note: RESUME EXITPROGRAM is best used without the "WITH_ERROR" clause, i.e. it's best to handle and clear the error prior to resuming to your global $EXITPROGRAM label. Otherwise, with the error still set, the global error trap will redirect control to itself, so that your $EXITPROGRAM code may never get executed. 

EXITPROGRAM can also be used as a standalone statement to perform the same global jump outside the context of any error. 

Note that since the local error trap code must be within the function, some care must be taken to make sure that it doesn't get executed except on error. One technique would be to use an EXITFUNCTION label just above it, as shown in the following example. 

## **Example** 

```
FUNCTION FN'TEST()
```

```
   ON ERROR GOTO TRAP
```

```
   ...
```

```
   ...
```

A-Shell Reference 

Page 1473 

```
   EXITFUNCTION
```

```
TRAP:
```

```
   PRINT "Error #";ERR(0);" in procedure TEST()"
   RESUME ENDFUNCTION WITH_ERROR 199
```

```
ENDFUNCTION
```

## **See Also** 

- Call Stack Tracing 

## **History** 

- 2024 February, A Shell 7.0.1756, compiler edit 1043:  Support for EXITPROGRAM added. 

A-Shell Reference 

Page 1474 

## **INVOKING A FUNCTION** 

To invoke the function, just reference it using array syntax, i.e.: 

```
A = FN'name(x,y,z)
```

You may also invoke it as a statement rather than an expression, using: 

```
CALL FN'name(x,y,z)
```

A-Shell Reference 

Page 1475 

## **PRIVATE FUNCTIONS AND PROCEDURES** 

_Added October 2016_ 

Function and Procedure definitions within ++INCLUDE modules may be preceded with the keyword PRIVATE to make them invisible outside of that ++INCLUDE file. This is analogous to the use of the PRIVATE keyword to declare a variable as being visible only within the ++INCLUDE file. For example: 

```
PRIVATE FUNCTION FN'TEST() AS F6
```

```
   ....
```

```
ENDFUNCTION
```

The two most likely motivations for declaring a function or procedure to be private are: 

- As a namespace mechanism to prevent conflicts with procedures of the same name in other include files. Previously, the only 

- way to avoid this risk would have been to append or prepend some module-specific text (perhaps the module name) to the routine name, but this ends up making your routine names overly long, making them difficult to type and read. 

- As a way of making the code easier to understand or debug later. (Eliminating the possibility that the routine is called from 

- anywhere outside the current module eliminates the need to consider impossible scenarios that would otherwise be difficult to rule out without searching every possible file that could use this module.) 

## **History** 

- 2016 August, A Shell 6.3.1523, compiler edit 770:  Add private attribute for functions and procedures. 

A-Shell Reference 

Page 1476 

## **DYNAMIC FUNCTIONS** 

_Updated August 2020; see History_ 

These are function calls that are dynamically bound—i.e. resolved—at runtime rather than at compile time. 

To define a function that can be dynamically bound, insert the new keyword "dynamic" in front of the Function keyword in the function definition. 

```
Dynamic Function Fn'Foo(...)
```

```
    ...
```

```
EndFunction
```

Tagging a function for dynamic binding like this does not interfere with traditional statically bound calls to the function; it simply opens up the additional possibility of dynamic binding. 

To call the function with dynamic binding, use one of functions DYNFUNC() or DYNFUNC$() ... 

## **DYNFUNC(funcname,arg1,...,argN)   ! numeric function** 

## **DYNFUNC$(funcname,arg1,...,argN)  ! string function** 

These are analogous to the XFUNC() and XFUNC$() functions, used to dynamically call external functions implemented as SBX modules, except that here the target function is part of (i.e. compiled within) the current program. As with XFUNC/XFUNC$, the first argument ( _funcname_ here) is a string expression resolving at runtime to the name of the function to call. Unlike XFUNC/XFUNC$, dynamic function calls support Named Parameters, and they can be invoked via the CALL statement in addition to the normal method as an expression. 

## **Examples** 

```
a$ = DYNFUNC$("Fn'Foo$",arg1,arg2)
```

```
n = 27
```

A-Shell Reference 

Page 1477 

```
f$ = "Fn'Foo" + str(n) + "$"
```

```
call DYNFUNC$(f$,arg1,arg2,arg3)
```

```
call DYNFUNC$(f$,arg1,code=12345,qty=ordqty)
```

The first example calls the string function Fn'Foo$(arg1,arg2) The second calls a string function Fn'Foo27$(), passing it one positional parameter (arg1) and two named parameters (code=12345 and qty=ordqty). The last calls a function whose name is returned from Fn'Get'FuncName$(x). 

The ASB error code, 72, undefined dynamic function, has been defined and added to the errmsg.xxx files. It will be triggered by an attempt to to dynamically call a function which is not declared dynamic within the current program. 

Note that in all cases, the choice of DYNFUNC() vs DYNFUNC$() determines whether the function is expected to return a string or numeric value. Since the type of a function is determined by the presences of a "$" suffix, the presence or absence of the suffix on the DYNFUNC keyword should agree at runtime with the name of the target function. In other words, use DYNFUNC() to call numeric functions, and DYNFUNC$() to call string functions. Neither the compiler nor the runtime system will complain if you mix types, but the results are likely to disappoint. 

Compatibility: RUN / SBX modules with Dynamic functions declared are fully compatible with earlier versions of A-Shell. But an attempt to call them from within an A-Shell session earlier than 6.5.1647.0 will generate an unsupported function error (35). 

## **History** 

- 2022 August, A Shell 6.5.1720, compiler edit 999:  Named parameters can now be used with DYNFUNC, and default parameter values are now supported in dynamic functions. Note that this affects both the compiler and runtime, so the use of named parameters in a DYNFUNC expression will now set the minimum runtime level to 6.5.1720. Also, with compiler edit 1000, /CI support has been extended to dynamic functions, both the function names and argument names. 

- 2020 October, A Shell 6.5.1689, compiler edit 937: Arrays/collections may now be passed to DYNFUNC(), as they can in normal function references. Previously only array elements were supported. 

- 2018 September, A Shell 6.5.1647, compiler edit 879: Added function to A-Shell 

A-Shell Reference 

Page 1478 

## **ELLIPSIS FUNCTION ARGUMENTS** 

_Added October 2018_ 

The use of ellipsis (...) in argument lists facilitates passing arguments through a wrapper function. An example will make this more clear. Consider the following function: 

```
Function Fn'DynFunc$(fn$ as s260:inputonly, ...) as s0
```

```
    on error goto trap
    Fn'DynFunc$ = dynfunc$(fn$, ...)
    exitfunction
```

```
trap:
```

```
    if err(0) = 72 then             ! if function not found
        Fn'DynFunc$ = .NULL         ! set result to null
        resume endfunction          ! and return with no error
    else
        resume endfunction with_error   ! else pass error through
```

```
    endif
```

```
EndFunction
```

The function serves as a wrapper to the underlying dynfunc$() call; it adds value by trapping the function-not-found error and returning .NULL instead. The ellipsis mechanism eliminates what would otherwise be a sticky problem - we have no idea how many parameters will be passed, so there is no good way to code the dynfunc$() call. With the ellipsis mechanism, the "..." in the dynfunc$(fn$, ...) call is replaced by the actual parameters corresponding to the ...in the Fn'DynFunc$() call, allowing us to pass them through without knowing anything about them. 

## **History** 

A-Shell Reference 

Page 1479 

- 2018 September, A Shell 6.5.1647, compiler edit 880: Added function to A-Shell 

A-Shell Reference 

Page 1480 

## **INDIRECT FUNCTION CALLS** 

A reference to a function or procedure may be passed as an argument to another function or procedure. This is an advanced technique that is mainly useful in multi-level (often recursive) algorithms consisting of a generic intermediate layer and a specific lower layer which may need to be customized for each particular problem. The indirect function call technique allows you to effectively customize the generic intermediate routine without actually having to modify it. Instead, you pass your custom routine to it, which it then calls indirectly to do the parts of the algorithm which you want to customize. 

The custom routine in this scenario is sometimes referred to as a "callback routine", since the idea is for the generic intermediate routine to call your routine back to perform the part of the algorithm requiring customization. 

For example, when parsing an XML file, you may want to employ a generic routine to walk the tree, but a custom routine to process nodes that meet some criteria. Because of the recursive nature of the routine to walk the tree, it is difficult for it to exit back to your application each time it hits one of the target nodes, without losing its position and ability to continue to the next node. The solution is to design the generic routine to accept a callback routine to be called for each target node. Each application can then use the generic routine in a different way by passing a different callback routine to it. 

The scheme consists of three parts: 

## **1. The Callback Routine.** 

This is a normal function or procedure. 

## **2. The Generic/Intermediate Routine** 

This receives the callback reference and makes calls to the callback routine. In this routine, the parameter to receive the indirect/callback reference must be defined as follows: 

```
Procedure Foo( ..., @fn'cb() as lblref, ... )
```

For functions, the formal name must follow the standard naming rules, i.e. start with "Fn'" and end with $ if the functions returns a string value. In all cases it must start with "@", and end with the "as lblref" clause. An empty pair of parentheses, as in the example above, is optional. (Parameters to be passed to the indirect routine are not specified in the declaration.) Beyond that, the name may be anything, for example: 

```
@fn'callback as lblref
```

A-Shell Reference 

Page 1481 

```
@FN'PROC$ AS LBLREF
```

```
@Fn'Custom$() as lblref
```

```
@myproc() as lblref
```

The above parameter declarations would apply to a numeric function, two string functions, and a procedure, in that order. 

Inside the intermediate routine, you can call the callback routine using the name specified in the declaration. For example: `call fn'cb(arg1,...)  ! call actual callback with actual args` 

Note: unlike nearly all other formal parameter types, lblref parameters default to .NULL rather than "" if the caller does not supply the actual parameter. This allows you to test whether the function reference was supplied, e.g. 

```
if .ISNULL(fn'cb) then           ! if myproc not passed
    call my'default'proc(...)    ! use a default routine
```

```
else
```

```
    call fn'cb(...)              ! else call the passed routine
```

```
endif
```

Within the intermediate routine, if you need to pass the callback routine indirectly again to another routine, or recursively to yourself, then retain the @ prefix, e.g. 

```
Procedure Foo(..., @fn'cb() as lblref, ...)  ! intermediate rtn
```

```
    ...
```

```
    call Foo(...,, @fn'cb(), ...)   ! pass callback again indirectly
    ...
```

```
endprocedure
```

A-Shell Reference 

Page 1482 

## **3. The call to the generic/intermediate routine** 

In this you pass the reference to your callback routine as a parameter. Here you must precede the actual callback routine name with "@" and use an empty set of parens, e.g. 

```
Function Fn'Bar(...)    ! actual callback routine
```

```
    ...
```

```
Endfunction
```

```
    ...
```

```
call Foo(...,@Fn'Bar(), ...)   ! passing callback to intermediate Foo()
```

Note: if you fail to specify the "@" prefix when passing the callback routine to the intemediate routine, it will still be syntactically and semantically legal, but the result will be completely different. To clarify, consider the following two examples: 

```
call Foo(Fn'Bar())
```

```
call Foo(@Fn'Bar())
```

In the first call, the function Fn'Bar() is evaluated first and its return value is passed to the procedure Foo(). In the second call, a reference to  the Fn'Bar() function is passed indirectly to the procedure Foo(), which  will then be able to call that function without knowing its real name. 

## **Example 1** 

The following example illustrates the scheme using a generic intermediate routine which scans a directory tree recursively looking for files whose names match a pattern. For each file that matches, it calls your custom routine with the filespec so that you can perform some processing on it. By using the callback technique, the generic recursive directory scanning logic can be reused without modification in many different applications; the customized callback routine allows each application to process the files differently. 

A-Shell Reference 

Page 1483 

```
Function Fn'Dir'Scan(dir$ as s260, wild$ as s100, &
```

```
                         @procfile() as lblref) as i4
```

```
    do
```

```
        file$ = <next entry in directory>
```

```
        if <file$ is a normal file and matches wild$>
```

```
            Fn'Dir'Scan += 1           ! count matching files
            call procfile(file$)      ! callback routine for file
        elseif <file$ is a subdir>
```

```
            count += Fn'DirScan(file$, wild$, @procfile())  ! recursion
        endif
```

```
    loop until <end of directory>
```

```
EndFunction
```

To use the Fn'Dir'Scan routine, we need to define our callback routine and pass it by reference to the Fn'Dir'Scan routine. For a simple example, here is a callback routine that just prints the file name: 

```
Procedure Show'File'Info(fspec$ as s260:inputonly)
```

```
    print fspec$
```

```
EndProcedure
```

Now we can use the generic Fn'Dir'Scan() function to print the names of the .bp files in all of the subdirectories of c:\vm as follows... 

```
count = Fn'Dir'Scan("c:\vm", ".bp", @Show'File'Info())
```

A-Shell Reference 

Page 1484 

Later in the same app we might want to copy all the matching files to a backup directory. We can use the same Fn'Dir'Scan() routine, but supply a different callback function... 

```
Procedure Backup'File(fspec$ as s260:inputonly)
```

```
    xcall MIAMEX, MX_COPYFILE, fspec$, ...
```

```
EndProcedure
```

```
...
```

```
count = Fn'Dir'Scan("c:\vm", "*.bp", @Backup'File())
```

## **Example 2** 

See this more complete example Fn'Dir'Scan() in SOSLIB:[907,10]. 

A-Shell Reference 

Page 1485 

## **- USER DEFINED FUNCTION EXAMPLES** 

Here is a simple example of a function to format a decimal integer value as a hex string: 

```
Function Fn'Dec2Hex$(decval as f8:inputonly,flags=0 as b2:inputonly,width=0 as b2:inputonly) as s16
```

```
   map1 hexon,f
```

```
   xcall MIAMEX, MX_GETHEX, hexon      ! see if we are in hex mode
```

```
   if (not hexon) then xcall MIAMEX, MX_SETHEX, 1          !  if not, set it
```

```
   xcall MIAMEX, MX_OCVT, decval, width, OT_MEM or flags, Fn'Dec2Hex$
```

```
   if (not hexon) then xcall MIAMEX, MX_SETHEX, hexon  ! restore octal
```

```
EndFunction
```

Note that although unpassed parameters will default to zero (or "" for strings), specifying default initial values (=0) in the function definition (flags=0 and width=0) allows the caller to explicitly specify width by name without having to specify flags, e.g. ... 

```
? Fn'Dec2Hex$(value,width=10)   ! width = 10 (by name)
```

```
? Fn'Dec2Hex$(value,10)         ! flags = 10 (by position)
```

This slightly more complex example of a function to allocate a file illustrates some additional capabilities, such as static local variables and error trapping: 

```
Function Fn'Alloc(spec$ as s120, bytes as b4) as b2
```

```
map1 blocks,f,6
```

```
static map1 s'tot'allocations,f
```

A-Shell Reference 

Page 1486 

```
on error goto Trap  ! local error trap
```

```
blocks =  int((bytes + 511) / 512)
allocate spec$,blocks
```

```
s'tot'allocations = s'tot'allocations + blocks
```

```
Fn'Alloc = 0    ! unnecessary but explicit
exitfunction    ! exit function
```

```
Trap:     ! note this label doesn't conflict with outer TRAP
Fn'Alloc = err(0)   ! set return value to error #
resume endfunction  ! clear ASB error and return
EndFunction
```

In the above example, the local static variable s'tot'allocations will get incremented by the number of blocks each time the function is called. (It doesn't serve any purpose in this example, as there is no way to retrieve it, but it might, for example, be used to prevent the program from allocating too many blocks in one session, or for computing statistics.) 

A-Shell Reference 

Page 1487 

## **IMPLICIT FUNCTION RETURN VALUE CAPTURE** 

_Written January 2021_ 

This mouthful of a title is really a kind of "syntactic sugar" to simplify referencing the result of a previously called function without having to map a variable and explicitly assign the value to it. To invoke the feature, you simply prefix the called function with a dot, after which the returned value of that function will be available by referencing a variable with the same name as the function—including the dot. For example: 

```
if .fn'foo(x) < 0 then                 ! dot prefix call
    print "fn'foo(x) error "; .fn'foo  ! use implicit capture value
```

```
endif
```

```
...
```

```
function fn'foo(value as f6:inputonly) as f6
```

```
    ...
```

```
endfunction
```

In the above example, we have a function `fn'foo()` that takes a numeric argument. For the purposes of our example, assume the return value is >= 0 for success, or < 0 for an error. In the call to the function (at the top of the example), including the dot prefix— `.fn'foo(x)` instead of just `fn'foo(x)—` causes the return value to be captured in a variable named `.fn'foo` , matching the name of the called function, with the dot prefix. That variable is then available to be used subsequently. 

Effectively, this is equivalent to: 

```
map1 .fn'foo,f,6
```

```
.fn'foo = fn'foo(x)
```

A-Shell Reference 

Page 1488 

```
if .fn'foo < 0 then
```

```
    ...
```

In other words, the compiler expands a reference to a function using the dot prefix into the combination of a variable definition (map statement) and an assignment from the function to the variable. The "fingertip savings" consists of the automatic mapping of the variable and the automatic assignment, plus, in a case like the above where the function reference is not a simple call but is part of an expression, it effectively embeds the assignment into the expression in a way that otherwise would have requirement multiple statements and a possible rearrangement of the logic. 

Another way to look at it is that aside from simply reducing the amount of coding busy work, the automatically-created dot variable ( `.fn'foo` in this example) provides a runtime savings by eliminating the need to call the function again in order to recall its value. So logically speaking, the original example would be equivalent to: 

```
if .fn'foo(x) < 0 then                    ! normal call
    print "fn'foo(x) error "; .fn'foo(x)  ! second call
endif
```

## **Comments** 

If the dot variable already exists in the scope of the function call, then the existing variable is re-used. The normal scoping rules apply, including the various extern directives, just as they do with any other variable reference. Only if the variable is not defined within the visible scope is it created. The newly created variable has the same scope as any other variable mapped at the present location would. 

Because of the scoping rules, it is possible for multiple instances of the automatically created dot variable to exist simultaneously, with independent values. For example, a program could call the `.fn'foo(x)` function (using the example above) from a global context (creating a global instance of the `.fn'foo` variable), and it could later call the `.fn'foo(x)` function from within another function, using a different value of x, resulting in a local instance of the `.fn'foo` variable with a correspondingly different value. This can obviously lead to confusion, so caution is advised when referencing one of these implicitly created Dot Variables, particularly if a long way from the call that last assigned it. 

A-Shell Reference 

Page 1489 

The implicit function return value capture feature only applies to user-defined functions with names starting with `fn'` . It does not apply to built-in Dot Functions like `.instrr()` . 

The dot prefix is not part of the function name; instead it acts as a kind of operator. The function can be called with or without the dot prefix, but the implicit return value capture only occurs when called with the dot prefix. 

The feature requires compiler edit 939, which is included with the 6.5.1695.0 release as well as separately, and it is entirely implemented within the compiler. There is no runtime dependency. 

**Warning** : this feature only works with functions that declare all of their parameters—i.e., other words, with function calls that do not specify any more parameters than are listed in the function definition. 

## **History** 

- 2021 January, A Shell version 6.5.1695, compiler edit 939:  Function added to A-Shell 

A-Shell Reference 

Page 1490 

## **TAB FUNCTIONS** 

Tab 'functions', while conforming to standard function syntax, are not real functions in that they don't return any value. Instead, they perform some kind of terminal / file / client output or control operation. For this reason and because there are so many of them, especially in the sub-category of ATE Functions, they are covered in their own section of the documentation:  Tab Functions. 

A-Shell Reference 

Page 1491 

## **SOSFUNC LIBRARY FUNCTIONS** 

_New February 2026_ 

A-Shell's Shared Open Source FUNCtion Library, SOSFUNC, contains a large set of functions in source code that are technically user-defined but are of general use, developed by others and maintained by MicroSabio. The master library is maintained in the 907010 directory of the MicroSabio SOSLIB Repository which you can browse online. To take maximum advantage, create an ERSATZ definition pointing to a [907,10] directory on your system and download the complete set, checking occasionally for updates. Use the FUNCIDX utility to browse it locally by keyword, file or function name. 

A-Shell Reference 

Page 1492 

## **PROCEDURES** 

_Updated February 2024_ 

## **{PRIVATE} PROCEDURE procname(var1{=defval} {as <typsiz>{:<mod},...varN{=defval} {as <typsiz>{:<mod})** 

## **<optional local MAP statements, with optional STATIC prefix>** 

## **<optional XGETARGs>** 

## **<nearly any kind of statements>** 

## **<optional XPUTARGs>** 

## **ENDPROCEDURE** 

## **Notes** 

- Procedures are exactly like User Defined Functions except they: 

- Do not return any value and thus cannot be used as expressions. 

- Cannot be given names starting with FN' (which is used exclusively for functions). 

- Use slightly different but parallel keywords: PROCEDURE, ENDPROCEDURE, EXITPROCEDURE vs. FUNCTION, ENDFUNCTION 

- EXITFUNCTION. 

To call the procedure, use a form of the CALL statement: 

```
CALL procname(var1,...varn)
```

A-Shell Reference 

Page 1493 

Note that functions can also be called in the same way, and their return values can be ignored, so there is no actual need for procedures at all, and many programmers just use functions exclusively. 

## **History** 

- 2016 August, A Shell 6.3.1523, compiler edit 770:  Add private attribute for functions and procedures. 

- 2014 January, A Shell 6.1.1373: Named parameters implemented in A-Shell. 

A-Shell Reference 

Page 1494 

## **SUBROUTINES** 

## **Description** 

Subroutines are conceptually similar to Functions and Procedures but evolved from different origins. They fall into three categories: 

**In-Program Subroutines:** These are basically just glorified GOTOs. They consist of a group of statements in the main body of your program, preceded by a label that can be referenced in a CALL or GOSUB statement, and ending in a RETURN, such as: 

```
CALL FOOBAR
```

```
...
```

```
FOOBAR:
```

```
...
```

```
RETURN
```

These subroutines do not exist outside the running program, and cannot be called or otherwise referenced by other programs. To avoid confusion, these will henceforth be referred to as “GOSUBs”, while “subroutines” will be understood to refer only to the following categories. 

**Embedded Subroutines:** For historical reasons, many frequently-used subroutines are built into A-Shell. They are written in C and have been linked into the A-Shell executable. You can call them from within any program, without reference to any files or folders. See Introduction to Subroutines for a more complete discussion. 

**SBX Subroutines:** These are programs written in A-Shell BASIC and compiled into a subroutine format and filename (“.sbx”). The compiled programs are placed into one of the directories in the A-Shell environment SBX search path, and can then be called by any program without need to specify a location or full filespec. See SBX Subroutines for a more complete discussion. 

Embedded and SBX subroutines are called using one of the following statement types: 

A-Shell Reference 

Page 1495 

```
XCALL name {, param1, ..., paramN}
```

```
VXCALL string-expr {, param1, ..., paramN}
```

XCALL requires a literal name, whereas VXCALL takes a string expression that evaluates to the target subroutine name. Note that SBX routines can also be invoked as functions; see External (XFUNC) Functions for details. 

## **Organization** 

As mentioned above, the embedded subroutines are built into the A-Shell executable You never need to worry where they are, and you cannot modify them. You can, however, rename them, and thereby modify their behavior via the ALIASSP and SBRSP directives and in the system configuration file. 

The SBX subroutines, hereafter referred to by their extension “SBX,” are individual files residing in the SBX search path. They originate from separate sources: 

**Included with A-Shell:** these subroutines are installed along with the rest of A-Shell, and are documented in the “Subroutines” section of this document. 

**Your SBXes** are those you have written for your application(s). 

**Shared SBXes** are those maintained in the A-Shell Shared Open Source Library (SOSLIB), which you need to retrieve and install. These are programs written by MicroSabio or A-Shell developers and made available to the A-Shell community. 

A final category of subroutines is **External Library Functions** . They are typically housed in DLLs for Windows and .so files for Linux. If the routine/function has a C-compatible interface, and most do, it can be called from A-Shell using the embedded subroutine DYNLIB. 

Here is a diagram which provides a possibly-helpful visual of the relationship between the various components being discussed: 

## **See Also:** 

- Subroutines 

- SBX Subroutines 

A-Shell Reference 

Page 1496 

- Subroutines vs. Functions/Procedures 

- ALTSBXEXT 

A-Shell Reference 

Page 1497 

## **ERROR TRAPPING** 

_Reviewed and Revised May 2024_ 

According to received wisdom, error handling is one of the two most challenging issues in programming. Along with naming things. (And off-by-one errors.) 

When an error (aka "exception") occurs while processing an ASB statement, two things happen: 

- The error number and location are saved in internal variables that can be queried via the ERR() function. 

- The flow of control is interrupted and redirected to either the default error handler, or an explicitly defined trap label. 

- If the TRACE system parameter BASERR option is enabled, as it normally should be, details about the error, including the 

- stack trace, are written to the ashlog.log file. 

This is the ASB version of the "try / catch" framework for error handling used by some other languages. 

## **Default Error Trapping** 

If no explicit error trapping has been declared in the current context, the default error handler does one of the following, depending on that context: 

- If within a User Defined Function, an implicit EXITFUNCTION is executed, terminating the function and forwarding the error back to the caller, where it appears as if the error had occurred on the statement calling the function. Note that this handler applies whether or not the function is within a main program or an SBX subroutine. 

If not within a function (i.e if in the main routine), an implicit END is executed. In the case of an SBX Subroutine, control returns to the program that called it, with the error status cleared. Otherwise, it displays an error message of the following form and then drops to the Command Prompt with the error condition cleared. 

- `?<error description> {in line #} at location counter &hxxxx of <program name>` 

The error description is extracted from the SYS:ERRMSG.xxx file (xxx is the current language extension, e.g. "USA") based on the error number. The line number clause appears only if the program has line numbers. The location counter always appears; it can be cross-referenced to the source code using the compiler List File. 

A-Shell Reference 

Page 1498 

## **Explicit (Application Controlled) Error Trapping** 

To exercise greater control, you can declare your own error handlers, using the ON ERROR GOTO statement, which see for details. 

## **Comments** 

Note that all of the discussion above refers only to a particular class of errors that occur within and interrupt ASB statements. Many internal (non-SBX) Xcall subroutines and even system functions may explicitly detect other classes of errors, returning them as status (aka error) codes. Those kinds of errors are not affected by the error trapping described in this topic. 

## **See Also** 

- Error Trapping in Functions 

- Error Trapping in Subroutines 

- Call Stack Tracing 

A-Shell Reference 

Page 1499 

## **CALL STACK TRACING** 

When an ASB error occurs and the system trace opcode BASERR is set, details about the error will be automatically logged to the ashlog.log file. For example: 

```
04-Dec-12 14:36:50 [JACKX201:02-2]<TEST1:UTIL99:11a19> Trapped ASB error #10 at location counter 11a19
```

```
04-Dec-12 14:36:50 [JACKX201:02-2]<TEST1:UTIL99> Call stack trace, from program TEST1 :
        From loc 494, Xcall UTIL99
```

```
        From loc f42d, Call Proc() @f5d6
        From loc fc85, Call Proc() @10d37
```

The first line indicates that the error #10 occurred at location 11219 (hex) in UTIL99.SBX which was called by TEST1; and that it was trapped. 

If the error occurs anywhere but the main body of the main program, a call stack trace will be shown as well, so as to help you identify how the program got to where the error occurred. For deeply nested errors, this can be a significant aid to debugging. The above stack trace starts out in program TEST1, location 494 (hex), where there is an XCALL to subroutine UTIL99. Next, at location f42d within UTIL99.SBX, there is a call to procedure whose address is 5fd6. you will need to use the LSX file to look up that location to determine the name of the procedure. Similarly, from within that procedure, there is another procedure call at location fc85, to a procedure whose address is 10d37. 

Under Unix, the call stack trace will also be logged in the case of segmentation fault (which should be a rare occurrence, but when it does happen, the stack trace is invaluable since there is no way to trap the error before the entire process is terminated. 

LSX file notes:  Each source line may span a range of locations, such that there may not be a line in the LSX file explicitly identified with the location number of interest. You will have to interpolate to find the line with the highest location number prior to the location you're looking for. Also note that for obvious reasons it's critical that the LSX file matches the compiled program— i.e. were both generated from the same source file compilation. You can confirm this by comparing the hash codes for the source and object file listed in the LSX file header. 

**See Also** 

A-Shell Reference 

Page 1500 

- MX_CALLSTACK 

## **History** 

- 2012 December, A Shell 6.1.1325:  Feature added to A-Shell 

A-Shell Reference 

Page 1501 

## **OTHER BASIC TOPICS** 

A-Shell Reference 

Page 1502 

## **DOT FUNCTIONS** 

_Reorganized August 2025_ 

Like Dot Variables, Dot Functions are so named because they begin with a period (dot). There is no particular significance to the dot, other than to minimize conflicts with existing variables or functions when adding new system functions to ASB. For example, when the .EXTENT() function was added, the dot prefix was chosen to avoid potential conflict with existing arrays or user-defined functions named EXTENT. In the case of the .INSTRR() function, the dot prefix was chosen to create more separation with the similarly named INSTR() function. 

Dot functions fall into various categories, as shown below. 

## **Collections and Arrays** 

- Multi-level List MLIST 

- Special ORDMAP Functions 

- .EXTENT() 

## **String** 

- .INSTRR() 

- .ISEMPTY() 

## **Print File Processing** 

- .LINENO() 

- .PAGENO() 

## **Random and ISAM File  File Processing** 

- .FSTAT() 

- .RECNO() 

A-Shell Reference 

Page 1503 

- .RECSIZ() 

## **Defstruct Member Reference** 

- .OFFSET() 

- .OFFSIZ$() 

## **Function and Subroutine Support** 

- .ARGTYP() 

- .ARGSIZ() 

- .EXTERN() 

- Implicit Function Return Value Capture 

## **See Also** 

- Dot Variables 

- .CLEAR statement 

A-Shell Reference 

Page 1504 

## **EXTENSIONS** 

## _Rewritten May 2024_ 

Although probably not of much immediate interest to modern ASB programmers, those who came from the AMOS world may be interested to know that the features of ASB can be broken down into the following three sets: 

|**Source**|**Descriptions**|
|---|---|
|AlphaBASIC|The entire AlphaBASIC 1.3 and 1.4 language.  Use the compiler switch /o to limit support to<br>just the 1.3 standard and maintain RUN binary compatibility.|
|AlphaBASIC_Plus_|Selected features from the AlphaBASIC_Plus_standard.  Use compiler switch /x:1 to enable.|
|A-Shell|Features unique to A-Shell. In most cases, the language elements have been inspired by<br>features in other languages, but are not intended to be code compatible with any other BASIC<br>standard. Use compiler switch /x:2 to enable.|



## **See Also** 

- ASB Keywords 

- COMPIL 

A-Shell Reference 

Page 1505 

## **PLUS EXTENSIONS** 

The /X:1 switch (or equivalently, COMPLP) extends the compiler support to include certain statements which were originally implemented by BASIC _plus_ ; these are listed below. Refer to the BASIC _plus_ User's Manual for more details on these language features. 

Note that although A-Shell supports these BASIC _plus_ language extensions in source code, in no way does it support the .RP (compiled BASIC _plus_ ) file format. Instead, it compiles them as non-standard extensions to the .RUN format, and any such .RUN files will not be compatible with RUN.LIT or RUNP.LIT under AMOS. Thus, if you choose to use these language extensions and want to run them under both A-Shell and AMOS, you will have to recompile the source on both platforms. 

The /RC (Run Compatible) on COMPIL, when used in place of the /X:1 or /X:2 switch, allows many of these extensions to be compiled into a RUN format that remains compatible with AMOS. In the following table, the "/RC?" column says whether, when compiling with the RC switch, use of this statement or feature will produce a run file that is run compatible ("RC") with AMOS. 

|**Extension**|**/RC?**|**Meaning**|
|---|---|---|
|AMOS||Execute AMOS commands as subroutines|
|CMDLIN||Retrieve command line|
|DEFINE|Yes|Define a symbolic constant|
|UNDEF||Cancels (undefines) a symbol created by a priorDEFINEorDEFALIASdirective|
|DIVIDE’BY’0||Determine how to handle divide by zero|
|DO LOOP|Yes|Repeat loop while (or until) a condition is (or becomes) true.|
|EDIT$ ()||String editing function|
|ERRMSG(x)||Returns the text of the error message associated with the specified error number (from the<br>SYS:ERRMSG.xxx file).|
|EXIT|Yes|May be placed inside of a DO...WHILE or For ... Next loop to cause an immediate exit of the loop.|
|FILL$ ()||Copies the given expression, partially or multiple times, up to the specified length.|
|FOR … NEXT|Yes|Traditional loop structure using a loop counter.|



A-Shell Reference 

Page 1506 

|**Extension**|**/RC?**|**Meaning**|
|---|---|---|
|GETKEY||Input a character|
|Hex, Octal, ASCII<br>Values|Yes|Specifying literal values in an alternate radix|
|I variable type||Integer variable type|
|IF / ENDIF|Yes|IF <condition> THEN<br>statements<br>ENDIF|
|INPUT RAW||Raw input, from file channel or keyboard, into X variables.|
|ISAM’INDEXED<br>{‘EXCLUSIVE},<br>ISAMP’INDEXED<br>{‘EXCLUSIVE}|Yes|These file type specifiers may be used in file OPEN statements to clarify if the file is to be handled<br>as ISAM 1.x or ISAM-A. See /I switch above. Note that this applies to AlphaBASIC 1.4 as well as<br>BASIC_plus_.|
|LOOKUP ("fspec")||Similar to LOOKUP but returns file size as value of expression. Note that a zero block file returns<br>0.5.|
|ODTIM<br>()||Day / Time output conversion/formatting|
|OPEN for APPEND||Enhancement to OPEN #CH, FSPEC, APPEND|
|PRAGMAS||See++PRAGMAS<br> in A-Shell Extensions.|
|READ'ONLY||File open mode modifier|
|REPEAT|Yes|Jump to top of loop structure to begin next iteration|
|STRIP(var) or STRIP$ (var)||Returns_var_with all trailing spaces removed.|
||Yes|Conditional execution based on value of an expression.|



A-Shell Reference 

Page 1507 

## **- A SHELL EXTENSIONS** 

In addition to the AlphaBASIC and BASIC _plus_ statements, A-Shell also supports a set of statements which are only available under A-Shell—i.e., are not part of the AlphaBASIC environment. These statements are listed in the table below, and are referred to as the A-Shell Extensions. To invoke these extensions, use: 

- /X:2 to create a standard .RUN file 

- /X:3 to create an .SBX file 

Note that /X:3 does not disturb an existing .RUN, so it is possible to compile the same source into both a .RUN and a .SBX, as follows: 

```
.COMPIL MYPROG/X:2    ; create MYPROG.RUN
```

```
.COMPIL MYPROG/X:3    ; create MYPROG.SBX
```

The /RC (Run Compatible) on COMPIL, when used in place of the /X:1 or /X:2 switch, allows many of these extensions to be compiled into a RUN format that remains compatible with AMOS. In the following table, the "/RC?" column says whether, when compiling with the RC switch, use of this statement or feature will produce a run file that is run compatible ("RC") with AMOS. 

|**Extension**|**/**<br>**RC?**|**Meaning**|
|---|---|---|
|3D Print Tab|Note<br>1|Tab(x,y,z). SeeThree-D Print Tab<br>.|
|Call Stack Tracing|||
|Comment|Yes|Comment may follow an & on a continuation line|
|COMPILER_VERSION Macro|||



A-Shell Reference 

Page 1508 

|**Extension**|**/**<br>**RC?**|**Meaning**|
|---|---|---|
|Conditional Compilation|Yes||
|DEBUG||Control variable. If /DEBUG compile switch specified, acts as if it equals 1, otherwise 0. If /DEBUG<br>switch is not specified, then it may still be activated at runtime by using SET DEBUG, or<br>MX_DEBUG. Note that for backwards compatibility, mapping DEBUG explicitly as an ordinary<br>variable will disable the control variable DEBUG. See Note 3 below.|
|DEBUG statements|Yes|SeeDEBUG Statements<br>.|
|DEFSTRUCT|Yes|Allows you to assign a type name to a set of MAP statements and then use that as if it was a data<br>type.|
|DIMX|Note<br>4|Enhanced dynamic array allocation. SeeDynamic Arrays (DIMX)<br>.|
|Dot Variables||Read-only system variables.|
|DPRINT|Note<br>2|Creates a static text control using the current default GUI (proportional) font and with the sunken<br>attribute. Note that if the /X:2 switch not specified, TPRINT is compiled as PRINT. Intended for<br>displaying data fields. SeePRINT Statement<br>.|
|Dynamic variables||Dynamically Sized Variables<br>.|
|ELSEIF Clauses|Yes|One or more ELSEIF clauses may be inserted into an extendedIF/ELSEIF/ELSE/ENDIFstatement.|
|EPRINT||Embeds the output fields in edit boxes; is typically used for displaying editable data fields. See<br>PRINT.|
|++ERROR<br> <message>|Yes|Causes the message to be displayed and is treated as a compiler error. This is particularly useful|



A-Shell Reference 

Page 1509 

|**Extension**|**/**<br>**RC?**|**Meaning**|
|---|---|---|
|||in conjunction with conditional compilation, as shown in the preceding example.|
|INPUT CSV||Input comma separated values|
|INSTR()||When the fourth parameter (flags) is specified (even if 0), the pattern is treated as a regular<br>expression.|
|ISAM File Statements|||
|Line length|Yes|Maximum source line length of 3070 instead of 512.|
|MAP Statement||PRIVATE and PUBLIC keywords for fine tuning scope of variables (MAPorDIMX).|
|++MESSAGE||Equivalent to++ERROR<br><message> except that no error is generated.|
|Nested ++INCLUDEs|Yes|Nesting to 13 levels deep|
|PAD()||Pad a string with spaces|
|++PRAGMAs|Yes|Compiler Directives<br>.|
|Procedures|||
|REDIMX||Re-dimensions an array originally created withDynamic Arrays (DIMX)<br>.|



A-Shell Reference 

Page 1510 

|**Extension**|**/**<br>**RC?**|**Meaning**|
|---|---|---|
||||
|Return <expression>||Return value fromXFUNC()<br>.|
|Shortcut Operators|Yes||
|Three-D Print Tab|Note<br>1|Tab(x,y,z).|
|TPRINT|Note<br>2|Same as DPRINT but without the sunken effect. Also note that SET AUTOTPRINT causes all PRINT<br>statements to behave at runtime as if they were compiled as TPRINT. SeePRINT Statement<br>.|
|TRACE Statements|Note<br>3|These statements open, print to, and close the System Messages window.|
|Underlines in variable names|Yes|Variable names (and constants) may contain underlines. Although this has no special meaning, by<br>convention it is used primarily with constants.|
|Dynamic Structure Functions|||
|WRITECD||Output comma delimited values|
|WRITETD||**Deprecated**; see WRITECD<br> for important note. Old documentation: same as WRITECD, except<br>that it outputs Tab delimiters instead of comma delimiters.|
|UNDEF <symbol>|Yes|Causes the specified symbol to be undefined, allowing it to be redefined or to fail a++IFDEF<br>symbol test.|
|XFUNC()||Call an external (SBX) function|



A-Shell Reference 

Page 1511 

|**Extension**|**/**<br>**RC?**|**Meaning**|
|---|---|---|
||||
|XGETARG||Retrieve subroutine parameters. SeeX-ARGs<br>.|
|XGETARGS||Retrieve subroutine parameters. SeeX-ARGs<br>.|
|XPUTARG||Return subroutine parameters. SeeX-ARGs<br>.|
|XREAD||Allow record access via explicit record numbers. SeeXREAD, XWRITE, XUNLOKR<br>.|
|XWRITE||Allow record access via explicit record numbers. SeeXREAD, XWRITE, XUNLOKR<br>.|



## **Notes** 

- 1: Compiler ignores "z" value. 

## 2: DPRINT / EPRINT / TPRINT are compiled as if PRINT. 

3: TRACE.XXXX / DEBUG.XXXX are compiled as XCALL EVTWIN; need to supply AMOS implementation. 

4: Statement will be compiled if `OPTIONS=RC_DIMX` in miame.ini; however, the runtime token is not AMOS-compatible, so you must have other runtime logic to detect AMOS and avoid the statement. 

A-Shell Reference 

Page 1512 

## **GDI PRINTING** 

A-Shell Reference 

Page 1513 

## **INTRODUCTION TO GDI PRINTING** 

Refer to PASSTHROUGHSP for a discussion on the GDI printing method versus the "RAW" or PASSTHROUGH method. Note that GDI printing is primarily a Windows topic, but might still apply to A-Shell/Unix if ATE is available on the workstation as an auxiliary print service. In that case, you would need to use `COMMAND=SBX:GDIPRT` in the printer ini file on the Unix side. 

When working in the Windows environment, it is natural to want to do things in the most Windows-like fashion possible so that your A-Shell application appears to function just like "any other standard Windows application." However, a "standard Windows application" does not open a print file to create a report and then send it to the spooler when the report is complete, as does a typical ASB application. Instead, it opens up a "printer context" within Windows' Graphic Device Interface subsystem, and then uses GDI functions to tell the GDI system how to create the report. Even the ordinary text of the report is "fed" to the GDI system, which decides how to render it in a form the printer can use. 

Switching to the "standard Windows" technique of creating reports would force you to have to rewrite all of your report programs, and several new language statements would have to be added to BASIC to support it. Since this doesn’t seem practical for the majority of A-Shell programmers who have already developed large numbers of report programs, A-Shell does the conversion dirty work for you. It does this by taking the report file which you sent to the spooler, and then feeds it to the GDI system for you, along with some initial directives to establish the printer orientation, font, etc. 

Where does it get these "initial directives?" First, it consults the printer’s initialization file, where it may find such directives as FONT, FONTWIDTH, FONTHEIGHT, ORIENTATION, TMARGIN, LMARGIN, etc. Based on the parameters found there, it creates a suitable printer context and then feeds the contents of your report file to the GDI using that context. 

The only problem with this technique is that it doesn’t give you any opportunity to change fonts or issue other special printer graphics commands in the middle of the report. (Even if you knew the printer type in advance, it generally doesn’t work to embed actual escape sequences in the report when using this technique, because the printer driver called by the GDI system to process the text is likely to try to render them graphically as special characters.) To deal with this problem, the A-Shell embedded print directives were developed. These commands may be embedded directly in the print file (as their name suggests) but they are logical directives expressed in a form that the GDI system can understand (after appropriate translation by A-Shell) rather than printer-specific escape sequences. Besides the advantage of actually working at all, this technique has the additional advantage of being device independent. 

## **Comments** 

A-Shell Reference 

Page 1514 

When a //GDI directive fails, the directive itself is printed (rather than the intended effect of the directive). In addition, if the directive failed because of a Windows error, then the error code will be printed at the end of the line, e.g. "(err 1400)". You can look up Windows error codes on the web, or translate them using MX_ERRNOMSG. 

## **Subtopics** 

- Writing GDI Print Directives 

- Parameters: Symbols vs. Values 

- Line (Vertical) Spacing 

- Relative vs. Absolute Position 

- Printing Special Symbols 

- Forms Printing 

A-Shell Reference 

Page 1515 

## **WRITING GDI PRINT DIRECTIVES** 

_Updated September 2024_ 

Here are some rules and guidelines for dealing with A-Shell's GDI print directives. 

- To embed GDI print directives in your print file, they must begin in column one with // (two forward slashes) followed by the 

- name of the directive and its parameters. 

- A comma must immediately follow the directive, and commas must separate all parameters, with no intervening spaces. 

- String arguments may be quoted with quote marks "like this" to make sure punctuation characters within the string itself— 

- especially embedded commas—are not confused with the syntax of the directive. However, quoting is optional for the last parameter. This applies mainly to the various //TEXTxxx directives. 

- The maximum length of a directive is 16K.  (This applies mainly to the //TEXTxxx directives.) 

- In the case of //TEXTxxx directives, where the last parameter is the text to output, you may end the text with a backslash to 

- indicate that the next line is to  be concatenated to it, assuming the next line does not start with a forward slash. This might be useful to avoid very long lines in your source text. To include a literal backslash as the last character of a text argument, either append a space to it or quote the entire  text argument. 

- Embedded GDI directives are only processed if PASSTHROUGH=OFF. 

- Comments, which are ignored for printing purposes, are indicated by beginning a line with "//;", two slashes followed by a 

- semicolon, starting in column 1. This is useful for documenting your other GDI print directives which might otherwise be less than obvious when examining the file in a text editor. Note that comments may not appear elsewhere, like on the end of the line after an exclamation point as in ASB. 

- To change font or issue some other GDI print directive in the middle of a line of output, append a backslash to the end of the 

- first part(s) of the line to hold the position so that the next line of output starts where the previous one left off. See the example in the next section for further clarification. Note that this only works for plain text, not for text output via //TEXTxxx directives, which do not affect the 'cursor' position in any case. If you want to change font in the middle of a string of text output by a //TEXTxxx directive, you'll have to split it into two //TEXTxxx directives, separated by the font change directive. 

- Some printer/printing characteristics, such as paper orientation (landscape or portrait), can be changed _only_ with printer 

- initialization file commands and not with GDI commands. 

A-Shell Reference 

Page 1516 

- While most GDI printing operations can be performed by embedding GDI Print Directives into the print file, there are some 

- printer init commands that may affect or work in conjunction with GDI Print Directives. Specifically, the commands XOFFSET, YOFFSET, XORIGIN, YORIGIN control the "fine" positioning of the print on the paper. 

- Also note that the printer init parameters PITCH, LPP, CPP, FONT, FONTHEIGHT and FONTWIDTH may affect the way plain 

- text is rendered, even when it is found in a print file otherwise full of GDI print directives. 

- Neither the GDI directives nor their associated parameters are case sensitive. 

## **Sample GDI Printfile** 

This example of a GDI printfile illustrates a few important things such as comments, embedded GDI directives, and the use of the backslash line terminator to allow a change of font in the middle of a line. 

- `//; This is an example of a printfile using embedded GDI directives.` 

- `//; Any line starting with //; is a comment and is ignored during printing` 

```
//; Set units to 1/100 of an inch
```

```
//SETMAPMODE,LOENGLISH
```

- `//; Establish font (otherwise we'll get the default or one set by printer init` 

```
//SETFONT,120,Times New Roman,0,16
```

```
Lines like this are printed using the current font,
```

```
and advance down the page in the normal way.
```

```
//TEXTOUT,25,45,"Text can also be output with //TEXTOUT at specific positions"
```

```
//RECTANGLE,40,75,240,100,1
```

```
//TEXTCENTER,40,75,240,100,"This text is in a shaded box"
```

A-Shell Reference 

Page 1517 

```
//;TEXTxxx does not move internal cursor, but MOVETO does
```

```
//MOVETO,0,110
```

```
//;Lines ending in backslash leave cursor in position at end of line
```

```
This line changes to \
```

```
//SETFONT,120,Times New Roman,0,16,0,3
```

```
Underlined Italic \
```

```
//SETFONT,120,Times New Roman,0,16,0,0
```

```
in the middle of the line.
```

The above sample would print as shown below. Note the use of the backslash to break the last line into parts so that the font could be changed in the middle of the line. 

## **History** 

- 2024 September, A Shell 7.0.1762:  Add support for special handling of trailing backslash in //TEXTxxx directives. Previously it was only recognized as a special character in plain text outside of GDI directives. 

A-Shell Reference 

Page 1518 

## **PARAMETERS: SYMBOLS VS. VALUES** 

Many GDI printing parameters can be expressed either numerically (in normal base 10 or hex notation), or symbolically, using symbol names that happen to match those used by Windows, as well as being defined in ASHINC:ASHELL.DEF. 

Prior to build 945, A-Shell forced you to express all such parameters in base ten numeric format within the print file itself, resulting in GDI commands like the following: 

```
//SETFONT, 120, Arial, 34, 0, 512, 1
```

Beginning with build 945, you can express those arguments using the hex notation (&h022) or symbolic names as documented with the individual GDI directives. So the above directive could be expressed in any of the following ways: 

```
//SETFONT, 120, Arial, &h022, ANSI_CHARSET, FW_EXTRABOLD,FS_ITALIC
```

```
//SETFONT, 120, Arial, VARIABLE_PITCH | FF_SWISS, ANSI_CHARSET, FW_EXTRABOLD,FS_ITALIC
```

```
//SETFONT, 120, Arial, variable_pitch | ff_swiss, ansi_charset, fw_extrabold,fs_italic
```

```
//SETFONT, 120, Arial, variable | swiss, ansi, extrabold, italic
```

These examples illustrate the following points: 

- Upper and lower case doesn't matter. 

- You can use the vertical bar symbol to combine two symbolic values into a single parameter. (This applies only to symbolic 

- names, not to decimal or hex values.) 

- You can drop the suffixes and prefixes such as _CHARSET, _PITCH, FW_, FS_, etc. 

This last point may cause some confusion, since normally symbol names (like variable names) must be precise. If you handle any of these parameters as numeric values (perhaps storing them in numeric variables) then you will want to use the precise symbols as defined in ASHINC:ASHELL.DEF, e.g. `FONT'FAMILY = FF_SWISS` , since these are interpreted by the compiler, which is not very forgiving. But if you are going to use the symbol names as literal strings in the print file, the A-Shell print formatter will parse them by looking for the "important" parts of the symbol names. Thus, the prefixes and suffixes which are common to all the symbols in a group are ignored and need not be included. 

A-Shell Reference 

Page 1519 

Use of the symbol names rather than the numeric values will make both your programs and the print files themselves easier to understand and therefore to modify. 

A-Shell Reference 

Page 1520 

## **LINE (VERTICAL) SPACING** 

Although it is possible to create output in which every bit of text is explicitly positioned (e.g. using TEXTOUT), it is common for some or even all of the text in a GDI report to rely on some kind of automatic line spacing. To this end, the GDI output system maintains a virtual "cursor" (print head?) which marks the position where the next character will be output, unless some kind of explicit repositioning directive is issued first. This cursor moves horizontally (based on the character widths) as text is output, and vertically whenever a line terminator (CRLF or just LF) is processed. 

The remainder of this topic discusses the various commands and parameters which determine how the vertical line spacing is calculated. 

LPP in the printer ini file: The initial line spacing is determined by the combination of the LPP (lines per page) parameter in the printer ini file and the effective paper size (which may be determined at print time based on user actions and/or printer driver defaults). For example, if LPP=63, and the effective paper length (minus the physical printer margins) is 10.5 inches, the initial line spacing will be set to 1/6 inch. If there is no LPP specified in the printer ini file (or if there is no printer ini file), a default value of 66 is used for portrait and 51 for landscape. Note that unless the printer ini file also specifies PITCH=AUTO, the line 

spacing will be independent of the initial font size (which is determined by a FONT parameter in the printer ini file, SETFONT directives in the print file itself, or the printer driver defaults). 

SETVMI: This directive in the print file overrides any previous line spacing and establishes new spacing. Note that such spacing is independent of font and paper sizes. See comments below for details on precision. 

RESETLPP: This directive in the print file cancels the line spacing established by the printer ini file and/or a prior SETVMI. Once the default line spacing has been reset in this way, it will be automatically adjusted to match the natural line spacing of font of the current font (and will continue to be automatically adjusted by subsequent SETFONT directives). 

SETFONT: These directives in the print file do not normally change the line spacing established by the printer ini file and/or a prior SETVMI, unless the prior line spacing has been reset by a RESETLPP directive, in which case the line spacing is adjusted to match the natural cell height (including external leading) of the font. 

SETTEXTALIGN: This does not affect the line spacing, but does affect the relationship of the characters to the "cursor". Without an explicit SETTEXTALIGN directive, the cursor position is taken to be the upper left corner of the next character cell. 

## **Comments** 

A-Shell Reference 

Page 1521 

Prior to A-Shell 5.1.1150.0, the vertical line spacing resulting from the above factors was always rounded down to the nearest pixel of the output device. This sometimes resulted in overall vertical spacing less than anticipated. For example, if you used the combination of `//SETMAPMODE,TWIPS` and `//SETVMI,180` to establish 8 lines per inch spacing, on a 300 DPI device, that comes to 37.5 pixels per line, which was being rounded to 37. By the bottom of the page, those half-pixels could add up to the equivalent of an entire line. But changing the DPI of the output device to 600 would have made the rounding error go away. 

Starting with A-Shell build 5.1.1150.0, the line spacing is instead maintained internally in tenths of pixels and only rounded to the nearest pixel when actually positioning a line of text. This eliminates the accumulation of rounding / conversion errors as you move down the page, and makes the spacing nearly immune to changes in the device resolution (both good things) but could result in slightly different vertical spacing (i.e. more precise) vs. the prior version. 

A-Shell Reference 

Page 1522 

## **RELATIVE VS. ABSOLUTE POSITION** 

_Added September 2018_ 

The x,y coordinates in all //GDI directives are interpreted, by default, as relative to the coordinate space of the current page, with the point 0,0 usually being the upper-left logical corner. The units are determined by the SETMAPMODE directive. 

Beginning with A-Shell 6.5.1637 of June 2018, any of the coordinates may also be specified as relative to the current cursor position by prefacing the coordinate value with "+" or "-". For directives with more than one x,y pair (such as RECTANGLE or POLYGON), any relative coordinates are treated as relative to the prior coordinate on the same axis. Some examples: 

```
//;absolute coordinates - from (100,200) to (300,400) ...
```

```
//RECTANGLE,100,200,300,400
```

```
//;relative coordinates - from 50 units above the current x,y cursor,
```

```
//;extending 200 to the right and 75 down
```

```
//RECTANGLE,+0,-50,+200,+75
```

Notes: 

- While mathematically N is the same as +N, within the context of GDI directives, they are all strings, allowing the +N to be 

- recognized and treated differently than N—i.e. as relative rather than absolute. 

- To preserve backwards compatibility with A-Shell prior to version 6.5.1637, those directives that intepreted -1,-1 as the 

- current position continue to do so. 

- The IMAGE directive supports negative right and bottom coordinates as indicating width and height. Fortunately, there is no 

- particular need for negative widths or heights, so nothing is lost by treating negative and positive relative right and bottom coordinates the same here. 

## **See Also** 

A-Shell Reference 

Page 1523 

- SETMAPMODE 

- SETTRANSFORM 

- XOFFSET, YOFFSET 

- XORIGIN, YORIGIN 

## **History** 

- 2018 June, A Shell 6.5.1637:  cursor-relative coordinates added to A-Shell. 

A-Shell Reference 

Page 1524 

## **PRINTING SPECIAL SYMBOLS** 

You may insert nearly any special symbol into printed text by embedding the corresponding Unicode Symbol Entity Reference into the text (whether plain text or text passed as an argument to TEXTOUT). These Symbol Entity References must have one of the following syntaxes: 

- &#ddd; decimal version, ddd are decimal digits 

- &#xhhhh; hex version, hhhh are hex digits 

In either case, the numeric value is taken as a reference to the corresponding UNICODE "code point". Note that the trailing semicolon is required. 

## **Example** 

The formula for the circumference of a circle is 2&#x03c0;r 

(&#x03c0; is converted at print time to the symbol for pi) 

## **See Also** 

- SETOPTION 

- TEXTOUT 

- TEXTCENTER 

- TEXTRECTANGLE 

A-Shell Reference 

Page 1525 

## **FORMS PRINTING** 

_Written February 2020_ 

When you need to submit data on an existing form, there are several possible approaches to take. You would normally use A- Shell's GDI printing commands to position report data on the form, and then: 

- Physically print the data onto a pre-printed form using a printer as the "combining" mechanism. This is the method that was 

- used in the early days of computers. 

- Create (scan) an image of the form. By then using the IMAGE directive, followed by the form data, you create a single 

- document that is ready for printing. 

- Use GDI print commands to actually create the form in A-Shell, then print the data in the form areas you have created. 

- If you use A-Shell's PDFX module, you also have the option of using the official PDF form (from a government agency, 

- typically) as an unaltered "overlay" onto which you print the data. 

In all of these except the first, "printing" is understood to mean both actual physical printing, and virtual printing which normally means sending to a printer-like PDF creator. 

For an in-depth discussion of the issues involved in creating forms in A-Shell, refer to this discussion on the A-Shell forum. 

A-Shell Reference 

Page 1526 

## **PRINT DIRECTIVES** 

Below is a list of all the available print directives, with links to extended descriptions for each. 

|**Directive**|**Description**||**Directive**|**Description**|
|---|---|---|---|---|
|Totpages (%#)|Total pages in document||SETBRUSH|Sets line thickness and style for filling|
|BIN|Specifies paper bin or tray||SETFONT|Sets font|
|DUPLEX|Sets DUPLEX options||SETMAPMODE|Sets position for subsequent drawing|
|ELLIPSE|Draws ellipse||SETOPTION|Enables various printing options.|
|ESCAPE|Passes raw ESC codes||SETPEN|Sets drawing line thickness and style|
|IMAGE|Inserts image||SETPENEX|Extended version of SETPEN|
|INCLUDE|Processes external file||||
|LINETO|Draws a line||SETTEXTALIGN|Sets alignment method|
|META|Embeds meta data||SETTEXTCOLOR|Sets text color|
|METAFILE|Inserts metafile||SETTRANSFORM|Transforms the coordinate space.|



A-Shell Reference 

Page 1527 

|**Directive**|**Description**||**Directive**|**Description**|
|---|---|---|---|---|
|MOVETO|Positions cursor||SETVMI|Sets vertical spacing|
|ORIENTATION|Sets landscape or portrait||TEXTCENTER|Outputs and centers a line of text|
|PAPERSIZE|Sets paper size||TEXTINDENT|Variation of TEXTOUT for indents|
|PASSTHROUGH|Sets printer mode||TEXTOUT|Outputs a line of text|
|PDFX|Controls PDF generation||TEXTRIGHT|Outputs a line of text right justified|
|POLYGON|Draws a polygon||TEXTRECTANGLE|Output multiline text into rectangle|
|RECTANGLE|Draws a rectangle||XOFFSET, YOFFSET|Makes minor positioning adjustments|
|RESETFONT|Restores original font.||XORIGIN, YORIGIN|Defines offset from paper corner|
|RESETLPP|Resets lines-per-page value||XMDATA, XMFIELDS|Controls XTEXT mail merge|
|SETBKCOLOR|Sets background color||XTEXT|Prints text or RTF file into rectangle|



A-Shell Reference 

Page 1528 

## **TOTPAGES (%#)** 

The pseudo-directive **%#** , inserted anywhere in the printfile, will be converted to the total number of pages in the printfile. Note that "totpages" is not part of the directive; just the symbol **%#** . Also note that unlike the other GDI print directives, this one does NOT require the // prefix. See the discussion of the EZSPL Old Format for more details. 

A-Shell Reference 

Page 1529 

## **BIN** 

## **//BIN, bin-ID** 

BIN is one of the GDI print directives with a Printer ini file Equivalent. For detailed information, see the printer ini file command BIN. 

Unlike other such directives, which must occur at the top of the file, BIN can occur at any point in the print file. If printing has already begun when BIN is encountered, the effect is delayed until the next page break. To force it to have an immediate effect, insert a chr(12) (form feed) character at the start of the line following the BIN directive. 

A-Shell Reference 

Page 1530 

## **DUPLEX** 

## **//DUPLEX, mode** 

DUPLEX specifies which of the three types of duplexing will be used. The possible values, along with their several aliases, are shown in the following table. 

|**Value**|**Aliases**|
|---|---|
|Horizontal|Horz, H, Short, S, 3|
|Vertical|Vert, V, Long, L, 2|
|None|Off, False|



DUPLEX is one of the GDI printing directives with a Printer ini file Equivalent. 

A-Shell Reference 

Page 1531 

## **ELLIPSE** 

## **//ELLIPSE, left, top, right, bottom, {fill}** 

ELLIPSE draws an ellipse within a specified bounding rectangle. 

## **Parameters** 

## _left, top, right, bottom_ 

Coordinates of the bounding rectangle, in the current mapping units, within which the ellipse is drawn. Note that if these coordinates describe the special case of a square, then the resulting ellipse will actually be a circle. 

## _fill_ 

If specified, causes the ellipse interior to be filled with various shades of gray or colors. See the table of fill values under RECTANGLE for details. 

A-Shell Reference 

Page 1532 

## **ESCAPE** 

## **//ESCAPE, b1, b2, b3, b4,... (up to b14 max)** 

ESCAPE is used for passing raw ESC codes to the printer in the midst of GDI output. 

Each parameter should be a decimal value representing the value of a single byte. Parameters B2 thru B14 are optional. 

This directive is most useful for passing PCL commands to a PCL-compatible printer when you can't figure out how to accomplish the same thing using GDI commands. For example, laser printers normally have a built-in physical margin of 0.25 inches around the outer edit of the paper. But there is a PCL command to adjust this so that the first column printed is closer or farther from the edge of the paper. (This is useful for calibrating a printout to a form.) The PCL to move the left margin 300 decipoints to the right is: 

```
ESC &l300U
```

If you try to just embed this directive in a GDI printout, it will probably be ignored by the driver. But using the ESCAPE directive, you can embed it as follows: 

```
//ESCAPE,27,38,108,51,48,48,55
```

A-Shell Reference 

Page 1533 

## **IMAGE** 

## **//IMAGE, imagespec, left, top, right, bottom {,flags, borderwidth, imagespec2, rotation, pageno}** 

IMAGE works like METAFILE except that it supports BMP, JPG, PCX, TIF and PNG format images. It requires, however, that an external graphics library, vic32.dll, be present and licensed. Note that if any error occurs while trying to print the image, including the specified rectangle extending beyond the printable region of the page, the IMAGE directive itself will print rather than the image. See the topic Parameters: Symbols vs. Values if you have questions about which to use. 

Note that you must specify a SETMAPMODE option other than TEXT. 

## _imagefilespec_ 

File specification of the image (AMOS-style or native). PNG files with WMF extensions are supported. Note that true metafiles with WMF extensions should be handled by METAFILE. 

## _left, top, right, bottom_ 

Bounding rectangle (within current coordinate system) into which the image will be fit. The image may be stretched to fill the rectangle, depending on the flags argument. Setting the right and/or bottom parameter to 0 will be interpreted as the rightmost and/or bottommost edge of the page. Use 0,0,0,0 to fill the entire page, minus the printer’s physical margins. 

## _flags_ 

Add together the applicable options: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|IMGF_HALFTONE|&h001|Use halftone print method.|
|IMGF_SCATTER|&h002|Use scatter print method.|



A-Shell Reference 

Page 1534 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|IMGF_STRETCH|&h004|Stretch image to fit bounding rectangle. Otherwise retain aspect ratio, meaning the image will likely be smal<br>than the rectangle in one of the two dimensions.|
|IMGF_SCALEQ|&h008|Interpolate—i.e., use hq scaling.|
|IMGF_FORCEXFER|&h010|(ATE) Force image filespec to be treated as relative to the host and transfer it to the client. Applies to<br>IMGOP_LOAD and IMGOP_LOADDISP.|
|IMGF_OPTIONAL|&h020|Applies only if_imagefilespec_is missing. Then: if_imagefilespec2_is present, print it. If it is not present, print<br>nothing. Value may also be expressed as the text "Optional." See "Image Is Not Present" discussion, below.|
|IMGF_OFFSET|&h040|Causes images to be shifted according to theXOFFSETandYOFFSETvalues. Normally images only obey th<br>XORIGINandYORIGINvalues, ignoring theXOFFSETandYOFFSETvalues (which allows text to be shifted<br>relative to images when lining up computer-generated forms). But when using multipleXOFFSETand<br>YOFFSETdirectives to shift/repeat sections of GDI output, the ability to move the images along with<br>everything else is critical.|



## _borderwidth_ 

If non-zero, specifies the width, in pixels, of a solid black border to be drawn around the outside of the rectangle 

## _imagefilespec2_ 

File specification of the image to be printed if _imagefilespec1_ is not present. 

## _rotation_ 

The angle in degrees, as in the SETFONT directive. Note that the image is first rotated, then fitted to the specified coordinates. 

## _pageno_ 

A-Shell Reference 

Page 1535 

Specifies the page from within a multi-page TIF file. The first page is considered page number one, but 0 or nothing is also treated as 1. Note that to use APEX as a multi-page TIF image viewer, you would need to first use the AUI_IMAGE 

IMGOP_PAGEINFO operation to determine the number of pages, then generate a series of IMAGE directives, one for each page, probably separated by page breaks. 

## u **File Locations** 

A-Shell will look for the referenced image file in the directories pointed to by the environment variables ATECACHE and ATE, if it is not found in the originally specified directory. This is mainly useful for ATE printing, where the host may pre-transfer images to one of the cache directories without having to modify the print file or deal with incompatibilities between the directory structure used on the host and on the ATE client. 

See the print filter ATPXFR.SBX in SOSLIB:[907,29] for a way to automate such transfers in conjunction with AUXLOC printing. - " Also see the A Shell forum topic AUXLOC printing with //IMAGE" for a detailed description of the issue. 

The GDI print commands IMAGE, XTEXT, and METAFILE will locate the specified file in the same directory as the printfile if it fails to find it in the directory specified in the GDI directive or in the local cache. This is mainly a convenience when printing from another directory. For example, if a printfile BAS:TEST.PRT contains `//IMAGE,TEST.JPG` ,... and you tried to print it from another directory using PRINT BAS:TEST.PRT, versions of A-Shell prior to 995.3 would have failed to find the image test.jpg in the BAS: directory, because you weren't logged there. It also comes in handy when moving print files and their associated images to another location (such as with ASHLPD), since you can combine all the associated files in an arbitrary directory. 

Beginning with A-Shell 1111 of 3 May 08, XTEXT, IMAGE, and METAFILE will look for the file in the same directory as the printfile itself, if not found at the location specified, even when the location specified is a Unix path. This was previously true, since 5.0.999, but only when the original spec was a Windows path. The new logic is mainly of use in ASHLPD or other environments where you generate the GDI printfile under Unix and then transfer it to Windows. 

## u **Image Is Not Present** 

A-Shell Reference 

Page 1536 

A flag and optional second filespec parameter are included to allow more flexibility in handling the case where the specified image is not present. Normally in such a case, the text of the IMAGE directive will be printed at the current "cursor" location on the page. If you would rather have nothing printed, then you can specify the new flag IMGF_OPTIONAL (&h020). You may also specify a second image filespec, which, if the first image is not present, will be printed instead. Either or both of these can be useful in cases where the image file name is derived from some other data (such as a part number), but is not always present (i.e. not every part has an associated image). Rather than the application having to check individually for the presence of each one, the IMAGE directive can do the work for you. 

Note that the IMGF_OPTIONAL value can also be expressed as the text "OPTIONAL", for example: 

```
//IMAGE,p123.jpg,100,100,200,200,OPTIONAL,1,generic.jpg
```

In this example, if p123.jpg is present, it will be printed. If not, and generic.jpg is present, it will be printed. If neither is present, nothing will be displayed (including no border), and there will be no indication of an error. 

Also see the print filter ATPXFR.SBX in SOSLIB:[907,29] and the META GDI directive for alternate approaches to making sure that image files referenced by IMAGE directives are transferred to the client PC before needed during remote (AUXLOC:) printing. 

## u **History** 

- 2013 September, A Shell 6.1.1362:  Add _pageno_ parameter. 

- 2013 February, A Shell 6.1.1339: IMAGE now fully supports printing of PNG images, including with rotation, using the new GDI+ library. 

- 2012 November, A Shell 6.1.1322:  Add _rotation_ parameter. 

- 2012 November, A Shell 6.0.1263:  Image position may now be set relative to current position, without knowing your current position on the page. The left and/or top coordinate parameters may be set to -1 to indicate the current horizontal and vertical position. The right and/or bottom coordinate parameters may be set to negative values to indicate width and height, rather than absolute right and bottom positions.For example, 

A-Shell Reference 

Page 1537 

```
//IMAGE, spec, -1, -1, -100, -200
```

will scale the image to 100 by 200 units (in the current mapmode) and position it with the upper left corner at the current cursor position. 

- 2012 May, A Shell 6.0.1249: Added IMGF_OFFSET 

A-Shell Reference 

Page 1538 

## **INCLUDE** 

_Added March 2025_ 

## **//INCLUDE,file** 

This directive processes the specified file, expressed as DevPPN or native filespec, as if it were part of the current file. It is similar in concept to the PREFIX= and SUFFIX= printer initialization commands, except this one is embedded in the document. 

## **History** 

- 2025 March, A Shell 7.0.1769:  Directive added to A-Shell. 

A-Shell Reference 

Page 1539 

## **LINETO** 

## **//LINETO, x, y** 

LINETO draws a line, using the current pen (see SETPENEX), from the previous cursor position to the specified position. The parameter _x_ specifies the ending horizontal position and _y_ the ending vertical position, both using the current mapping units. The current mapping unit is determined by the SETMAPMODE directive. 

A-Shell Reference 

Page 1540 

## **META** 

## **//META, type, param1, param2, ...** 

META can be used to embed unspecified meta data in the printfile. The META lines will not print or display in APEX, but will remain in the file, possibly of use to archival or other post-printing routines. 

The string parameter _type_ specifies the type of operation or meta-data being used. The parameters following _type_ , if any, are determined by the type of meta-data being passed and the parameters that have been defined for that type of data or operation. 

The only META _type_ implemented is FTP, for transferring files between host and PC. See the following topic. 

Also see the print filter ATPXFR.SBX in SOSLIB:[907,29] for another approach to making sure that auxiliary files related to printing (such as images referenced by an IMAGE directive) are transferred to the remote PC before needed during printing. 

A-Shell Reference 

Page 1541 

## **FTP** 

## **//META, FTP, dirflag, hostpath, localpath, {flags}** 

If the META FTP directive is seen by APEX running within ATE, it will attempt to perform an FTP transfer of hostfile to/from localpath. 

Note that this directive is a sub-command of META, which see for more information. 

## **Parameters** 

## _dirflag_ 

Direction code; see AG_FTP for _dirflag_ values and meanings. 

## _hostpath_ 

should be in native format, to be understood by the FTP server on the host. 

## _localpath_ 

should be in PC format, or it may use the special syntax "@.xxx" where xxx is the desired file extension. The "@." will be replaced by the complete filespec of the file currently being printed or previewed, minus its extension. This is useful for sending printfile sidecar files which will be matched up later based on having the same filename, but where you don't know the complete filename that will be assigned by ATE or APEX to the printfile. (ATE/APEX typically create versions of the original file, in the Documents\APEX directory, with a unique numeric suffix.) 

## _flags_ 

The optional _flags_ argument may be set to 1 to cause any FTP errors to be display in an error message dialog. If this option is not set, any such failure will go unreported, which might be preferable in the context of printing. 

A-Shell Reference 

Page 1542 

## **METAFILE** 

## **//METAFILE, metafilespec, leftorg, toporg, right, bottom** 

METAFILE "plays" an existing Win32 "enhanced" metafile into the current output context, stretching or squeezing as needed to fit within the specified rectangle. 

## **Parameters** 

_metafilespec_ 

File specification of the image (AMOS-style or native) 

_left, top, right, bottom_ 

Bounding rectangle (within current coordinate system) into which the metafile will be fit. 

## **Comments** 

A metafile is a device-independent set of instructions for creating graphic output. Metafiles can be created by a number of popular graphics or drawing programs. As an example, you might use a forms-layout program to create a blank form and then output it as a metafile. The form could then be merged with text and images using the METAFILE directive. (This would normally be much easier than using TEXTOUT and LINETO commands to create a form.) 

The metafile will be _played_ using the current coordinate system, unless the metafile itself changes the coordinate system. Metafiles that are meant to always appear in the same place on the page should set their own mapping accordingly, and should be played back with the origin set to 0,0. On the other hand, metafiles that are meant to be resized and positioned (e.g. a logo or signature) should be setup to start at location 0,0 in the current coordinate system. This way it can be repositioned with the _leftorg_ and _toporg_ parameters, and sized by changing the mapping system. 

## **Technical Note** 

In all other cases, the mapping modes are based on the origin being at the upper right corner of the page, with the units increasing in the positive direction as you move down and across the page. However, for metafiles, this is only true for mapping mode Text. For all other modes, the origin is still the upper left corner and the horizontal units increase as you move across the page, but the vertical units decrease (i.e. increase in the negative direction) as you move down the page. Consequently, if your 

A-Shell Reference 

Page 1543 

metafiles are internally based on a mapping mode other than Text, you must set the same mode prior to playing the metafile (unless the metafile internally sets its own mapping mode.) Regardless of what happens inside the metafile, the current position and mapping mode for subsequent drawing primitives is preserved (i.e. unchanged). 

## **File Locations** 

A-Shell will look for the referenced image file in the directories pointed to by the environment variables ATECACHE and ATE, if it is not found in the originally specified directory. This is mainly useful for ATE printing, where the host may pre-transfer images to one of the cache directories without having to modify the print file or deal with incompatibilities between the directory structure used on the host and on the ATE client. 

The GDI print commands IMAGE, XTEXT, and METAFILE will locate the specified file in the same directory as the printfile if it fails to find it in the directory specified in the //GDI directive or in the local cache. This is mainly a convenience when printing from another directory. For example, if a printfile BAS:TEST.PRT contains `//IMAGE,TEST.JPG` ,... and you tried to print it from another directory using PRINT BAS:TEST.PRT, versions of A-Shell prior to 995.3 would have failed to find the image test.jpg in the BAS: directory, because you weren't logged there. It also comes in handy when moving print files and their associated images to another location (such as with ASHLPD), since you can combine all the associated files in an arbitrary directory. 

Beginning with A-Shell 1111 of 3 May 08, XTEXT, IMAGE, and METAFILE will look for the file in the same directory as the printfile itself, if not found at the location specified, even when the location specified is a Unix path. This was previously true, since 5.0.999, but only when the original spec was a Windows path. The new logic is mainly of use in ASHLPD or other environments where you generate the GDI printfile under Unix and then transfer it to Windows. 

A-Shell Reference 

Page 1544 

## **MOVETO** 

## **//MOVETO, x, y** 

MOVETO positions the internal cursor to the specified point relative to the current mapping mode (see SETMAPMODE). The parameter _x_ specifies the starting horizontal position and _y_ the starting vertical position, both using the current mapping units. 

Its only effect will be on subsequent operations (e.g. LINETO) and subsequent text that is not part of an explicit GDI directive. 

MOVETO may also be used to disable A-Shell's auto-page break. A single `//MOVETO,0,0` anywhere on each page tells A-Shell to turn off its line-counting logic. 

A-Shell Reference 

Page 1545 

## **PAPERSIZE** 

## **//PAPERSIZE,<size>** 

The <size> parameter may either be one of the symbolic names, or the equivalent numeric value. For example, the following two are equivalent. 

- `//PAPERSIZE,LEGAL` 

- `//PAPERSIZE,5` 

One way to get the numeric equivalents is to activate the LP trace and print a file containing any PAPERSIZE directive; this will cause all the supported paper size names (and numbers) to be listed in the log or debug window. 

PAPERSIZE is one of the GDI printing directives with a Printer ini file Equivalent. 

## **History** 

- 2009 August, A Shell 1158:  Function added to A-Shell 

A-Shell Reference 

Page 1546 

## **PASSTHROUGH** 

## **//PASSTHROUGH on** 

## **//PASSTHROUGH off** 

The PASSTHROUGH option may be toggled as above. PASSTHROUGH is one of the GDI printing directives with a Printer ini file Equivalent. 

A-Shell Reference 

Page 1547 

## **PDFX** 

PDFX is A-Shell's "print to PDF file" subsystem, which consists of an entire set of GDI printing directives related to producing and post-processing PDF files. All of these commands begin with " `//PDFX` ," followed by a key and then a value. For example, the following directive tells PDFX to overwrite the existing file if it exists: 

```
//PDFX,Save.When.Exists,1
```

The most common function of PDFX is to produce PDF documents such as invoices and automatically email them to clients. PDFX includes a variety of email-related commands for that purpose. 

The PDFX subsystem is documented in a separate help file which you can access from the A-Shell downloads...documents page. Contact MicroSabio if you have questions or would like to add PDFX to your A-Shell license. 

A-Shell Reference 

Page 1548 

## **POLYGON** 

_Revised December 2017_ 

## **//POLYGON, mode, brush, x1, y1, x2, y2, {...X10, Y10}** 

POLYGON draws a polygon based on up to 10 points. Straight lines are drawn between the points using the current pen, including a line from the last point back to the first. The points are specified in the current map mode. 

## **Parameters** 

_mode_ specifies the polygon fill mode: 

|**Symbol**|**Value **|**Description**|
|---|---|---|
||0|Use existing mode (whatever was last set)|
|Alternate|1|Fills in the area between odd and even sides|
|Winding|2|Fills in any area with a non-zero "winding value".|



The difference between the modes is not significant for simple enclosed polygons, but becomes apparent with polygons whose sides cross over themselves. An illustrative example would be a five-pointed star, whose lines intersect to create a pentagon in the middle. The _alternate_ fill mode would fill in the points, whereas the _winding_ fill mode would fill in the entire region. 

The _winding_ value is defined as the number of times a pen used to draw the polygon would go around the region. 

_brush_ selects a value for _fill_ from the table below. See the topic Parameters: Symbols vs. Values if you have questions about which to use. 

|**Symbol**|**Value**|**Description**|**Comment**|
|---|---|---|---|
|WHITE_BRUSH|0|White|Overrides color set bySETBRUSH|



A-Shell Reference 

Page 1549 

|**Symbol**|**Value**|**Description**|**Comment**|
|---|---|---|---|
|LTGRAY_BRUSH|1|Light gray|Or color set bySETBRUSH|
|GRAY_BRUSH|2|Gray|Or color set bySETBRUSH|
|DKGRAY_BRUSH|3|Dark gray|Or color set bySETBRUSH|
|BLACK_BRUSH|4|Black|Overrides color set bySETBRUSH|
|NULL_BRUSH|5|Hollow (default)|Overrides color set bySETBRUSH|



## **History** 

## - 2011 January, A Shell 6.0.1203:  Added to A-Shell 

A-Shell Reference 

Page 1550 

## **RECTANGLE** 

## **//RECTANGLE, left, top, right, bottom {,fill {,crwidth {,crheight}}}** 

RECTANGLE draws a rectangle at the specified coordinates in the current mapping mode (as determined by SETMAPMODE), with optionally rounded corners. 

## **Parameters** 

## _left, top, right, bottom_ 

specify the respective sides of the rectangle, in the current mapping units 

## _fill_ 

select a value for _fill_ from the table below. See the topic Parameters: Symbols vs. Values if you have questions about which to use. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|WHITE_BRUSH|0|White|
|LTGRAY_BRUSH|1|Light gray|
|GRAY_BRUSH|2|Gray|
|DKGRAY_BRUSH|3|Dark gray|
|BLACK_BRUSH|4|Black|
|NULL_BRUSH|5|Hollow (default)|



The light gray, gray, and dark gray fill values will be overridden by a brush defined using SETBRUSH. 

Regardless of the _fill_ option, a border will be drawn around the rectangle using the current pen (see SETPENEX). To achieve a solid colored rectangle with no apparent border, set the RGB background in both the SETPENEX and SETBRUSH to the same color. 

A-Shell Reference 

Page 1551 

## _crwidth, crheight_ 

These optional parameters refer to the "corner radius" width and height, in the current mapping units. For normal (symmetrical) rounded corners, _crheight_ is not needed, and _crwidth_ should be set to the radius of the circle used to draw the arc of the rounded corner. When _crheight_ is specified, the corners are made from the arc of an ellipse whose total height (bounding rectangle) is two times _crheight_ and whose total width is two times _crwidth_ . 

A-Shell Reference 

Page 1552 

## **RESETFONT** 

## **//RESETFONT** 

RESETFONT restores the font that was initially calculated based on the printer init and auto-pitch settings. This is useful in reports where you rely on the automatic font settings for the beginning section of the report, then switch to some explicit SETFONT settings, perhaps for a summary page, and then want to return to the original font. 

## **History** 

- 2013 June, A Shell 6.1.1354:  Function added to A-Shell 

A-Shell Reference 

Page 1553 

## **RESETLPP** 

## **//RESETLPP** 

RESETLPP resets the current lines-per-page (LPP) value, which is used to determine the vertical line spacing, so that the line spacing will be based instead on the current font. Even when there is no explicit LPP value in the printer ini file, a default LPP is established based on the paper size and default font. Once established, changing the font does not change the vertical spacing (unless you use the RESETLPP directive). 

For example, assume that the default LPP results in vertical line spacing of 6 lines per inch. If you then change to a 24 point font, and output multiple lines, the lines will overlap vertically because the 24 point font is taller than 1/6 of an inch. To avoid that and instead adjust the vertical line spacing to what would be natural for a 24 point font, just use the RESETLPP directive either before or immediately after the SETFONT, as shown here: 

```
//ResetLPP
```

```
//SetFont,240,Arial
```

```
This line output in 24 point Arial
So is this line (with natural 24 point spacing)
```

A-Shell Reference 

Page 1554 

## **SETBKCOLOR** 

## **//SETBKCOLOR, r, g, b** 

SETBKCOLOR sets the background color to be used for subsequent text output. The _r, g,_ and _b_ (red, green, blue) values have the same meaning as in the SETTEXTCOLOR directive (which see for a discussion of the RGB color system). The default background color is 255,255,255 (white), which is taken as transparent. Any other background color setting will cause a ribbon of background color to be written along with any text. For example, this would be necessary in order to print white on blue. 

When one color is written on top of another, generally the effect is not additive. Rather, the last written foreground and background colors will prevail. The exception is when the background is 255,255,255 (white), this is taken as transparent and thus will not affect the underlying background color (allowing, for example, text to be written on top of an image.) If you wanted your overlay text to have its own white background, you should set the background color to 254,254,254, which is very nearly white but opaque rather than transparent. 

A-Shell Reference 

Page 1555 

## **SETBRUSH** 

## **//SETBRUSH, style, hatch {, r, g, b}** 

SETBRUSH is similar to SETPENEX except that it selects a brush that is used only to fill in rectangles and ellipses, and only then when you use the fill options light gray, gray, and dark gray. In those cases, the brush defined previously by SETBRUSH will be used instead of the default brush. See the topic Parameters: Symbols vs. Values if you have questions about which to use. 

## **Parameters** 

## _style_ 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|BS_SOLID|0|Solid|
|BS_NULL|1|No brush (negatesSETBRUSH)|
|BS_HATCHED|2|Hatched, see below|



## _hatch_ 

If _style_ is set to BS_HATCHED, then _hatch_ defines the type of hatch pattern used by the brush, from the following table: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|HS_HORIZONTAL|0|Horizontal lines (- - - - -)|
|HS_VERTICAL|1|Vertical lines (| | | | |)|
|HS_BDIAGONAL|2|Diagonal lines (\ \ \ \ \)|
|HS_FDIAGONAL|3|Diagonal lines (/ / / / /)|
|HS_CROSS|4|Crosshatch (+ + + + +)|
|HS_DIAGCROSS|5|Diagonal crosshatch (x x x x x)|



A-Shell Reference 

Page 1556 

_r, g, b_ 

The _r, g,_ and _b_ parameters are optional, but if specified, must all be specified. See the SETTEXTCOLOR directive for notes. 

A-Shell Reference 

Page 1557 

## **SETFONT** 

## **//SETFONT, height, face, pitch-family, {charset, weight, style, rotation, width}** 

SETFONT is used to select the printer font. If not used, the font will be determined by the FONT parameter within the printer initialization file. The last four parameters are optional, or may be specified as zero for defaults. Note that the color of the font will be black characters on a white transparent background, unless overridden by a SETTEXTCOLOR directive. See the topic Parameters: Symbols vs. Values if you have questions about which to use. 

Also see the "Update Note" section at the bottom of this page. 

TIP: To change font in the middle of a line of text, use the backslash (\) line terminator on the line prior to the font change in order to suppress the automatic line feed. For this and other tips, pointers and relevant information about writing GDI printing directives, please see Writing GDI Print Directives. 

## _height_ 

Height of the font in tenths of points. For example, use 120 to select a 12 point font. 

## _face_ 

Face name of the font. These are the names that appear in the typical Windows font selection dialogs. Typical face names are Courier New, Helvetica, Fixed Sys, Times Roman, etc. 

## _pitch-and-family_ 

Formed as the sum of the following: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|DEFAULT_PITCH|0|Default pitch, don't care about family.|
|FIXED_PITCH|1|Fixed pitch (monospace).|
|VARIABLE_PITCH|2|Variable pitch (proportional space).|



A-Shell Reference 

Page 1558 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|FF_DONTCARE|&h000|Don't care.|
|FF_ROMAN|&h010|Roman family (serifs, variable pitch)<br>Example: Times Roman.|
|FF_SWISS|&h020|Swiss family (sans serifs, variable pitch)<br>Example: MS Sans Serif.|
|FF_MODERN|&h030|Modern family (fixed pitch, serif or sans serif.)<br>Examples: Courier, Pica, Elite.|
|FF_SCRIPT|&h040|Script family (look like handwriting.)<br>Examples: Script, Cursive|
|FF_DECORATIVE|&h050|Decorative family (novelty fonts.)<br>Example: Old English.|



## _charset_ 

## Specifies the desired character set, from the following values: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|ANSI_CHARSET|0|ANSI|
|DEFAULT_CHARSET|1|Don't care|
|SYMBOL_CHARSET|2|Symbols|
|OEM_CHARSET|255|OEM (system dependent)|



_weight_ 

A-Shell Reference 

Page 1559 

Specifies the desired boldness of stroke, from the following choices. Note that most of these are not supported but are mapped to the nearest supported choice. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|FW_DONTCARE|0|Don't care|
|FW_THIN|100|Thin|
|FW_EXTRALIGHT|200|Extra Light|
|FW_LIGHT|300|Light|
|FW_NORMAL|400|Normal|
|FW_MEDIUM|500|Medium|
|FW_SEMIBOLD|600|Semibold, demibold|
|FW_BOLD|700|Bold|
|FW_EXTRABOLD|800|Extrabold, ultrabold|
|FW_HEAVY|900|Heavy|



## _style_ 

## Specifies font style options. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|FS_UPRIGHT|&h00|Normal upright|
|FS_ITALIC|&h01|Italic|
|FS_UNDERLINE|&h02|Underline|
|FS_STRIKEOUT|&h04|Strikeout|



A-Shell Reference 

Page 1560 

_rotation_ 

The default is zero. Rotation is specified in degrees, with positive numbers being rotated clockwise. 

## _width_ 

This option allows you to stretch or squeeze the width of the font independent of the height. The units of _width_ are equivalent to that of _height_ (tenths of points). You may also use _width_ to specify the character width in terms of the number of characters that would fit on a line, by setting it to the negative of that value. For example, to select a font that would fit 90 characters across the page, set _width_ to -90. 

## **Examples** 

```
//SETFONT,120,Arial
```

```
This is 12 point Arial, standard options
```

```
//SETFONT,100,Times Roman,0,0,200,1
```

```
This is 10 point Times Roman, extra light weight, italic
```

```
//SETFONT,120,Courier,FIXED_PITCH,ANSI_CHARSET,FW_EXTRABOLD,FS_UPRIGHT
```

```
This is 12 point Courier (or something similar in fixed pitch), extra bold, upright
```

## **Comments** 

In the context of fixed-pitch (mono-spaced) fonts, the terms "pitch" and "point" are sometimes confused or at least conflated by the traditional typewriter-era rule-of-thumb that a 12 point font (e.g. Courier, Pica) was equivalent to 10 pitch (10 CPI or characters per inch horizontal), while a 10 point font (e.g. Elite) was equivalent to 12 pitch. In the digital era, that rule-of-thumb falls apart, especially with proportional fonts, where the relationship between height in points and number of characters per inch 

A-Shell Reference 

Page 1561 

is completely unpredictable, but even with fixed-pitch fonts, due to the fact that the characters can be made wider or thinner without changing the height. If it is important to select a font with a certain pitch (CPI), use the width parameter to specify it explicitly. 

Also note that while there is a natural relationship between the vertical line spacing (LPI or lines per inch vertical) and the font height (i.e. point size), changing the font does not automatically change the line spacing. See the GDI printing directive RESETFONT. 

## **History** 

- 2009 May, A Shell build 1149:  GDI printing bug fix/refinement: The width parameter in the SETFONT directive now works more precisely and reliably with fixed pitch fonts, across all font families, printers and resolutions. Previously, certain fonts (most notoriously Courier) didn't "behave" very well. And in addition, since the individual cell width was being rounded to the nearest integer number of pixels, small adjustments to the width were often not having the desired effect with lower printer device resolutions. Now, the cell width is interpolated to 1/8 of a pixel, resulting in fine control even with 100 DPI (e.g. fax) devices. 

Note that this update could possibly result in a small change in the horizontal character spacing of existing printouts. The change will probably be small, and will always represent a correction, but it is possible that having worked out precise spacing by trialand-error, you may need to make adjustments after this fix. (After considerable soul-searching and public comment, we decided that since width is a relatively new parameter, rarely used, that the likelihood of this fix actually improving the spacing of existing reports was many times greater than the chance of it making a report worse. But if you use the width parameter to fine tune the fixed pitch spacing of a very precise form, and especially if you used trial-and-error rather than math to figure out the ideal width, you may need to take another look. (The upside is, anyone affected by this would have been at risk of their reports looking different on different printers; so even if you have to make an adjustment, the report will now print consistently across devices.) 

- " " A more detailed discussion is available on the A Shell forum topic Fixed Pitch Precision. 

A-Shell Reference 

Page 1562 

## **SETMAPMODE** 

## **//SETMAPMODE, mode** 

SETMAPMODE establishes the coordinate system for subsequent GDI operations that take positional parameters. Note that in all modes, the point 0,0 is the upper left corner of the page, and the units increase as you go down and across the page. The _mode_ parameter may be expressed as one of the following: 

|**Mode**|**Description**|
|---|---|
|Text|This is the default coordinate system. Each unit is equal to a pixel. For example, if outputting to a<br>300 DPI laser printer, each unit is 1/300 of an inch. Note that the horizontal and vertical resolution<br>of the output device may differ.|
|Loenglish|Units are 1/100 of an inch.|
|Hienglish|Units are 1/1000 of an inch.|
|Lometric|Units are 1/10 of a millimeter (254 per inch.)|
|Himetric|Units are 1/100 of a millimeter (2540 per inch).|
|Twips|Units are 1/20 of a typesetting Point. A Point is 1/72 of an inch, so a Twip is 1/1440 of an inch.|
|Decipoints|Units are 1/10 of a typesetting Point (i.e. 1/720 of an inch). Two decipoints equals one twip.|



A-Shell Reference 

Page 1563 

## **SETOPTION** 

_Updated April 2020; see History_ 

## **//SETOPTION, option {,boolean}** 

SETOPTION selectively enables various options affecting GDI printing. 

## _embedded-entity-references_ 

enables the interpretation of the symbol entities via their UNICODE values. The default is to treat them as plain text, thus eliminating the remote chance that a semi-random string of data/text will be misinterpreted as containing embedded symbol entities. 

## _fontsize-char_ 

- determines method of calculating font size: true for character size, false for cell size. See further discussion in Fontsize Char topic. 

## _ignore-escape-errors_ 

causes A-Shell to ignore errors occurring during the processing of the ESCAPE directive. Normally, when such errors occur, the GDI directive itself is printed to the target device, to make it easier to spot the fact that the directive contained an error. But in the case of ESCAPE, if you redirect the output to a device incompatible with the one for which the ESCAPE sequence was intended, an error may be "normal", hence you wouldn't want it to appear in the output. For example, if you use ESCAPE to embed some special PCL command into a document, but then send it to a PDF generator instead, you would probably want the fact that the PDF driver didn't support the ESCAPE to be ignored. 

## _no-auto-page-breaks_ 

Turns off automatic page break logic. This is handy in single-page GDI files that contain a mixture of drawing commands and many lines of plain text. The same effect has previously been achievable by inserting a MOVETO directive anywhere on the page, but this is more self-documenting. Note that as with all other SETOPTION attributes, the initial setting is FALSE, while the default 

A-Shell Reference 

Page 1564 

{,boolean} parameter is TRUE. So typically the directive is only used to enable the attribute (making the {,boolean} unnecessary to specify). 

## _no-auto-margins_ 

When specified, this option disables the automatic 1/4" margin adjustment applied by the SETFONT directive when calculating the character width from a negative width parameter—i.e. from the number of characters to fit in the width of the page. This automatic adjustment was added years ago in conjunction with the APEX auto-margin adjustement, on the theory that even if the printer doesn't report a physical margin, at some point you may want to print to paper, where the margin would most likely need to be applied. So it seems better to be calculate the font width so as to be compatible with physical printing. 

There are situations however where this doesn't make sense and in fact causes problems. One would be when using SETFONT with a negative width parameter to come up with an appropriate font size to match up to a form generated from an image scaled to the page. In that case, you probably want the width basis used for the font calculation to be the same as used for the image scaling, i.e. without any automatic margin offsets. 

## _textrect-conservative-vert_ 

Normal TEXTRECTANGLE logic (syntax one) is such that it will start a new line of text as long as the starting point is above the bottom of the rectangle. But in the typical alignment, the starting point is at the upper left corner of the text cell, allowing the last line of text to straddle the bottom of the rectangle. Developers may have previously (before _textrect-conservative-vert_ was available) worked around this problem by drawing the border of the RECTANGLE below the specified bottom of the TEXTRECTANGLE. 

This parameter, _textrect-conservative-vert_ , provides a cleaner approach, assuming you don't want to switch all your text alignment to use TA_BOTTOM. It effectively moves the threshold point (used to decide whether another line will fit in the rectangle) up by the current vertical line spacing. This way, you can use the same coordinates for the TEXTRECTANGLE as for the RECTANGLE. 

## _textrect-nowrap_ 

This parameter allows you to disable wrap within TEXTRECTANGLE (syntax one). It may be useful in situations where you have multiple lines of text that already have hard line breaks and you would prefer to truncate the lines that are too long rather than 

A-Shell Reference 

Page 1565 

cause a wrap and end up losing some of the text at the bottom. Note that this effect has long been available with TEXTRECTANGLE syntax two, simply by omitting the TRF_WORDBREAK option. 

## _UTF8_ 

When specified, the remainder of the file is considered to be in UTF8 encoding, which is compatible with 7 bit ASCII characters (0-127), but interprets bytes with the 8th bit set as a lead-in to a multi-byte sequence supporting the entire range of UNICODE code points. When printing files which start with the special 3 byte sequence EF EB BF, UTF8 mode is activated automatically. This is a semi-standard protocol for identifying UTF8-encoded text files, favored by Microsoft. 

## **Example** 

```
//SETOPTION,EMBEDDED-ENTITY-REFERENCES
```

```
Symbol:  &#x03a9;  Code: \
```

```
//SETOPTION,EMBEDDED-ENTITY-REFERENCES,0
```

```
&#x03a9;
```

## **Comments** 

The booleans (default = TRUE) can be: 

FALSE: FALSE, F, 0, N, OFF 

TRUE: TRUE, T, 1, Y, ON (or anything else) 

Since the options are all initialized to FALSE at the start of each print request, you must specify the enable the options of interest at the start of each print file. But since the default Boolean switch is TRUE, you generally don't need to specify that argument, except when you need to turn an option back off again, after having first enabled it earlier in same file. 

Note: All parts of this directive are case insensitive. 

## **History** 

A-Shell Reference 

Page 1566 

- 2020 April, A Shell 6.5.1678:  Add _no-auto-margins_ 

- 2018 November, A Shell 6.5.1651:  Add _fontsize-char_ 

- 2012 November, A Shell 6.0.1365:  Add _UTF8_ 

- 2012 October, A Shell 6.0.1261: Add _textrect-conservative-vert_ and _textrect-nowrap_ 

- 2012 August, A Shell 6.0.1154:  Add _no-auto-page-breaks_ parameter 

- 2012 June, A Shell 6.0.1152: SETOPTION added to A-Shell 

A-Shell Reference 

Page 1567 

## **- FONTSIZE CHAR** 

_Written November 2018_ 

Beginning with A-Shell 6.5.1651 of November 2018, the _fontsize-char_ parameter is available to allow the precise setting of font sizes. 

When _fontsize-char_ is true, the point size in a SETFONT directive is taken to be relative to the size of the character symbols in that font, rather than the size of the character cells. The difference between the two is that the character cell includes one or more rows of empty pixels for the internal leading, resulting in slightly smaller characters and larger overall vertical spacing for a given point size and external leading. 

Most word processing programs calculate fonts based on the character size ( _fontsize-char_ = true) rather than the cell size ( _fontsize-char_ =false), so if you are trying match the fonts you would otherwise get from the output of a word processor (or XTEXT) then you should set this option to true. 

Note that in prior versions of A-Shell, there was—and still is—an alternative way to get the same effect: set the point size to a negative value. For example: 

```
//; 12 point Arial based on the cell size (default)
```

```
//SETFONT,120,Arial
```

```
//; 12 point Arial based on the character size (negative point size)
```

```
//SETFONT,-120,Arial
```

```
//; Set option to base font size on character size...
```

```
//SETOPTION,FONTSIZE-CHAR
```

```
//; 12 point Arial based on the character size (FONTSIZE-CHAR true)
```

A-Shell Reference 

Page 1568 

```
//SETFONT,120,Arial
```

## **Comments** 

As with all other SETOPTION values, the initial/default value established at the start of each print request is false, but within the context of any given SETOPTION directive, the default value is true—i.e. you don't need to specify the ,true parameter. 

## **See Also** 

- SETVMI 

## **History** 

- 2018 November, A Shell 6.5.1651:  Parameter added to SETOPTION 

A-Shell Reference 

Page 1569 

## **SETPENEX** 

## **//SETPENEX, style, thickness {r, g, b}** 

SETPENEX selects a "pen" (line thickness and style) for subsequent line drawing operations—e.g. LINETO and RECTANGLE. SETPENEX is an EXtended version of, and supersedes, the original SETPEN. 

## **Parameters** 

## _style_ 

Select one from each of the sections shown in the table. Also see Comments, below. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|PS_SOLID|0|Solid pen|
|PS_DASH|1|-------|
|PS_DOT|2|.......|
|PS_DASHDOT|3|_._._.|
|PS_DASHDOTDOT|4|_.._.._|
||||
|PS_ENDCAP_ROUND|0|Round endcaps (default)|
|PS_ENDCAP_SQUARE|&h0100|Square endcaps|
|PS_ENDCAP_FLAT|&h0200|Flat endcaps|
||||
|PS_JOIN_ROUND|0|Round joins (default)|
|PS_JOIN_BEVEL|&h1000|Bevel joins|



A-Shell Reference 

Page 1570 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|PS_JOIN_MITER|&h2000|Miter joins|



## _thickness_ 

Thickness of the pen is defined in current map mode units. (A value of zero will result in a thickness of 1 pixel.) Note that this differs from the similar function SETPEN, which interprets _thickness_ as being in pixel units. 

_r, g, b_ 

The _r, g,_ and _b_ parameters are optional, but if specified, must all be specified. See the SETTEXTCOLOR directive for notes. 

SETPENEX was added to A-Shell in Build 931 of 22 May 05. 

## **Comments** 

A sample print file, SETPEN.TXT in EXLIB:[908,37], illustrates these options. Note, however, that the join options do not appear to have any effect. They have been implemented and documented to match the underlying Windows ExtCreatePen() function, but it isn't clear what they are for. 

The endcap options are quite useful though. By default, line segments have rounded endcaps consisting of a semicircle with diameter equal to the width of the line, making them more significant as the line thickness increases. The square option makes the endcaps square, which is equivalent to extending the lines by half their thickness, on each end. This may seem illogical at first (i.e. why not just ask for a longer line?) but is actually useful for making complete corners. If you don't want any endcaps, then use the flat option (which is probably what you were expecting in the first place). 

A-Shell Reference 

Page 1571 

## **SETPEN** 

Note: SETPEN has been succeeded by SETPENEX, which offers a greater range of options. Although SETPEN is supported, SETPENEX should be used unless there is a good reason for not doing so. 

## **//SETPEN, style, thickness {,r, g, b}** 

SETPEN selects a "pen" (line thickness and style) for subsequent line drawing operations—e.g. LINETO and RECTANGLE 

## **Parameters** 

## _style_ 

Select one of the following: 

|**Value**|**Description**|
|---|---|
|0|Solid (default)|
|1|Dash (only valid when pen thickness is 1)|
|2|Dot (only valid when pen thickness is 1)|
|3|Dash-Dot (only valid when pen thickness is 1)|
|4|Dash-Dot-Dot (only valid when pen thickness is 1)|
|5|NULL|
|6|Inside frame|



## _thickness_ 

Thickness of the pen in pixels. (0 is treated the same as 1.) Note that previous versions of this documentation incorrectly indicated that the units for _thickness_ were based on the current map mode. See SETPENEX for an enhanced version of SETPEN which does use the current map mode units. 

A-Shell Reference 

Page 1572 

_r, g, b_ 

The _r, g,_ and _b_ parameters are optional, but if specified, must all be specified. See the SETTEXTCOLOR directive for notes. 

A-Shell Reference 

Page 1573 

## **SETTEXTALIGN** 

## **//SETTEXTALIGN, flags** 

SETTEXTALIGN determines way text is aligned within the character cell grid. The default is the upper left corner of the character cell, meaning that `//TEXTOUT,x,y text` will print the text below and to the right of the position x,y. Add together the applicable options, one for each coordinate, from the table below. See the topic "Parameters: Symbols vs. Values" if you have questions about which to use. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|**Horizontal Alignment**|||
|TA_LEFT|0|x coordinate aligns with left side of character cell. (Default)|
|TA_RIGHT|2|x coordinate aligns with right side of character cell.|
|TA_CENTER|6|x coordinate aligns with center of character cell.|
|**Vertical Alignment**|||
|TA_TOP|0|y coordinate aligns with top of character cell. (Default)|
|TA_BOTTOM|8|y coordinate aligns with bottom of character cell.|
|TA_BASELINE|24|y coordinate aligns with character baseline.|



A-Shell Reference 

Page 1574 

## **SETTEXTCOLOR** 

## **//SETTEXTCOLOR, r, g, b** 

SETTEXTCOLOR sets the color to be used for subsequent text output. 

The _r_ (red), _g_ (green), _b_ (blue) values may each range from 0-255. You can use these to specify virtually any color, regardless of whether your printer actually supports it. Some common color values are shown below. 

|**R,G,B**|**Color**||**R,G,B**|**Color**|
|---|---|---|---|---|
|0,0,0|Black||192,192,192|Gray|
|255,255,255|White||255,0,255|Magenta (intense)|
|255,0,0|Red (intense)||183,231,58|Lime green|



## **Comments** 

To figure out the values for special colors, you can use the toolbar _Settings...Colors_ dialog in A-Shell. Click on a color, then select the Define Custom Color button and you will see a dialog which allows you to select any color from a three-dimensional grid. The third dimension is a slide bar on the right side that controls lightness and darkness. As you move the color cursor around, you will see the color values changing. Don't confuse them with the Hue, Saturation, and Luminescence values, which are part of an alternative system of defining colors. 

Note that when one color (e.g. text) is written on top of another, the effect is not additive. Rather, the last written color replaces the underlying one(s). So for example, you can write white text on top of a dark background—e.g., image, solid rectangle, etc.— by outputting the background first, then the text. The following set of directives illustrates this by outputting two white text strings inside a black circle. 

```
//;Print multiple independent white strings in one black circle
```

```
//SETMAPMODE,LOENGLISH
```

```
//ELLIPSE,100,100,200,200,BLACK_BRUSH
```

A-Shell Reference 

Page 1575 

```
//SETTEXTCOLOR,255,255,255
```

```
//SETFONT,200,ARIAL,DEFAULT_PITCH,ANSI_CHARSET,FW_LIGHT
```

```
//TEXTCENTER,100,120,200,135,"US"
```

```
//SETFONT,320,ARIAL,DEFAULT_PITCH,ANSI_CHARSET,FW_HEAVY
```

```
//TEXTCENTER,100,145,200,175,"9.5"
```

A-Shell Reference 

Page 1576 

## **SETTRANSFORM** 

## **//SETTRANSFORM, m11, m12, m21, m22, dx, dy** 

where: 

m11,m12,m21,m22 are floating point multipliers 

dx,dy specify a reference point in twips (1440/inch) 

SETTRANSFORM transforms the coordinate space to rotate, translate, shift or stretch the output. 

The effect of this operation is to tranform every point (x1,y1) in the original coordinate space to a new point (x2,y2) based on the following formulas: 

x2 = (x1 * m11) + (y1 * m21) + dx 

y2 = (x1 * m12) + (y1 * m22) + dy 

Note that the transformation is independent of SETMAPMODE and affects all subsequent output, with the exception of METAFILE. 

## **Examples** 

```
//;mirror about horizontal axis at y=7920 (5.5" down)
```

```
//SETTRANSFORM, 1, 0, 0, -1, 0, 15840
```

```
//;mirror about vertical axis at x=6120 (4.25"over)
//SETTRANSFORM, -1, 0, 0, 1, 12240, 0
```

```
//;rotate 180 around point 4.25" over, 5.5" down (8.5x11 center)
//SETTRANSFORM, -1, 0, 0, -1, 12240, 15840
```

A-Shell Reference 

Page 1577 

```
//;shrink horiz 25%, stretch vert 50%, shift down 1" and right .5"
//SETTRANSFORM, 0.75, 0, 0, 1.5, 720, 1440
```

## **History** 

## - 2018 May, A Shell 6.5.1635: Add function to A-Shell 

A-Shell Reference 

Page 1578 

## **SETVMI** 

## **//SETVMI, #** 

SETVMI sets vertical line spacing, where # is the desired number of units (must be an integer) in the current map mode to set the "Vertical Motion Increment" to—i.e., vertical line spacing. This can be useful when filling in pre-designed forms that require a certain uniform line spacing that isn't quite what you would otherwise get from setting the LPP value in the printer ini file or by setting a particular font and then using RESETLPP. 

Note that if you want 6 lines per inch, to be precise, you may need to first switch to the TWIPS mapmode, since its units per inch can be evenly divided by 6. For example: 

```
//SETMAPMODE,TWIPS
```

```
//; set 6 lines per inch (1440/240 = 6)
```

```
//SETVMI,240
```

You can then switch back to another map mode, but that defeats the purpose, since the units will be converted and rounded down. So converting to LOENGLISH, for example, would give you the equivalent of `//SETVMI,16` . In that case, you might have done better by just setting `//SETVMI,17` . 

## **History** 

- 2009, May, A Shell build 1149:  Printing bug fix/refinement: SETVMI vertical spacing is now interpolated to fractional pixels, rather than being rounded to the nearest pixel. This corrects a problem where, depending on the VMI factor and resolution, you might have ended up with vertical spacing that was off by a fraction of a pixel. That doesn't sound like much, but by the time you get to the bottom of a page (60+ lines) a half pixel error multiplies to 30 pixels, which might be as much as an entire line. This problem typically showed up when switching between a laser printer (at 600 or 1200 DPI) and a PDF or FAX device at 100300 DPI. And even then, it would generally have gone unnoticed unless you were using a mixture of GDI directives to draw boxes (which wouldn't have been subject to a per-line error accumulation) and regular print lines to fill them in. 

A-Shell Reference 

Page 1579 

Compatibility Note:  Existing printouts which used SETVMI to set the vertical spacing necessary for print lines to line up with boxes drawn with GDI primitives may be affected by this (generally in a way that improves the alignment, unless you happened to have relied on the accumulated rounding error without realizing it). 

- " " See the A Shell forum discussion GDI spacing variance between printers for more detailed information. 

A-Shell Reference 

Page 1580 

## **TEXTCENTER** 

_Updated September 2024_ 

## **//TEXTCENTER, left, top, right, bottom, text** 

TEXTCENTER outputs a line of text, positioning it in the center of the specified rectangular coordinates. TEXTCENTER also supports embedded entity references. 

## **Parameters** 

## _Left, top, right, bottom_ 

Specify the respective sides of the bounding rectangle, in the current mapping units. Note that if the rectangle has no height (bottom >= top) then the text is vertically positioned based on the top parameter and the current SETTEXTALIGN setting. Otherwise, it is not affected by SETTEXTALIGN. 

## _text_ 

A string of text to output, up to a maximum of 512 characters (after expansion of any variables). TEXTCENTER does not require quoting of the text argument if it contains commas, although quoting is allowed and recommended. 

A string of text to output, up to a maximum of 16K for the complete directive (after expansion of any variables). It is not necessary to quote this argument, even if it contains embedded commas. A trailing backslash will cause the next line to be concatenated to the text, unless the next line starts with a forward slash. For a literal trailing backslash, you may quote the text string. See explanatory note under TEXTINDENT and History note below. 

See TEXTRECTANGLE for a more powerful variation of outputting text within a rectangular area. 

## **History** 

- 2024 September, A Shell 7.0.1762:  Add support for special handling of trailing backslash in //TEXTxxx directives. Previously it was only recognized as a special character in plain text outside of GDI directives. 

- 2013 December, A Shell 1370:  An unmatched leading quote is now treated as a literal character. Previously it was stripped. 

A-Shell Reference 

Page 1581 

- 2012 November, A Shell 6.0.1263: TEXTCENTER now supports embedded entity references; previously these were only processed by TEXTOUT and for raw text. 

A-Shell Reference 

Page 1582 

## **TEXTINDENT** 

## **//TEXTINDENT,x, y, text** 

## **//TEXTINDENT** 

TEXTINDENT is a variation of TEXTOUT designed for outputting multiple lines of text at a particular indent. 

The first form of the directive acts exactly like TEXTOUT except: 

- it establishes an indent value of x, so that subsequent lines output without using TEXTOUT will retain the same indent. 

- it sets the internal printer 'cursor' to the specified x,y position so that subsequent lines (output without any explicit 

- positioning) will appear in the expected place. 

- you can set x and/or y to -1 to refer to the current x and/or y position (useful when you don't know the current position). 

- Note that for the x position, you might need to use the technique of ending the previous output with a backslash ("\") to hold the position, for example: 

```
//TextOut,100,100,Our indented text starts here---> \
```

```
//TextIndent,-1,100,[Start Indented Text]
```

```
[2nd line of indented text]
```

```
//TextIndent
```

The second form (without any arguments) disables the indent, restoring the original margin. 

This directive is useful when outputting a multiline block of text, such as you would get from INFLD multiline mode or INMEMO. For example, assuming that we have retrieved the multiline text into a variable MEMO$, you might use the following code: 

```
PRINT #CH, "//TEXTINDENT,";XPOS;",";YPOS;",";MEMO$
```

```
PRINT #CH, "//TEXTINDENT"       ! turn indent off
```

Note that because the MEMO$ variable contains embedded CRLF terminators, in the printfile it would look something like the this: 

A-Shell Reference 

Page 1583 

```
//TEXTINDENT,150,300,This is the first line of the memo
```

```
This is the second line of the memo
```

```
This is the third line of the memo
```

```
//TEXTINDENT
```

Also note that the vertical spacing for the subsequent lines (second and third lines in the example immediately above) is determined based on the last established font, and is the same as what you would get when outputting text without using TEXTOUT. 

Although in general it is necessary to quote arguments that contain embedded commas, neither TEXTINDENT nor TEXTOUT require it. This is particularly useful when outputting a multi-line string directly from some data source like INMEMO or a multiline INFLD. 

A-Shell Reference 

Page 1584 

## **TEXTOUT** 

_Updated September 2024_ 

## **//TEXTOUT, x, y, text** 

TEXTOUT outputs a line of text starting at the specified position. 

|**Parameter **|**Description**|
|---|---|
|x|Starting horizontal position, using the current mapping units. Note that -1 may be used to specify the current position;<br>this can be useful when you don't know the position.|
|y|Starting vertical position, using the current mapping units. Note that the position marks the upper right corner of the<br>cell in which the first character is printed. This is usually a few pixels above the tops of the letters. Also note that -1<br>may be used to specify the current position; this can be useful when you don't know the position.|
|text|A string of text to output, up to a maximum of 16K for the complete directive (after expansion of any variables). It is<br>not necessary to quote this argument, even if it contains embedded commas. A trailing backslash will cause the next<br>line to be concatenated to the text, unless the next line starts with a forward slash. For a literal trailing backslash, you<br>may quote the text string. See explanatory note underTEXTINDENT<br>and History note below.|



For information on printing special characters and symbols, see Printing Special Symbols. 

## **Comments** 

TEXTOUT does not change the current print cursor position. 

Ordinary text lines in the print file are essentially processed as if they were preceded by TEXTOUT,-1,-1, (i.e. x and y set to the current position), except: 

- Unlike "real" TEXTOUT directives, ordinary text lines do update the current position. Normally this will be the first position on 

- the next line, based on the current vertical motion index as set by the last SETVMI or RESETLPP directive, unless the line ends with "\" (see next). 

- Ordinary text lines that end in "\", the current position is set just past the last character on the line. 

A-Shell Reference 

Page 1585 

Like nearly all printer output, TEXOUT directives and ordinary text lines print in the current font, using the current pen. 

For simple cases of changing fonts in the middle of a line, the "\" technique mentioned above works reasonably well. See the sample GDI printfile in Writing GDI Print Directives for an example. But for more complex formatted printing with many font, color, and other changes mid-line or mid-paragraph, XTEXT will be much more efficient. 

## **See Also** 

- Printing Special Symbols 

- SETTEXTALIGN 

- TEXTCENTER 

- TEXTINDENT 

- TEXTRECTANGLE 

- TEXTRIGHT 

- XTEXT 

## **History** 

- 2024 September, A Shell 7.0.1762:  Add support for special handling of trailing backslash in //TEXTxxx directives. Previously it was only recognized as a special character in plain text outside of GDI directives. 

A-Shell Reference 

Page 1586 

## **TEXTRIGHT** 

## **//TEXTRIGHT, x, y, text** 

The logic is the same as for TEXTOUT, except that the specified xy position marks the right edge of the output rather than the left edge. Note that the vertical position with respect to the reference point is still determined by the SETTEXTALIGN options. As with TEXTOUT, TEXTRIGHT does not require that the text argument be quoted if it includes commas. 

A-Shell Reference 

Page 1587 

## **TEXTRECTANGLE** 

_Updated September 2024_ 

## **Syntax One** 

## **//TEXTRECTANGLE, left, top, right, bottom** 

```
bla bla bla bla bla bla bla bling
```

```
bla bla bla bla bla bla
```

## **//TEXTRECTANGLE** 

TEXTRECTANGLE is similar to the TEXTINDENT directive, both in what it is used for and also in the fact that it consists of a starting and ending directive (the ending directive has no arguments), with any number of lines of text in between the two. 

TEXTRECTANGLE formats the text to fit within the rectangular coordinates provided, applying word wrap to the lines as needed. Note that any existing CRLF line terminators will be respected; in the example above, the word "bling" will mark the end of a line, no matter how the rest of it formats. 

If the text does not all fit in the rectangle, the last word will be printed with an ellipsis (...) following it. See MX_GDICALC for information on calculating in advance how much text will fit. 

TEXTRECTANGLE supports rotated multi-line text, with autowrap. Support is limited; it doesn't clip to the rectangle if there are too many lines to fit. 

TEXTRECTANGLE also supports embedded entity references. In earlier versions of A-Shell, these were only processed by TEXTOUT and for raw text. 

Some text rotation options are also supported; see History, below. 

See MMOGDI in EXLIB:[908,37] for an example. 

## **Syntax Two** 

A-Shell Reference 

Page 1588 

## **//TEXTRECTANGLE, left, top, right, bottom, flags, text** 

This variation (identified by more than four parameters) is both simpler to use than the traditional multi-part TEXTRECTANGLE sequence, and offers some additional features such as multi-line horizontal and vertical centering. 

_flags_ may be any sensible combination of the following: 

|**Flag**|**Value**|**Meaning**|
|---|---|---|
|TRF_TOP|&h00000000|top justification|
|TRF_LEFT|&h00000000|left justification|
|TRF_HCENTER|&h00000001|horizontal centering|
|TRF_RIGHT|&h00000002|right justification|
|TRF_VCENTER|&h00000004|vertical centering|
|TRF_BOTTOM|&h00000008|bottom justification|
|TRF_WORDBREAK|&h00000010|wrap the text onto multiple lines|
|TRF_SINGLELINE|&h00000020|output text as a single line|
|TRF_EXPANDTABS|&h00000040|expand tabs (8 spaces each)|
|TRF_NOCLIP|&h00000100|no clipping|
|TRF_EXTERNALLEADING|&h00000200|incl. ext. leading in spacing|
|TRF_CALCRECT|&h00000400|calc only (use with MX_GDICALC)|
|TRF_PATH_ELLIPSIS|&h00004000|path ellipsis|
|TRF_END_ELLIPSIS|&h00008000|end ellipsis|
|TRF_WORD_ELLIPSIS|&h00040000|word ellipsis|



As with other GDI printer directives, the flags can be specified as a decimal value, hex value, or using the symbol names. 

A-Shell Reference 

Page 1589 

_text_ may be any string, up to 16K characters for the entire directive line. It may include "^M" symbol(s) to indicate hard CRLF(s). You may split the text argument over multiple lines (similar to the Syntax One case) by appending a backslash to each line to be continued; see History below. Quoting the entire string is optional; embedded commas are treated as literal characters rather than syntax delimiters in either case. Note that quoting will defeat the special meaning of the trailing backslash, causing it to be printed as an ordinary character. As with other text output, embedded symbols are supported; see Printing Special Symbols. 

Note that if the text parameter is missing—i.e., only 5 parameters are specified—it is treated like "" , which creates no output. 

## **History** 

- 2024 September, A Shell 7.0.1762:  Add support for special handling of trailing backslash in //TEXTxxx directives. Previously it was only recognized as a special character in plain text outside of GDI directives. 

- 2014 June, A Shell 1387: Single-line TEXTRECTANGLE now supports character wrap in the 90, 180, -90 and -180 rotations. Previously only word wrap was supported and if any lines were too long, the output was way out of position. 

- 2013 December, A Shell 1370:  An unmatched leading quote is now treated as a literal character. Previously it was stripped. 

- 2012 November, A Shell 6.0.1263: TEXTRECTANGLE now supports rotated multi-line text, with autowrap; that support is limited, it doesn't clip to the rectangle if there are too many lines to fit. TEXTRECTANGLE also supports embedded entity references; previously these were only processed by TEXTOUT and for raw text. 

- 2012 October, A Shell 6.0.1261: 

- TEXTRECTANGLE (syntax one, with multiple lines) now adds an ellipsis "..." to the right of the last line in the case where the 

- last visible line is not truncated, but there are additional lines of text (with hard line breaks) that did not fit into the box. 

- New SETOPTION flag "TEXTRECT-CONSERVATIVE-VERT" improves vertical spacing control. 

- New SETOPTION flag "TEXTRECT-NOWRAP" disables wrap within TEXTRECTANGLE. This may be useful in situations where you 

- have multiple lines of text that already have hard line breaks and and you would prefer to truncate the lines that are too long rather than cause a wrap and end up losing some of the text at the bottom. 

- 2011 October, A Shell 5.1.1235: TEXTRECTANGLE now supports limited rotation options (TRF_SINGLELINE with 90, -90, or 180 degree rotation only). Note that the rectangle itself is not rotated, nor is the interpretation of the alignment options (TRF_LEFT, 

A-Shell Reference 

Page 1590 

TRF_TOP, etc. remain relative to the rectangle in the standard orientation of the page. Only the text is rotated. See the sample GDI text file textrectr.txt in SOSLIB:[908,37] for examples. 

A-Shell Reference 

Page 1591 

## **XMDATA, XMFIELDS** 

## **//XMFIELDS, fldnam1|fldnam2|...|fldnamN** 

## **//XMDATA, data1|data2|...|dataN** 

## **//XTEXT, left, top, right, bottom, fspec{, pageoffset}** 

These commands facilitate mail merge with XTEXT. 

Mail merge is supported only by XTEXT documents in RTF or SSE format. To create the template, edit the document and insert field names by highlighting them and pressing Control-D to give them the double underline style. To perform the merge/print operation, insert one or more XMFIELDS directives (to define the field names), one or more XMDATA directives (to define the field replacement data), and one or more XTEXT directives (one for each page or rectangle of output). You will also need at least a SETMAPMODE directive to define the measurement units which are required by the XTEXT directive, plus any other //GDI directives that you want (i.e. to combine application-generated output with the mail merge output). 

The individual field names and data items must be delimited by the vertical bar (|). You can use multiple XMFIELDS and XMDATA directives, if you have a lot of fields (or long data). The important thing is that the Nth data item matches up with the Nth field name. (So in the example above, all occurrences of "fldnamN" in the document would be replaced by "dataN". 

XMFIELDS and XMDATA both require a single comma after the name of the directive, but after that, the fields are delimited with |. Fields may contain commas and quotes but they are treated like any other character. 

The optional pageoffset parameter is used to specify the starting position within the fspec document for the merge. Use negative numbers for page numbers, positive for byte offsets. (-1 = page 1, -2 = page 2, etc.) 

Note that the XMFIELDS and XMDATA definitions remain live for the duration of the spool operation (i.e. the processing of the text file containing those directives, not the RTF documents reference by XTEXT). Also note that the XTEXT directive used for the mail merge operation is identical to that previously documented for printing regular XTEXT text. (The only difference between XTEXT mail merge/print and regular XTEXT printing is whether there are fields defined which match up with fields in the document. So you could, for example, define a set of 30 fields and corresponding data items, then issue several XTEXT commands which may or may not reference any of those fields.) 

A-Shell Reference 

Page 1592 

## **Example:** 

```
//SETMAPMODE,LOENGLISH
```

```
//XMFIELDS,Name|Address|City
//XMDATA,Jack|123 Main St.|Woodland Hills
//XTEXT,50,50,800,1000,mydoc.rtf,-1
^L
//XTEXT,50,50,800,1000,mydoc.rtf,-2
```

In the above example, we are printing a 2 page mail merge document. Note the need for the chr(12) (appearing as "^L") to mark the page break. 

## **History** 

- 2008 May, A Shell 5.1.1111: Added to GDI Printing Directives. 

A-Shell Reference 

Page 1593 

## **XOFFSET, YOFFSET** 

## **//XOFFSET, ###** 

## **//YOFFSET, ###** 

These commands effect minor horizontal and vertical adjustments to the overall positioning of everything on the page except images. The units are twips (1440 to the inch), with positive values shifting the output down and to the right, negative up and to the left. 

Because these commands do not affect images (e.g. IMAGE), they are most useful for adjusting text relative to a background image being used as a form. They are also the easiest way to shift an entire document (one without images), perhaps to line up better with a pre-printed form. TMARGIN and LMARGIN, which may seem similar, are actually very limited for that purpose, given their coarseness, side effects, and the fact that they have no effect on objects explicitly positioned with GDI directives. 

XOFFSET and YOFFSET are among the operators that may be used both as printer ini file commands and as GDI printing directives. However, since the kinds of benefits provided by ?OFFSET tend to be document-specific rather than printer-specific, it makes more sense to use them as GDI printing directives than as ini file commands. 

See also, and compare to, XORIGIN/YORIGIN, which are usually preferable. 

Note that when used in conjunction with XORIGIN and YORIGIN, the effect is additive. This might make sense if you used XORIGIN and YORIGIN in all your printer ini files to standardize the origin across all your printers, and then found that you need to shift the contents of a particular report, or if you needed to shift the text relative to the images. 

Note also that XOFFSET and YOFFSET can be used more than once. This is useful for repeating a printing pattern with a vertical and/or horizontal offset. 

A-Shell Reference 

Page 1594 

## **XORIGIN, YORIGIN** 

## **//XORIGIN, ###** 

## **//YORIGIN, ###** 

These commands define the minimum offset, in twips, from the top left physical corner of the paper to the 0,0 print position. 

A-Shell and APEX will operate on the LARGER of the (a) XORIGIN,YORIGIN values and (b) the physical margin as defined by the printer driver. So in other words, if you set them each to 360, you should get _at least_ 1/4" top/left margin, even on printers (like some image printers, PDF printers, and even APEX itself) that don't have any built-in physical margin limitation. This can be very useful in reducing the alignment fluctuations between different printer models caused by differing hardware paper margins. 

While similar to the XOFFSET/YOFFSET commands, these differ in two important ways: First, they affect everything on the page, including images. Second, they interact with the physical margin of the printer in such a way as to eliminate the minor differences in physical margins between printers, thus improving device independence when precise positioning on the page is important. To fully achieve that benefit, you should set the XORIGIN and YORIGIN values to be at least as large as the largest physical margin on any printer you expect to print to, because the effective (0,0) point will be set to the larger of the physical margin and the XORIGIN/YORIGIN specification. In most cases, 400 twips (slightly more than 1/4") should be sufficient. 

- " " See the A Shell forum discussion Generating forms on demand for a look at how the XORIGIN, YORIGIN, XOFFSET and YOFFSET commands help with alignment and printer independence. 

XORIGIN and YORIGIN are among the printer commands that may be used both in the printer ini file and in reports themselves as GDI printing directives. However, since the benefits of standardizing the origin point are probably not specific to a single document or even a single printer, it generally makes more sense to use these commands in the printer ini file(s). 

These directives must appear before any commands or text that generate printable output. As mentioned above, these directives have a Printer ini file Equivalent. 

A-Shell Reference 

Page 1595 

## **XTEXT** 

## **//XTEXT, left, top, right, bottom, fspec {, offset}** 

XTEXT permits printing a text or RTF file via XTEXT into a specified rectangle. 

_left, top, right, bottom_ 

define the printing boundaries, using the current map mode. 

_fspec_ 

file to print; must be a plain text or RTF file. 

_offset_ (default 0) 

starting character offset within the file where printing will begin. This is mainly of use if you have to split the output into multiple XTEXT rectangles. 

The output will be wrapped, if necessary, to fit within the left and right boundaries of the rectangular area, and will be clipped if it goes beyond the bottom limit. See MX_GDICALC for a method of determining in advance how much of the file will fit within the area. 

XTEXT currently works only in portrait mode. 

## **File Locations** 

The GDI print commands IMAGE, XTEXT, and METAFILE will locate the specified file in the same directory as the printfile if it fails to find it in the directory specified in the //GDI directive or in the local cache. This is mainly a convenience when printing from another directory. For example, if a printfile BAS:TEST.PRT contains `//IMAGE,TEST.JPG` ,... and you tried to print it from another directory using PRINT BAS:TEST.PRT, versions of A-Shell prior to 995.3 would have failed to find the image test.jpg in the BAS: directory, because you weren't logged there. It also comes in handy when moving print files and their associated images to another location (such as with ASHLPD), since now you can combine all the associated files in an arbitrary directory. 

Beginning with A-Shell 1111 of 3 May 08, XTEXT, IMAGE, and METAFILE will now look for the file in the same directory as the printfile itself, if not found at the location specified, even when the location specified is a Unix path. This was previously true, 

A-Shell Reference 

Page 1596 

since 5.0.999, but only when the original spec was a Windows path. The new logic is mainly of use in ASHLPD or other environments where you generate the GDI printfile under Unix and then transfer it to Windows. 

A-Shell Reference 

Page 1597 

## **TAB FUNCTIONS** 

_Rewritten December 2023_ 

Tab() functions serve to convert high-level commands related to terminal/workstation display (cursor positioning, clear screen, set colors, etc.) into the cryptic character sequences (aka "ESCAPE sequences") used by the terminal/workstation/display device. Aside from making these operations human-intelligible, Tab() commands work with the terminal drivers built in to A-Shell, or OS-level terminal support packages like TERMINFO, to provide a uniform set of commands at the application level even though the character sequences may vary among terminal or emulator types. For example, `TAB(6,9)` generates the ESCAPE sequence to position the cursor at row 6, column 9, even though the actual character sequence required may vary between, say, workstations using the AM75G and WYSE50 emulations. 

Since all Tab() commands are meant to be seen by the terminal/client/workstation, they must be provided as an argument to a statement that sends characters to the device. The most typical such command is PRINT (or ?), which is why these commands are often referred to as "Print Tab Functions". But it should be noted that WRITECD (a variation for outputting delimited lists) and potentially other statements which output character sequences may work as well, or better, depending on the situation. 

The two general classes of Tab functions are: 

• Terminal Functions, by which we mean functions that are used with traditional or "dumb" terminals. These were originally known as TCRT calls, although the origin of that acronym is unknown. 

• ATE Functions which are used only with "smart" terminals, also known as "clients" or "workstations." In A-Shell environments, the usual smart client is a PC running A-Shell's terminal emulator software ATE. 

A-Shell Reference 

Page 1598 

## **TERMINAL FUNCTIONS** 

|**Tab**|**Description**|
|---|---|
|(x)|One dimensional typewriter-style Tab to column x.|
|(x,y)|Two dimensional cursor positioning: row x, column y.|
|(-1,x)|Original Functions<br>.|
|(-2,x)|Set Foreground Color. Tab(-2,x) is implemented very much as under AMOS, although most AMOS applications were monochrome<br>and thus you may not be familiar with this command. Set the foreground color to x, where x normally ranges from zero to seven<br>(0=black, 1=white, 2=blue, 3=magenta, 4=red, 5=yellow, 6=green, 7=cyan). You can also specify color values from 8 to 15 but<br>these are equivalent to the "dim" versions of colors 0-7. (It is actually possible to define these all independently, either in<br>A-Shell/Windows or in most color terminal emulators, so that "dim" may be a misnomer. But from a programming standpoint,<br>Tab(-2,x);Tab(-1,11) is equivalent to Tab(-2,x+8). Color values beyond 15 are mapped to the modulo-8 equivalent. Note that color<br>is a "mode" attribute, meaning that it takes up no space on the screen and it stays in effect chronologically (rather than spatially)<br>until overridden by another color.|
|(-3,x)|Set the background color. Same as above, but for background color.|
|(-5,x)|Set Number of Rows. Tab(-5,x) sets the number of display rows to x. This was originally only available the AM65 and AM75<br>terminals, and x was essentially limited to 24 or 42. Under A-Shell, it is still limited to the display device, but in the case of A-<br>Shell/Windows, the display device supports from 1 to 50 rows. In the case of ZTERM, it also supports from 1 to 50 rows. See<br>Selecting a Terminal Emulation<br>.|
|(-6,x)|Set Number of Columns. Tab(-6,x) sets the number of display columns to x. This is purely an A-Shell extension and only applies to<br>A-Shell/Windows, which supports from 1 to 160 columns. Dumb terminals and emulators are typically limited to 80 and perhaps<br>132 columns, which the Tab(-1,80) and Tab(-1,81) commands are designed to switch between.|
|(-10,x)|ATE Functions<br>.|
|(x,y,z)|"Three-D"Print Tab<br>.|



**See Also** 

A-Shell Reference 

Page 1599 

• TRMCHRXS to query the current color and row/col settings, i.e. current values of the tab(-2,x), tab(-3,x), tab(-5,x) and tab(-x,6) 

A-Shell Reference 

Page 1600 

## **ORIGINAL FUNCTIONS** 

Following are lists of the Print Tab(-1,x) functions. These are called "original" functions because when they were invented/designed, the Print Tab (-2,-3, etc) functions were not yet imagined; the 256 Print Tab(-1,x) functions were envisoned as the entire set of terminal control functions. 

The codes are grouped into tables by type for quick reference. If you prefer a sequential listing of all codes, see the last entry in the table. Note that most of these functions can be displayed from within VUE by using >HELP TCRT. 

|**Range**|**Action**|
|---|---|
|0 - 37|Basic|
|38 - 53|Line Draw Characters|
|64 - 78|Alternate Characters|
|100 - 123|Mode-style Monochrome Attributes|
|132 - 147|AM70-Style Colors|
||All Others|
|0 - 254|Numeric List (all)|



**History** 

A-Shell Reference 

Page 1601 

- 2024 September, A Shell 7.0.1763:  the various blinking TAB(-1,x) attributes are now (some might say "finally?") supported in A-Shell/Windows and ATE. 

A-Shell Reference 

Page 1602 

## **BASIC** 

## **TAB(-1,code);** 

## **! terminal function** 

|**Code**|**Action**|
|---|---|
|0|Clear screen and set normal intensity|
|1|Cursor home (move to col 1, row 1)|
|2|Cursor return (move to col 1 without linefeed)|
|3 / 4|Cursor one row up / down|
|5 / 6|Cursor one column left / right|
|7 / 8|Keyboard lock / unlock|
|9 / 10|Erase to end of line / screen|
|11|Enter background display mode (reduced intensity)|
|12|Enter foreground display mode (normal intensity)|



A-Shell Reference 

Page 1603 

|**Code**|**Action**|
|---|---|
|13 / 14|Protected fields enable / disable|
|15 / 16|Line delete / insert|
|17 / 18|Character delete / insert|
|19 / 20|Not supported|
|21 / 22|Blinking field start / end|
|23 / 24|Alternate char set (line draw) enable / disable|
|25 / 26|Not supported|
|27|Set terminal attributes|
|28 / 29|Cursor on / off|
|30 / 31|Underscore start / end|
|32 / 33|Reverse video start / end|



A-Shell Reference 

Page 1604 

|**Code**|**Action**|
|---|---|
|34 / 35|Reverse blink start / end|
|36 / 37|Screen display off / on|



## **Example** 

- `? tab(x,y); tab(-1,11); "Name:"; tab(-1,12); name$; tab(-1,9);` 

A-Shell Reference 

Page 1605 

## **LINE DRAW CHARACTERS** 

## **? TAB(-1,23);** 

## **! enable alternate character set** 

**? TAB(-1,code); ... TAB(-1,code);** 

## **! output alternate character(s)** 

## **? TAB(-1,24);** 

## **! return to normal character set** 

As shown in syntax lines above, line draw / alternate character mode must be enabled with TCRT code 23 prior to executing the following codes and, after using these codes, disabled with TCRT code 24. 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|38|Top left corner||46|Horizontal line|
|39|Top right corner||47|Vertical line|
|40|Bottom left corner||48|Intersection|
|41|Bottom right corner||49|Solid block|
|42|Top intersection||50|Cross-hatch block|



A-Shell Reference 

Page 1606 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|43|Right intersection||51|Slanted cross-hatch block|
|44|Left intersection||52|Double horizontal line*|
|45|Bottom intersection||53|Double vertical line*|



* Note that double lines are only supported when using the OEM character set; the more typical ANSI character set doesn't support them. 

## **Example** 

- `! draw a box from srow,scol to erow,ecol` 

- `? tab(-1,23);                  ! enable alternate character set` 

- `? tab(srow,scol); tab(-1,38);  ! top left corner` 

- `? tab(srow,ecol); tab(-1,39);  ! top right corner` 

- `? tab(erow,scol); tab(-1,40);  ! bottom left corner` 

- `? tab(erow,ecol); tab(-1,41);  ! bottom right corner for c = scol+1 to ecol-1` 

- `? tab(srow,c);tab(-1,46);  ! top line` 

- `? tab(erow,c);tab(-1,46);  ! bottom line` 

A-Shell Reference 

Page 1607 

```
next c
```

```
for r = srow+1 to erow-1
```

```
    ? tab(r,scol);tab(-1,47);  ! left side
    ? tab(r,ecol);tab(-1,47);  ! right side
```

```
next r
```

- `? tab(-1,24);                  ! back to normal character set` 

## **See Also** 

- MSBOXX 

A-Shell Reference 

Page 1608 

## **ALTERNATE CHARACTERS** 

## **TAB(-1,23);** 

## **! enable alternate character set** 

## **TAB(-1,code);** 

## **! output alternate character(s)** 

## **TAB(-1,24); ! disable alternate character set (back to normal mode)** 

As shown in syntax lines above, line draw / alternate character mode must be enabled with TCRT code 23 prior to executing the following codes and, after using these codes, disabled with TCRT code 24. 

|**Code**|**Action**|**Code**|**Action**|
|---|---|---|---|
|64|Up arrow|72|Cent sign|
|65|Down arrow|73|One-quarter|
|66|Raised dot|74|One-half|
|67|End of line marker|75|Degree|
|68|Horizontal tab|76|Trademark|
|69|Paragraph|77|Copyright|



A-Shell Reference 

Page 1609 

|**Code**|**Action**|**Code**|**Action**|
|---|---|---|---|
|70|Dagger|78|Registered|
|71|Section|||



## **Example** 

- `? tab(22,10);"Temperature: 100"; tab(-1,23);tab(-1,75);tab(-1,24);"F"` 

A-Shell Reference 

Page 1610 

## **- MODE STYLE MONOCHROME ATTRIBUTES** 

## **TAB(-1,code);** 

## **! start special attribute display mode** 

## **<output text>** 

## **! output text using display mode** 

## **TAB(-1,code); ! end special attribute display mode** 

Note that the following apply to mode style emulations (AM65, AM75, PC*), and not field-style emulations (AM62x, WY5*). 

|**Code**|**Action**|
|---|---|
|100 / 101|Underscored blinking field start / end|
|102 / 103|Underscored reverse field start / end|
|104 / 105|Underscored reverse blinking field start / end|
|106 / 107|Underscored text without space start / end|
|108 / 109|Reverse text without space start / end|
|110 / 111|Reverse blinking text without space start /end|



A-Shell Reference 

Page 1611 

|ell Reference||
|---|---|
|112 / 113|Underscored blinking text without space start / end|
|114 / 115|Underscored reverse text without space start / end|
|116 / 117|Underscored reverse blinking text w/out space start / end|
|118 / 119|Blink without space start / end|



## **Example** 

```
? tab(23,10);"Normal";tab(-1,108);"Reverse";tab(-1,109);"Normal"
```

## **See Also** 

- The system parameter OPTIONS=FIELDEMU for a discussion of mode versus field emulations 

A-Shell Reference 

Page 1612 

## **- AM70 STYLE COLORS** 

|**Text**|**Black**|**White**|**Blue**|**Magent**<br>**a**|**Red**|**Yellow**|**Green**|**Cyan**|
|---|---|---|---|---|---|---|---|---|
|Normal|132|133|134|135|136|137|138|139|
|Reversed|140|141|142|143|144|145|146|147|



A-Shell Reference 

Page 1613 

## **ALL OTHERS** 

## **TAB(-1,code);                                    ! special function** 

|**Code**|**Action**|
|---|---|
|54 / 55|Send message to function key line unshifted / shifted|
|63|Send message to host message field|
|80 / 81|Set terminal width to wide (132 col) / normal (80 col)|
|82 / 83|Transparent print mode enter / exit|
|91|Block fill with character|
|92|Draw a box|
|93 / 94|Scroll box one line up / down|
|120 / 121|Set cursor to block blinking / not-blinking|
|122 / 123|Set cursor to underline blinking / not-blinking|
|128|Select top status line without address|



A-Shell Reference 

Page 1614 

|**Code**|**Action**|
|---|---|
|129|End status line (all kinds)|
|130 / 131|Select status line without address unshifted / shifted|
|148 / 149|Amigos-style area save / restore|
|158 / 159|Mouse Cursor Reporting enable / disable<br>.|
|160|InSight<br>/ AM75 set cursor shape. SeeMouse Interaction<br>.|
|162|InSight / AM75 define hot spot. SeeMouse Interaction<br>.|
|192|InSight id (Unix only)|
|201|Tracker save current screen attributes|
|202 / 203|Tracker entire screen save / restore|
|253|Display Euro symbol (Windows)|
|254|Flush Screen Output Buffer|



A-Shell Reference 

Page 1615 

Note that while some of the above functions are standalone, such as 253 (display Euro symbol under Windows), others are typically used in pairs, such as the functions to print to a status line (54, 55, 63, 128, 130, 131) which must all be followed by the termination function 129. 

## **Examples** 

- `? tab(-1,128);"Top Status Line Message"; space(20); tab(-1,129);` 

```
do while <some process>
```

```
    <some process...>
```

```
    ? "."; tab(-1,254);        ! print dot (lifesign) and flush to screen
```

```
loop
```

```
? tab(-1,201);tab(-1,202);     ! save screen attributes and contents
```

```
...
```

- `? tab(-1,203);tab(-1,203);     ! restore previously saved attributes and contents` 

A-Shell Reference 

Page 1616 

## **MOUSE CURSOR REPORTING2** 

_Updated June 2021, see History_ 

Tab(-1,158) must be followed by "C", and then a coded byte indicating the number of lead-in bytes to be sent with each mouse action, followed by the lead-in bytes. The coded byte should be chr(32+number of lead-in bytes). For example, the ESP package uses the following to enable mouse cursor reporting: 

```
PRINT TAB(-1,158); "C"; CHR$(34); CHR$(27); CHR$(30)
```

This causes the two lead-in bytes, CHR$(27) and CHR$(30) to be sent at the start of each mouse event. These are followed by one byte indicating the row (coded as CHR$(31+row) followed by one or two more bytes indicating the column (from the same table), and finally a status code: CHR$(32) = sequence terminated; CHR$(33) = right button pressed; CHR$(34) = left button pressed; CHR$(35) = middle button pressed. 

A single click will generate two sets of the above sequences, the first ending with the status code indicating the button (corresponding to the down click) and the second ending with the termination status code (corresponding to the up click). A double click will generate three sets of the above sequences, with the last two both ending with the termination status (as if it were one down click followed by two up clicks). Consequently, you would probably need to use a timed input routine, such as TINKEY[XS] or GETKEY to determine whether the last part of the sequence was present. 

Additional information may be found in the discussions on Mouse Interaction and MX_MCRS. 

## **History** 

- 2021 June, A Shell 6.5.1704:  The TAB(-1,158) scheme for converting mouse clicks into byte sequences now works with controls that are nested within parent controls, such as a TABX or dialog. 

A-Shell Reference 

Page 1617 

## **FLUSH SCREEN OUTPUT BUFFER** 

Tab(-1,254) does nothing under AMOS, which doesn’t buffer screen output. But under both Windows and Unix, A-Shell output is buffered to minimize system overhead. The buffer is flushed after nearly every Tab(-1,x) command and every carriage return, as well as before every input. Under Windows, the buffer is also flushed every half second or so. Usually, the effect is not noticeable. But in some circumstances, you may find it annoying. One case in particular is where a report program displays “life signs” -- either a dot for every few records processed, or a % complete indicator. If the PRINT statement updating this display has a semicolon on the end (to suppress an unwanted carriage return), then instead of seeing a steadily updating indicator, it may appear as if nothing is happening, and then all of a sudden, it goes from 0 to 100% in one jump. Adding a Tab(-1,254); on the end of these PRINT statements (e.g. PRINT “.”;Tab(-1,254);) will make the output display as expected. 

A-Shell Reference 

Page 1618 

## **NUMERIC LIST (ALL)** 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|0|Clear screen and set normal intensity||80|Set to wide (132 column) mode|
|1|Cursor home (move to col 1, row 1)||81|Set to normal (80 column) mode|
|2|Cursor return (move to col 1 without linefeed)||82|Enter transparent print mode|
|3|Cursor up one row||83|Exit transparent print mode|
|4|Cursor down one row||84-90|Undefined, unsupported, reserved|
|5|Cursor left one column||91|Block fill with character|
|6|Cursor right one column||92|Draw a box|
|7|Lock keyboard||93|Scroll box up one line|
|8|Unlock keyboard||94|Scroll box down one line|
|9|Erase to end of line||95-99|Undefined, unsupported, reserved|
|10|Erase to end of screen||100|Start underscored, blinking field|



A-Shell Reference 

Page 1619 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|11|Enter background display mode (reduced intensity)||101|End underscored, blinking field|
|12|Enter foreground display mode (normal intensity)||102|Start underscored, reverse field|
|13|Enable protected fields||103|End underscored, reverse field|
|14|Disable protected fields||104|Start underscored, reverse, blinking field|
|15|Delete line||105|End underscored, reverse, blinking field|
|16|Insert line||106|Start underscored text without space|
|17|Delete character||107|End underscored text without space|
|18|Insert character||108|Start reverse text without space|
|19-20|Undefined, unsupported, reserved||109|End reverse text without space|
|21|Start blinking field||110|Start reverse blinking text without space|
|22|End blinking field||111|End reverse blinking text without space|



A-Shell Reference 

Page 1620 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|23|Start line drawing mode / enable alt char set||112|Start underscored blinking text without space|
|24|End line drawing mode / disable alt char set||113|End underscored blinking text without space|
|25-26|Undefined, unsupported, reserved||114|Start underscored reverse text without space|
|27|Set terminal attributes||115|End underscored reverse text without space|
|28|Cursor on||116|Start underscored reverse blinking text w/out space|
|29|Cursor off||117|End underscored reverse blinking text w/out space|
|30|Start underscore||118|Start blink without space|
|31|End underscore||119|End blink without space|
|32|Start reverse video||120|Set cursor to blinking block|
|33|End reverse video||121|Set cursor to steady block|
|34|Start reverse blink||122|Set cursor to blinking underline|



A-Shell Reference 

Page 1621 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|35|End reverse blink||123|Set cursor to steady underline|
|36|Turn off screen display||124-127|Undefined, unsupported, reserved|
|37|Turn on screen display||128|Select top status line without address|
|38|Top left corner||129|End status line (all kinds)|
|39|Top right corner||130|Select unshifted status line without address|
|40|Bottom left corner||131|Select shifted status line without address|
|41|Bottom right corner||132|Select black text (AM70-style color)|
|42|Top intersect||133|Select white text|
|43|Right intersect||134|Select blue text|
|44|Left intersect||135|Select magenta text|
|45|Bottom intersect||136|Select red text|



A-Shell Reference 

Page 1622 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|46|Horizontal line||137|Select yellow text|
|47|Vertical line||138|Select green text|
|48|Intersection||139|Select cyan text|
|49|Solid block||140|Select black reverse text|
|50|Slant block||141|Select white reverse text|
|51|Cross-hatch block||142|Select blue reverse text|
|52|Double line horizontal||143|Select magenta reverse text|
|53|Double line vertical||144|Select red reverse text|
|54|Send message to function key line||145|Select yellow reverse text|
|55|Send message to shifted function key line||146|Select green reverse text|
|56-62|Undefined, unsupported, reserved||147|Select cyan reverse text|



A-Shell Reference 

Page 1623 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|63|Send message to host message field||148|Amigos-style save area|
|64|Up-arrow||149|Amigos-style restore area|
|65|Down-arrow||150-157|Undefined, unsupported, reserved|
|66|Raised dot||158|Enable Mouse Cursor Reporting|
|67|End of line marker||159|Disable Mouse Cursor Reporting|
|68|Horizontal tab symbol||160|InSight / AM75 set cursor shape. SeeMouse Interaction<br>.|
|69|Paragraph||161|Undefined, unsupported, reserved|
|70|Dagger||162|InSight / AM75 define hot spot.Mouse Interaction<br>.|
|71|Section||163-191|Undefined, unsupported, reserved|
|72|Cent sign||192|InSight id (Unix only)|
|73|One-quarter||193-200|Undefined, unsupported, reserved|



A-Shell Reference 

Page 1624 

|**Code**|**Action**||**Code**|**Action**|
|---|---|---|---|---|
|74|One-half||201|Tracker save screen attributes|
|75|Degree||202|Tracker save entire screen|
|76|Trademark||203|Tracker restore entire screen|
|77|Copyright||253|Display Euro symbol|
|78|Registered||254|Flush Screen Output Buffer|
|79|Undefined, unsupported, reserved||||



A-Shell Reference 

Page 1625 

## **- THREE D PRINT TAB** 

A-Shell supports a "three dimensional" form of the Print Tab command: 

## **? TAB(row, col, Z); ...** 

This is equivalent to the standard "2D" form of ? Tab(row,col), with the addition of a third argument, Z, which is used as an index into a table of text attributes that can affect the appearance of anything output with this PRINT command (i.e., color, font, size, etc.). Although this feature does not make anything new possible, it does offer a very flexible tool for migrating legacy text programs to a GUI (or perhaps just a more colorful) environment. 

The theory is that you would convert existing `Tab(row,col)` statements to the `Tab(row,col,Z)` format, replacing Z with one or more variables that correspond to the nature of the text being displayed. Having done that, you can then define a set of display attributes for each of the types, through a series of calls to MX_DEFTABXYZ. 

The subroutine allows you to associate a variety of text attributes with the value Z, so that when you use `PRINT TAB(X,Y,Z);VAR$` , A-Shell will apply the specified attributes to the display of `VAR$` . See MX_DEFTABXYZ for more information. Use multiple calls to the function, one per text type or Z value. 

## **Comments** 

You must COMPIL with the /X:2 switch to enable support for 3D Tabs. Otherwise you will get a syntax error, UNLESS you use /RC, in which case TAB(X,Y,Z) will compile as if it were TAB(X,Y). (This allows you to compile down for backwards compatibility.) Programs using TAB(X,Y,Z) and compiled with /X:2 will not be compatible with prior versions of RUN. 

You can also disable the 3D Tab behavior at runtime by adding OPTIONS=NO3DTAB to miame.ini. This might be useful if you want to quickly revert to the old behavior even with programs compiled for the new behavior. Of course, you could also achieve the same effect by disabling your MX_DEFTABXYZ calls. 

It has been left as an exercise for the application programmer (that's you!) to come up with a user interface to allow individual users to define their own attributes for the various Z values you decide to use. 

## **Example** 

A-Shell Reference 

Page 1626 

As an example of how to use this feature in practice, let's say that after analyzing your application, you decide that there are really only five main types of text output: 

```
1=headers
```

```
2=field labels
```

```
3=data
```

```
4=aux data (legends, helpful messages relating to data)
```

```
5=warning messages
```

You might then define five symbolic constants representing these types: 

```
define TBX_HDR = 1! headers
define TBX_LBL = 2! labels
define TBX_DTA = 3! data
define TBX_AUX = 4! aux
define TBX_WRN = 5! warnings
```

Then you would go through your programs converting existing `TAB(row,col)` to `TAB(row,col,Z)` depending on the nature of the `PRINT` statement. For example: 

```
SCREEN'HEADER:
```

```
PRINT TAB(1,1,TBX_HDR);"Customer Maintenance"
...
SCREEN'BACKGROUND:
PRINT TAB(5,5,TBX_LBL);"Name: "
```

A-Shell Reference 

Page 1627 

```
PRINT TAB(6,5,TBX_LBL);"Address:"
```

```
...
```

```
DISPLAY'DATA:
```

```
PRINT TAB(5,20,TBX_DTA);CUS'NAME
PRINT TAB(6,20,TBX_DTA);CUS'ADDR1
```

```
...
```

At runtime, you would issue five MX_DEFTABXYZ calls to define attributes for the five types of text (assuming you wanted to alter the appearance of that type of text from its original style) 

Although this could be a tedious job, there are a several advantages to this approach versus some other methods of migrating existing code, such as replacing PRINT statements with TPRINT/DPRINT/EPRINT or AG_CONTROL or AUI_CONTROL statements: 

- You might be able to write a filter program to automate the conversion, by looking at the nature of the things being printed. 

- (Literal strings would usually be label text, unless perhaps on row 1 or 2; variables would be data, etc.) What can't be handled by your filter can probably be handled by a very junior programmer, since the cost of making a mistake is purely aesthetic. 

- Until you activate the feature by defining attributes, the 3D Tabs continue to work just like the old 2D Tabs. 

- The /RC switch will compile 3D Tabs as if they were 2D Tabs (ignoring the 3rd parameter), providing a path to backwards 

- compatibility. 

- With the new 3D Tabs in place, you are now in a position to allow a great deal of flexibility at runtime in deciding which 

- attributes to use. Depending on the situation (user, site, stock market, etc) you can decide to leave the display in legacy text mode but apply different colors to the different types of text. Or you can go all the way and convert them to GUI text objects using various different styles, font attributes, etc. 

## **See Also** 

- Sample program TABXYZ in EXLIB:[908,38] illustrates the feature. 

A-Shell Reference 

Page 1628 

## **ATE FUNCTIONS** 

_Reviewed and revised December 2023_ 

"ATE Functions" refer to the operations that can be used with A-Shell's smart client terminal emulator, ATE. Since ATE is effectively embedded within A-Shell/Windows, they are also supported in any configuration where A-Shell is running under Windows—standalone PC, networked PCs, RDP, etc. They are all initiated via PRINT TAB(-10,x) functions, with the response, if any, sent back via the keyboard channel. Note that many of the functions have higher-level subroutine wrappers, typically using the MIAMEX or AUI subroutines, which in most cases are preferable, since the wrapper automatically decides whether to execute the command on the server or forward to the client (or provides an option), and also handles the complications of retrieving a response via the keyboard channel. Otherwise, for functions that return a response, the caller has to either use an INPUT statement or the MX_AGWRAPPERXS function. The main advantage of using the Tab(-10,x) functions directly is that they don’t require anything on the server side other than support for one of the terminal emulations ending in "G" (PCTDVG, AM75G, etc.), eliminating any need to update the server to support newly implemented ATE functions. 

Note that the Tab(-10,x) command will be translated by any of the "G" drivers to the raw byte sequence <ESC>GUI<x>. If issued using a non-compliant driver, the result will be some garbage characters on the screen. On the receiving end, if the client doesn't recognize the command, or doesn't support the particular function number (x), you'll get no response. This is one advantage of MX_AGWRAPPER in that it supports a timeout if the expected response is not forthcoming.) 

The Tab(-10,x) command is equivalent to the raw byte sequence <ESC>GUI<x>. 

- See the next topic, TAB( 10,x) Function Listing, for a table containing a list of functions, brief descriptions, and links to detailed descriptions. 

## **Usage Notes** 

The general format of the commands is: 

## **? tab(-10, x); <arg1> <delim> <arg2> <delim>. . .<argn>; chr(127);** 

where "x" identifies the function. While the function identifier can be a literal number, e.g. 23, it is preferable—and far more legible—to use the corresponding AG_xxx symbol (e.g. AG_WINEXEC) defined in ashell.def. The following two statements, one using the traditional number and the other using the symbol, are equivalent: 

A-Shell Reference 

Page 1629 

## **? tab(-10,23); cmdlin; chr(127);** 

## **? tab(-10, AG_WINEXEC); cmdlin; chr(127);** 

While not strictly mandatory, it is highly recommended that all Tab(-10,x) statements be terminated with a semicolon (as in the examples above). Otherwise, a CRLF will be output (as it is for any PRINT statement which does not end with a semicolon); in the case of Tab(-10,x) commands, that terminating CRLF would be entirely spurious and might cause unwanted side effects on your screen, like scrolling. 

The <delim> may vary from one command to the next, but it usually a dash ("-"), tilde ("~"), or comma. Any argument that itself contains an embedded delimiter character must be quoted. It is important to note that in all cases, the literal delimiters must appear in the output string, as the entire string is parsed by the terminal driver (or ATE client) rather than by the compiler. Also note that all Tab(-10,x) commands must be terminated with a chr(127) (which cannot appear in the list of arguments). For example, the AG_SAVERES command takes two arguments and uses a comma for a delimiter. The following would be legal: 

```
? TAB(-10,AG_SAVERES);CMD$;",";ID; chr(127);
```

```
? TAB(-10,AG_SAVERES);"S,5";chr(127);
```

This, however, is not legal syntax: 

```
? TAB(-10,AG_SAVERES);CMD$,ID;chr(127);
```

The problem with the last example is that the comma separating the two arguments is interpreted by the compiler and runtime system, but not actually output to the terminal device. 

If the command returns a response, typically you will need some kind of input statement following the Tab(-10,x) statement to retrieve the response. For example: 

```
? TAB(-10,AG_GETENV); "MIAME"; chr(127);
```

```
INPUT LINE "",ENV$
```

INPUT LINE (as shown above) is preferable to INPUT, since the returned text may contain commas (which would act as delimiters). In the case of commands that return a single byte response (typically chr(13) for "ok" and chr(3) for "error", 

A-Shell Reference 

Page 1630 

following the ZTERM Escape Sequences protocol), keep in mind that the chr(3) (aka "Control C") will abort your program if you don't take steps to trap it. Typically in these cases, it is better to disable Control-C processing (see CCOFF[XS] ) and use a byteoriented input routine like ACCEPN[XS] . 

The operation of inputting the response can be problematic, due to the possibility of the operator managing to manually force keyboard characters into the input stream ahead of the command input. Typically, the AG_xxx function will lock the keyboard to prevent this, but that can be manually unlocked by the user. And there is also the possibility of type-ahead (characters already typed but not yet received by the application) getting mixed in. In addition, you may not want the returned characters to appear on the screen (for which you can set NOECHO mode, or use an input routine that doesn’t echo, like ACCEPN[XS] ). To reduce or even eliminate these complications and simplify your application coding, we recommend using the subroutine equivalent of the AG_xxx function (when available, as noted in the table above), and if there is no specific subroutine equivalent, you can use the generic MX_AGWRAPPER function to encapsulate the sending of the command and inputting of the response. The subroutine wrapper generally takes care of all the issues just described. 

## **See Also** 

- Selecting a terminal emulation. 

- MX_AGWRAPPERXS 

- ZTERM Escape Sequences. 

- Sample program TCRTEX.BP in EXLIB:[908,31] for examples of the Tab(-10,x) extended TCRT commands. 

- AGCMD.LIT which provides a handy command line interface to the entire range of TAB(-10,x) commands, useful both for 

- testing and for embedding such functions into command files. 

- Whole Array Assignment for a high-level approach to parsing multiple values out of a delimited string. 

A-Shell Reference 

Page 1631 

## **- TAB( 10,X) SYNTAX AND USAGE NOTES** 

_This topic last updated 21 June 2026_ 

The syntax shown for the AG_xxx functions has been simplified for easier reading but is misleading in that the delimiters between parameters (usually commas, sometimes tildes or other special characters) are meant to be transmitted literally. For example, if the syntax line shows: 

```
? tab(-10,AG_XXX); arg1, arg2, arg3; chr(127);
```

the actual print statement would need to be altered to send literal commas as shown here: 

- `? tab(-10,AG_XXX); arg1; ","; arg2; ","; arg3; chr(127);` 

In the case of comma delimiters, the easiest way to achieve this effect would be to replace the ? (PRINT) command with WRITECD (comma delimited), e.g; 

```
writecd tab(-10, AG_XXX); arg1, arg2, arg3; chr(127);
```

WRITECD not only takes care of the comma delimiters but also adds quotes as needed to any arguments that have embedded commas. 

To further clarify, assuming that the value of arg1 was "one", arg2 was "two" and arg3 was "three", the actual string sent to the client (between the tab prefix and the chr(127) suffix would be: 

```
"one,two,three";
```

Note that in most cases it will be cleaner and simpler to just use the MX_AGWRAPPER wrapper function. 

## **See Also** 

- AGCMD.LIT, a utility to test AG_xxx functions and responses without writing any code 

A-Shell Reference 

Page 1632 

## **- TAB( 10,X) FUNCTION LISTING** 

The following table is sorted alphabetically by symbol name. The same table sorted by value is provided after the Notes, below. 

|**Symbol**|**Valu**<br>**e**|**Notes**|**Description**|
|---|---|---|---|
|AG_ATEDISCONNECT|44|1|Force immediate ATE disconnect|
|AG_ATTRSUB|68|(none)|Change underline attribute|
|AG_AUTOPARENT|87|3|? tab(-10,AG_AUTOPARENT); ctrlid; chr(127); seeMX_AUTOPARENT|
|AG_BEVEL|13|3|Set beveling flags|
|AG_BROWSEFOLDER|70|3,5|Select Windows folder|
|AG_BUFSIZ|42||Increase the ATE buffer size|
|AG_CHKPCNET|74|3,5|Check ATE network state|
|AG_CLIPBOARD|65|3|Perform clipboard operations|
|AG_CLRINBUF|106|1,3|Clears the ATE client input buffer: ? tab (-10,AG_CLRINBUF); chr(127). Note that<br>MX_CLRINBUF<br> will automatically issue this command, so you would normally only<br>use AG_CLRINBUF separately in specialized situations.|
|AG_CONTROL|20|3,5|Edit GUI control|



A-Shell Reference 

Page 1633 

|ell Reference||||
|---|---|---|---|
|||||
|AG_DATETIME|64|1,5|Retrieve ATE date and time|
|AG_DELAYOP|107|(none)|Run Delayed Operation in Background|
|AG_DESIGN|61|6|Design mode operations|
|AG_DIRCLEAN|114|4,5|Counts or deletes files based on various filter attributes.|
|AG_DISCONNECTPW|53|1|Set disconnect password|
|AG_DPM|110|(none)|Activate Windows "Dpi Per Monitor awareness|
|AG_DRAGDROP|112|4,5|Implements both destructive and non-destructive drag-drop modes|
|AG_EVENTWAIT|33|3|Event wait|
|AG_EVTMSG|57|(none)|Output system message|
|AG_FILESTATS|31|3,5|Get file stats|
|AG_FILETIMES|113|4,5|Get / set a file's modification, creation or access time|



A-Shell Reference 

Page 1634 

|ell Reference||||
|---|---|---|---|
|AG_FLASHWINDOW|28|(none)|Flash Window|
|AG_FTP|22|1,2,5|FTP|
|AG_FTPSETPW|29|1,2|Set FTP login / password|
|AG_FTPSYNC|55|1,2|Used internally withATSYNC.LIT. Inquire if interested.|
|AG_GETDPI|111|3,5|Return the DPI for workstation and monitor|
|AG_GETENV|45|4,5|Get ATE environment variable|
|AG_GETFLAGS|92|6|? tab(-10,AG_GETFLAGS); opcode; chr(127);  Retrieves a single digit (0 or 1)<br>followed by a CRLF, indicating if theme support is active on the client.|
|AG_GETLOCALE|115|4,5|Retrieves the name of the user's locale on the client workstation.|
|AG_GETOFD|47|3,5|Display open/save file dialog|
|AG_GETSHELLPATH|71|3,5|Retrieve Windows path|
|AG_HANDSHAKE|85|1|Send/receive various info with ATE client|
|AG_HOLDKBD|36|1, 6|Set ATE keyboard hold|



A-Shell Reference 

Page 1635 

|ell Reference||||
|---|---|---|---|
|AG_IATIMEOUT|79|1,3,5|Set / retrieve timeout period|
|AG_IMAGE|35|3|Image processing|
|AG_ISFOREGROUND|78|5|Test for foreground status|
|AG_LANGUAGE|116||Queries or sets the ATE / Windows client LDF LANGUAGE setting.|
|AG_MENU|21|3,5|Edit menu control|
|AG_MESSAGEBEEP|3|(none)|Play Windows sound|
|AG_MESSAGEBOXOK|4|3,5|Display OK / cancel message box|
|AG_MESSAGEBOXSTD|17|3,5|Display standard message dialog|
|AG_MINTITLE|1|(none)|Set minimized window title|
|AG_MKDIR|32|3,5|Make directory|
|AG_MOUSE|100|(none)|Set / Restore AutoMouse|
|AG_NEWPRODUCT|6|6|Allows override of certain info in the ABOUT box|



A-Shell Reference 

Page 1636 

|ell Reference||||
|---|---|---|---|
|AG_OPTIONS|69|4,5|Set / retrieve OPTIONS for ATE|
|AG_OSVER|66|3,5|Get OS info|
|AG_PALETTE|15|5|Query colors. SeeDefine or Query Color Palette<br>.|
|AG_PLAYSOUND|105|(none)|Play Sound File|
|AG_RAWDATA|83|1|Send raw data|
|AG_RELEASEKBD|49|1,3|Release ATE keyboard release|
|AG_RESETWINDOW|16|(none)|Reset window|
|AG_SAVERES|40|(none)|Save / restore screen with ID|
|AG_SBRFLAGS|102|3,4,5|Set / Retrieve SBR Flags|
|AG_SCROLLBACK|109|(none)|Control Scrollback Bar|
|AG_SENDKBD|82|(none)|Send keyboard characters|
|AG_SETCOLOR|15|(none)|Define or query color palette|



A-Shell Reference 

Page 1637 

|ell Reference||||
|---|---|---|---|
|AG_SETCURSOR|50|(none)|Set Mouse Cursor|
|AG_SETENV|77|3,4|Set environment variable|
|AG_SHLEXEC|24|3,5|Shell execute|
|AG_SHORTCUT|72|3,5|Create a shortcut|
|AG_SHOWFONT|99|(none)|Deprecated. Display font info.|
|AG_SHOWWINDOW|27|3|Show window|
|AG_SPOOLCFG|54|1|Auxiliary port control|
|AG_STATUSLINES|34|(none)|Enable / disable status lines|
|AG_SYSBCLR|26|3|Associate A-Shell and Windows colors|
|AG_SYSCOLOR|63|(none)|Change RGB Value|
|AG_TABWRAPPER|117||Wraps 'problematic' TAB(-1,x) commands for delivery to the client.|
|AG_TRACE|76|4,5|Clear / set / query ATE trace flags|



A-Shell Reference 

Page 1638 

|ell Reference||||
|---|---|---|---|
|AG_WALLPAPER|39|(none)|Display wallpaper|
|AG_WEBCACHE|108|3,5|Get / Set WEBCACHE Options|
|AG_WINEXEC|23|5|Execute Windows command line|
|AG_WINPTR|56|3,5|Display printer selection dialog|
|AG_WINSETTINGS|46|3,5|Get / set / load / save settings|
|AG_WINTITLE|2|(none)|Change the title that displays on the title bar of the A-Shell window|
|AG_WRAP|62|(none)|Enable / disable wrap|
|AG_XFUNC|25|5|Call SBX as a function (numeric)|
|AG_XFUNC2|73|(none)|Call SBX as a function (no return value)|
|AG_XFUNCS|75|5|Call SBX as a function (string)|



## **Notes** 

1 Applies only to ATE. It may be technically possible to use the command in non-ATE situations, but it doesn’t make much sense. 

A-Shell Reference 

Page 1639 

2 Requires that an FTP service be activated on the server, which uses the same root directory as A-Shell running on the server (which is rarely the case with Windows). 

3 The MX_xxx or AUI_xxx equivalent is preferable, as it will be simpler to use (no need for an INPUT statement to retrieve the result) and will automatically route the command to the ATE client or handle locally on the application server, depending on the environment. Note, however, that in some cases, the MX_xxx or AUI_xxx equivalent may support an option of whether to perform the function on the server or forward it to the ATE client, whereas the AG_xxx functions are always sent to the client. See the MX_xxx / AUI_xxx documentation for details. In the case of A-Shell/Windows without ATSD, the client and server are effectively the same. 

4 Similar to the MX_xxx equivalent, but always works relative to the client PC, whereas the MX_xxx equivalent always works relative to the application server. In the case of A-Shell/Windows without ATE, the two are functionally the same. 

5 In lieu of using `? Tab(-10, AG_xxx)` followed by some form of INPUT to retrieve the response, we recommend the use of the MX_AGWRAPPER function as a way of combining the two operations into a single subroutine (provided server is running A-Shell and the MX_AGWRAPPER function is available). 

- 6 Used mostly or entirely for internal purposes only. Please inquire if you want more information on this function. 

## **Table Sorted by Value** 

|**Symbol**|**Valu**<br>**e**|**Notes**|**Description**|
|---|---|---|---|
|AG_MINTITLE|1|(none)|Set minimized window title|
|AG_WINTITLE|2|(none)|Change the title that displays on the title bar of the A-Shell window|
|AG_MESSAGEBEEP|3|(none)|Play Windows sound|
|AG_MESSAGEBOXOK|4|3,5|Display OK / cancel message box|



A-Shell Reference 

Page 1640 

|ell Reference||||
|---|---|---|---|
|AG_NEWPRODUCT|6|6|Allows override of certain info in About box|
|AG_BEVEL|13|3|Set beveling flags|
|AG_SETCOLOR|15|(none)|Define or query color palette|
|AG_PALETTE|15|5|Query colors. SeeDefine or Query Color Palette<br>.|
|AG_RESETWINDOW|16|(none)|Reset window|
|AG_MESSAGEBOXSTD|17|3,5|Display standard message dialog|
|AG_CONTROL|20|3,5|Edit GUI control|
|AG_MENU|21|3,5|Edit menu control|
|AG_FTP|22|1,2,5|FTP|
|AG_WINEXEC|23|5|Execute Windows command line|
|AG_SHLEXEC|24|3,5|Shell execute|
|AG_XFUNC|25|5|Call SBX as a function (numeric)|



A-Shell Reference 

Page 1641 

|ell Reference||||
|---|---|---|---|
|AG_SYSBCLR|26|3|Associate A-Shell and Windows colors|
|AG_SHOWWINDOW|27|3|Show window|
|AG_FLASHWINDOW|28|(none)|Flash Window|
|AG_FTPSETPW|29|1,2|Set FTP login / password|
|AG_FILESTATS|31|3,5|Get file stats|
|AG_MKDIR|32|3,5|Make directory|
|AG_EVENTWAIT|33|3|Event wait|
|AG_STATUSLINES|34|(none)|Enable / disable status lines|
|AG_IMAGE|35|3|Image processing|
|AG_HOLDKBD|36|1, 6|Set ATE keyboard hold|
|AG_WALLPAPER|39|(none)|Display wallpaper|
|AG_SAVERES|40|(none)|Save / restore screen with ID|



A-Shell Reference 

Page 1642 

|ell Reference||||
|---|---|---|---|
|AG_BUFSIZ|42||Increase the ATE buffer size|
|AG_ATEDISCONNECT|44|1|Force immediate ATE disconnect|
|AG_GETENV|45|4,5|Get ATE environment variable|
|AG_WINSETTINGS|46|3,5|Get / set / load / save settings|
|AG_GETOFD|47|3,5|Display open/save file dialog|
|AG_RELEASEKBD|49|1,3|Release ATE keyboard release|
|AG_SETCURSOR|50|(none)|Set Mouse Cursor|
|AG_DISCONNECTPW|53|1|Set disconnect password|
|AG_SPOOLCFG|54|1|Auxiliary port control|
|AG_FTPSYNC|55|1,2|Used internally withATSYNC.LIT. Inquire if interested.|
|AG_WINPTR|56|3,5|Display printer selection dialog|
|AG_EVTMSG|57|(none)|Output system message|



A-Shell Reference 

Page 1643 

|ell Reference||||
|---|---|---|---|
|AG_DESIGN|61|6|Design mode operations|
|AG_WRAP|62|(none)|Enable / disable wrap|
|AG_SYSCOLOR|63|(none)|Change RGB Value|
|AG_DATETIME|64|1,5|Retrieve ATE date and time|
|AG_CLIPBOARD|65|3|Perform clipboard operations|
|AG_OSVER|66|3,5|Get OS info|
|AG_ATTRSUB|68|(none)|Change underline attribute|
|AG_OPTIONS|69|4,5|Set / retrieve OPTIONS for ATE|
|AG_BROWSEFOLDER|70|3,5|Select Windows folder|
|AG_GETSHELLPATH|71|3,5|Retrieve Windows path|
|AG_SHORTCUT|72|3,5|Create a shortcut|
|AG_XFUNC2|73|(none)|Call SBX as a function (no return value)|



A-Shell Reference 

Page 1644 

|ell Reference||||
|---|---|---|---|
|AG_CHKPCNET|74|3,5|Check ATE network state|
|AG_XFUNCS|75|5|Call SBX as a function (string)|
|AG_TRACE|76|4,5|Clear / set / query ATE trace flags|
|AG_SETENV|77|3,4|Set environment variable|
|AG_ISFOREGROUND|78|5|Test for foreground status|
|AG_IATIMEOUT|79|1,3,5|Set / retrieve timeout period|
|AG_SENDKBD|82|(none)|Send keyboard characters|
|AG_RAWDATA|83|1|Send raw data|
|AG_HANDSHAKE|85|1|Send/receive various info with ATE client|
|AG_AUTOPARENT|87|3|? tab(-10,AG_AUTOPARENT); ctrlid; chr(127); seeMX_AUTOPARENT|
|AG_GETFLAGS|92|6|? tab(-10,AG_GETFLAGS); opcode; chr(127);  Retrieves a single digit (0 or 1)<br>followed by a CRLF, indicating if theme support is active on the client.|
|AG_SHOWFONT|99|(none)|Deprecated. Display font info.|



A-Shell Reference 

Page 1645 

|ell Reference||||
|---|---|---|---|
|AG_MOUSE|100|(none)|Set / Restore AutoMouse|
|AG_SBRFLAGS|102|3,4,5|Set / Retrieve SBR Flags|
|AG_PLAYSOUND|105|(none)|Play Sound File|
|AG_CLRINBUF|106|1,3|Clears the ATE client input buffer: ? tab (-10,AG_CLRINBUF); chr(127). Note that<br>MX_CLRINBUF<br> will automatically issue this command, so you would normally only<br>use AG_CLRINBUF separately in specialized situations.|
|AG_DELAYOP|107|(none)|Run Delayed Operation in Background|
|AG_WEBCACHE|108|3,5|Get / Set WEBCACHE Options|
|AG_SCROLLBACK|109|(none)|Control Scrollback Bar|
|AG_DPM|110|(none)|Activate Windows "Dpi Per Monitor awareness|
|AG_GETDPI|111|3,5|Return the DPI for workstation and monitor|
|AG_DRAGDROP|112|4,5|Implements both destructive and non-destructive drag-drop modes|
|AG_FILETIMES|113|4,5|Get / set a file's modification, creation or access time|
|AG_DIRCLEAN|114|4,5|Counts or deletes files based on various filter attributes.|



A-Shell Reference 

Page 1646 

|ell Reference||||
|---|---|---|---|
|||||
|AG_GETLOCALE|115|4,5|Retrieves the name of the user's locale on the client workstation.|
|AG_LANGUAGE|116||Queries or sets the ATE / Windows client LDF LANGUAGE setting.|
|AG_TABWRAPPER|117||Wraps 'problematic' TAB(-1,x) commands for delivery to the client.|



A-Shell Reference 

Page 1647 

## **AG_ATEDISCONNECT** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_ATEDISCONNECT); {flags{,msg}}; chr(127);** Tab( 10,x) Syntax Notes 

AG_ATEDISCONNECT (44) allows the application running on the server to force the ATE client to disconnect. Typically this causes the ATE client window to close. 

## **Parameters** 

## _flags_ 

may contain one or more of the following bits: 

|**Value**|**Meaning**|
|---|---|
|&h0001|Force close-on-disconnect option to ON (no dialog on close)|
|&h0002|Force close-on-disconnect option to OFF (display dlg on close)|
|&h0004|Don't disconnect (just update the close-on-disconnect and msg options)|



## _msg_ (string, up to 100 characters) 

may contain an optional replacement for the default "Connection reset" message that appears inside a message box when the close-on-disconnect option is not set. 

## **Response** 

none 

## **Comments** 

It is generally considered good style if the application program automatically closes the ATE connection when the user exits or aborts from the main menu (or application login dialog). This eliminates the need for users to learn the various ways of 

A-Shell Reference 

Page 1648 

performing independent or manual disconnects (which are usually best avoided altogether). However, there are a few guidelines and points to be aware of when adding this function to your application: 

- Although A-Shell/Windows will ignore the command, other emulators will just see a foreign ESC sequence. An easy way to 

- test whether the command is supported is to use AUI_ENVIRONMENTXS and test for the AGF_GUIEXT flag. 

- Since the disconnect operation will trigger a SIGHUP signal (same as if the client initiated the disconnection), which in turn 

- will shut down the application, you should perform all your shutdown housecleaning (closing files, etc) before sending the AG_ATEDISCONNECT command. 

- For maintenance purposes, it is useful to provide a backdoor around the server-initiated disconnect. (You can base this on the 

- user login, a hidden menu item, a startup switch, etc.) 

- To prevent the user from independently or manually disconnecting at an inappropriate time, see Set Disconnect Password. 

## **History** 

- 2016 January, A Shell 6.2.1422:  The text message option in AG_ATEDISCONNECT is now independent of the flags option. Previous, if the text message was specified, it logged the message to the ashlog file, but effectively forced the flags option to &h0001 (no dialog on close). In other words, the custom message was only being seen in the log, not by the user—which, upon review, seemed just wrong. 

- 2012 September, A Shell 6.0.1258:  Added the two parameters 

A-Shell Reference 

Page 1649 

## **AG_ATTRSUB** 

_Rewritten December 2023_ 

## - **tab(-10, AG_ATTRSUB); attrtype, clrtype, fg'r, fg'g, fg'b, bg'r, bg'g, bg'b; chr(127);** Tab( 10,x) Syntax Notes 

AG_ATTRSUB (68) allows for changing the reverse or underline attribute to an arbitrary foreground/background color 

combination. It is useful for slight aesthetic improvement to legacy text-mode programs which use reverse video and underline, which may seem excessively retro for some tastes. 

## **Parameters** 

## _attrtype_ 

Attribute type:  0=reverse, 1=underline 

## _clrtype_ 

Type of color:  1=palette index, 2=RGB 

## _fg'r, fg'g, fg'b_ 

Foreground color. For _clrtype_ 1 (palette index), only fg'g and fg'b are ignored; fg'r is treated as the palette index (0-7 for foreground palette, 8-15 for reduced foreground). For _clrtype_ 2 (RGB), foreground red, green and blue RGB values. 

## _bg'r, bg'g, bg'b_ 

Background color. For _clrtype_ 1 (palette index), only bg'g and bg'b are ignored; bg'r is treated as the palette index (0-7 for background palette, 8-15 for reduced foreground) 

For _clrtype_ 2 (RGB), foreground red, green and blue RGB values. 

## **Response** 

None 

## **History** 

A-Shell Reference 

Page 1650 

- 2023 December, A Shell 7.0.1752.2:   bg'r value was previously (incorrectly) indexing the foreground rather than background palette when clrtype=1. 

A-Shell Reference 

Page 1651 

## **AG_BEVEL** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_BEVEL); bevelflags; chr(127);** Tab( 10,x) Syntax Notes 

AG_BEVEL (13) provides a way to set the values that are on the _Settings...Beveling_ menu. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _bevelflags_ 

Typically 255 to turn on beveling and replace all the standard line drawing characters with 3D versions. 0 deactivates beveling. 

## **Response** 

none 

## **Example** 

```
? TAB(-10,AG_BEVEL);"255";chr(127);      ! turn beveling on
```

```
? TAB(-10,AG_BEVEL);str(0);chr(127);     ! turn beveling off
```

## **Notes** 

Note that beveling works best with a gray or pastel background; see AG_PALETTE for details on defining colors from within the program. Also note that you can turn on beveling via the _Settings...Beveling_ menu, and then save it permanently in the settings file. For more information, see Beveling _._ 

## **See Also** 

- MX_BEVELXS 

A-Shell Reference 

Page 1652 

## **AG_BROWSEFOLDER** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_BROWSEFOLDER); folder, rootID, title, flags; chr(127);** Tab( 10,x) Syntax Notes 

AG_BROWSEFOLDER (70) invokes a standard Windows dialog allowing the user to browse for and select a folder or other non-file resource such as a computer or device. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _folder_ 

Optional default folder. Note even when the rootID parameter is specified, this default folder specification must be absolute (i.e. not relative to the rootID). But it must specify a folder on or below that rootID folder. 

## _rootid_ 

Root folder (using the standard CSIDL_xxx identifiers), above which the user would not be able to navigate. 

## _title_ 

Title for the dialog box 

## _flags_ 

See MX_BROWSEFOLDERXS for flags definitions. 

## **Response** 

Selected folder (complete path) followed by a carriage return: 

_folder_ <CR> 

A-Shell Reference 

Page 1653 

## **AG_BUFSIZ** 

_Added July 2024_ 

## - **tab(-10, AG_BUFSIZ); bufsiz; chr(127);** Tab( 10,x) Syntax Notes 

AG_BUFSIZ (42) may be used to change the default ATE buffer size (3072) to accommodate larger parameter lists. This is primarily useful in conjunction with INFLD[XS] , where the _setdef_ parameter can become quite large, as well as some of the AUI subroutines. 

## **Parameters** 

## _bufsiz_ 

New buffer size in bytes 

## **Response** 

none 

A-Shell Reference 

Page 1654 

## **AG_CHKPCNET** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_CHKPCNET); chr(127)** Tab( 10,x) Syntax Notes 

AG_CHKPCNET (74) allows you to detect the state of the ATE-connected PC'S internet connectivity from the server. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

none 

## **Response** 

_flags_ <CR> 

## **Comments** 

The return flags can be captured into a B,2 variable. Unlike the MX_CHKPCNET version where the status and returned flags are separate, here they are combined, with the status in the upper byte and the flags in the lower. They can be split back out as follows: 

```
status = flags / 65536
```

```
flags = flags and &hffff
```

XS See MX_CHKPCNET for definitions of _status_ and _flags_ . 

A-Shell Reference 

Page 1655 

## **AG_CLIPBOARD** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_CLIPBOARD); opcode, srow, scol, erow, ecol, rtnflag, text; chr(127);** Tab( 10,x) Syntax Notes 

AG_CLIPBOARD (65) allows for copying text from a variable or screen coordinates to the clipboard, or for retrieving the contents of the clipboard. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _rtnflag_ 

Set to 1 to request a response 

See MX_CLIPBOARDXS for descriptions of the remaining parameters. 

## **Response** 

If _rtnflag_ is not set to 1, none. Otherwise the response depends on the opcode. For opcodes 1, 3, and 5, the response is: 

## _status_ ,~ 

For opcodes 0 and 2, the response (retrieve clipboard contents) is: 

_status_ ,<clipboard contents>~ 

Note that unlike most other AG_xxx responses, this one ends with a tilde instead of a carriage return, partly because the clipboard contents may or may not contain carriage returns. Consequently you cannot use a traditional INPUT statement to retrieve the response and must rely on a method which doesn't require a carriage return termination. See Examples. 

## **Examples** 

Copy some explicit text to the ATE clipboard: 

- `! opcode=3, coordinates=0, rtnflag=0 (no response needed)` 

A-Shell Reference 

Page 1656 

```
? tab(-10,AG_CLIPBOARD);"3,0,0,0,0,0,some clipboard text";chr(127);
```

Retrieve ATE clipboard contents. Note that return string is formatted as 'status,text~' with no trailing <CR>, so we can't use INPUT to retrieve it. Instead we'll input it one character at a time to build up the string, then parse it into the status and text... `MAP1 PLINE$,S,512` 

```
MAP1 A,F
```

```
? tab(-10,AG_CLIPBOARD);"2,0,0,0,0,1";chr(127);
```

```
do
```

```
A = getkey(-1)
if A # 126 PLINE$ = PLINE$ + chr(A)
loop until A=126  ! terminate on tilde (126)
```

```
! now parse it out
A = instr(1,PLINE$,",")
if A > 0 then STATUS = PLINE$[1,A-1] : PLINE$ = PLINE$[A+1,-1]
```

```
? "Status: ";STATUS
```

```
? "Clipboard contents: ";PLINE$
```

Note that the above case could be handled much more simply with a single instance of MX_CLIPBOARD. 

See Also 

A-Shell Reference 

Page 1657 

- MX_CLIPBOARDXS 

A-Shell Reference 

Page 1658 

## **AG_CONTROL** 

_Reviewed and revised December 2023_ 

**tab(-10, AG_CONTROL), opcode, ctlid, ctext, cstate, ctype, cmd, func, srow, scol, erow, ecol, fgc, bgc, fontattr, fontscale, fontface, tooltip, parentid, rtnflag, winclass, winstyle, winstylex, ctype2; chr(127);** - Tab( 10,x) Syntax Notes 

## **tab(-10,AG_CONTROL); ctext, ctype; chr(127);** 

## **tab(-10,AG_CONTROL); ctext, typejust; chr(127);** 

AG_CONTROL (20) is the equivalent of AUI_CONTROLXS. It is used internally for forwarding those functions from A-Shell/Unix to ATE, although it also can be used directly with an application to create, delete, or perform various other operations on GUI controls. The second and third syntax variations are abbreviated versions for simplified creation of text and data field controls, with the coordinates based on the current screen position and length of the text and most other attributes defaulted. 

The number of required parameters depends on the opcode; see AUI_CONTROLXS for details and additional information. 

To output an explicit double-quote character in the middle of a field, you can "escape" it using HTML syntax, by %22 (a percent sign followed by the value of the character in hex notation). AUI_CONTROLXS haandles this for you—yet another reason to use it instead of AG_CONTROL. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

Nearly all of the parameters correspond to those already documented for th AUI_Control routine. The only exceptions are the removal of the AUI_CONTROL _cstatus_ parameter (which is output-only and thus has no purpose in the command string sent to the client), and the addition of: 

## _rtnflag_ 

"1" causes the function to return a string of result information in the keyboard buffer. Otherwise there is no response. 

A-Shell Reference 

Page 1659 

## _typejust_ 

(For text fields) a two character abbreviation from the set of ( **TL, DL, TC, DC, TR, DR** ) indicating a type ( **T** for plain text or label; **D** for data), and a justification code ( **L** for left, C for center, **R** for right). The **D** ata type is displayed inside a sunken box; XS see MX_SINK . 

## **Response** 

None, unless _rtnflag_ is set to "1", in which case it returns a comma delimited list of two values: _cstatus_ , _ctlid_ <CR>. See example below. 

## **Example** 

- `? TAB(-10,AG_CONTROL);"1,0,OK,0,";MBF'BUTTON;",%VK_xF101%,",12,5,13,10";chr(127);` 

- `? TAB(-10,AG_CONTROL);"1,,Dr A~VK_xF1001~~Dr B...";chr(127);` 

```
xcall NOECHO
```

```
input CSTATUS,CTLID
```

## **See Also** 

- AUI_CONTROLXS 

A-Shell Reference 

Page 1660 

## **AG_DATETIME** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_DATETIME); chr(127);** Tab( 10,x) Syntax Notes 

AG_DATETIME (64) queries the system date and time according to the Windows or ATE client. 

## **Parameters** 

None 

## **Response** 

A comma delimited list in the form of _date, time, status_ CR where _date_ is the decimal value of the separated date format (see IDTIM[XS] for details), _time_ is the number of seconds since midnight, and _status_ will be 0 if the operation was successful else a Windows error code. 

## **Example 1** 

```
map1 today,b,4
```

```
map1 now,b,4
map1 status,f
```

```
? tab(-10,AG_DATETIME);chr(127);
input "",today,now,status    ! e.g. "108725004,40891,0"
```

You might then compare this information against the values returned by the DATE and TIME system functions on the server to decide whether the client is reasonably in sync, and if not, you might prompt the client to update the clock on either the server or the client. 

## **Example 2** 

A-Shell Reference 

Page 1661 

The following illustrates AG_DATETIME being called via the MX_AGWRAPPERXS function, which eliminates the need for a separate INPUT statement to retrieve the results. The result string contains three comma-delimited fields which we split out using a utility function Fn'Explode() in SOSLIB:[907,10], although you could use other methods, such as INSTR() or Whole Array Assignment. 

```
++include ashinc:ashell.def
```

```
++include sosfunc:fnexplode.bsi
```

```
map1 misc
```

```
    map2 response$,s,100
    map2 fields,i,2
    map2 today,b,4
    map2 clocktime,b,4
    map2 status,i,4
```

- `? "Querying PC for time ..."` 

```
    xcall MIAMEX, MX_AGWRAPPER, AG_DATETIME, "", response$
```

```
    ? "Response: ";response$ ! should be sysdate,systime,status
```

- `! split out the fields and convert to human readable format...` 

```
    fields = Fn'ExplodeEx(response$,",",0,today,clocktime,status)
```

```
    if fields >= 3 and status = 0 then
```

- `? ODTIM(today,clocktime,0)` 

A-Shell Reference 

Page 1662 

```
    else
```

```
         ? "Error"
```

```
    endif
```

```
end
```

A-Shell Reference 

Page 1663 

## **AG_DELAYOP** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_DELAYOP); opcode, delayms, ctlid; ; chr(127);** Tab( 10,x) Syntax Notes 

AG_DELAYOP (107) allows application to request a delayed operation to be performed in the background. Currently this only works for deleting a control, but the range of possibilities may be expanded later. 

## **Parameters** 

## _opcode_ 

is the operation code. Currently only CTLOP_DEL (3) is supported. 

## _delayms_ 

is the number of milliseconds to wait before performing the operation. 

## _ctlid_ 

is the id (name or number) of the control to delete. 

## **Response** 

none 

## **Comments** 

If _delayms_ and _ctlid_ are omitted, and a prior delayed operation request is still pending, it will force the operation to take place immediately. 

The motivation behind providing this command was mainly to allow applications to create status message panels that go away by themselves after the specified interval. This provides more feedback to the user, without requiring any action on the user's part to acknowledge it, or on the application's part to remove it, or forcing the application to pause to allow the user to read it. 

For example, if the user gives the command to post some transactions, the application may want to display a confirmation message "Posting..." that appears for just a couple of seconds and then goes away. 

A-Shell Reference 

Page 1664 

In addition to the command, a wrapper procedure, StsMsgBox() in SOSLIB:[907,12] facilitates such messages, capitalizing on the new capability if available, and simulating it earlier versions. 

## **History** 

- 2015 May, A Shell 6.1.1411: Function added to A-Shell. 

A-Shell Reference 

Page 1665 

## **AG_DIRCLEAN** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_DIRCLEAN); dirspec, {,wildspec, flags, timelimit, bytes}; chr(127);** Tab( 10,x) Syntax Notes 

AG_DIRCLEAN (114) scans a specified directory, counting and/or deleting files based on various filter attributes. See MX_DIRCLEANXS for specifications on parameters. 

This function has both a subroutine and a print tab implementation. 

## **Response** 

_status, bytes_ CR 

_status_ indicates the number of files matched or deleted; negative values are errors 

_bytes_ returns the number of bytes in matched or deleted files 

## **See Also** 

- MX_DIRCLEANXS 

## **History** 

- 2023 August, A Shell 6.5.1740:  Function added to A-Shell. 

A-Shell Reference 

Page 1666 

## **AG_DISCONNECTPW** 

_Reviewed and revised December 2023_ 

## - **tab(-10,AG_DISCONNECTPW); pw{"~"; msg{"~"; title;}} chr(127);** Tab( 10,x) Syntax Notes 

AG_DISCONNECTPW (53) allows the application to establish a disconnect/terminate password, which the user must enter in order to disconnect (from ATE) or terminate (from a local A-Shell/Windows session). When established, this supersedes the big dialog/warning message that otherwise appears when you click on the "X". And perhaps more importantly, it also gets triggered when the "Disconnect" menu option is clicked, which otherwise exits without any fanfare whatsoever. 

Note that unlike most other AG_xxx functions, the delimiter here is tilde. The _msg_ and _title_ parameters are optional, but if 

included, must be preceded by a tilde to mark the end of the prior parameter. And in this case, trailing blanks between the end of _pw_ and subsequent tilde or chr(127) are significant. 

## **Parameters** 

## _pw_ 

If null, the password feature is disabled and disconnect behavior reverts to the way it was before. 

## _msg_ 

can be used to replace the standard message which otherwise appears on the password dialog: 

_Msg_ may include a CRLF to force a line break; otherwise it is wrapped to fit the space. Since the space is designed for about 200 lower case characters, if you have a lot less, you might want to use a leading CRLF just to vertically center it. 

## _title_ 

replaces the default title ("ATE Disconnect" or "Terminate A-Shell Session?") of the dialog box that prompts for the password. 

## **Response** 

none 

A-Shell Reference 

Page 1667 

## **Comments** 

The combined length limit for _msg_ plus _title_ is 248 characters. 

Since you can set the password any way you like, some people use a formula, perhaps based on the date, or on any information you can obtain programmatically about the environment, job, etc., so that it can be given out as needed without necessarily revealing the formula. 

If want to allow the user to disconnect from certain "safe" places (like the main menu), re-send the AG_DISCONNECTPW command with an empty password (to disable the prompt). 

The password is not encrypted, because no matter how secretive we make it, there is no way to stop the user from forcefully disconnecting by such brutal methods as rebooting, pulling the Ethernet cable, powering down, etc. So this is at best a merely a way to discourage sloppiness rather than a way to prevent it entirely. 

There is no way to disable the password but still require the user to enter some kind of confirmation. To get something like that effect, just change the message to explicitly state what the 'password' is, e.g. "...or enter 'GERONIMO' in the box below:" 

To complete the disconnect, use AG_ATEDISCONNECT. 

A-Shell Reference 

Page 1668 

## **AG_DPM** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_DPM); mode; chr(127);** Tab( 10,x) Syntax Notes 

AG_DPM (110) activates Windows "Dpi Per Monitor awareness," which generally results in smaller but sharper display objects on higher resolution screens. 

## **Parameters** 

Mode is is one of the following: 

|**Mode**|**Meaning**|
|---|---|
|-1|DPI Unaware|
|-2|DPI System Unaware|
|-3|DPI Per Monitor Aware|
|-4|DPI Per Monitor Aware Version 2|
|-5|DPI Unaware GDI Scaled|



-4 is equivalent to using the dpm command line switch. -1 is equivalent to not using the -dpm switch. For details on the other options, see the Microsoft documentation for SetThreadDpiAwarenessContext(). 

**Response** : 

A-Shell Reference 

Page 1669 

none 

## **Comments** 

Note that as with all TAB(-10,xxx) commands, the implementation is on the client side, so no update of the server side is needed. If the client doesn't recognize the command, it will just be ignored. 

## **History** 

- 2020 April, A Shell 6.5.1680:  Function added to A-Shell 

A-Shell Reference 

Page 1670 

## **AG_DRAGDROP** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_DRAGDROP); opcode, ctlid {,fidx}; chr(127);** Tab( 10,x) Syntax Notes 

AG_DRAGDROP (112) implements both destructive and non-destructive drag-drop modes. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _opcode_ 

|**Value**|**Description**|
|---|---|
|0|query drop buffer, set_status_parameter to the number of files in the drop target (_ctlid_)|
|1|retrieve_fspec_corresponding to_fidx_from the specified drop target (_ctlid_)|
|2|clear the contents of the drop target buffer|
|3|set non-destructive (previous "asynchronous") mode|



_ctlid_ 

_control ID of the target control_ 

## **Response** 

_status, fspec_ CR 

A-Shell Reference 

Page 1671 

_status_ values:  <=0 indicates failure, or no files available in opcode 0; >0 indicates success (number of files for _opcode_ 0 or the number of bytes in _fspec_ for _opcode_ 1) 

_fspec_ is the file specification in opcode 1 

See MX_DRAGDROPXS for additional details and parameters. 

A-Shell Reference 

Page 1672 

## **AG_EVENTWAIT** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_EVENTWAIT); parentid, ctlid, opcode; chr(127);** Tab( 10,x) Syntax Notes 

AG_EVENTWAIT (33) waits for an event, while allowing the focus to be moved around a set of buttons defined by the _parentid_ and _opcode_ parameters. The command is used internally by ATE for implementing the AUI_EVENTWAIT function, which should be used in applications rather than AG_EVENTWAIT directly. 

## **Response** 

A comma-delimited pair of numbers: _exitcode, ctlid_ CR 

This function has both a subroutine and a print tab implementation. 

## **See Also** 

- AUI_EVENTWAITXS 

A-Shell Reference 

Page 1673 

## **AG_EVTMSG** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_EVTMSG); opflags {,msg}; chr(127);** Tab( 10,x) Syntax Notes 

AG_EVTMSG (57) may be used to send a message to the System Messages window on the client / ATE workstation. 

## **Parameters** 

## _opcode_ 

one of the following: 

|**Value**|**Action**|
|---|---|
|1|open the System Messages window|
|2|msg; opens System Messages window if necessary|
|3|close the System Messages window|
|514|output msg, followed by "application paused - doubleclick to resume" and wait for doubleclick|



## _msg_ 

Message to output. Ignored for op 1 and 3. 

## **Response** 

none 

## **Comments** 

The AG_EVTMSG command underlies the implementation of the TRACE Statements. 

A-Shell Reference 

Page 1674 

## **AG_FILESTATS** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_FILESTATS); fspec {,versiz, hashsiz, flags}; chr(127);** Tab( 10,x) Syntax Notes 

AG_FILESTATS (31) allows you to retrieve info about a file. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _versiz, hashsiz_ 

these are numeric values representing the size of the strings you intend to retrieve them into. If 0 or not specified, then the corresponding field will not be returned. Set versiz=30 to get the #####.#####.#####.#####.##### format; see XS MX_FILESTATS . 

## _flags_ 

may contain one or more of the following: 

|**Value**|**Description**|
|---|---|
|&h0001|Check for fspec in ATE cache directories if not found otherwise|
|&h0002|Returned client native spec of located file|
|&h0004|Request return of last access time|



## **Response** 

The return string is of the format: _bytes, mtime, ctime, mode {,ver, hash, pcspec, atime}_ CR 

## **Example** 

```
.AGCMD AG_FILESTATS,"%ATE%\dsk0\007006\csv2xl.sbx",16,30,7
```

A-Shell Reference 

Page 1675 

Response is: `122656,1696396569,1455643406,33206,2.2.0.291,376-212-504-153,,1701566017` 

This example illustrates the AGCMD.LIT utility which allows you to send AG_xxx functions (by name, internally using the 

TAB(-10,...) syntax shown at the top of this topic) and see the response, without writing any code. The downside is that the response (in this case) is somewhat hard to read due to the large encoded values for the mtime, ctime, mode and atime fields, but it does make clear exactly what response the program will see. 

## **Comments** 

MX_FILESTATSXS is generally used in preference to AG_FILESTATS, because it is easier to use (standard subroutine return values), and works in all the same cases (including ATE), with the one exception that it requires A-Shell on the server. AG_FILESTATS could be used on any kind of server. 

The _pcspec_ is only returned in the case where the _fspec_ is not fully qualified and the _flags_ &h0002 bit is set causing the routine to locate the file in one of the cache directories. 

Note that all fields are comma delimited up to the last non-blank field. 

## **See Also** 

- MX_FILESTATSXS 

## **History** 

- 2023 August, A Shell 6.5.1740:  Add _atime_ parameter, last access time 

- 2011 June, A Shell 5.1.1222:  Add _flags_ parameter, reformat return string 

A-Shell Reference 

Page 1676 

## **AG_FILETIMES** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_FILETIMES); fspec, opcode {,loc'rem, mtime, ctime, atime}; chr(127);** Tab( 10,x) Syntax 

## Notes 

AG_FILETIMES (113) provides a way to set a file's last modification time ( _mtime_ ), creation time ( _ctime_ ), and/or last access time ( _atime_ ). Setting the mtime of a file is equivalent in the Unix world to using the touch command on the file. For convenience, the XS function can also retrieve the file times, overlapping functionality already provided by MX_FILESTATS . 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _fspec_ 

file spec (client perspective) to get or set times for 

## _opcode_ 

0 = get (MXOP_GET) or 1 = set (MXOP_sET) 

## _loc'rem_ 

C to check cache directories, else _fspec_ must be fully qualified 

## _mtime, ctime, atime_ 

modify, create, and access times to set (opcode 1), in seconds since the epoch. 

## **Response** 

_status, mtime, ctime, atime_ CR 

_status_ is 0 for success, else a Windows error code. Times are seconds since the epoch. 

## **Comments** 

A-Shell Reference 

Page 1677 

Note that access time isn't uniformly supported across Windows systems. 

## **See Also** 

- MX_FILETIMESXS 

- MX_FTFORMATXS to convert time values into human-readable form 

## **History** 

- 2023 August, A Shell 6.5.1740:  Function added to A-Shell 

A-Shell Reference 

Page 1678 

## **AG_FLASHWINDOW** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_FLASHWINDOW); flashop; chr(127);** Tab( 10,x) Syntax Notes 

AG_FLASHWINDOW (28) may be used to force the title bar of the A-Shell window or ATE client to start or stop flashing. This is often useful when the application wants the users attention, but the user has minimized the app and is not paying attention (and the speaker is off). Even when minimized, the flashing on the task bar is hard to ignore. 

## **Parameters** 

## _flashop_ 

A single digit 1 to start flashing, and 0 to stop. 

## **Response** 

none 

## **Examples** 

```
? TAB(-10,AG_FLASHWINDOW);"1";chr(127);    ! start flashing
```

```
? TAB(-10,AG_FLASHWINDOW);"0";chr(127);    ! stop flashing
```

## **Notes** 

Note that ATE supports both the ZTERM Escape Sequences and AG_FLASHWINDOW, but ZTERM does not support AG_FLASHWINDOW and A-Shell/Windows running locally does not support the ZTERM Escape Sequences. So if you support all three environments, you may want to use the AUI_ENVIRONMENT[XS] function to determine which environment you are in. 

## **See Also** 

- ZTERM Escape Sequences. 

A-Shell Reference 

Page 1679 

## **AG_FTP** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_FTP); dirflag; hostpath; "~"; localpath; {"~"; options;} chr(127);** Tab( 10,x) Syntax Notes 

AG_FTP (22) may be used on server installation of A-Shell to cause the ATE client to initiate a file transfer with the server. 

## **Parameters** 

## _dirflag_ 

A single character indicating the file transfer type and direction, from the following choices: 

|**Value **|**Direction**|**Type**|**Feedback**|
|---|---|---|---|
|0|Host to PC|Binary|message/dialog|
|1|PC to host|||
|2|Host to PC|ASCII||
|3|PC to host|||
|A|Host to PC|Binary|silent|
|B|PC to host|||
|C|Host to PC|ASCII||
|D|PC to host|||



Codes A though D are not ZTERM-compatible, so should only be used when you know the client is ATE. Note that with ATE, the message/dialog is hardly noticeable (unlike with ZTERM, where it looks just like the standard interactive FTP dialog), so the silent feature isn't that much of an improvement. Still, some people prefer to have their file transfers be invisible to the user. 

## _hostpath_ 

A-Shell Reference 

Page 1680 

Native specification for the file on the server. If sending to the server, this may specify just the directory, in which case the filename will be taken from the _localpath_ . 

## _localpath_ 

Native (PC) specification of the source file. When transferring to the PC, this may be just a directory, in which case the filename is taken from _hostpath_ . 

## _options_ 

Optional flags affecting the transfer protocol, expressed as a decimal value representing the sum of options taken from the table of FTPDLX opcodes. The most likely flag to be used here is XFTPF_VERSION2 (4096), to request use of the newer FTP2 implementation of the client side of the transfer. 

## **Response** 

A single byte will be placed in the keyboard buffer to indicate success (ASCII 13, aka RETURN) or failure (ASCII 3, aka ControlC). 

## **Examples** 

- `! transfer dsk0:test.dat[100,1] on server to dsk0:test.sav[100,999] on PC` 

- `? TAB(-10,AG_FTP);"0/vm/miame/dsk0/100001/test.dat";chr(126); &` 

- `"%MIAME%\dsk0\100999\test.sav";chr(127);` 

```
xcall ACCEPN,A
```

- `! transfer c:\xfer\test.new from PC to /import/test.dat on server using FTP2 client if avail.` 

- `? TAB(-10,AG_FTP);"1/import/test.dat";chr(126);"c:\xfer\test.new";chr(126);"4096";chr(127);` 

- `xcall ACCEPN,A` 

A-Shell Reference 

Page 1681 

- `! equivalent to above but using MX_AGWRAPPER` 

```
xcall MIAMEX, MX_AGWRAPPER, AG_FTP, "1/import/test.dat~c:\xfer\test.new~4096",response$
```

```
if asc(response$) = 3 then <error>  ! (^C response)
```

- `! transfer dsk0:*.*[1,2] on server to TEMP directory on PC` 

- `? TAB(-10,AG_FTP);"0/vm/miame/dsk0/001002/*";chr(126);"%TEMP%;chr(127);` 

```
xcall ACCEPN,A
```

- `? transfer all files from PC "ATELOCALDIR" directory to /vm/miame/dsk0/033033` 

- `? TAB(-10,AG_FTP);"1/vm/miame/dsk0/033033";chr(126); &` 

```
"%ATELOCALDIR%\*";chr(127);
```

```
xcall ACCEPN,A
```

## **Comments** 

AG_FTP invokes FTP2XS using either FTP or SFTP protocol, depending on the options on the File Transfer tab of the ATE Connection Properties dialog. Typically this will be set to use the same protocol and credentials as the ATE terminal connection. 

The file wildcard "*" may be used to transfer all the files in a particular directory; see the last two examples above. 

This command only works when the client is ATE. If you have a mixture of ZTERM and ATE clients, you would be better off using 

A-Shell Reference 

Page 1682 

the ZTERM Escape Sequences, which work for both ZTERM and ATE. In either case, you are limited to transferring files between the server where the application is running, and the client workstation, using the FTP login credentials stored in the ZTERM or ATE configuration. 

If you are running locally under A-Shell/Windows and want to transfer files to an arbitrary FTP server, then use FTP2[XS] , which allow you to specify the server IP address and login parameters. For debugging ideas, see FTP Debugging. 

Note that while your application (running on the server) requests the operation by sending the AG_FTP command, in the context of the FTP / SFTP protocols, it is actually the ATE workstation that acts as the file transfer client, and the A-Shell application server acts as the file transfer server. (We might call this server/client/server protocol.) Even though the file transfer service is running on the same server as the A-Shell session, it runs in a different process and may have a completely different security environment from A-Shell. It may even be "homed" or "sandboxed" to a directory other than the true root of the file system (this is particularly common for FTP servers) and thus it may not be possible to access files that are otherwise visible to A-Shell running on the same server. 

Within an SSH connection (i.e. using SFTP file transfer), AG_FTP automatically adds the file.ext from the localpath to the hostpath when transferring to the host and the hostpath does not include a filename and extension. While it is often the case with file transfers, as with file copy operations, that a destination consisting of just a directory will be automatically updated to use the source filename, that is not the case with SFTP, often leading to confusion as to why file transfers fail. This refinement hopefully smooths things over. 

## **Wildcards** 

You can separately wildcard the file name and extension, and you can include partial literals in both parts of the name. Examples: 

```
/vm/miame/dsk0/007006/*.dat
```

```
/vm/miame/dsk0/007006/ab*
```

A-Shell Reference 

Page 1683 

```
c:\vm\miame\dsk0\007006\xyz*.d*
```

Notes: 

- The only wildcard character is "*" (? is not supported) 

- PC filespecs are not case sensitive, but host filespecs are. 

## **Alternatives** 

To transfer files to or from a machine other than the A-Shell server or the ATE client, you should use FTP2XS directly, as it allows specification of an arbitrary remote server address and credentials. 

To transfer files between two arbitrary machines both running A-Shell, but without relying on any external file transfer services, you can implement your own file transfer protocol using TCPXXS. The sample program TCPXFR in EXLIB:[908,25] provides a working example of such a protocol, complete with interactive and command line server and client interfaces. 

It is also possible to transfer files in both directions between the A-Shell server and the ATE client over the terminal connection using the xcalls ATEAPXXS and ATEGFKXS. 

## **Debugging** 

Since both FTP and SFTP are standard protocols, one way to rule out whether the problem is in the client or the server would be to use another client (e.g. FileZilla) to try to connect to your server. If it can't connect, ATE won't be able to either. 

Depending on whether ATE is using FTPDLX[XS] or FTP2[XS] to implement the client side, there are different debugging options. In 

A-Shell Reference 

Page 1684 

the case of FTPDLX[XS] , there will always be a ftpdlx.log file in the [1,4] directory on the ATE workstation with details for the last transfer attempt. In addition, if you set the environment variable ASHFTPDEBUG=1 (on the ATE side, e.g. through the Windows applet or using AG_SETENV), then a detailed log file will be in %temp%\ftpdebug.log. 

See FTP Debugging for more details. In the case of FTP2, file transfer errors will cause a dialog box with extensive details to automatically appear. 

## **See Also** 

- FTP2XS 

- ATEAPX.SBX 

- ATEGFK.SBX 

- ZTXF.LIT 

## **History** 

- 2025 December, A Shell 7.0.1781:  Simulate support for the FTP ASCII conversion option (LF-CRLF) when the transfer protocol is actually SFTP. 

- 2024 January, A Shell 7.0.1754: AG_FTP now invokes FTP2 in all cases, regardless of the options. FTPDLX no longer supported. 

- 2023 November, A Shell 1751:  Within an SSH connection (i.e. using SFTP file transfer), AG_FTP now automatically adds the file.ext from the localpath to the hostpath when transferring to the host and the hostpath does not include a filename and extension. 

- 2014 December, A Shell 1399:  MX_AGWRAPPER enhanced to properly handle the ^C failure response from AG_FTP. Previously it 

A-Shell Reference 

Page 1685 

may have aborted the program; now it just shows up as a data character in the response buffer. 

- 2013 December, A Shell 1369, ASHNET 138:   Implement the FTP2 alternative client for file transfers; add the options parameter to AG_FTP. 

- 2009 December, A Shell 1131:  You can now request that the PC file name be set to match that assigned to the last file printed via the AUXLOC: channel, by specifying a PC filespec ending in "-#." + the extension. For example, 

```
TAB(-10,AG_FTP);"0/tmp/abcdef.dat~%abcdef-#.dat";chr(127);
```

This will send the file /tmp/abcdef.dat to the PC, where it will given the full spec ??????.dat, where ????? is the complete path of the last printfile captured by ATE (minus the extension). Note that the only part of the PC filespec which matters in this case was "-#.dat"; including the "abcdef-#.dat" only serves as a fallback if the version of ATE doesn't support the feature, or there was no prior printed filespec to refer to. 

This trick can be useful for sending metadata files which should be associated with print files, perhaps containing routing or archiving instructions. 

A-Shell Reference 

Page 1686 

## **AG_FTPSETPW** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_FTPSETPW); loginname; "~"; psword; chr(127);** Tab( 10,x) Syntax Notes 

AG_FTPSETPW (29) changes the FTP login information which is otherwise stored in the ATE configuration for the current connection. 

## **Parameters** 

_loginname_ 

FTP login name string 

_psword_ 

FTP login password string 

## **Response** 

none 

## **Example** 

```
? TAB(-10,AG_FTPSETPW);"kane";chr(126);"rosebud";chr(127);
```

## **Notes** 

Only applies to ATE (prior to using the FTP function) not ZTERM. For local A-Shell/Windows FTP, just use FTPDLX.SBX, which accepts explicit arguments for the login name and password. 

A-Shell Reference 

Page 1687 

## **AG_FOREGROUND** 

_Rewritten May 2025; see History_ 

## - **? tab(-10, AG_FOREGROUND); opcode; chr(127);** Tab( 10,x) Syntax Notes 

AG_FOREGROUND (78) allows the application to test whether the client (A-Shell Windows or ATE) is in the foreground (opcode 0), or to force it into the foreground (opcode 1). Note that this function was formerly named AG_ISFOREGROUND. 

## **Parameters** 

## _opcode_ 

optionally indicates the operation (if omitted, 0 is assumed): 

|**Value **|**Action**|
|---|---|
|0|returns response indicating if client is in the foreground or not|
|1|force client into foreground status (and display its window if minimized|



## **Response** 

(opcode 0):  "0" or "1" followed by a carriage return (for not in foreground, in foreground, respectively) 

(opcode 1):  no response 

## **History** 

2025 May, A-Shell 7.0.1772:  Add optional _opcode_ parameter so that it can be used to set the foreground as well as detect it. 

A-Shell Reference 

Page 1688 

## **AG_GETDPI** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_GETDPI); {ctlid;} chr(127);** Tab( 10,x) Syntax Notes 

AG_GETDPI (111) returns the DPI for the workstation, and optionally for the monitor associated with the specified _ctlid_ . See MX_GETDPI for details. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _ctlid_ 

optional numeric ID of a control associated with the monitor to get the DPI from 

## **Response** 

## _sysdpi, ctldpi_ <CR> 

_sysdpi_ is the DPI for the primary monitor; _ctldpi_ is the DPI for the monitor on which the control specified by _ctlid_ is located (or 0 if no ctlid specified.) 

## **See Also** 

- MX_GETDPIXS 

## **History** 

- 2020 October, A Shell 6.5.1692: Function added to A-Shell 

A-Shell Reference 

Page 1689 

## **AG_GETENV** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_GETENV); var {,demangle}; chr(127);** Tab( 10,x) Syntax Notes 

AG_GETENV (45) will return (in the keyboard buffer) the definition of the specified environment variable as defined to the ATE client (or A-Shell/Windows). 

This function has both a subroutine and a print tab implementation. 

In addition to real environment variables, this command also recognizes three pseudo-environment variables only understood by the A-Shell/Windows or ATE client: 

- ATEEXE: the full filespec of the client executable, e.g. "c:\ATE\bin\ashw32.exe" 

- ATEVER: the version string for the client executable, e.g. "7.0.1753.2" 

- ATELICMODE: a decimal value containing flags indicating how the client was licensed (see ATELICMODE for details) 

## **Parameters** 

## _var_ 

the name of an environment variable whose value you want to check 

## _demangle_ 

if set to "1", if the variable is in the ancient DOS 8.3 compressed format, demangle it to the full long format, if possible. 

## **Response** 

The value of the specified environment variable, or "" if not defined. 

## **Examples:** 

```
map1 envval$,s,0
```

- `? tab(-10, AG_GETENV); "TEMP"; chr(127);` 

A-Shell Reference 

Page 1690 

```
input "",envval$
```

In some very old versions of Windows, the response might look something like this: 

```
C:\DOCUME~1\yourname\LOCALS~1\Temp
```

To demangle it, add the ",1" ... 

```
? tab(-10, AG_GETENV); "TEMP,1"; chr(127);
input "",envval$
```

... to get a response more like: 

- `C:\DOCUMENTS AND SETTINGS\yourname\LOCAL SETTINGS\Temp>` 

## **See Also** 

- MX_GETENVXS for retrieving an environment variable from the application server—as opposed to client—machine. 

- GETENV.LIT 

A-Shell Reference 

Page 1691 

## **AG_GETLOCALE** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_GETLOCALE); chr(127);** Tab( 10,x) Syntax Notes 

AG_GETLOCALE (115) retrieves the name of the user's locale on the client workstation. 

## **Parameters** 

_locale_ 

the name of the locale on the client, e.g. "en-US," the Windows indication for English language with USA regional settings. 

## **Response** 

_locale_ CR 

## **Comments** 

There is not currently an equivalent MX_ version to get the server locale, but for ATSD connections, you can use the utility function Fn'GetUserDefaultLocaleName$() in the SOSFUNC:fnwin32utl.bsi module to get the same information. For Linux, the following command will work: 

```
xcall HOSTEX, "locale | grep LANG=", status, locale$
```

## **History** 

- 2023 September, A Shell 6.5.1742:  Function added to A-Shell. 

A-Shell Reference 

Page 1692 

## **AG_GETOFD** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_GETOFD); path, filter, title, flags, defExt, type; chr(127);** Tab( 10,x) Syntax Notes 

AG_GETOFD (47) displays a standard Windows open or save file dialog, such as the one shown below (from Windows 10). This operation can only take place on a GUI-enabled client, either ATE or A-Shell/Windows. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

The parameter formats and values are the same as in MX_GETOFDXS, which is the preferred way of accessing the function. 

## **Response** 

## _paths, flags, filename_ CR 

_paths_ may contain one more complete filespecs, separated by chr(10) characters. _filename_ is just the name and extension. See MX_GETOFDXS for details on the flags. 

## **Example** 

## **See Also** 

- MX_GETOFDXS 

- AshExplorer 

## **History** 

- 2013 July, A Shell 6.1.1355: Filenames containing commas are now quoted; previously they were not, which almost certainly led to incorrect parsing of the response. 

A-Shell Reference 

Page 1693 

## **AG_GETSHELLPATH** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_GETSHELLPATH); csidl; chr(127);** Tab( 10,x) Syntax Notes 

AG_GETSHELLPATH (71) retrieves the physical directory path corresponding to a logical Windows directory identified by its CSIDL identifier. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_csidl_ 

One of the defined CSIDL_xxx identifiers 

## **Response** 

Folder path corresponding to the _csidl_ identifier, followed by carriage return: 

folder <CR> 

## **Example** 

```
++include ashinc:csidl.def   ! include CSIDL_xxx definitions
```

```
? tab(-10, AG_GETSHELLPATH); CSIDL_APPDATA; chr(127);    ! (26)
input "", folder$
```

- `? folder$                    ! C:\Users\jack\AppData\Roaming` 

A-Shell Reference 

Page 1694 

## **See Also** 

- MX_GETSHELLPATHXS 

A-Shell Reference 

Page 1695 

## **AG_HOLDKBD** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_HOLDKBD); opcode; chr(127);** Tab( 10,x) Syntax Notes 

AG_HOLDKBD (36) puts the ATE client into "keyboard hold" (aka "local keyboard") mode. For example: 

```
tab(-10, AG_HOLDKBD); "2"; chr(127);
```

## **Parameters** 

## _opcode_ 

2 or 4 

## **Response** 

None 

## **Opcode 2** 

_opcode_ 2 locks ATE into the local/hold mode, where it will stay until explicitly released. 

Once locked into this mode, no keyboard characters will be transmitted to the server except indirectly via ATE command/response packets. Normally, the server and ATE determine between themselves when ATE should act like a dumb terminal (transmitting all keyboard characters) and when it should act like a client GUI workstation (sending keyboard input to local edit controls only), based on contextual clues. 

The lock feature is mainly intended for AMOS and other non-A-Shell servers which cannot detect or communicate such clues. Locking the ATE client into local keyboard mode eliminates problems with type ahead being sent inappropriately to the server, or worse, interrupting/confusing commands sent between the server and client via the keyboard channel. 

To remove the lock, use: 

```
? tab(-10,AG_RELEASEKBD);"2";chr(127);
```

Or, you can also clear it via the Settings menu to clear the Local Kbd Mode checkmark. 

A-Shell Reference 

Page 1696 

Note that once set, the local lock remains set until cleared by one of the above methods, even at the dot prompt. So while the feature may be thus turned on globally in a startup command file, you must be sure to turn it off before exiting to the dot or before performing any non-GUI input operations, including subroutines GET, TINKEY, ACCEPT, the INPUT statement, etc. 

## **Opcode 4** 

_opcode_ 4 activates a timer in ATE that after 15 seconds of no activity from host (when not otherwise waiting on user actions, such as within INFLD, XTREE, XTEXT, EVENTWAIT, etc.), a message box is displayed warning the user that communication with host appears to be broken, and giving the option to continue waiting or send a cancel (^C). 

This can help mitigate a situation where the host application has crashed, leaving ATE in a state which appears to the user to be hung but actually isn't. To activate/deactivate the feature: 

```
? tab(-10,AG_HOLDKBD);"4";chr(127);         ! activate
```

```
? tab(-10,AG_RELEASEKBD);"4";chr(127);      ! deactivate
```

Timeout monitor is only active when the ATE workstation is in "hold-kbd mode"—i.e. when the AG_HOLDKBD "2" option has been activated or when currently processing an ATE command from the host. 

There are situations where it may be normal for ATE to be left waiting for something from the host for longer than 15 seconds. For example, if the host uses XCALL HOSTEX to launch a child task, it could be left waiting indefinitely for a response, leaving ATE in a waiting state. It is the responsibility of the host application to identify such situations and disable the appropriate AG_HOLDKBD mode(s). 

When _opcode_ 4 is set, ATE will display a "waiting for <host address>..." message on the session status line (if visible), when appropriate. Even if not visible, the cursor will be change to the wait cursor while in this state. The idea is to give the user some indication of what is going on when output is delayed due be network, application, or server problems, and is somewhat analogous to the similar message displayed by most browsers when waiting on a server response. 

The display is updated every one second by adding a dot, and after fifteen seconds, a modeless dialog appears that says: 

```
Server/network not responding. Click CANCEL to send abort request. Or just wait to see if it recovers.
[Cancel]
```

Clicking CANCEL sends a CTRL+C to the host, which may or may not be useful, depending on the situation and how the application responds to CTRL+C. 

A-Shell Reference 

Page 1697 

As soon as any characters arrive from the server, the dialog is removed and the cursor is restored the normal arrow or I-beam. 

## **History** 

- 2015 January, A Shell 6.1.1399:  Add opcode 4. 

- 2013 October, A Shell 6.1.1364: When the keyboard is locked into local mode with argument "2", ^C no longer clears the local hold. It is simply queued up as would be the case for other keyboard characters, either to be consumed by a local input operation or eventually forwarded to the host when the hold is removed. 

- 2013 May, A Shell 6.1.1352: Add option "2" to lock ATE into local keyboard mode. 

A-Shell Reference 

Page 1698 

## **AG_IATIMEOUT** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_IATIMEOUT); opcode, timesecs; chr(127);** Tab( 10,x) Syntax Notes 

AG_IATIMEOUT (79) retrieves or sets the inactivity timeout period. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_opcode_ should be 1 (MXOP_SET) to set the timeout, and 1 (MXOP_gET) to retrieve it (in seconds). Since the default opcode is 0 (MXOP_get) and the _timesecs_ argument is ignored in the case of the retrieve operation, both arguments can be eliminated when retrieving the timeout. 

## **Response** 

For opcode 0, the current inactivity timeout value in seconds: 

## _timesecs_ <CR> 

Note that this differs from the IATIMEOUT parameter in the system ini file, which uses units of minutes. 

## **Examples** 

Retrieve: 

```
? tab(-10,AG_IATIMEOUT);chr(127);
```

```
input "",timeout'seconds
```

Set: 

- `? tab(-10,AG_TIMEOUT);"1,";timeout'seconds;chr(127);` 

A-Shell Reference 

Page 1699 

## **Comments** 

Note that in the case of ATE, if the server-side timeout expires, the job will receive error 254, whereas if the client-side timeout expires, the job will experience this as a hang-up (error 250). See Job Terminations for more details on how hang-ups are handled. 

## **See Also** 

- MX_IATIMEOUTXS 

- IATIMEOUTSP 

## **History** 

- 2011 June, A Shell 5.1.1221:  Command added to A-Shell 

A-Shell Reference 

Page 1700 

## **AG_IMAGE** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_IMAGE); opcode, <parameters>; chr(127);** Tab( 10,x) Syntax Notes 

**Note** : as with most other AG_xxx functions, the subroutine front-end is preferable if available. In this case, that would be AUI_IMAGE, which see for definitions of the parameters—including _status_ —referenced below. 

## AG_IMAGE (35) provides access to A-Shell's image processing functions. Use the following syntax: 

```
tab(-10,AG_IMAGE); IMGOP_LOAD, handle, fspec; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_CLOSE, handle; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_DISPLAY, handle, srow, scol, erow, ecol, flags; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_LOADDISP, handle, srow, scol, erow, ecol, flags, fspec; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_INFO, handle, fspec; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_HIDE, handle; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_ACQUIRE, handle, fspec, compfactor, appname, pages, scanflags; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_SELECTSRC, handle, srcname; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_TWERR, handle; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_CAPTURE, handle, fspec, compfactor, winid; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_SAVEAS, handle, fspec, compfactor; chr(127);
```

```
tab(-10,AG_IMAGE); IMGOP_PAGEINFO, handle, fspec; chr(127);
```

## **Response** 

For IMGOP_INFO: 

A-Shell Reference 

Page 1701 

_status, handle, owidth, olength, dwidth, dlength, bpp_ CR 

For IMGOP_ACQUIRE: 

_stspages_ <CR>  (a composite two byte value, with the status in the lower byte and the number of pages scanned in the upper byte). 

For IMGOP_PAGEINFO: 

_pages_ <CR>  (number of pages in the specified file) 

For all other opcodes: 

_status, handle_ CR 

## **Example** 

```
map1 status, i, 4
```

```
map1 handle, i, 4
map1 imgspec$,s,160
```

```
writecd tab(-10,AG_IMGOP_LOAD); handle, imgspec$; chr(127);
```

```
input "", status ,handle
```

## **See Also** 

- AUI_IMAGEXS 

A-Shell Reference 

Page 1702 

## **AG_LANGUAGE** 

_Added September 2025_ 

## **tab(-10, AG_LANGUAGE); lang$; chr(127);** 

AG_LANGUAGE (116) queries or sets the ATE / Windows client LDF LANGUAGE setting. It is equivalent to the existing 

MX_LANGUAGE function but applies to the ATE or Windows client rather than the machine on which the application is running. 

If the _lang$_ parameter is empty, it will send back the current language name in the keyboard buffer. Otherwise it will change the current language to the specified value$ and return nothing in the keyboard buffer. 

## **Example** 

```
? TAB(-10, AG_LANGUAGE); chr(127);        ! query
input "", LANG$                           ! return name of current language
```

```
? TAB(-10, AG_LANGUAGE); LANG$; chr(127);
```

```
! set (no response to this operation)
```

The LANG$ parameter may be just the name (e.g. ENGLSH or SPANSH), in which case it will look in the usual places for the LDF file of that name. Or you may specify a complete filespec (relative to the client). 

The only way to determine if the set operation worked is to follow it with a query. 

A-Shell Reference 

Page 1703 

## **AG_MENU** 

_Reviewed and revised December 2023_ 

**tab(-10, AG_MENU) opcode, menuid, mnutxt, mstate, mtype, cmd, func, mstatus {,dlgid}; chr(127);** - Tab( 10,x) Syntax Notes 

## **tab(-10, AG_MENU) opcode, mdfspec, mstate, mstatus {,dlgid}; chr(127);** 

This function has both a subroutine and a print tab implementation. 

AG_MENU (21) is the equivalent of the AUI_MENUXS calls. It is used internally for forwarding those functions from A-Shell/Unix to ATE, although it also can be used directly with an application to add or delete menu items. It also may be used to invoke built-in menu commands, using this format: 

## **tab(-10, AG_MENU); id; chr(127);** 

Where _id_ is the value corresponding to the menu command, from the following list: 

|**Symbol**|**Value **|**Description**|
|---|---|---|
|IDM_ABOUT|101|Help..About|
|IDM_LOAD|107|File..Load Settings|
|IDM_SAVE|108|File..Save Settings|
|IDM_SAVEAS|109|File..Save Settings As|
|IDM_DEFAULTS|112|File..Default Settings|



A-Shell Reference 

Page 1704 

|**Symbol**|**Value **|**Description**|
|---|---|---|
|IDM_PRINTS|110|File..Print Screen|
|IDM_EXIT|111|File..Exit|
|IDM_AUTOMOUSE|124|Edit..AutoMouse|
|IDM_COPY|115|Edit..Copy|
|IDM_PASTE|116|Edit..Paste|
|IDM_SCHEDULE|106|Settings..Scheduling|
|IDM_BEVELING|122|Settings..Beveling|
|IDM_COLORS|113|Settings..Colors|
|IDM_FONTSYS|123|Settings..Font..System|
|IDM_FONTGUI|132|Settings..Font..GUI|
|IDM_FONTGRID|144|Settings..Font..Grid|



A-Shell Reference 

Page 1705 

|**Symbol**|**Value **|**Description**|
|---|---|---|
|IDM_MISC|130|Settings..Misc Settings|
|IDM_DLGSIZING|134|Settings..Dialog Sizing|
|IDM_PVPREF|142|Settings..Preview Preferences|
|IDM_KBDLOCK|117|Settings..Keyboard Lock|
|IDM_RESET|131|Settings..Reset|
|IDM_SCROLLBACK|160|Settings..Scrollback|



**Response** 

none 

A-Shell Reference 

Page 1706 

## **AG_MESSAGEBEEP** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_MESSAGEBEEP); soundcode; chr(127);** Tab( 10,x) Syntax Notes 

AG_MESSAGEBEEP (3) sends a request to Windows to play the sound (wave form file) corresponding to the specified _soundcode_ . If _soundcode_ is not specified, the default sound—a simple beep—is generated. Note that you can change the wave forms associated with the various sounds in the Control Panel. 

If specified, _soundcode_ must be a single ASCII byte whose value is 32 + plus the value of one of the symbols in the table below, which are also used for specifying the icons in the standard Windows message box; see AG_MESSAGEBOXSTD and MSGBOXXS. If soundcode is not specified, the default simple beep sound will be requested. 

|**Symbol**|**Value**|**Description***|
|---|---|---|
|MBICON_STOP|&h0010|Windows Critical Stop|
|MBICON_QUESTION|&h0020|Windows Question|
|MBICON_EXCLAMATION|&h0030|Windows Exclamation|
|MBICON_ICON|&h0040|Windows Asterisk|



Note that the sounds mentioned in the Description column of the table are all standard Windows sounds. See the _Sounds_ applet in Windows Control Panel for more information. 

## **Response** 

A-Shell Reference 

Page 1707 

none 

## **Examples** 

- `? tab(-10,AG_MESSAGEBEEP); chr(127);                       ! default simple beep` 

- `? tab(-10,AG_MESSAGEBEEP); chr(32+MBICON_STOP); chr(127);  ! critical stop` 

## **See Also** 

- Play Sound File 

A-Shell Reference 

Page 1708 

## **AG_MESSAGEBOXOK** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_MESSAGEBOXOK); btnflag; msg, "~"; title; chr(127);** Tab( 10,x) Syntax Notes 

AG_MESSAGEBOXOK (4) displays a message in a dialog box that is positioned along the bottom couple of lines of the window, as shown below. This may be considered a GUI approximation of the standard MESAG subroutine. 

## **Parameters** 

## _btnflag_ 

A single character which must be a space (ASCII 32) to display just an OK button in the dialog, or an exclamation point (ASCII 33) to display both OK and CANCEL buttons 

## _msg_ 

A text string containing the message to display in the body of the dialog. 

## _tilde_ 

A single, literal tilde character (  ~  ). 

## _title_ 

A text string to be displayed on the title bar of the dialog. 

## **Response** 

A single byte indicating which button was pushed:  ESCAPE (ASCII 27) for the Cancel button, RETURN (ASCII 13) for the OK button. 

## **Example** 

```
map1 btnflag,s,1
```

A-Shell Reference 

Page 1709 

```
map1 msg,s,80
```

```
map1 title,s,80
```

```
map1 x,b,1
```

```
btnflag = "!"   ! OK and Cancel buttons
```

```
msg = "Please make sure checks are aligned before printing."
```

```
title = "Printer Check"
```

```
? TAB(-10,AG_MESSAGEBOXOK); btnflag; msg; "~"; title; chr(127);
```

```
xcall ACCEPN, x
```

```
if x = 27 ? "Cancel"
```

```
if x = 13 ? "OK" ? TAB(-10,AG_MESSAGEBOXOK);"!Make sure you have a backup before posting!"; ~Read
This!";chr(127);
```

## **Notes** 

MSGBOX a similar but more flexible and powerful implementation in subroutine form. The main advantage of AG_MESSAGEBOXOK is that it could be issued from an arbitrary server (not running A-Shell), provided the client was ATE. 

## **See Also** 

- MSGBOXXS 

- EVTMSG.SBX and XTRMSG.SBX in SOSLIB:[907,20] 

A-Shell Reference 

Page 1710 

## **AG_MESSAGEBOXSTD** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_MESSAGEBOXSTD); flag1; flag2; msg; "~"; title; chr(127);** Tab( 10,x) Syntax Notes 

AG_MESSAGEBOXSTD (17) displays a standard Windows message box dialog, which consists of a title bar, text message (up to 1024 characters) and a set of buttons as in the following example. Note how different versions of Windows produce different versions of the dialog, with no changes to the A-Shell code. 

Note that MSGBOXXS provides a more convenient interface to this function, and offers the additional bonus of detecting if the environment doesn’t support GUI functions, implementing the message box in text mode via INMEMOXS if necessary. 

## **Parameters** 

## _flag1_ 

A single character whose ASCII value is 32 plus the sum of a single choice from each of the following two tables (a button choice and an icon choice): 

|**Value**|**Button Option**|
|---|---|
|0|OK button|
|1|OK and CANCEL buttons|
|2|ABORT / RETRY / IGNORE buttons|
|3|YES / NO / CANCEL buttons|
|4|YES /NO buttons|
|5|RETRY / CANCEL buttons|



A-Shell Reference 

Page 1711 

|**Value**|**Icon Option**|
|---|---|
|16|ICON: "X" (stop)|
|32|ICON: "?" (question)|
|48|ICON: "!" (exclamation)|
|64|ICON: "i" (information)|



For example, the sample message dialog above would have set the _flag1_ parameter to chr(32+2+48) 

## _flag2_ 

A single character whose ASCII value is 32 plus the sum of zero or more options from the following table: 

|**Value**|**Description**|
|---|---|
|1|Default is button #2|
|2|Default is button #3|
|4|Dialog is task modal|
|8|Dialog is system modal|
|64|Add a help button|



## _msg_ 

A text string containing the message to display in the body of the dialog. 

## _tilde_ 

A single, literal tilde character (  ~  ). 

_title_ 

A-Shell Reference 

Page 1712 

A text string to be displayed on the title bar of the dialog. 

## **Response** 

A single byte indicating how the dialog was exited, according to the following table: 

|**Return**<br>**Char**|**Descriptio**<br>**n**|
|---|---|
|33|OK|
|34|Cancel|
|35|Abort|
|36|Retry|
|37|Ignore|
|38|Yes|
|39|No|
|40|A|
|41|Help|



## **Example** 

```
! simple test of AG_MSGBOXSTD (from doc)
```

```
++include ashinc:ashell.def
```

```
MAP1 A,F
```

- `? TAB(-10,AG_MESSAGEBOXSTD);chr(32+2+48);chr(32+1+4); &` 

A-Shell Reference 

Page 1713 

```
    "Best man tried on the bride's ring.";chr(13); &
```

```
    "Now he can't get it off.~Wedding ceremony crisis.";chr(127);
```

```
xcall ACCEPT,A    ! receive response (see notes below)
```

```
END
```

## **Comments** 

Unlike the OK/Cancel Message Dialog (-10,4),which appears as a short but wide dialog along the bottom of the window, this one is more rectangular and appears in the middle of the screen. Also, unlike the OK/Cancel dialog which is really only suitable for single-line messages, this one can handle up to 1024 characters. You can break the lines explicitly, as in the example above, with a chr(13), or you can rely on the routine itself to break the lines as it sees fit. 

## **See Also** 

- AG_MESSAGEBOX 

- MSGBOXXS 

- EVTMSG.SBX and XTRMSG.SBX in the SOSLIB:[907,20] 

A-Shell Reference 

Page 1714 

## **AG_MINTITLE** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_MINTITLE); mintitle; chr(127);** Tab( 10,x) Syntax Notes 

AG_MINTITLE (1) changes the title that is displayed on the task bar when the application is minimized. Also see ZTERM Escape Sequences. 

## **Parameters** 

_mintitle_ 

Title string. 

## **Response** 

none 

## **Example** 

```
TAB(-10,AG_MINTITLE);"Killer App";chr(127);
```

A-Shell Reference 

Page 1715 

## **AG_MKDIR** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_MKDIR); dirspec {, rtnsts}; chr(127);** Tab( 10,x) Syntax Notes 

AG_MKDIR (32) creates a Windows directory relative to the client workstation. 

This function has both a subroutine and a print tab implementation. 

## **Response** 

None, unless the _rtnsts_ parameter is passed and set to "1", in which case the response will be "0" for success, else the Window system error code. 

## **See Also** 

- MX_MKPATHXS, which is the preferred way to access this function. 

A-Shell Reference 

Page 1716 

## **AG_MOUSE** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_MOUSE); opcode {,flags}; chr(127);** Tab( 10,x) Syntax Notes 

AG_MOUSE (100) sets or restores the AutoMouse setting. 

## **Parameters** 

## _opcode_ 

choices are 7 to set flags or 8 to restore flags. 

## _flags_ 

values from the following table may be combined 

|**Value**|**Action**|
|---|---|
|&h0001|Automouse disabled (default is enabled)|
|&h0002|Double click sends string only (no CR)|
|&h0008|Single click sends string only (no CR)|
|&h0010|Singleclick sends string+CR|
|&h0020|No single click auto col adjustment|
|&h0040|No single click auto row adjustment|
|&h0080|Doubleclick sends CR only|
|&h0100|tab(-1,158) cursor reporting|
|&h0200|Doubleclick sends ESC only|
|&h0400|Doubleclick sends string+CR|
|&h0800|Don't consider slash a token delimiter|



A-Shell Reference 

Page 1717 

## **Response** 

None 

A-Shell Reference 

Page 1718 

## **AG_OPTIONS** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_OPTIONS); opcode {, options1, options2}; chr(127);** Tab( 10,x) Syntax Notes 

AG_OPTIONS (69) allows you to set or retrieve A-Shell system configuration OPTIONS to/from the ATE client. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _opcode_ 

One value from the following table: 

|**Value **|**Description**|
|---|---|
|0|Get current options. These are returned in the keyboard buffer in the format options1,options2. For example:<br>`? tab(-10,AG_OPTIONS);"0";chr(127);`<br>`input "",OPT1,OPT2`|
|1|Set values (using passed options1, and if specified, options2)|
|2|Set only the option2 value|
|4|OR (set) individual bits from options1 and options2. This allows you to set one or more bits without having to first retrieve the<br>current settings (in order to avoid changing existing flags). Note that you can specify options1 or option2 = 0 to avoid changing it.|
|8|Clear individual bits. In this case, any bit that you specify in options1 or options2 will be cleared from the current settings. Again,<br>you can specify 0 to avoid changing one set of flags or the other.|



_options1, options2_ 

A-Shell Reference 

Page 1719 

Option flags (combined into 32-bit values) to set if opcode > 0. See table in MX_GETOPTIONSXS, MX_SETOPTIONSXS for options bit definitions. 

## **Response** 

For _opcode_ > 0, none. Else: 

## _options1, options2_ CR 

where each value represents the combination of the individual bits currently set in each of the options fields. Variables must accommodate at least 32 bits. 

## **Comments** 

The symbols in the examples (e.g. GOP_EXTFIO) are defined in ashell.def; note that it is the symbol value (e.g. the value of symbol GOP_SBX_RUNDIR is &h2000 or 8192), not its name, that needs to be transmitted. If you fail to include the ashell.def file and compile without the /M option, your symbols will evaluate to 0 and won't work as intended. 

## **Examples** 

|**Valu**<br>**e**|**Example**|
|---|---|
|1|`? tab(-10,AG_OPTIONS);"1,"; options1; chr(127);                ! set options1`<br>`? tab(-10,AG_OPTIONS);"1,"; options1; ","; options2; chr(127); ! set options1,options2`|
|2|`? tab(-10,AG_OPTIONS);"2,"; options2; chr(127);                ! set options2`|
|4|`? tab(-10,AG_OPTIONS);"4,"; GOP_EXTFIO; chr(127);              ! set GOP_EXTFIO flag in options1`<br>`? tab(-10,AG_OPTIONS);"4,0,"; GOP2_GUISPCINDENT; chr(127);     ! set GOP2_GUISPCINDENT flag in`|



A-Shell Reference 

Page 1720 

|**Valu**<br>**e**|**Example**|
|---|---|
||`options2`|
|8|`? tab(-10,AG_OPTIONS);"8,"; GOP_EXTFIO; chr(127);              ! clear GOP_EXTFIO flag in options1`<br>`? tab(-10,AG_OPTIONS);"8,0"; GOP2_SBX_RUNDIR; chr(127);        ! clear GOP2_SBX_RUNDIR flag in`<br>`options2`|



## **See Also** 

- MX_GETOPTIONSXS, MX_SETOPTIONSXS 

- OPTIONSSP 

A-Shell Reference 

Page 1721 

## **AG_OSVER** 

_Rewritten December 2023_ 

## - **tab(-10, AG_OSVER); chr(127);** Tab( 10,x) Syntax Notes 

AG_OSVER (66) retrieves information about the current Windows or ATE client operating system, including its name, version, and release, plus the platform for which this copy of A-Shell was compiled. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

None 

## **Response** 

_osname, osver, osrel, asplatform_ CR 

## **Example** 

```
map1 osname, s,16
```

```
map1 osver,s,20
map1 osrel,s,20
```

```
map1 asplatform,s,20
```

```
? tab(-10,AG_OSVER); chr(127);
```

```
input "", osname, osver, osrel, asplatform
```

```
? os'name        ! "Win10/64"
```

```
? os'ver         ! ""
```

A-Shell Reference 

Page 1722 

```
? os'rel         ! 22621
```

- `? as'platform    ! Windows/32` 

## **See Also** 

- MX_OSVERXS for more infomation 

A-Shell Reference 

Page 1723 

## **AG_PLAYSOUND** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_PLAYSOUND); fspec, flags {,status}; chr(127);** Tab( 10,x) Syntax Notes 

AG_PLAYSOUND (105) forces the ATE client to play a sound file. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

XS _fspec_ and _flags_ are the same as for the MX_PLAYSOUND . _status_ may be set to non-zero if you want to get the return status in the keyboard buffer. Otherwise (if 0 or omitted), there is no response. 

Note that _fspec_ must be a PC native filespec, and that AG_PLAYSOUND supports the standard image file search path and %env% variables. 

## **Response** 

None, unless _status_ is "1", in which case the response will be the string representation of one of the following values followed by <CR>: 

|**Value**|**Description***|
|---|---|
|1|Success|
|0|file (fspec) not found|
|-98|Unable to loadwinmm.dll|
|-99|DLL loaded but unable to link to PlaySound function|



A-Shell Reference 

Page 1724 

**Value Description*** 

## **See Also** 

- Play Windows Sound 

- MX_PLAYSOUNDXS 

## **History** 

- 2013 November, A Shell 6.1.1367:  Command added to A-Shell 

A-Shell Reference 

Page 1725 

## **AG_RELEASEKBD** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_RELEASEKBD); {opcode}; chr(127);** Tab( 10,x) Syntax Notes 

AG_RELEASEKBD (49) releases the ATE "keyboard hold" so that it can be used as a dumb terminal again—i.e. so that keyboard characters are transmitted immediately to the server. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_opcode_ 

may be omitted, or 2 or 4; see AG_HOLDKBD 

## **Response** 

None 

The opcode parameter is optional and is normally omitted, in which case the keyboard hold is released, provided it hasn't been locked (via AG_HOLDKBD opcode 2). This command is normally used only internally by A-Shell, as part of the ATE command 

protocol, although it may be used in situations where the ATE command protocol would normally leave the keyboard in local hold mode but you need to temporarily revert to dumb terminal mode. 

In order to remove the locked hold, you must specify _opcode_ "2", e.g. `? tab(-10,AG_RELEASEKBD);"2";chr(127);` 

See the discussion under Set ATE Keyboard Hold for information on _opcode_ 4. 

## **See Also** 

- MX_RELEASEKBDXS 

## **History** 

A-Shell Reference 

Page 1726 

- 2015 January, A Shell 6.1.1399:  Add opcode 4. 

A-Shell Reference 

Page 1727 

## **AG_RESETWINDOW** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_RESETWINDOW); chr(127);** Tab( 10,x) Syntax Notes 

AG_RESETWINDOW (16) resets the window to the colors, size, font, and other parameters according to the current settings file. 

– See the o command line switch for details on specifying a settings file. 

## **Response** 

none 

## **See Also** 

- AUI_WINDOWXS 

A-Shell Reference 

Page 1728 

## **AG_SAVERES** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SAVERES); cmd, id; chr(127);** Tab( 10,x) Syntax Notes 

AG_SAVERES (40) provides a way to save and restore copies of the screen using an ID number rather than a stack like Tab(-1,202) and Tab(-1,203). 

## **Parameters** 

## _cmd_ 

Character code indicating the action to perform: 

|**Value **|**Description**|
|---|---|
|S|Save screen|
|R|Restore screen|
|P|Pop (discard) previously saved screen|



## _id_ 

A numeric digit, 0 thru 9. 0 on the restore or pop commands refers to the last saved screen (whatever id it has). 

## **Response** 

none 

## **Examples** 

```
? TAB(-10,AG_SAVERES);"S,1";chr(127);     ! save screen with ID 1
```

```
? TAB(-10,AG_SAVERES);"S,5";chr(127);     ! save screen with ID 5
```

```
? TAB(-10,AG_SAVERES);"R,1";chr(127);     ! restore screen saved as ID 1
```

A-Shell Reference 

Page 1729 

```
? TAB(-10,AG_SAVERES);"R,0";chr(127);     ! same as TAB(-1,203)
```

```
                                  ! (i.e. restore last saved screen)
```

```
? TAB(-10,AG_SAVERES);"P,3";chr(127);     ! pop/discard screen saved as ID 3
```

```
? TAB(-10,AG_SAVERES);"P,0";chr(127);     ! pop/discard last saved screen
```

## **Comments** 

This capability was implemented via a Tab(-10,x) sequence rather than by extending the existing Tab(-1,202) or Tab(-1,203) commands, because those commands do not have terminators and thus we cannot just add optional arguments. Because Tab(-10,x) commands must be terminated with chr(127), they support variable length arg lists. 

AG_SAVERES sequences are only supported under A-Shell/Windows and under Unix when the client is ATE. 

AG_SAVERES does save and restore GUI controls. However, it is advisable that you clear the screen with Tab(-1,0) before restoring a saved screen which contains GUI controls; otherwise the restore controls will be added to any controls already existing on the screen. 

Unlike Tab(-1,202) and Tab(-1,203), which operate on the machine where the software is running, Tab(-10,x) sequences operate on the workstation. Thus, under Unix, the save/restore operation takes place entirely on the workstation. This reduces both network traffic, memory, and CPU usage on the server, but it should be noted that the server's copy of the screen map will not be updated. This could interfere with server-based screen pictures, and also with the operation of TCRT calls 202/203 after AG_SAVERES, since those TCRT calls interact with the server's screen map. (The problem is temporary though, since the server's screen map gets re-synchronized whenever you clear and repaint the screen with regular, server-based PRINT statements.) 

A-Shell Reference 

Page 1730 

## **AG_SBRFLAGS** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SBRFLAGS); opcode {,flags1,flags2}; chr(127);** Tab( 10,x) Syntax Notes 

AG_SBRFLAGS (102) allows dynamic retrieval and updating of SBR= flags from the client workstation (e.g. ATE). 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _opcode_ 

indicates the operation: 

|**Value **|**Action**|
|---|---|
|0|retrieve current flags. opcode may be omitted entirely in this case.|
|1|replace existing flags with new flags1 and flags2|
|2|ignore flags1; replace flags2 with new values|
|+4|Set the specified bits of flags1 and flags2|
|+8|Clear the specified bits of flags1 and flags2|



## _flags1, flags2_ 

made up of bits as defined in SOSLIB:ashell.def in the SBRF_xxx and SBRF2_xxx symbols. 

## **Response** 

For _opcode_ greater than 0, none. For _opcode_ 0, current flags values: 

_flags1, flags2_ <CR> Variables must accommodate at least 32 bits. 

A-Shell Reference 

Page 1731 

## **See Also** 

- MX_SBRFLGXS for additional information 

## **History** 

- 2012 December, A Shell 6.1.1328:  Command added to A-Shell 

A-Shell Reference 

Page 1732 

## **AG_SCROLLBACK** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SCROLLBACK); opcode; chr(127);** Tab( 10,x) Syntax Notes 

AG_SCROLLBACK (109) hides, shows, or toggles the visibility of the vertical scrollback bar. 

## **Parameters** 

## _opcode_ 

|**Value**|**Description***|
|---|---|
|0 or omitted|disable/hide the vertical scroll bar|
|1|enable/show it|
|-1|toggle its visibility|



**Response** : 

none 

A-Shell Reference 

Page 1733 

## **AG_SENDKBD** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SENDKBD); text; chr(127);** Tab( 10,x) Syntax Notes 

AG_SENDKBD (82) is used to send keyboard characters (literal text, virtual function key sequences, control characters using ^ notation). This is mainly useful for sending key clicks to another A-Shell/Windows instance, or from a server to ATE. 

## **Response** 

None 

A-Shell Reference 

Page 1734 

## **AG_SETCOLOR, AG_PALETTE** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SETCOLOR); ctype, cnum, r, g, b; chr(127);** Tab( 10,x) Syntax Notes 

AG_SETCOLOR (15) (aka AG_PALETTE) provides a way to query and/or modify the RGB value associated with a specific color palette index (aka color number). For example, in the standard palette, color 2 is a rather primary intense blue. If you would rather have a more pastel blue, then you can either modify the definition of color 2 on the Display...Colors dialog, or via this command. In this operation, perhaps AG_SETCOLOR may seem like a better name. 

You may also query the RGB definitions of any of the A-Shell palette colors using the second syntax above. AG_PALETTE and AG_SETCOLOR have the same value, 15, but AG_PALETTE seems like less of a misnomer when querying rather than setting. 

## **Parameters** 

## _ctype_ 

1=set fg color, 2=set reduced fg color, 3=set bg color, 4=get fg color, 5=get reduced fg color, 6=get bg color 

## _cnum_ 

a single digit (0-7) indicating the number of the palette entry you want to query or set 

## _r,g,b_ 

The Red, Green, and Blue values (0-255).  Applicable only when _ctype_ <= 3. 

## **Response** 

For ctype <= 3 (i.e. when setting a color), there is no response.  For ctype >= 4, response consists of: 

## _r, g, b_ <CR> 

where r, g, and b are the red, green and blue values for the specified palette and _cnum_ . 

A-Shell Reference 

Page 1735 

## **Examples** 

```
! set fg color #2 to RGB(33,44,222)
```

```
? TAB(-10,AG_SETCOLOR);"1,2,33,44,222";chr(127);
```

```
! query bg color 7
```

```
? TAB(-10, AG_PALETTE);"6,7"; chr(127);
INPUT "", R, G, B
```

## **Notes** 

You can experiment with RGB values on the _Settings...Colors_ dialog by clicking on one of the color buttons and then Define Custom Color. 

Although you can use this method to define colors that are more like the standard Windows colors (which are more pastel than the default DOS-like palette colors), for certain logical colors, like the standard window background (gray), text font (black), and - edit window background (white), perhaps a better method would be to use the Associate A Shell and Windows Colors command or SET.LIT TERMINAL options to associate a color palette number with a particular Windows logical color. That way, the user can adjust the color settings logically in the Control Panel and the A-Shell color palette will adjust with it. 

A-Shell Reference 

Page 1736 

## **AG_SETCURSOR** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SETCURSOR); chr(CursorCode); chr(127);** Tab( 10,x) Syntax Notes 

AG_SETCURSOR (50) allows you to change the mouse cursor to the symbol of your choice, from the normal A-Shell/Windows cursor of an "I Beam" (which changes automatically to an arrow when the mouse is moved over a button or the menu bar). The value of CursorCode determines the cursor symbol, from the table below: 

|**CursorCode**|**Description**||**CursorCode **|**Descriptio**<br>**n**|
|---|---|---|---|---|
|32|Arrow||44|Watch 4|
|35|Pointing hand||45|Watch 5|
|40|Hourglass||46|Watch 6|
|41|Watch 1||47|Watch 7|
|42|Watch 2||48|I-Beam|
|43|Watch 3||||



## **Response** 

## none 

For example, while performing an operation that may take a few seconds, like building a list of customers to load into an XTREE, you can set the cursor to an hourglass with this command: 

```
PRINT TAB(-10,AG_SETCURSOR);chr(40);chr(127);     ! set cursor to hourglass
```

For backwards compatibility, A-Shell/Windows and ATE also support the older Tab(-1,160) command: 

## **print tab(-1,160); chr(CursorCode);** 

A-Shell Reference 

Page 1737 

Note that the AG_SETCURSOR syntax should be used in new development. 

A-Shell Reference 

Page 1738 

## **AG_SETENV** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SETENV); var=value; chr(127);** Tab( 10,x) Syntax Notes 

AG_SETENV (77) is used to set an environment variable. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_var_ 

environment variable to set 

_value_ 

value to set the environment variable to 

## **Example** 

```
? TAB(-10,AG_SETENV);"APEX=%MIAME%\cache";chr(127);
```

This defines (or redefines) the environment variable APEX to equal the specified directory, after first expanding the environment variable MIAME. Note that the APEX environment variable determines where ATE puts the print files captured for local print or preview operations. 

## **See Also** 

- MX_SETENVXS for setting an environment variable on the application server as opposed to client 

- SETENV.LIT 

A-Shell Reference 

Page 1739 

## **AG_SHLEXEC** 

_and revised December 2023_ 

## - **tab(-10, AG_SHLEXEC); objecspec, action, parms, dir, showcmd, waitflag; chr(127);** Tab( 10,x) Syntax 

Notes 

AG_SHLEXEC (24) provides an interface to one of the two fundamental mechanisms for launching a new process under Windows, i.e. "Shell Execute". The other method is Execute Windows Command Line, also known as "CreateProcess" or " or "Win Exec". Shell Execute is the method used by Windows itself when you click on a file or shortcut in Explorer, or even type a command line in the Start...Run dialog, and although it supports the ability to form command lines with parameters, it is most commonly used by specifying just an object (e.g. a file, URL, folder, etc.), and letting Windows decide which application is needed to perform the default (or specified) action on the object. Windows does this based on a table of file type associations in the Registry (which you can edit by means of the File Types dialog on the Explorer Tools...Folder Options menu). 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _objectspec_ 

is the specification (Windows format) of the file/object to open or act on, or the URL to link to. For example, you might specify a XLS file, such as c:\windows\temp\my spreadsheet.xls, in which case the presumed action would be to launch the spreadsheet program (e.g. Excel) to open the spreadsheet. For example, you might specify a URL, such as "http://www.microsabio.com" in which case the presumed action would be launch the browser and link to the specified web site or HTML document. 

Embedded environment variables (using the %env% notation, e.g. %temp%\test.doc) are supported. 

You may also specify an executable, such as %systemroot%\system32\mspaint.exe. (Use the _parms_ parameter for the remainder of the arguments and switches to be passed to the executable.) 

A special macro, "$ASHELL" can also be used to launch another session of A-Shell using the same executable and ini file as the current session. (You can combine this with additional switches in the _parms_ parameter to customize the action of the new session.) 

A-Shell Reference 

Page 1740 

Note that in the ATE environment, the _objectspec_ will be evaluated by (and relative to) the ATE client, not the server. If the object originates on the server, you will have to first transfer it to the ATE client before using Shell Execute on it. 

## _action_ (Str) 

may specify an action: open, edit, print, find, explore or runas. If omitted, the default action for that file association is performed. Typically the default action is "open", which just opens the document. Such actions are defined with the file association in the Explorer Tools...Folder Options...File Types dialog. 

Note that the "runas" action invokes the request for elevation dialog. For GUI commands, this is automatic, but for console commands (e.g. regsvr32), it is not, and this would be the only way to get it to prompt the user for the elevation needed. (Otherwise the operation would just fail.) Unfortunately there is no way to programmatically supply the administrator password. If you need something like that, you may want to check out a Microsoft-sponsored utility called "PsExec". 

## _parms_ (Str) 

is an optional list of parameters. Typically _parms_ is used when _objectspec_ contains the name of an executable (e.g. %miame% \bin\ashw32.exe), in which combination of _objectspec_ and _parms_ may effectively form a complete command line. 

## _dir_ (Str) 

is an optional starting directory. This can generally be omitted or specified as "". 

## _showcmd_ 

is an optional numeric parameter specifying the way to show the window launched by the program associated with the object and action. If omitted, the default window size will be used. Note that if you do specify the parameter, a value of zero means to make the window invisible. The values are the same as for AUI_WINDOWXS. Note that this is only a suggestion to the target application. There is no way to force it to follow your suggestion if it insists otherwise. 

## _waitflag_ 

|**Value**|**Description**|
|---|---|
|0|No wait. Focus will most likely remain on launched app.|
|1|Wait until launched app exits before returning.|



A-Shell Reference 

Page 1741 

|**Value**|**Description**|
|---|---|
|2|Don't wait, but try to get the focus back.|
|&h0100|Combine with any of the above values to return enhanced exit status. See Response.|
|&h0200|Returns the exit code of the launched process.|



Note that waiting (1) doesn't necessarily wait until the launched app exits. It only waits until the app "signals", which can mean different things for different applications. (It will wait for A-Shell). 

Option 2 will get the focus and keep getting it (if necessary) over a period of 4 seconds, in order to deal with difficult apps (like image viewers) that may take a couple of seconds to launch, after which they set the focus on themselves. 

## **Response** 

If the &h0200 bit is not set in _waitflag_ , the return value will be a single byte to indicate success (ASCII 13, aka RETURN) or failure (ASCII 3, aka Control-C). Note that success just means that the command was successfully executed, not necessarily that the resulting process ran correctly. In the case of _waitflag_ value 1, the status byte is not returned until the sub-process exits, else it is returned as soon as the sub-process is launched. 

If the &h0200 flag is set in _waitflag_ , the return value is a string containg a pair of integer values (launch-status and exit-status) separated by a comma. The launch-status indicates whether the sub-process launched ok (0=success, else a standard Windows error code indicating failure). The exit-status is only relevant when combined with _waitflag_ value 1 (i.e. &h0201), in which case it indicates the exit-status returned by the launched sub-process when it exits. Most programs follow the standard of returning 0 for success, else an error code, although the error codes may vary among programs. 

When the launch-status is non-zero, a file will also be left in the current directly, shellex.log, containing further details about the launch parameters to help in debugging failures. 

## **Examples** 

- `! browse to a website using the default browser` 

- `? TAB(-10,AG_SHLEXEC);"http://www.microsabio.com";chr(127);` 

A-Shell Reference 

Page 1742 

```
xcall ACCEPN,A
```

- `! Open a CSV file (presumably in a spreadsheet app)` 

- `? TAB(-10,AG_SHLEXEC);"%ATELOCALDIR%\test data.csv";chr(127);` 

```
xcall ACCEPN,A
```

- `! Open Explorer to browse a directory on the Windows LAN` 

- `? TAB(-10,AG_SHLEXEC);"\\server\share";chr(127);` 

```
xcall ACCEPN,A
```

- `! Launch email client to send message` 

- `? TAB(-10,AG_SHLEXEC);"mailto:arnold@calif.gov";chr(127);` 

```
xcall ACCEPN,A
```

- `! Launch an instance of A-Shell/Windows to execute an IMGDSX.LIT command` 

- `? TAB(-10,AG_SHLEXEC);"$ASHELL,,–e IMGDSX ";IMGSPEC$;",,1,2";chr(127);` 

- `! Play a video, SW)SHOWMAXIMIZED, wait, get exit status` 

- `? TAB(-10,AG_SHLEXEC);"mplayer2.exe,,/play,c:\temp\vid.wmv,,3,501";chr(127);` 

```
input STATUS,EXITSTS
```

## **Notes** 

This method is generally preferred over the Execute Windows Command Line method (e.g. executing an explicit command line with an explicit location and name for the executable) since it eliminates three of the biggest problems normally associated with launching local applications: knowing the actual name of the executable, the command line syntax, and directory where it is located. All of these are taken care of by the association definition. 

Under Under Windows versions with UAC (User Account Control), there is an added bonus in that "Shell Execute" will 

automatically request "elevation" if necessary in order to perform the specified action, whereas "CreateProcesss" will simply fail if the user doesn't have the necessary privileges. 

A-Shell Reference 

Page 1743 

## **See Also** 

- MX_SHELLEXXS, which provides the same functionality. 

- ZXPWIN.LIT, which combines the file transfer and shell execute functions with a command line interface 

## **History** 

- 2012 June, A Shell 6.0.1254 / 6.1.1314:  Add _waitflag_ value &h0200. 

A-Shell Reference 

Page 1744 

## **AG_SHORTCUT** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SHORTCUT); target, lnkspec {, descr, workdir, icon, iconidx}; chr(127);** Tab( 10,x) Syntax 

Notes 

AG_SHORTCUT (72) creates a shortcut on the client. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

See MX_SHORTCUTXS for descriptions. 

## **Response** 

A number followed be a carriage return indicating the status of the operation:  0=ok.  Positive numbers are Windows system error codes. (See MX_ERRNOMSG to display text). -1 indicates no GUI support available (requires Windows or ATE), and -15 indicates that ATE did not respond. 

## **Comments** 

Note that this AG_SHORTCUT command version does not support expansion of %ENV% variables.  (But the MX_SHORTCUT does, providing another reason to use it instead.) 

## **See Also** 

- MX_SHORTCUTXS 

A-Shell Reference 

Page 1745 

## **AG_SHOWWINDOW** 

_Rewritten December 2023_ 

## **tab(-10, AG_SHOWWINDOW); opflag, lft, top, rgt, btm, rows, cols, tsts, bsts, rtnflg, cid; chr(127);** 

- Tab( 10,x) Syntax Notes 

AG_SHOWWINDOW (27) performs the same function as the subroutine AUI_WINDOWXS, which see for the parameter descriptions, in addition to the differences noted below. 

## **Parameters** 

## _opflag_ 

In addition to the numeric values listed under AUI_WINDOW, may also be one of the following: 

|**Char**|**Description**|
|---|---|
|M|SW_MINIMIZE|
|X|SW_SHOWMAXIMIZED|
|R|SW_RESTORE|
|N|SW_SHOWNORMAL|



_rtnflg_ 

A-Shell Reference 

Page 1746 

Must be set to >= 1 to receive any response.  If >= 2, the  number of monitors will be appended to the response list.  If >= 3, the windows status will also be appended.  Note that setting the _rtnflg_ >0 only really makes sense if _opflag_ is <0 (query operations). 

## **Response** 

Unless _rtnflg_ > 0, none. 

For _rtnflg_ = 1: 

_vleft, vtop, vright, vbottom, rows, cols, tsts, bsts, hg, vg_ CR 

_For rtnflg = 2:_ 

_vleft, vtop, vright, vbottom, rows, cols, tsts, bsts, hg, vg ,monitors_ CR 

For _rtnflg_ >= 3: 

_vleft, vtop, vright, vbottom, rows, cols, tsts, bsts,hg, vg, monitors, winsts_ CR 

These are all the same output values returned by AUI_WINDOW, which see for details. 

## **Examples** 

```
! minimize
```

- `? tab(-10,AG_SHOWWINDOW); "M"; chr(127);` 

- `! maximize` 

```
? tab(-10,AG_SHOWWINDOW); "X"; chr(127);
```

- `! modify display attributes of dialog "dlgSample"` 

```
writecd tab(-10,AG_SHOWWINDOW); SW_SHOWNORMAL, lft, top, rgt, btm, rows, cols, tsts, bsts, 0, "dlgSample";
chr(127);
```

A-Shell Reference 

Page 1747 

- `! query window information` 

```
writecd tab(-10,AG_SHOWWINDOW); SW_QRYCTLPIX,0,0,0,0,0,0,0,0,1; chr(127);
input "", lft, top, rgt, btm, rows, cols, tsts, bsts, hg, vg
```

- `! query monitor information` 

```
writecd tab(-10,AG_SHOWWINDOW); SW_QRYMON,0,0,0,0,0,0,0,0,2; chr(127);
```

```
input "", lft, top, rgt, btm, dummy, dummy, dummy, dummy, xres, yres, monitors
```

## **See Also** 

- AUI_WINDOWXS 

A-Shell Reference 

Page 1748 

## **AG_SPOOLCFG** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SPOOLCFG); file, ptr, fsize, internal, switches, copies, filesize, ack; chr(127);** Tab( 10,x) 

Syntax Notes 

AG_SPOOLCFG (54) allows the host to adjust or control how ATE handles data sent to its "auxiliary port." 

**Background** : Terminal emulators often emulate the auxiliary port feature that some dumb terminals had. Since the most common use of such auxiliary ports was to connect a printer to the back of a terminal, the usual way to emulate this capability is for the terminal emulator to capture the data intended for the aux port and then send it to a Windows printer instead. ZTERM, ATE, and other emulators allow the user to define which printer to use, or to select a "prompt" option in which the user is prompted to select a printer each time data is output to the auxiliary port. The application initiates output to the auxiliary port by sending Tab(-1,82). Everything output to the terminal after this should be captured by the emulator and redirected to the aux port (however it is defined) rather than to the screen. To mark the end of the auxiliary output, the application sends a Tab(-1,83). 

Note: ZTERM and ATE also support "Serial Passthrough", which is a scheme for bidirectional communications with an actual device (such as cash drawer) physically connected to a serial port on the PC. See ZTERM Escape Sequences for more details. 

If the application knows that the emulator is ATE (see AUI_ENVIRONMENTXS), it can adjust the aux port behavior by sending a AG_SPOOLCFG command prior to the start of the auxiliary port operation, i.e. prior to the Tab(-1,82). Note that the effect of the AG_SPOOLCFG command only lasts until the end of the next auxiliary port operation (i.e. the original configuration is restored by the next Tab(-1,83) command). 

## **Parameters** 

## _file_ 

is an optional filename to use for the print operation on the client side. This is handled automatically by the AUXLOC: driver so is only of use when you are going to use Tab(-1,82) directly to output text to the aux port (rather than indirectly via spooling to the AUXLOC: driver). 

## _ptr_ 

A-Shell Reference 

Page 1749 

is an optional printer name, which temporarily overrides the printer choice in the ATE connection properties. Without this feature, the only way to change the ATE printer is for the user to do it manually via the Connection Properties dialog, which makes it hard to ensure synchronization with the needs of the application. 

## _fsize_ 

is an optional parameter specifying the number of bytes to be output. When non-zero, the subsequent auxiliary port output operation will be handled as binary data. This provides a means of transferring a binary file from the server to the client through the terminal channel without requiring FTP. 

## _internal_ 

is a field reserved for internal use. If you want to specify the _switches_ parameter, then insert an extra comma between fsize and switches to mark the position of this parameter. 

## _switches_ 

contains the SPOOL switches you want to pass to the ATE client. Depending on the circumstances, some or all of them may be ignored—e.g. when the operation is really just a file transfer, the printing switches are not relevant. But if the operation does result in printing, these switches will generally override those otherwise set in the client configuration. One exception is that the APEX Preview Preference settings "Never" and "Always" take precedence over the PREVIEW and NOPREVIEW switches specified by the application. 

## _copies_ 

if not specified, the default is 1. The value will be used by the ATE client to generate multiple copies of the subsequent printfile send via the AUXLOC: mechanism. This feature is primarily used within A-Shell when processing AUXLOC: printing requests. If used directly by an application, you should first verify that the client is ATE 5.1.1208.0 or higher; see MX_GETVERXS. There is no harm in sending the copies parameter to older versions of ATE, but it will have no effect (and thus the extra copies 

## _filesize_ 

size of the print file in bytes. Helps the client be more responsive. 

## _ack_ 

see Response. 

A-Shell Reference 

Page 1750 

All of the parameters are optional, although all are supplied by A-Shell when printing to the AUXLOC: device. 

## **Response** 

None, unless the ack parameter is specified and set to a non-zero value, in which case the response will be "ack" 

## **Examples** 

One example of this would be if the app wanted to export a report to PDF, and it "knew" that all ATE clients had a PDF printer whose name started with "PDF": 

```
PRINT TAB(-10,AG_SPOOLCFG)",PDF";chr(127);
```

```
xcall SPOOL,FILE,"AUXLOC"
```

Assuming that there is a printer ini file on the server called "AUXLOC" that contained DEVICE=AUXLOC:, this would transfer the file to the PC, and send it to the "PDF" printer regardless of (and without changing) the current printer setting for the ATE connection. We don't need to specify the filename above in the AG_SPOOLCFG statement because the AUXLOC: driver handles that automatically (but we do need the comma so that PDF is properly recognized as the ptr parameter). 

Another example would be to use the DISK: pseudo-printer to simulate an ASCII FTP transfer: 

```
PRINT TAB(-10,AG_SPOOLCFG);"DISK:%ATECACHEDIR%";chr(127);
```

```
xcall SPOOL,FILE,"AUXLOC"
```

This would transfer _file_ from the server to the ATE client %ATECACHEDIR% directory, which might be handy if FTP was not available on the server. 

## **See Also** 

- ATEAPX.SBX in SOSLIB:[907,33], which uses AG_SPOOLCFG to implement both ASCII and BINARY file transfers from the 

- server to the client. 

A-Shell Reference 

Page 1751 

## **AG_STATUSLINES** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_STATUSLINES); stslin, visible, textmode {, textmsg}; chr(127);** Tab( 10,x) Syntax Notes 

AG_STATUSLINES (34) controls the visibility and font class of the top and bottom status lines, and/or the text appearing on the system status line. The system status line is below the bottom status line and usually reserved for system messages from A- Shell, rather than application messages, but can be updated with this command. 

## **Parameters** 

## _stslin_ 

Character code indicating which status line is being impacted. 

|**Value **|**Description**|
|---|---|
|1|Top status line|
|2|Bottom status line|
|3|System status line|
|4|Save visibility/configuration of all status lines|
|5|Restore saved configuration|



## _visible_ 

|**Value **|**Description**|
|---|---|
|0|Invisible|
|1|Visible|
|""|No change|



A-Shell Reference 

Page 1752 

## _textmode_ 

|**Value **|**Description**|
|---|---|
|0|Fixed pitch font|
|1|Proportional font|



The default textmode is 0, but automatically switches to 1 if any GUI controls are created before an explicit AG_STATUSLINES command is issued. The assumption here is that if you are using GUI text or other controls in the window, you would probably want the status line text to also use that mode. Once you issue an AG_STATUSLINES command, the mode stays fixed until another AG_STATUSLINES command changes it. 

Note that the number of characters allowed on the status line does not change between modes, even though typically proportional text is more compact. Also, the proportional text is tokenized (similar to the way the OPTIONS=GUI_SPC_IND feature works) so that any text tokens preceded by two or more spaces will be repositioned to start in the same position as it would have in fixed pitch mode. 

This does not apply to the system status line, which always uses the proportional font. 

Leave the textmode parameter blank when specifying the textmsg parameter (e.g. stslin,visible,,textmsg). 

## _textmsg_ 

A message of up to 160 characters to display on the system status line. The parameter is only recognized if the visible parameter is followed by 2 commas—i.e. omit _textmode_ . The system status line always uses a proportional font, so _textmode_ doesn't apply here. An empty _textmsg_ will clear the system status line. 

## **Response** 

None 

## **Examples** 

A-Shell Reference 

Page 1753 

- `? TAB(-10,AG_STATUSLINES);"1,0";chr(127);        ! remove top status line` 

- `? TAB(-10,AG_STATUSLINES);"2,1";chr(127);        ! display bottom status line` 

- `? TAB(-10,AG_STATUSLINES);"1,1,1";chr(127);      ! restore (display) top status line, proportional font ? TAB(-10,AG_STATUSLINES);"3,1,,Boo!";chr(127);  ! Enable system status line, display "Boo!"` 

- `? TAB(-10,AG_STATUSLINES);"3,1,,";chr(127);      ! Clear (but leave visible) system status line` 

## **Comments** 

Adding or removing status lines does not affect the size of the main window, but by increasing or decreasing the amount of vertical space left for the text grid, affects the height of the rows and consequently the character height. 

The top and bottom status lines were part of the original terminal specifications emulated by ATE and the A-Shell/Windows - - client, typically used by applications to display auxiliary information. Use the Tab Functions ( 1,128) thru ( 1,131) to write to them. 

The system status line was never part of the terminal specification and is intended for system-level messages from A-Shell itself, typically about low level operations such as file transfers, downloads, auxiliary port printing  or other communications between the server and client. Applications can however write to it via the second syntax of this AG_STATUSLINES command. 

Visibility of the status lines may also be set interactively by the user for A-Shell/Windows via the Settings > Status Lines menu (and then optionally saved as part of the standard configuration via the File > Save menu). For ATE, use the Connection Properties Dialog Emulation tab. 

## **See Also** 

- Terminal Functions 

- Settings Menu 

- Webcaching 

## **History** 

A-Shell Reference 

Page 1754 

- 2023 August, A Shell 6.5.1739:  URLs of files being downloaded from the web (via WEBCACHE or explicit http specifications such as image loading) will now appear on the system status line during the download. 

- 2011 April A Shell 5.1.1214:  Add _stslin_ options to save and restore status line visibility states. 

- 2011 April A Shell 5.1.1212:  Status line enhancement: The top and bottom status lines can now be displayed using a proportional font. 

A-Shell Reference 

Page 1755 

## **AG_SYSBCLR** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_SYSBCLR); bgsys, bgwin, fgtext {,opcode}; chr(127);** Tab( 10,x) Syntax Notes 

AG_SYSBCLR (26), formerly AG_SETWINCLR, provides a way to associate some of the A-Shell color palette numbers with the most important Windows colors (the ‘system’ gray commonly used for the background of windows and dialogs, the color used for the background of edit controls, and the standard text color). 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _bgsys_ 

A single digit (0-7) indicating the color number from the A-Shell background palette to be associated with the standard Windows gray (aka "button face" or "dialog background" color). You may also specify "-1" to leave this color alone (in order to set one of the others). 

## _bgwin_ 

A single digit (0-7) indicating the color number from the A-Shell background palette to be associated with the standard Windows color used for the background of edit controls and list boxes (usually white). You may also specify "-1" to leave this color alone (in order to set one of the others). 

## _fgtext_ 

A single digit (0-7) indicating the color number from the A-Shell foreground palette to be associated with the standard Windows text color (usually black). You may also specify "-1" to leave this color alone (in order to set one of the others). 

## _opcode_ 

An optional digit indicating the operation: 0 to set the color associates, 1 to query them. The default is 0 to set. 

## **Response** 

A-Shell Reference 

Page 1756 

If _opcode_ is set to 1, then a string formatted as "#,#,#" will be forced into the keyboard buffer to return the current values of the color associations (in the order of the parameters as shown above). 

## **Examples** 

- `! set bg 0 to system gray, bg 1 to edit bg color, and fg 1 to text color` 

- `? TAB(-10,G_SYSBCLR);"0,1,0";chr(127);` 

- `! query the current colors` 

- `? TAB(-10,G_SYSBCLR);0,0,0,1";chr(127);` 

```
input bgsys,bgwin,ftext
```

## **See Also** 

- MX_SYSBCLRXS 

- SET.LIT 

A-Shell Reference 

Page 1757 

## **AG_SYSCOLOR** 

_Rewritten December 2023_ 

## - **tab(-10, AG_SYSCOLOR); id{,r,g,b}; chr(127);** Tab( 10,x) Syntax Notes 

AG_SYSCOLOR (63) allows you to query and/or change the Windows RGB color value for certain parts of the Windows user interface. Querying may be useful when creating your own controls (see AUI_CONTROLXS) in order to match the prevailing Windows color scheme.  Changing the standard Windows colors, on the other hand, although supported, is not recommended due to:allows you to change the Windows RGB value for certain parts of the Windows user interface. Note that this is offered on an as-is basis, and is not recommended due to: 

- Conflicts between these settings and the current Theme 

- Conflicts with the "approved" way of changing Windows desktop settings (via the Control Panel) 

- Differences in the way it may work under different versions of Windows 

- Possible problems with the way other applications may respond to the fact of color changes (since any such change triggers a 

- notification message to be sent to all affected applications). 

That said, you can experiment as you wish. 

## **Parameters** 

## _id_ 

Identifier for the Windows user interface component, from the following table: 

|**Symbol**|**Valu**<br>**e**||**Symbol**|**Valu**<br>**e**|
|---|---|---|---|---|
|COLOR_SCROLLBAR|0||COLOR_HIGHLIGHTTEXT|14|
|COLOR_BACKGROUND|1||COLOR_BTNFACE|15|
|COLOR_ACTIVECAPTION|2||COLOR_BTNSHADOW|16|



A-Shell Reference 

Page 1758 

|**Symbol**|**Valu**<br>**e**||**Symbol**|**Valu**<br>**e**|
|---|---|---|---|---|
|COLOR_INACTIVECAPTION|3||COLOR_GRAYTEXT|17|
|COLOR_MENU|4||COLOR_BTNTEXT|18|
|COLOR_WINDOW|5||COLOR_INACTIVECAPTIONTEXT|19|
|COLOR_WINDOWFRAME|6||COLOR_BTNHIGHLIGHT|20|
|COLOR_MENUTEXT|7||COLOR_3DDKSHADOW|21|
|COLOR_WINDOWTEXT|8||COLOR_3DLIGHT|22|
|COLOR_CAPTIONTEXT|9||COLOR_INFOTEXT|23|
|COLOR_ACTIVEBORDER|10||COLOR_INFOBK|24|
|COLOR_INACTIVEBORDER|11||||
|COLOR_APPWORKSPACE|12||COLOR_HOTLIGHT|26|
|COLOR_HIGHLIGHT|13||||



_r, g, b_ 

If specified, these red, green, and blue values will be combined to replace the color of the interface component specified by id. (0,0,0=black, 255,255,255=white) 

## **Response** 

If the r,g,b parameters are specified (i.e. setting the color), there is no response.  Otherwise the response is a comma-delimited list of the three current red, blue and green values followed by a carriage return: 

## _r,g,b_ CR 

## **Example** 

```
writecd tab(-10,AG_SYSCOLOR), COLOR_BTNFACE, 80, 120, 210; chr(127);    ! set
```

A-Shell Reference 

Page 1759 

```
writecd tab(-10,AG_SYSCOLOR), COLOR_BTNFACE; chr(127);   ! query
```

```
input "", r, g, b
```

This first changes the color for the face of standard Windows buttons to RGB value (80,120,210). Then it queries the same element, which should send the response "80,120,210" CR 

## **Comments** 

Note that if you are associating A-Shell palette numbers with the standard Windows dialog background, window background, or text (see AG_SYSBCLR), you must do that first before using the AG_SYSCOLOR command. 

A-Shell Reference 

Page 1760 

## **AG_TABWRAPPER** 

_Added November 2025_ 

## - **tab(-10,AG_TABWRAPPER); chr(#); ... ; chr(127);)** Tab( 10,x) Syntax Notes 

AG_TABWRAPPER (117) is used to wrap 'problematic' TAB(-1,#) commands for delivery to the client without interfering with the screen tracking logic on the server side. May be used with any TAB(-1,#) command, but is mainly useful with the mouse cursor TAB commands that are followed by raw data bytes, e.g. TAB(-1,158), TAB(-1,160)  and TAB(-1,162). 

This function has both a subroutine and a print tab implementation. 

## **Response** 

none 

## **Comments** 

In general, to convert from: 

```
TAB(-1,#); <trailer bytes>;
```

use: 

```
TAB(-10,AG_TABWRAPPER); chr(#); <trailer bytes>; chr(127);
```

## **Example** 

The equivalent of: 

```
TAB(-1,158); "C"; chr(34); chr(27); chr(30);
```

is: 

```
TAB(-10,AG_TABWRAPPER); chr(158); "C"; chr(34); chr(27); chr(30); chr(127);
```

Or, as an alternative to AG_SETCURSOR, you could replace TAB(-1,160); chr(#) with TAB(-10,AG_TABWRAPPER); chr(160); chr(#); chr(127); 

A-Shell Reference 

Page 1761 

## **See Also** 

- MX_AGWRAPPERXS 

## **History** 

- 2025 November, A Shell 7.0.1781:  Function added to A-Shell, 

A-Shell Reference 

Page 1762 

## **AG_TRACE** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_TRACE); opcode {,trflags}; chr(127);** Tab( 10,x) Syntax Notes 

AG_TRACE (76) allows the application on the server to clear, set, or query the trace flags on the ATE client in real time. This is mainly useful for debugging, but in such a case, can be very handy since it is not often practical to arrange for users to change the trace flags on individual copies of ATE. 

## **Parameters** 

## _opcode_ 

0=clear, 1=set, 2=query 

## _trflags_ 

32 bit value containing the trace bit flags to clear, set or query  (see table in MX_GETTRACE for bit definitions). Note that only the flags indicated by the bits set to 1 in _trflags_ will be cleared, set or queried. 

## **Response** 

For opcode 0 and 1, none.  For opcode 2, a 32 bit value representing the previously-set trace flags: 

## _trflags_ 

## **Example** 

```
MAP1 OPCODE,B,1             ! 0=clear, 1=set, 2=query
```

```
MAP1 TRFLAGS,B,4            ! Flags to clear, set or query
```

```
? TAB(-10,AG_TRACE);"1,";(TROP_XTREE or XTROP_XDEBUG);chr(127);
```

To specify all flags, you can use the shorthand -1: 

A-Shell Reference 

Page 1763 

```
? TAB(-10,AG_TRACE);"2,-1";chr(127);        ! query all flags
input "",TRFLAGS                            ! for query, retrieve results
```

```
? "Current ATE trace flags: ";Fn'Dec2Hex$(TRFLAGS);  ! display in hex
```

```
if (TRFLAGS and TROP_ATE) then "ATE trace set"
```

```
if (TRFLAGS and TROP_XTREE) then "XTREE trace set"
```

```
etc.
```

A-Shell Reference 

Page 1764 

## **AG_WALLPAPER** 

_Reviewed and revised December 2023_ 

## - **? TAB(-10, AG_WALLPAPER); imagespec {,opcode {,dlgid}}; chr(127);** Tab( 10,x) Syntax Notes 

AG_WALLPAPER (39) provides a way to display a bitmap file as "wallpaper" for the background of the main A-Shell window. 

## **Parameters** 

## _imagespec_ 

File specification of an image. May be any image type recognized by AUI_CONTROL; JPG is probably the best option here. Either AMOS or native syntax may be used, but it will be interpreted relative to the PC. So if running on a Unix server with ATE, you must arrange for the file to be present on the PC before you can invoke it. 

## _opcode_ 

|**Code**|**Description**|
|---|---|
|0|(default) Load new wallpaper, deleting any old wallpaper. If_imagespec_is null, then it just deletes any existing<br>wallpaper. For dialogs,_opcode_must be 0. The only valid operation is to set the wallpaper to the dialog; it is<br>destroyed when the dialog is deleted.|
|1|Clear current wallpaper but save it.|
|2|Restore previously saved wallpaper.|
|+4|(Add 4). Normally, the wallpaper save and restore operations are destructive in the sense that "save" clears<br>the current wallpaper, and an attempt to restore when there is no saved wallpaper will effectively delete the<br>current wallpaper. To accommodate applications that want to be able to issue redundant save and restore<br>operations, you can add 4 to_opcode_. Part of the incentive for this feature is that restoring a previously saved<br>wallpaper is much faster than re-loading it from disk.|
|+8|expand image to fit dialog|
|+16|stretch (distort) as needed to fit|



A-Shell Reference 

Page 1765 

## _dlgid_ 

may either be the numeric or alphanumeric identifier for the dialog. If _dlgid_ is zero or omitted, the command works on the main window as before. In most cases, you will want to create the dialog with the bgc parameter set to RGB_TRANSPARENT, else the background of static text controls will cover that portion of the wallpaper. 

## **Response** 

none 

## **Examples** 

## Load examples: 

- `? TAB(-10,AG_WALLPAPER);"bmp:pinup1.bmp";chr(127);` 

- `? TAB(-10,AG_WALLPAPER);"c:\my documents\wallpaper\rainforest.png";chr(127);` 

- `? TAB(-10,AG_WALLPAPER);"%MIAME%\bitmaps\clouds.jpg";chr(127);` 

- `? TAB(-10,AG_WALLPAPER);".\my life in pictures.jpg";chr(127);` 

- `? TAB(-10,AG_WALLPAPER);"";chr(127);       ! (remove wallpaper)` 

## Other examples: 

- `? TAB(-10,AG_WALLPAPER);",1";chr(127);     ! Save (and then clear) wallpaper` 

- `? TAB(-10,AG_WALLPAPER);",5";chr(127);     ! Save (but don't clear) wallpaper` 

- `? TAB(-10,AG_WALLPAPER);",2";chr(127);     ! Restore wallpaper; clear saved copy from memory` 

- `? TAB(-10,AG_WALLPAPER);",6";chr(127);     ! Restore wallpaper only if there is saved wallpaper` 

## **Notes** 

A-Shell Reference 

Page 1766 

Main window wallpaper is generally only useful when you are going to display a dialog on top of it. Otherwise, unless the wallpaper is very subtle, it makes it difficult to read text displayed on it. VUE and EZTYP temporarily disable the wallpaper (using _opcodes_ 1 and 2). Only BMP files are supported. 

For main window wallpaper, the load command ( _opcode_ 0) also automatically saves a copy if there is not already a saved copy. Thus you can do a load following by a restore ( _opcode_ 2) without first doing an explicit save. 

When loading or clearing main window wallpaper, you need to then execute a screen clear command (e.g. ?TAB(-1,0)) in order to for the wallpaper to become fully visible or fully cleared. 

AGCMD.LIT is handy for experimenting with main window wallpaper without the need for any programming. For example, the following commands load the wallpaper from a specified file and then remove it again. The `XY=0` commands are necessary to finalize each wallpaper update operation. 

```
.AGCMD WALLPAPER MYWP.PNG      ; load wallpaper
```

```
.XY=0
```

```
.AGCMD WALLPAPER               ; clear wallpaper (load null wallpaper)
```

```
.XY=0
```

## **History** 

- 2017 June, A Shell 6.5.1606:  Add _opcode_ flags +8 and +16 to better display wallpaper. Previously, dialog wallpaper only supported opcode 0, in which case the image was tiled as needed to fit the dialog 

- 2016 December, A Shell 6.3.1540: AG_WALLPAPER now supports PNG and other image formats for main window wallpaper. This was always the case for dialog wallpaper, but until now the main window wallpaper was limited to BMP files. 

- 2016 September, A Shell 6.3.1527:  Add _dlgid_ and the ability to apply wallpaper to dialogs. 

A-Shell Reference 

Page 1767 

## **AG_WEBCACHE** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_WEBCACHE); opcode {,flags ,url}; chr(127);** Tab( 10,x) Syntax Notes 

AG_WEBCACHE (108) gets/sets webcache options from host. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _opcode_ 

0 (MXOP_GET) to retrieve and 1 (MXOP_SET) to set. On retrieval, the returned string will contain "flags,url" (current webcache flags and repo url). 

## _flags_ 

is a decimal number containing the WCDF_xxx flags 

_url_ 

if specified, is the web directory for the repository. 

## **Response:** 

For _opcode_ 0, none.  For _opcode_ 1: 

_flags, url_ CR 

## **Example** 

```
? tab(-10,AG_WEBCACHE);"1,";(WCDF_ENABLE or WCDF_ALL); ",http://www.myrepo.com/app1";chr(127);  ! enable; set
repo
```

```
? tab(-10,AG_WEBCACHE);"1,0";chr(127);       ! disable
? tab(-10,AG_WEBCACHE);"0";chr(127);         ! retrieve
```

A-Shell Reference 

Page 1768 

```
? tab(-10,AG_WEBCACHE);chr(127);             ! same (retrieve)
input line, response$                        ! input flags,url
```

## **See Also** 

- MX_WEBCACHEXS 

## **History** 

- XS 2016 October, A Shell 6.3.1529 and 1531: WEBCACHE function added to A-Shell. 

A-Shell Reference 

Page 1769 

## **AG_WINEXEC** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_WINEXEC); cmdlin; {"~"; workdir;} chr(127);** Tab( 10,x) Syntax Notes 

AG_WINEXEC (23) executes a Windows command line on the local Windows workstation or ATE client. Note that unlike most AG_xxx functions, the delimiter here is a tilde ("~") rather than a comma. If _workdir_ is specified, it must be separated from _cmdlin_ with a tilde. 

## **Parameters** 

## _cmdlin_ 

A string containing a valid Windows command line. The string may contain any of the suffix characters supported by HOSTEX[XS] to control how the command line is executed and whether we have to wait for it to complete, as summarized in the following table. Only one suffix option, at max, is allowed, and it must be preceded by a space. See History notes below for macros that can be used in _cmdlin_ . 

|**Suffi**<br>**x**|**Description**|
|---|---|
||(no suffix) The process launched by_cmdlin_takes the foreground and A-Shell must wait for it to exit.|
|&|The process is launched in minimized mode and runs independently of A-Shell (i.e. A-Shell doesn’t wait for it.)|
|%|The process is launched minimized, but A-Shell still waits for it to complete. This is mainly useful for quick<br>commands where you don’t want to distract the user with its display.|
|$|The process is launched in the foreground but A-Shell does not wait for it.|



## _workdir_ 

establishes the working directory context for the command; if not specified, the current workstation directory is used. 

**Response** 

A-Shell Reference 

Page 1770 

A single byte will be placed in the keyboard buffer to indicate success (ASCII 13, aka RETURN) or failure (ASCII 3, aka ControlC). Note that success just means that the command was successfully executed, not necessarily that the resulting process ran correctly. In the cases where A-Shell is supposed to wait for the command (no suffix or "%" suffix), the byte is not returned until the process exits. 

## **Examples** 

- `! launch notepad to view miame.ini on PC and wait` 

- `? TAB(-10,AG_WINEXEC);"notepad.exe %MIAMEFILE%";chr(127);` 

```
xcall ACCEPN,A
```

- `! launch calculator and don't wait` 

- `? TAB(-10,AG_WINEXEC);"CALC.EXE $";chr(127);` 

```
xcall ACCEPN,A
```

## **Notes** 

Environment variables (known to the PC) may be embedded in the command line using the %VARNAME% syntax, as shown in the first example above. 

HOSTEX[XS] provides nearly the same functionality under A-Shell/Windows, but under A-Shell/Unix executes a Unix command line on the server, whereas AG_WINEXEC always executes a Windows command line on the local workstation. 

Also see the following topic, Shell Execute. 

## u **History** 

- 2006 October, A Shell 4.9.969: Two new macros have been added: 

```
TAB(-10,AG_WINEXEC);"$COPY ";src$;" ";dst$;"~";flags;chr(127);
```

```
TAB(-10,AG_WINEXEC);"$MOVE ";src$;" ";dst$;"~";flags;chr(127);
```

These macros provide a clean way to move or copy a file. They are both equivalent to the MX_COPYFILEXS function and they 

A-Shell Reference 

Page 1771 

share the same flags (0=copy, +1=move, +2=overwrite existing destination). The only difference between $MOVE and $COPY is in how the flags argument is defaulted if not specified. Note that this is a deviation from the usual behavior where an omitted numeric argument is equivalent to an explicit zero. In this case, specifying a flags value of 0 or 2 would override $MOVE, converting it to $COPY. 

## - 2005 May, A Shell 4.9.932: AG_WINEXEC now supports a new macro $DEL to delete a file. For example: 

```
? TAB(-10,AG_WINEXEC);"$DEL %ATELOCALDIR%\myfile.dat";chr(127);
```

```
input "",A
```

This would delete myfile.dat from the directory specified by the environment variable ATELOCALDIR (which is set by ATE to point to its FTP Local Directory). The return code is CR for success or ^C for failure. Note that a non-existent file is treated as success, so the only error would be if the file existed but could not be deleted. 

- 2005 April, A Shell 4.9.926:  A special symbol, "$ATE", may now be used with AG_WINEXEC to make it easier to launch another ATE session. For example: 

```
? TAB(-10,AG_WINEXEC);"$ATE";chr(127);
```

```
? TAB(-10,AG_WINEXEC);"$ATE ";cmdlin;chr(127);
```

The first example above ($ATE with no other argument) launches another ATE connection to the current server using the current profile, without suspending the current connection. 

The second example ($ATE following by additional arguments) launches another A-Shell/Windows session on the local ATE client and passes it the command line _cmdlin_ . You could use this format to launch a connection to some other server, assuming you knew the profile name, for example: 

- `? TAB(-10,AG_WINEXEC);"$ATE telnet ";CFG$;chr(127);` 

Since ATE connections are established with the telnet command, the above command would launch a new ATE connection using the profile CFG$. Note that by default, AG_WINEXEC suspends the current session until the child session completes. If you don't want that, you must append the special suffix characters used by HOSTEX[XS] . For example, to not suspend the current session, 

A-Shell Reference 

Page 1772 

the above command could be amended to add " $", i.e.: 

```
? TAB(-10,AG_WINEXEC);"$ATE telnet ";CFG$;" $";chr(127);
```

Or you could execute any valid A-Shell command in the child session, for example: 

```
? TAB(-10,AG_WINEXEC);"$ATE VUE %MIAMEFILE%";chr(127);
```

This would launch VUE to edit ATE's copy of miame.ini. Or: 

```
? TAB(-10,AG_WINEXEC);"$ATE VUE %MIAME%\ashlog.log";chr(127);
```

The above command would VUE ATE's log file. 

A-Shell Reference 

Page 1773 

## **AG_WINPTR** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_WINPTR); chr(127);** Tab( 10,x) Syntax Notes 

AG_WINPTR (56) brings up the Windows printer selection dialog. 

This function has both a subroutine and a print tab implementation. 

## **Response** 

A string containing four or more comma-delimited parameters depending on the circumstances and user response, i.e.: 

_status, ptrname$, port$, dvr$ {, orientation, length, width, form, duplex, bin, color, quality_ } CR 

## **Example** 

Selecting the PDF-XChange Printer 2012 will return something like: 

```
1,PDF-XChange Printer 2012,PDF-XChange5,winspool,1,0,0,Letter/ANSI A,0,0,2,300
```

The first parameter, _status_ , will be 1 if the user selected a printer, else 0 

See MX_WINPTRXS for the definitions of the remaining parameters. 

Note that since ATE and A-Shell/Windows versions prior to 6.0.1248.0 will only return the first four fields, and that INPUT will continue to prompt for parameters that were not supplied. It is therefore best to input the entire string as a single line, as shown above, and then parse it out, perhaps using INSTR() or STRTOK[XS] Using MX_WINPTRXS will take care of all the parsing automatically. 

## **See Also** 

- MX_WINPTRXS 

## **History** 

- 2012 April, A Shell 6.0.1248:  Added all parameters after "PTRDVR$" 

A-Shell Reference 

Page 1774 

## **AG_WINSETTINGS** 

_Reviewed and revised December 2023_ 

To retrieve (get) a specific value ( _opcode_ 0): 

## - **writecd tab(-10, AG_WINSETTINGS); opcode, id, , rtnflg; chr(127);** Tab( 10,x) Syntax Notes 

To update (set) a specific value ( _opcode_ 1): 

## **writecd tab(-10, AG_WINSETTINGS); opcode, id, value; chr(127);** 

To load or save complete settings file ( _opcodes_ 2 and 3) 

## **writecd tab(-10, AG_WINSETTINGS); opcode, fspec; chr(127);** 

AG_WINSETTINGS (46) retrieves or updates individual configuration settings—the types of settings that may be set in the Settings menu dialogs and saved or loaded from the File menu options—as well as saving or loading the entire set of values. 

This function has both a subroutine and a print tab implementation. 

XS Because the syntax is a bit tricky, in most cases it will be preferable to use MX_WINSETTINGS . 

## **Parameters** 

_opcode_ 

retrieve a settings value;  1) set a value; 2) save the current values to disk; 3) load a new set of values from disk 

_id_ 

XS identifies the individual settings parameter to retrieve or update; see the table MX_WINSETTINGS . 

_value_ 

specifies the string or numeric value to set for the specified parameter. Leave blank for opcode 0. 

_rtnflg_ 

A-Shell Reference 

Page 1775 

specifies the file to load from or save to. If left blank, the current settings file will be used. 

## _fspec (opcode_ 0 only _)_ 

must be set to 1 to enable a response 

## **Response** 

## depends on _opcode_ , per the following table: 

|**Opcode **|**Response**|**Description**|
|---|---|---|
|0|Value<br><CR>|Current value of the setting identified by id|
|1|none||
|2|status<br><CR>|0 for success, -15 for timeout, else other error|
|3|Fspec, fgc, bgc <CR>|Fully qualified settings file name (mainly useful if empty or partial fspec passed),<br>followed by the current foreground and background palette color indices.|



## **See Also** 

• MX_WINSETTINGSXS 

A-Shell Reference 

Page 1776 

## **AG_WINTITLE** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_WINTITLE); title; chr(127);** Tab( 10,x) Syntax Notes 

AG_WINTITLE (2) changes the title that displays on the title bar of the A-Shell window. Also see ZTERM Escape Sequences and SET.LIT for other ways of setting the title. 

## **Parameters** 

_title_ 

Title string. 

## **Response** 

none 

## **Example** 

- `? TAB(-10,AG_WINTITLE);"Once Upon an App";chr(127);` 

A-Shell Reference 

Page 1777 

## **AG_WRAP** 

_Reviewed and revised December 2023_ 

## - **tab(-10, AG_WRAP); opcode; chr(127);** Tab( 10,x) Syntax Notes 

AG_WRAP (62) may be used to control wrapping in A-Shell/Windows and ATE. Use _opcode_ "0" (with quotes) to disable, "1" to enable. By default, wrap is enabled. 

## **Response** 

none 

A-Shell Reference 

Page 1778 

## **AG_XFUNC** 

_Rewritten December 2023_ 

Numeric Function: 

## - **tab(-10, AG_XFUNC); sbxname; arg1, arg2,....argn; chr(127);** Tab( 10,x) Syntax Notes 

String Function: 

## **tab(-10, AG_XFUNCS); sbxname; arg1, arg2,....argn; chr(127);** 

No Response: 

## **tab(-10, AG_XFUNC2); sbxname; arg1,arg2,...argn; chr(127);** 

AG_XFUNC (25), AG_XFUNCS (75), and AG_FUNC2 (73) invoke a function implemented via an SBX, returning a numeric, string or no result, respectively. 

## **Parameters** 

## _sbxname_ 

File name (no device or extension) of an SBX Subroutine stored in the SBX search path (normally BAS:) of the ATE or windows client. For the XFUNC() and XFUNC$() versions, it  must include a RETURN expression. 

## _arg1, arg2, ..., argn_ 

Zero or more arguments passed to the SBX. These will appear to the target SBX as individual arguments passed in an XCALL statement. 

## **Response** 

For AG_XFUNC, the response is a single numeric value: 

## _numvalue_ CR 

A-Shell Reference 

Page 1779 

For AG_XFUNCS, the response is a string, which may potentially be in the form of a list, depending on the SBX, so should be parsed appropriately: 

_strvalue_ CR 

For AG_XFUNC2, there is no response 

## **Example 1** 

```
writecd tab(-10,AG_XFUNC);"CALCLCD", 21, 35; chr(127);
```

```
input "", lcd
```

This example passes a pair of numbers to a routine CALCLDC.SBX on the client and gets back the least common denominator. Note that writecd was used in place of the more typical print or ? statement in order to get the benefit of automatic comma delimiters. The equivalent print statement version would be: 

```
? tab(-10,AG_XFUNC);"CALCLCD"; ","; 21; ","; 35; chr(127);
```

or 

```
? tab(-10,AG_XFUNC);"CALCLCD,21,35"; chr(127);
```

The target CALCLDC.SBX would be internally invoked on the client side via: 

```
xcall CALCLCD, 21, 35
```

To work properly, it should be constructed something like this: 

A-Shell Reference 

Page 1780 

```
xgetargs value1,value2           ! receive the two arguments
```

```
result = Fn'LCD(value1,value2)   ! calc the least common denominator
```

```
return (result)                  ! return the result
```

## **Example 2** 

```
writecd tab(-10,AG_XFUNCS);"FGREP", file$, pattern$; chr(127);
```

```
input line "", match$
```

This example passes a filespec and a pattern to a routine FGREP.SBX on the client to search the specified field for the specified pattern, returning the first match, if any. Note the use of _input line_ rather than just _input_ for the response since we can't be sure if the return string contains commas (or anything at all). 

## **Example 3** 

```
writecd tab(-10,AG_XFUNC2);"ARCFILE", file$, file2$, file3$; chr(127);
```

This example calls a routine ARCFILE.SBX on the client to archive the specified files, whatever that may mean. There is no response in this case. 

## **Comments** 

Getting the SBX installed on the client is outside the scope of the function. To simplify this prerequisite, see Fn'ATE'SBX in SOSLIB:[907,11] which automatically takes care of transferring or updating the SBX from the application/server to the ATE/client if necessary, invoking the routine remotely, and return the result. 

See the OSVERCLI.SBX in SOSLIB:[907,33] for an example of a function invoked by AG_XFUNCS using the Fn'ATE'SBX$() wrapper. 

An example of a standard routine using this mechanism is provided in the documentation for HTTP, subtopic "ATE." 

A-Shell Reference 

Page 1781 

Note that the SBX may **not** perform any standard text mode input operations, as these would interfere with the host/client communication (TELNET/SSH) channel. Instead, if input is needed, use AUI functions, e.g. MSGBOX, EVENTWAIT, INFLD (in GUI mode), etc. 

Note that AG_XFUNCS is to AG_XFUNC as the underlying built-in function XFUNC$() is to XFUNC(). The former deals with functions returning a string, while the latter deals with functions returning a numeric value. In both cases, if the specified SBX is not found the return value will be -1, although in the case of AG_XFUNCS, it will be a string representing -1, e.g. "-1", as opposed to the numeric value -1. There is no particular limit on the length of the returned string. 

For the variations with a return value (i.e. AG_XFUNC and AG_XFUNCS but not AG_XFUNC2), see MX_AGWRAPPERXS as a way to encapsulate the two parts of the operation (Tab output and response input) into a single operation. In particular, its timeout feature would provide a measure of robustness given that the complexity of these remote calls increases the possibility of unexpected failures which might otherwise leave the application stuck waiting for a response that isn't coming. 

## **History** 

- 2017 November, A Shell 6.5.1621, Corruption avoidance fix: the string containing the argument list was previously used in place, but since the area is within the terminal system output buffer, it was subject to possible corruption by other functions that use the output system. This could have interfered with the operation of XGETARG(S). For example, in the following SBX code, the second XGETARG might have returned incorrect information due to potential sharing of the same buffer space with DEBUG.PRINT: 

```
XGETARG 1,ARG1
```

```
DEBUG.PRINT "ARG1 = "+ARG1
```

```
XGETARG 2,ARG2
```

This patch eliminates the danger of such a conflict. 

- 2016 October, A Shell/ATE 6.3.1534:  Eliminate 1K limit on size of returned string. 

A-Shell Reference 

Page 1782 

## **SUBROUTINES** 

Below is a table listing the subroutines (aka xcalls) found in A-Shell. For general information about subroutines, see the following Introduction topic. 

This table alphabetically lists A-Shell’s most generally useful routines. Most of these routines are embedded in A-Shell, but some are written in BASIC and are provided as separate files. In the "Origin" column abbreviations are used for Alpha Accounting ("AA"), Alpha Accounting UK ("AA UK") and MicroSabio ("MS"). 

Follow the links to the individual pages providing details about the routines. 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|ABOX|Unknown|Draw a box.|
|ACCEPN|A-BASIC|Input single character with no echo.|
|ACCEPT|A-BASIC|Input single character with echo.|
|ACCESS|Misc|Display one-line menu, accept one-character input.|
|AMBTOA|AM Belgium|Miscellaneous functions including timed input.|
|AMOS|MS|Deprecated; seeASHELL<br>.|
|ANYCN|AA / MS|Input "Any change?" number.|



A-Shell Reference 

Page 1783 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|ASCEBC|Unknown|ASCII-EBCDIC conversion.|
|ASFLAG|MS|Set A-Shell runtime flags: read-only, sync-write, etc.|
|ASHELL|MS|Execute A-Shell system command or run program.|
|ASQL|MS|Provides direct access to SQL databases.|
|ATEAPX|MS|Transfers a file from application server to ATE client PC.|
|ATEGFK|MS|Retrieves a file from the PC via the ATE terminal connection.|
|ATEGLI|MS|Creates a customized ATE login script.|
|ATSYNC|MS|Synchronize directories between server and PC. SeeATSYNC.LIT<br>.|
|ATHTTP|MS|A variant ofHTTP<br>, which see for details.|
|AUI|MS|A-Shell's GUI interface and toolkit.|
|AUTLOG|Soft Machines|Interface to AutoLog.|



A-Shell Reference 

Page 1784 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|B64ENC|A-Shell|Base 64 encoding (for email attachments).|
|BASORT|A-BASIC|Sort sequential and random data files.|
|BITOPS|HMOpro|Bit field operations.|
|BLOCKS|AA UK|Return number of free disk blocks.|
|BLOFSH|MS|Implements the Blowfish encryption algorithm.|
|BOX1C|Debug plc|Various box drawing functions.|
|BUTTED|Unknown|xcall butted, string removes all but 0-9 and A-Z.|
|CCOFF|AA UK|Disable Ctrl+C interrupts.|
|CCON|AA UK|Enable Ctrl+C interrupts.|
|CGIUTL|A-Shell|CGI programming utilities.|
|CHKKBD|Misc|Check keyboard; optionally input char if available: xcall chkkbd, flag (B,1) {,char (S,1)}.|



A-Shell Reference 

Page 1785 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|CHKONE|Unknown|Check keyboard to see if character is available.|
|CHKSPL|Unknown|Checks if spooler exists; must use<br>`ALIAS=CHKSPL:PRTCHK`; similar toPRTCHK<br>.|
|CISAM|MS|Interface to CISAM file system.|
|CMDR|Debug plc|Put command file in :R mode.|
|COMIO|MS|Serial port I/O under Windows.|
|COMMON|A-BASIC|Inter-program communication; configurable.|
|CONDEV|A-Shell|Get IP address, console device or machine name.|
|CRC16|ERS|Calculate 16 bit CRC on block of data.|
|CREMLX|ADGAP|Build multi-level index used by SEARCH.|
|CRYPTO|MS|Provides a collection of cryptographic-related functions.|
|DATES|Unknown|Many date conversions, Julian, etc.|



A-Shell Reference 

Page 1786 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|DELCHR|A-Shell|`xcall DELCHR, chrlst, string`removes all the characters that are specified in chrlst<br>from string. See theEDIT$()<br> function for related functionality.|
|DERR|A-Shell|SeeERRMSG<br>.|
|DEVCHK|AA UK|`xcall DEVCHK, dev, status`checks whether an AMOS logical device is defined to A-<br>Shell. The dev parameter should contain the name of the device (e.g. DSK0); on return the<br>status parameter (F,6) will be set to 1 if the device exists or 0 if it does not.|
|DIGEST|A-Shell|Returns various cryptographic digests of strings or files.|
|DSKCOM|A-Shell|Disk-based equivalent ofCOMMON<br>.|
|DSKPPN|Unknown|Return disk and ppn.|
|DSPLY|AA|Display variables with various formats.|
|DSTOI|A-Shell|Convert separated date to Julian.|
|DYNLIB|A-Shell|Loads, unloads, calls routines in external function libraries.|
|EBCASC|Unknown|ASCII-EBCDIC conversion.|



A-Shell Reference 

Page 1787 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|ECHO|A-BASIC|Enter line mode. Turn on terminal echo.|
|EFS|ERS|Encrypted file service.|
|EMAILP|MS|Email a report.|
|EMAILX|MS|Send email.|
|ERRMSG|MS|Error trap reporting routine; must alias to DERR.|
|EVTWIN|MS|Event tracing; seeEvent Tracing<br>.|
|EZSPL|MS|Send file to printer with enhanced options.|
|EZTYP|MS|Display file with paging, 80/132 switching.|
|EXTRAI|Celibec||
|F2HOST|A-Shell|Convert F,6 to IEEE format.|
|FIFO|MS|Named pipe communications under Unix.|



A-Shell Reference 

Page 1788 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|FILL|Unknown|Variation of theFILL$()<br> function;<br>`xcall fill, var, pattern {,length}.`|
|FILNAM|Unknown|Returns file name for the specified channel.|
|FILOCK|AA UK|Front-end toFLOCK<br>.|
|FINB|Debug plc|Input 1 byte from file:<br>`xcall finb, chan, byte, status.`|
|FLOCK|A-BASIC|File/record locking control.|
|FNDUSR|AMOS|Retrieves information about the current (or another) user from the database.|
|FORCE|A-Shell|Force characters into another job’s input.|
|FTPDLX|A-Shell|Deprecated. UseFTP2<br>.|
|FTP2|A-Shell|FTP file transfer, modified version.|
|FUNKEY|MS|Display function key line message.|
|GDIPRT|MS|Send report to AshLite client for printing.|



A-Shell Reference 

Page 1789 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|GET|AlphaSoft|Get single character from keyboard or file.|
|GETADR|MS|Return address and size of variable.|
|GETBYT|Unknown|Read raw bytes from a sequential file.|
|GETDEV|AA UK|Get current device.|
|GETDSK|AA UK|Get current device.|
|GETJOB|AA UK|Get job name, program, ppn, job number.|
|GETJTB|Debug plc|Get job table information.|
|GETLOG|Unknown|Get jobname, number, and ppn; must use<br>`ALIAS=GETLOG:`<br>`GETJOB`<br>.|
|GETMAC|MS|Get MAC (hardware) address of Ethernet controller.|
|GETPPN|AA UK|Get current PPN.|
|GETPRG|MS|Get current program or SBX name.|



A-Shell Reference 

Page 1790 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|GETTRM|MS|Get current terminal name: xcall gettrm, trmdef$.|
|GETUSN|Custom|Get user login name.|
|GETVER|MS|Get current program version.|
|GETX|A-Shell|Get single character with function key translation.|
|GRECNV|SSCI|Various Julian date manipulations.|
|GTJBNO|A-Shell|xcall gtjbno, jobnam, jobno returns job number for specified job name (0 for error).|
|GTLANG|A-BASIC|Return current language information.|
|HASH|A-Shell|Generate a hash code from a string of characters.|
|HOST2F|A-Shell|Convert IEEE 4 or 8 byte float to BASIC 6 byte.|
|HOSTEX|A-Shell|Execute host operating system cmd as a subroutine.|
|HTMLP|MS|View report in browser.|



A-Shell Reference 

Page 1791 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|HTTP|MS|Handle various kinds of HTTP requests.|
|IDTIM|A-BASIC|Input date.|
|IMAGE|A-Shell|Display images of common image file types.|
|INCOM|MS|Variation ofCOMMON<br>.|
|INFLD|MS|Extended Alpha Accounting input routine.|
|INIX|Steve Evans|Read and write to ini files.|
|INMEMO|MS|Memo/Jotter editing/handling routine.|
|INPUT|UK|Identical toINFLD<br>.|
|INPUTC|AA UK|Input variation used in the UK.|
|INVUE|Foxware|Requires<br>`ALIAS=INVUE:INFLD`.|
|ISMBLD|MS|Create ISAM 1.0 file.|



A-Shell Reference 

Page 1792 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|ISMPAR|MS|Return information from the ISAM "rock" about filespec.|
|ISMROK|DMSI|Return information from the ISAM "rock" about currently open ISAM file.|
|ITC|MegaSoft|Send message to another process (Unix only).|
|JSON|MS|Performs various JSON-related utility functions.|
|JOBCMD|MS|Set command to be executed whenever at command level (dot prompt).|
|JOBDAT|InSight|Get information about your job.|
|JOBNAM|Unknown|Equivalent toGETJOB<br>.|
|JOBNUM|AA UK|Return unique job number.|
|JOBTRM|Unknown|Return jobnam, trmdef, tdvnam.|
|JULCVT|Unknown|Julian date conversions.|
|KDAY|AA UK|Calculate elapsed days to given date (b,2).|



A-Shell Reference 

Page 1793 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|LAPSED|AA UK|Calculate elapsed days to given date (F,6).|
|LOKOUT|MS|Lock users out of A-Shell.|
|LOG|MS|Log to a new PPN or retrieve PPN info.|
|LOGRIO|MS|Logical record i/o (any size records).|
|LSTLIN|A-Shell|Return last command line.|
|MATCH|HMOpro|Compares a data field to a list of values or ranges.|
|MESAG|AA|Display message on bottom line of screen.|
|MIAMEX|A-Shell|Large library of A-Shell interface functions.|
|MMENU|AA|Display file maintenance menu.|
|MOUNT|AA|Display device mount message.|
|MPSCOM|Custom|Interface to MacDonald PartSelect catalog.|



A-Shell Reference 

Page 1794 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|MSBOXX|MS|Box and window utility.|
|MSGBOX|MS|Displays a message in a dialog box format.|
|MSGLOG|A-BASIC|Output coded message to SYSLOG.SYS.|
|NFIND|AA UK|Perform string search forwards or backwards.|
|NOECHO|A-BASIC|Enter image mode. Turn off terminal echo.|
|NOEKO|MS|Same asNOECHO<br>.|
|NOP|MS|Does nothing, provides a useful target forALIASSPdirectives for disabling an existing xcall that<br>no longer serves any purpose.|
|NUMCHK|MS|Checks a string for numeric only characters.|
|OAUTH2|MS|Provides the means to obtain an OAUTH2 access token.|
|ODTIM|A-BASIC|Output formatted time and date.|
|PACK|A-Shell|Pack three character string to B,2 RAD50:<br>`xcall pack, str, rad.`|



A-Shell Reference 

Page 1795 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|PCKLST|HMOpro|Display a pop-up pick list.|
|PEEK|Unknown|Wrapper for COMMON.|
|PGMID|MS|Display screen header with program name, time, etc.|
|PGMND|AA|Display end of program message.|
|PLYJOB|MS|Return detailed job info about current or other job.|
|POKE|Unknown|Wrapper for COMMON.|
|PPNSWP|Unknown|Log to a new device:[p,pn]. Must use<br>`ALIAS=PPNSWP:SETPPN`.|
|PRINT|AA|Build formatted print file.|
|PRIV|AA|Dummy routine, same as NOP. Was needed in AA, but not in A-Shell.|
|PRTCHK|AA UK|Check printer name and printer queue.|
|PUTBYT|Unknown|Write raw bytes to a sequential file.|



A-Shell Reference 

Page 1796 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|RDATE|AA|Get system date.|
|REGEX|MS|Regular expression processor.|
|REGEX2|MS|Regular expression processor that acts on a single string subject, pattern and replacement<br>specification|
|RENAM|MS|Same asRENAME<br>.|
|RENAME|A-BASIC|Rename a file.|
|ROUND|Custom|Round argument to nearest integer.|
|RVCOMN|Custom|LikeCOMMON<br>with one 1024 byte packet.|
|RXPCHK|MS|Checks a string for unprintable characters.|
|RXTERM|MS|Check input buffer for function key (Windows only).|
|SBRC|UK|Misc functions used by the R/W and P/G packages.|
|SBXINP|Firmaware|INFLD wrapper that simplifies some INFLD operations.|



A-Shell Reference 

Page 1797 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|SCGINP|Unknown|Variation of INPUT.|
|SCRN|Willowtree|Willowtree Screen Handler.|
|SCRSTS|MS|Scrolling status window handler.|
|SEARCH|ADGAP|Enhanced (disk optimized) variation of SERCH.|
|SEND|A-Shell|Send a message to another terminal.|
|SERCH|AA|Search random data file.|
|SETDEV|AA UK|Change current device: xcall setdev, « dsk2 ».|
|SETJTB|Debug plc|Set job table information.|
|SETPPN|AA UK|Change current PPN: xcall setppn,b2.|
|SIZE|A-Shell|Returns size of specified file in bytes.|
|SLEEP|A-BASIC|Stall processing for number of seconds.|



A-Shell Reference 

Page 1798 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|SORTIT|MegaSoft|Sort array in memory.|
|SPOOL|A-BASIC|Send file to printer. SeeEZSPL<br>.|
|SQUEEZ|MS|Implements the data "squeeze" algorithm used by MX_FILEHOOK.|
|SQL|MS|Provides access to SQL databases.|
|SRCH2|AA|Search random data file.|
|STALL|AA|Stall processing for number of seconds.|
|STENO|AA|Input starting/ending numbers.|
|STIME|Dalcon|Return current time in formatted string.|
|STRIP|A-BASIC|Strip trailing spaces from string.|
|STRTOK|MS|Parse strings.|
|SUBMIT|Custom|Launch a background task (Unix only).|



A-Shell Reference 

Page 1799 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|SWPSBR|Swap|Various Swap-related functions.|
|SYS000|Misc|Like COMMON (one packet, passive read):<br>`xcall sys000, sr (b,1), packet`<br>`(x,100).`|
|TBOX|Misc|Draw box around specified SR,SC,ER,EC.|
|TCKI|MS|Check to see if an input char is available without inputting it;<br>`xcall tcki, flag; flag`<br>returns 0 if no char is available, 1 if one or more chars are available.|
|TCPCLI|MS|Socket communications (client interface).|
|TCPSRV|MS|Socket communications (server interface).|
|TCPX|MS|Socket communications.|
|TIMES|MS|Returns high-precision time information.|
|TINKEY|AlphaSoft|Check for terminal input.|
|TMENU|AA|Display full transaction menu.|
|TMEN2|AA|Display partial transaction menu.|



A-Shell Reference 

Page 1800 

|**Routine**|**Origin**|**Function**|
|---|---|---|
||||
|TRIM|Debug plc|Strip trailing and leading spaces from string.|
|TRMCHR|A-BASIC|Return terminal characteristics.|
|UNIQUE|Unknown|Generate unique temp filename.|
|UNPACK|AA UK|Unpack RAD50 word, e.g. xcall unpack,b2,s3.|
|USPSBS|MS|Creates an encoded bar string for the US Post Office intelligent bar codes.|
|USRCNT|MS|Get current user count and number of nodes licensed.|
|USRTBL|Custom|xcall usrtbl, name, code, opcode.|
|VUESCR|Swap|Edit a rectangular array of text.|
|WAIT|AA|Output "Please wait...." message.|
|WAKNO|MS|Wake up a sleeping job (Unix only).|



A-Shell Reference 

Page 1801 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|WHOAMI|AA UK|Get job name.|
|WINFLG|InSight|Get InSight information about your job.|
|XCALEN|MS|XTREE-based enhanced calendar control|
|XDEFLT|MS|Insert text into the type-ahead buffer.|
|XFOLD|HMOpro|Intelligent folding of names.|
|XFRMMO|MS|Move or copy an INMEMO logical memo.|
|XLOCK|A-BASIC|Shared resource control.|
|XLSUTL|MS|Used internally by APEX, not suitable or intended for use in programs. Do not use!|
|XMOUNT|A-BASIC|Mount a device. Dummy routine.|
|XMPP|MS|Ennables the sending of instant messages using the XMPP protocol.|
|XOAUTH2|MS|Enhanced version of OAUTH2.|



A-Shell Reference 

Page 1802 

|**Routine**|**Origin**|**Function**|
|---|---|---|
|XOKEY|Omniledger|Wrapper for COMMON.|
|XPAINT|MS|Execute an AlphaPAINT 2.0 screen display.|
|XPPN|Unknown|Get ppn, device, job, term.|
|XRUNLOG|MS|Enables customized activity tracking.|
|XSHLEX|MS|Platform-independent "Shell Execute."|
|XSTRIP|MS|Perform various string manipulations.|
|XTEXT|MS|Windows text control.|
|XTREE|MS|Windows tree control.|
|XUSER|Omniledger|Wrapper for COMMON.|



A-Shell Reference 

Page 1803 

## **INTRODUCTION TO SUBROUTINES** 

ASB programs rely heavily on the use of subroutines to perform functions from the simple STRIP (strip trailing spaces from a string) to the more complex BASORT (sort sequential and random data files). In the days before A-Shell, subroutines were disk files with the extension SBR, and traditionally lived in DSK0:[7,6] (BAS:). When a program called a subroutine, it was loaded from disk if necessary, and processed from the beginning. 

Subroutine handling under A-Shell is functionally identical: your program invokes a routine, and A-Shell calls to its start. 

With some exceptions, for which see the following topic Calling External Subroutines, A-Shell subroutines do not exist as separate files; they are, instead, linked into the A-Shell object module and are therefore always available. 

A-Shell comes with several hundred subroutines, including nearly all of the so-called Alpha Accounting routines from [7,60] and the so-called "standard A-BASIC subroutines" from [7,6]. It also includes the most popular MicroSabio subroutines (INFLD, INMEMO, EZSPL, MSBOXX), plus a variety of routines that have been written specifically for A-Shell. In addition, A-Shell includes many third-party subroutines that have been converted over the years as more firms and developers have migrated to A-Shell. 

This document lists the most commonly used routines, and provides detailed documentation for most of them. Those not listed were skipped because they are too obscure or are specific to individual users. 

If there is a function that you need and do not see, be sure to inquire about it before writing your own. 

## **Subtopics** 

- Parameter Types 

- Calling External Routines 

- Additional Subroutine Topics 

A-Shell Reference 

Page 1804 

## **PARAMETER TYPES** 

Parameters used in subroutines and functions are normally passed By Value, which allows ASB to convert between the data types supplied by the caller and those expected by the routine, and vice versa for any parameters passed back. The mechanism is similar to the automatic data type conversion that occurs in assignment statements, where the rvalue is reduced to a string or floating point expression on the stack and then converted to the lvalue type to carry out the assignment. In the parameter passing case, the type conversion involves a matrix of from/to transformations carried out independently from stack. 

Overall, this affords the caller considerable—but not unlimited—flexibility in the choice of data types. For example, a subroutine that receives a Centigrade temperature and returns the Fahrenheit equivalent would accept any data type that can represent a number. But unless the type can also accommodate negative and fractional numbers, the accuracy and precision of the result will be compromised. A more extreme case occurs with parameters passed By Reference where the from and to types must match exactly. In an attempt to convey these kinds of requirements in abbreviated form, the subroutine documentation uses the following parameter type names—essentially a superset of Data Types. In all cases, the size of the data type needs to be sufficient for the range of possible values. 

Note that for read-only parameters passed by value, you can normally specify a string or numeric expression (of arbitrary complexity) rather than a variable of one of the prescribed data types, as long as the expression result is compatible with the parameter type expected by the subroutine. Actually, variables are only required for return parameters, or for more complex parameter types that can't be represented by an expression value such as arrays, collections, BLOBs, etc.). 

Also note that the following table provides brief descriptions while the popups referenced in column one provide, when needed, more details. 

|**Parameter Type**|**Description and Corresponding Data Type(s)**|
|---|---|
|String|Normally data type S, or possibly X.|
|Number|Any data type that can represent a number, including string.|



A-Shell Reference 

Page 1805 

|**Parameter Type**|**Description and Corresponding Data Type(s)**|
|---|---|
|Integer|Same range of data types as Number.|
|Integer-Signed|Same as Integer but excluding the unsigned B types.|
|Integer-Unsigned|Same as Integer but makes clear that B types are acceptable.|
|Bitmap|Same as unsigned integer but specifically for values representing collections of bit flags.|
|Structure|A MAP layout, or preferably, aDEFSTRUCT<br>.|
|BLOB|A series of raw bytes, typically stored in an X variable.|
|Array|Several variations. See popup at left and documentation for specific routine.|
|Collection|ORDMAPs,GRIDMAPs,MLISTs, etc.|
|<Explicit Data<br>Type>|For parameters passedBy Reference<br> (collections,DIMXarrays, some legacy subroutines),<br>the parameter type must precisely match an explicit data type, in which case the routine<br>documentation will specify the data type instead of a more general parameter type.|



A-Shell Reference 

Page 1806 

## **CALLING EXTERNAL ROUTINES** 

A key feature of ASB is the XCALL statement, which provides the ability to call routines that are external to the current program. The feature was included in the original BASIC to allow calling of subroutines written in assembly language, which could perform low-level or CPU-intensive actions that were not otherwise possible in BASIC. In the A-Shell environment, no one writes code in assembler any more, but the feature is widely used for: 

- Calling one of the hundreds of subroutines written in C by MicroSabio and which are embedded in the A-Shell run-time 

- environment. Many of these are rewritten versions of assembler routines which were popular in older environments, such as BASORT, INFLD, SPOOL, etc. 

- Calling subroutines written in ASB by independent developers, which are compiled into .SBX modules that are loaded from 

- disk on demand and subsequently cached in memory. 

A-Shell supports the following syntax variations of the XCALL statement: 

## **xcall NAME {,arg1, arg2, ... argN}** 

## **vxcall <stringexpr> (arg1, arg2, ... argN)** 

The first variation, with the parameter list separated from the subroutine name by a comma, is the original syntax supported all the way back to BASIC 1.3. The second variation, with the parameter list enclosed in parentheses, is an A-Shell extension; see History, below. The third variation, VXCALL, is another A-Shell extension that differs from XCALL in that the subroutine name is a - string variable interpreted at run-time, rather than a literal interpreted at compile-time; see Calling Variably Named Routines for more information. 

## **Parameters** 

## _name_ 

The literal name of the subroutine, made up of one to ten characters alphabetic and numeric characters. The first character must be alphabetic, case insensitive. Must match the name of a subroutine embedded within A-Shell, or the name of an external subroutine with an SBX extension. Traditionally, subroutine names were limited to six characters and were compiled into 4 rad50-encoded bytes in the RUN file. The standard search path for SBX modules is: current [p,pn], then [p,0], then dsk0:[7,6]. 

A-Shell Reference 

Page 1807 

An alternate search path variation can be enabled with the SBX_RUNDIR flag (current [p,pn], .RUN location, then dsk0:[7,6].) Once the SBX is located on disk, its modification timestamp is compared to the previously-cached version in memory (if present), and the file is loaded from disk if necessary. Otherwise, the cached version is reused, reducing the calling overhead for subsequent calls dramatically. 

## _stringexpr_ 

A variable or expression evaluating to the name of the subroutine; one to ten alphabetic and numeric characters, case insensitive, no extension. 

## _arg1, arg2, ... argN_ 

From 0 to 1023Expressions passed as arguments to the subroutine. Any arguments passed in the form of variables may potentially be updated by the routine, although it is impossible to know which ones just from looking at the subroutine statement syntax. 

## **See Also** 

- Introduction to Subroutines 

- SBX Subroutines 

- Call SBX as a Function 

- Named Parameters 

- XFUNC() 

- SBX_RUNDIR 

## **History** 

- 2014 October, A Shell 6.1.1392, compiler edit 718: You may now optionally use procedure-style syntax with the XCALL statement. In other words, instead of: XCALL NAME,ARG1,...ARGN, you can instead use XCALL NAME(ARG1,...ARGN). The advantage of the alternate syntax is perhaps mainly aesthetic, but will seem more natural to programmers coming from other language backgrounds. 

A-Shell Reference 

Page 1808 

## **EXTERNAL SUBROUTINE LIST** 

As described elsewhere, A-Shell includes two types of subroutines: 

• Those that are "internal" to A-Shell—i.e., are part of the main A-Shell program. They do not exist as discrete programs, are written in C, are linked in to the main A-Shell executable program, and are cannot be modified by users. 

• The "external" routines are not part of "core A-Shell," exist as separate files and programs, were written in ASB, and can modified if needed. A set of these external routines is provided with A-Shell, and you can see the run files with the extension SBX in DSK0:[7,6]. Source code for the routines may be found in the A-Shell SOSLIB. 

The following table alphabetically lists A-Shell’s external subroutines, most of which have links to more detailed information. 

|**Routine**|**Function**|
|---|---|
|APRNTSCRN|Screen Capture.|
|APXTEDIT|Documentation pending.|
|ASEXIT|A hook routine that will be called automatically just before A-Shell exits.|
|ATEAPX|Transfers a file from application server to ATE client PC.|
|ATECFX|ATE configuration dialog. SeeATE Reference<br>.|
|ATEGFK|Retrieves a file from the PC via the ATE terminal connection.|
|ATEPRT|Documentation pending.|



A-Shell Reference 

Page 1809 

|**Routine**|**Function**|
|---|---|
|ATEREG|Query and/or update ATE configuration.|
|ATHTTP|A variant ofHTTP<br>, which see for details.|
|ATPXFR|Documentation pending.|
|ATSYNC|Documentation pending.|
|AUXEXC|Documentation pending.|
|CSV2XL|Converts CSV files to XLS format.|
|EMAILP|Email a report.|
|EVTMSG|Documentation pending.|
|FNDUSR|Retrieves information about the current (or another) user from the database.|
|INIX|Read and write to ini files. Thanks Steve Evans!|
|ISMBLD|Create ISAM 1.0 file.|



A-Shell Reference 

Page 1810 

|**Routine**|**Function**|
|---|---|
|ISMPAR|Return information from the ISAM "rock" about filespec.|
|PDFLPR|Documentation pending.|
|PRTMAPI|Documentation pending.|
|PRTXLS|Exports reports from APEX (A-Shell's enhanced screen display) to XLS file.|
|PXLCFG|Documentation pending.|
|SBXINP|INFLD wrapper that simplifies some INFLD operations. Thanks Jorge Tavares!|
|SCRSTS|Scrolling status window handler.|
|XSHLEX|Platform-independent "Shell Execute."|



A-Shell Reference 

Page 1811 

## **APRNTSCRN** 

_Written January 2024_ 

## **xcall APRNTSCRN {, hwndmain, hwnddlg, prgname, progver}** 

APRNTSCRN.SBX is a screen capture routine specifically targeted at A-Shell applications, designed to facilitate both tech support and documentation. By default it is linked into the File menu, but can be called explicitly like any other external (SBX) subroutine. 

## **Parameters** 

_hwndmain_ (Num)  [in] 

Optional main window handle. Omit or 0 to default. Interacts with the user interface option to use the main window as the source for the capture. 

_hwnddlg_ (Num)  [in] 

Optional main dialog handle. Omit or 0 to default. Interacts with the user interface option to use the main dialog as the source for the capture. 

_prgname_ (String)  [in] 

Optional name of the current program. Omit or "" to default. Gets added to the email or file output, intended as clarification for tech support. 

_prgver_ (String)  [in] 

Optional current program version. Omit or "" to default. Gets added to the email or file output as with _prgname_ . 

## **See Also** 

- Print Screen for example of its user interface and details on its external configuration options 

A-Shell Reference 

Page 1812 

## **ATEREG** 

_Written January 2024_ 

## **xcall ATEREG, opcode, status, valuename, valuedata** 

## **xcall ATEREG, opcode, status {, "", config}** 

ATEREG.SBX applies only to ATE connections, allowing an application to query and/or update the ATE configuration for the current session, provided the client has the necessary privileges to access its Windows Registry. ATE configuration details are stored in the Registry on the ATE client. 

## **Parameters** 

_opcode_ (Num)  [in] 

## Operation to perform: 

|**Opcode**|**Syntax**|**Function**|
|---|---|---|
|0|First|Get Value.|
|1|First|Update Value.|
|2|Second|Get Scope (All vs Current User).|
|3|Second|Conditional Copy Scope; from All to Current User, only if Current User version doesn't exist.|
|4|Second|Unconditional Copy Scope; from  All to Current User, replacing an existing Current User|



A-Shell Reference 

Page 1813 

|**Opcode**|**Syntax**|**Function**|
|---|---|---|
|||version.|
|5|First|Change a single-value entry in the ATE client miame.ini.|



## _status_ (signed Num)  [out] 

## Return status: 

|**Status**|**Meaning**|
|---|---|
|0+|Ok.|
|-1|ATE or GUI environment required.|
|-2|Host file doesn't exist.|
|-3|File transferred but failed to verify afterwards.|
|-4|FTP transfer failure.|
|-95|Malformed response from ATE [101].|



A-Shell Reference 

Page 1814 

|**Status**|**Meaning**|
|---|---|
|-96|Valuename not defined for opcode 0 [101]).|
|-97|Unsupported opcode.|
|-98|Server A-Shell version not high enough for binary<br>transfer.|
|-99|ATE version not high enough.|
|<-100|ASB error offset by 100.|
|<-1000|Windows errors related to registry.|



For _opcode_ 0 and 1, status >= 0 indicates success, else failure. 

For _opcode_ 2, status 1 indicates the configuration scope is current user only; 2 indicates all users. 

For _opcode_ 3, status 1 indicates that the current user configuration already exists (copy skipped) 

For _opcode_ 3 and 4, status >1 indicates success (number of items in the configuration copies). 

For _opcode_ 5, status -1 indicates a value that cannot be changed this way (e.g. DEVICE); 0 indicates that _valuename_ was not previously set, 1 indicates it was previously set (now updated). 

_valuename_ (String)  [in] 

A-Shell Reference 

Page 1815 

Name of value to query or update, e.g. "CfgPassword". Use the ATE Configuration dialog Export button to export a configuration to a text file in order to see the available value names. 

_valuedata_ (String or Num)  [in/out] 

Value retrieved or to be updated. 

_config_ (String)  [in] 

Configuration name 

## **Comments** 

The subroutine needs to run on the client side in order to be able to easily access the client Registry and/or miame.ini file, but is typically called from the application running on the server. To bridge that gap, the routine automatically syncs itself from the server to the client; the server then remotely calls it on the client, which relays the result back to the server. 

The source code for this routine is available here: ATEREG.BP in SOSLIB:[907,33]. 

A-Shell Reference 

Page 1816 

## **ADDITIONAL SUBROUTINE TOPICS** 

## **Subroutine Name Length** 

Subroutine names may be up to 10 characters long. This is accomplished by automatically converting subroutine statements with names between seven and ten characters long to VXCALL statements. This feature requires /X:2 and is not supported by /RC. 

Note the potential for a backwards compatibility problem if you start using longer names in your subroutine statements and then try to RUN the resulting RUN files on an earlier version of A-Shell, which will only be looking at the first 6 characters. Presumably that would cause an SBX not found error, unless there happened to be an existing routine that matched the first six characters. For this reason, when using seven to ten character SBX names, you should avoid picking names for which an existing SBX would match the first six characters. 

## **Creating Subroutines** 

A-Shell also supports external, dynamically-loaded subroutines which you can write in BASIC and which are called in the exact same way from within your program. These routines have an extension of SBX, so named to avoid confusion with the SBR extension used under AMOS. See SBX Subroutines for information on writing your own routines. 

## **Configurable Subroutines** 

Some of the routines have been modified by developers for their own purposes. In order to make those changes and improvements available to all A-Shell users, many of the more common and useful modifications have been implemented as configurable patches. These are specified using the SBR directive in the system configuration file. The subroutines which have configurable functionality are: 

INFLD MESAG COMMON BASORT XLOCK ODTIM SERCH LSTLIN JOBNAM PRINT TRIM PRTCHK 

A-Shell Reference 

Page 1817 

## XPPN 

## ASHELL 

The subroutines GETJTB, SETJTB and PRTCHK are supplied for use under AMOS in the AMOS subdirectory. It is hoped that this will ease the writing of portable code. In particular, use of GETJTB can eliminate the need for many of the GETxxx routines to get information about your job, terminal, ppn, etc. 

A-Shell Reference 

Page 1818 

## **DEPRECATED SUBROUTINES** 

Although it is fairly rare, subroutines can become obsolete. We here at MicroSabio are reluctant to ever delete things from the documentation, out of fear that the old things might be needed for something by somebody sometime. But we also want to not "clog up" our documentation with old and useless information. So the compromise is to put all the old stuff in some out-of-theway corner where it can be accessed but where it isn't in the way of regular readers. 

Congratulations! You have stumbled onto just such a place, and you will find all of the no-longer-mainstream subroutines in this section and in the following list. 

## **AMOS** 

As of July 2024 and A-Shell 7.0.1761, AMOS has been renamed to ASHELL, which see for details. To maintain backward compatibility, AMOS is now an alias for ASHELL. 

## **MX_XCBDATAX** 

## **Deprecated** _._ 

## **xcall MIAMEX, MX_XCBDATAX, xcbadr, opcode, parmno, var** 

MX_XCBDATAX (MIAMEX 81) This function provides a means for an SBX to retrieve parameters passed to it from the calling program, and to pass parameters back. It remains supported but has been deprecated since A-Shell version 6.0, having been - superseded by the family of X ARGs which offer several advantages, including working with Functions and Procedures as well as SBXs. 

## **Parameters** 

_xcbadr_ (Num) 

A-Shell Reference 

Page 1819 

must be set to the address of the parameter structure. This value is passed on the command line to the SBX routine. 

_opcode_ (Num) 

0 (mxop_get) to retrieve a parameter or 1 (mxop_set) to pass it back. For convenience, these values are mapped in the xcall.bsi file as _xcbget_ and _xcbput_ , respectively. 

_parmno_ (Num) 

is the number of the parameter to receive or send, starting from 1. 

## _var_ 

is the actual variable to receive or send. It should be mapped in a way that is "reasonably compatible" with the actual type and size passed to the subroutine, although conversions and truncations will be applied automatically if necessary. 

## **See Also** 

- SBX Subroutines. 

## **MX_XCBINFOX** 

_Modified July 2017_ 

**Deprecated** . See _Comments_ below. 

## **xcall MIAMEX, MX_XCBINFOX, xcbadr, xcbcnt, xcbstructx** 

COMX_XCBINFO (MIAMEX 80) is needed at the start of an SBX subroutine to retrieve information about the parameters which were passed to the subroutine. Because every subroutine needs this information, the xcall.bsi file which is included by every subroutine includes a call to this function. 

## **Parameters** 

A-Shell Reference 

Page 1820 

_xcbadr_ (Num) 

must be set to the address of the parameter structure. This value is passed on the command line to the SBX routine. 

_xcbcnt_ (Num) 

returns the number of parameters passed. 

## _xcbstructx_ 

is a structure containing information about the parameters, mapped as follows: 

```
MAP1 XCBSTRUCTX
```

```
MAP2 XCBSTRUCT(20)         ! up to 20 parameters
   MAP3 XCB'PTYPE,b,2      ! 0=X, 2=S, 4=F, 6=B, +8=I, +16=array
   MAP3 XCB'PSIZE,b,2      ! size of parameter
```

## **Comments** 

This function is still supported but has been deprecated since the introduction of the .ARGCNT dot variables and the .ARGTYP() and .ARGSIZ() functions which are more elegant and preferred. See _History_ . 

Refer to Writing SBX Subroutines for more information on this and related MIAMEX functions. 

## **History** 

- 2017 July, A Shell 6.4.1553: XCB'PTYPE() is now stripped to just the low 5 bits (4 bit type code and 1 bit array flag) to avoid confusion with values that were not defined when this function was implemented. See .ARGTYP() and .ARGSIZ() for the latest complete set of argument type flags. 

- 2014 January, A Shell 6.1.1373.0:  Add .ARGTYP() and .ARGSIZ() dot functions; MX_XCBINFO now deprecated. 

A-Shell Reference 

Page 1821 

## **FTPDLX** 

With A-Shell 7.0.1754, FTPDLX is officially deleted. All calls to FTPDLX are re-directed to FTP2, which see for details. The original FTPDLX documentation has been left in place. 

A-Shell Reference 

Page 1822 

## **ABOX** 

## **xcall ABOX, srow, scol, height, width {,opcode}** 

ABOX is one of the many routines which draw boxes—among which, MSBOXX would be the most sophisticated and generally preferred. Note that ABOX draws the box _at_ the specified position rather than _around_ it. 

## **Parameters** 

_srow, scol_ [in] 

starting row and position 

_height, width_ [in] 

(not ending row/column) 

_opcode_ [in/out] 

Without an opcode, the default, ABOX will just draw the box border. If _opcode_ is specified and non-zero, the interior of the box will also be cleared. On return, _opcode_ will be set to the number of bytes written, or less than zero for errors 

A-Shell Reference 

Page 1823 

## **ACCEPT, ACCEPN** 

## **xcall ACCEPT, key {,xlt}** 

## **xcall ACCEPN, key {,xlt}** 

ACCEPT is an enhanced version of the BASIC subroutine of the same name which inputs a single character from the keyboard. One of the enhancements is that the _key_ parameter, in addition to the normal floating point type, can also be a one byte string. Two additional enhancements relate to the optional _xlt_ parameter, which must be of type String. If you pass it as a threecharacter string, such as "IFX", then the routine will translate any input sequences using the function key translation table DSK0:<tdvname>.<XLT string>[7,0]. For example if _xlt_ is "IFX" and the current terminal driver is "AM62A", then it would use DSK0:AM62A.IFX[7,0]. If you pass _Xlt_ as a null string, then there will be no function key translations, but it will still use the "cooked" input routine, which operates at a higher level than the "raw" routine used when _xlt_ is not specified at all. The "cooked" routine, for example, will return characters left over from prior function key translations. In no case, though, will ACCEPT (or ACCEPN) return input from a command file. 

ACCEPN is the same as ACCEPT, except that it does not echo the character input. ACCEPT will echo the character, unless it is an unprintable character. 

## **See Also** 

- GETXS  (keyboard or file input) 

- GETKEYXS 

- GETXXS 

- TINKEYXS 

A-Shell Reference 

Page 1824 

## **ACCESS** 

## **xcall ACCESS, mnustr, char, extflg {,row, col}** 

ACCESS is a handy utility for implementing single-line, single-character selection menus. The menu is made up of one or more choices, where each choice is displayed as a single upper case character followed by a close parenthesis and one or more lower case characters. The upper case characters are used to make the selections, and must be unique. A typical menu might look something like this: 

```
A)dd C)hange D)elete Q)uit
```

## **Parameters** 

_mnustr_ (null terminated String of appropriate length)  [in] 

must be formatted exactly as displayed (see example above) except that the spaces between the items are optional. Also, the string may begin with one or more of the following shortcut letters (with no following parentheses): 

|**Shortcut**|**Displays as**|
|---|---|
|A|`A)dd`|
|C|`C)hange`|
|D|`D)elete`|
|S|`S)can`|
|I|`I)nquiry`|



A-Shell Reference 

Page 1825 

|**Shortcut**|**Displays as**|
|---|---|
|X|`X)ternal`|
|L|`L)ist`|



For example, if _mnustr_ = "ACDLP)ostQ)uit" the menu would appear as: 

```
A)dd C)hange D)elete L)ist P)ost Q)uit
```

## _char_ (String,1)  [in/out] 

may be loaded with the character corresponding to the default option, and will be returned with the character entered by the user to make a selection. The user must enter one of the upper case characters in the list, or use BACKSPACE, ESCAPE, or a function key to exit. 

_extflg_ (F,6)  [out] 

will return 0 if a normal menu selection was made, or 1 if BACKSPACE or ESCAPE was hit, or a number in the range of negative 1 to negative 32 if a function key is hit. In order for the function keys to be accepted, you must have a <tdvname>.IFX file in the LIB: account which maps function keys according to the INFLD scheme (e.g. F1 = (CTRL+G)+(CTRL+A), F2 = (CTRL+G)+(CTRL+B), etc.). 

## _row, col_ [in] 

may be optionally used to specify the starting position to display the menu. If _row_ is 0 or not specified, the menu will be displayed starting from the position of the cursor at the time of the call. 

A-Shell Reference 

Page 1826 

## **ANYCN** 

## **xcall ANYCN, cngctl, whatno** 

ANYCN is used in many AlphaAccounting-derived programs to ask if the operator wants to make any changes before updating a record, and if so, which field number. The A-Shell implementation of ANYCN is pretty faithful to the original, except for a couple of extensions: support of foreign languages via the SBRMSG.lan file, and support of function key response codes. For convenience a complete summary of the functionality follows. 

## **Parameters** 

## _cngctl_ [in/out] 

## Controls variations of the function as described below: 

|**Value**|**Meaning**|
|---|---|
|1|Display the message "Any Change?" on line 24; allow the input of affirmative, negative, or a number. If an<br>affirmative response given, the operator is then prompted for "What Number?" If a number is entered, it is<br>treated as if an affirmative response was first given and then the number was entered at the "What<br>Number?" prompt.|
|2|Same as for 1, except that there is no option to input a number – only negative and affirmative responses<br>are allowed.|
|3|Display the message "INVALID SELECTION" and then proceed to prompt as if CNGCTL was set to 1.|



On return from the routine, _cngctl_ will be set to –1 if ESCAPE was entered, 0 for a negative response and 1 for an affirmative response. 

A-Shell Reference 

Page 1827 

## _whatno_ [out] 

If _cngctl_ is one, _whatno_ will be set to the number entered. If a function key is entered and the <tdv>.IFX function key translation file has been set up using the INFLD standard for function keys (i.e. F1 = (CTRL+G)+(CTRL+A), F2 = (CTRL+G)+(CTRL+B), etc.) then the negative of the function key number will be returned in _whatno_ (e.g. F1 returns –1, F2 returns –2, etc.). 

A-Shell Reference 

Page 1828 

## **ASEXIT** 

_Written August 2025_ 

## **xcall ASEXIT, jcbrec** 

ASEXIT.SBX is a hook routine that will be called automatically—if it exists in the BAS: directory—just before A-Shell exits, allowing you to perform any kind of housekeeping or other administrative work. 

## **Parameters** 

_jcbrec_ (ST_JCBREC)  [in] 

Contains a copy of the JOBTBL record for the current job. See JOBTBL.SDF in SOSLIB:[907,16]. 

## **Also see** 

- XRUNLOG 

- Hooks 

## **History** 

- 2017 February, A Shell 6.3.1544: Interface added to A-Shell 

A-Shell Reference 

Page 1829 

## **ASFLAG** 

## **xcall ASFLAG, flag** 

ASFLAG allows a program to set various internal A-Shell options that do not fall conveniently under another category. 

## **Parameters** 

## _flag_ (Num)  [in/out] 

One or more flags to set from the following table. Note that if _flag_ is mapped as B,2 or B,4, then the previous _flag_ settings will be returned in the variable; this is useful when you want to temporarily change the flags and then restore them. 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|||Same as 1 if omitted (i.e.<br>`xcall ASFLAG`equals<br>`xcall ASFLAG,1`).|
||&h00000|Turn off all flags.|
|AF_READONLY|&h000001|Turn on Read Only<br>.|
|AF_SYNCWRITE|&h000002|Turn onSynchronized Write<br>mode for D-ISAM.|
|AF_DIVIDEBY0|&h000004|Allow divide by zero. Treats a division by zero as equal to zero, rather than generating an<br>ASB error. This is the runtime equivalent of the_BASICplus_compile-time source directives<br>DIVIDE’BY’0andNO’DIVIDE’BY’0.|
|AF_EXITSBX|&h000008|Force exit to dot from SBX.|



A-Shell Reference 

Page 1830 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|AF_MMAP|&h000010|Memory Mapping<br>.|
|AF_NOIDXLOK|&h000020|No IDX Lock<br>.|
|AF_LOCALCOPY|&h000040|Make Local Copy<br> of file (Windows only).|
|AF_SETCTRLC|&h000080|May be used within an SBX subroutine to force aForce Ctrl+C to Parent<br> program (on<br>return from the SBX).|
|AF_NOMMAP|&h000100|Turn off memory mapping (overriding theMMAPLIST<br>setting inmiame.ini) for any files<br>subsequently opened in the current program.|
|AF_CRYPT|&h000200|Encrypt on allocate, disam create. Only applies to versions of A-Shell which support the<br>Encrypted File System (EFS). Contact MicroSabio for more info.|
|AF_NOCRYPT|&h000400|Override m1.crypt flags. Only applies to versions of A-Shell which support the Encrypted<br>File System (EFS). Contact MicroSabio for more info."|
|AF_CSVNOQUOTE|&h000800|Disables all special handling of double-quote characters (ASCII 34, or "), treating them as<br>ordinary data characters.|
|AF_CSVSMARTQUOTE|&h001000|_Obsolete as of A-Shell 5.1.1163 of October 09. In prior versions:_Enables "smart"<br>handling of double-quote characters. A-Shell looks at the context of the line to guess<br>whether a double-quote character is being used to enclose a field (that may contain|



A-Shell Reference 

Page 1831 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|||special characters, including line breaks), or it is simply an ordinary data character.|
|AF_MMAPIDXROOT|&h002000|Memory map just the critical root section of ISAM IDX; also see AF_MMAP.|
|AF_NOSTREAMEFS|&h004000|Bypass EFS for stream functions (EFS only)|
|AF_ISAMNODUPERRS|&h008000|Modifies the behavior of the ISAM-A CREATE'RECORD statement. Normally, if the record<br>already exists (and duplicates not allowed), it returns ASB error 208 (attempt to add<br>duplicate key). With the AF_ISAMNODUPERRS flag set, CREATE'RECORD will instead just<br>return FSTAT=2 but no ASB error. The motivation is mainly to improve performance of<br>certain specialized file build operations where you want to add a record if it doesn't exist<br>but do nothing if the record does exist. Setting the flag allows the program to eliminate a<br>FIND operation prior to each CREATE'RECORD, which may significantly increase the build<br>speed.|
|AF_SBXASRUN|&h010000|Set SBX as Run<br>.|
|AF_SQLPERSIST|&h020000|Don't auto-close SQL connections.|
|**Definition file: ashell.def**|||



**Comments** 

A-Shell Reference 

Page 1832 

- This subroutine was first introduced as SETRO since its only function was the "Set Read Only" mode. ASFLAG is backward 

- compatible with SETRO, so you can either change the name in your source code or alias it in miame.ini (e.g. `ALIAS=SETRO:ASFLAG` ). 

- A technique related to the memory mapping and local file schemes described above for speeding up single-user or read-only 

- access to a file is that of loading a file into user memory (with LOAD.LIT or MX_USRLOD) and then accessing it via the MEM: device. 

- All flags are reset at the start of each RUN program. Otherwise, unless modified by a subsequent ASFLAG operation, they 

- remain set for the duration of the current program. 

- The ASFLAGs are not cleared at the start of SBXs. Thus changes during the execution of a RUN or SBX will be passed down to 

- lower level subroutines, but they do not percolate back up. 

## **Subtopics** 

- Read Only 

- Synchronized Write 

- Memory Mapping 

- No IDX Lock 

- Local Copy 

- Force Ctrl+C to Parent 

- SBX as Run 

A-Shell Reference 

Page 1833 

## **READ ONLY** 

This mode causes any files opened subsequently for Random’Forced access within the current program to be treated as if the Read’Only open _flag_ had been specified. Since Read’Only was not introduced into BASIC until late in the game, some developers use ASFLAG instead to maintain source code compatibility with early versions of the BASIC compiler, supplying a dummy version of ASFLAG. 

The original motivation for Read'Only was strictly to avoid file locking conflicts in a program that was merely reading records and did not care whether they were locked, such as in a report. Under A-Shell/Unix, this is the default behavior anyway, so the original motivation is only applicable to Windows platforms. However, there is another motivation for this mode, which applies to all networked A-Shell platforms: it can dramatically speed up file access, even if there are no other users accessing the same file. The reason has to do with eliminating the need for communication between the client process and the locking daemon on the server, which is especially slow under NFS and some Windows networks. Experimenting with this is relatively simple, since you can always "remove" the ASFLAG calls by simply aliasing ASFLAG to a null subroutine, like PRIV (e.g. `ALIAS=ASFLAG:PRIV` ). 

A-Shell Reference 

Page 1834 

## **SYNCHRONIZED WRITE** 

This mode only applies to ISAM-A files implemented under D-ISAM. When activated, it forces any write operation to wait until the data has actually been committed to disk before returning to the program. This will dramatically slow down access but might be useful in certain networked situations where you want to eliminate the possibility of a user on another CPU reading an outdated copy of the data due to buffer synchronization problems. It may also be useful in extremely critical applications where you cannot afford the possibility that a system crash will leave a lot of uncommitted updates stranded in memory. 

A-Shell Reference 

Page 1835 

## **MEMORY MAPPING** 

This activates automatic memory mapping for any files subsequently opened within the current program. Option AF_MMAP (&h010) causes the subsequently opened random files to be "memory mapped." Memory mapping is a technique used very effectively on Unix systems to greatly speed up file access. Essentially it makes the file act like virtual memory, such that you can then access it with memory (rather than disk) operations. This eliminates most of the overhead of disk service calls (which under Unix require a context switch to supervisor mode, and under Windows networks may require machine-to-machine messaging). The advantage is most pronounced in files which are accessed very frequently and have small record sizes. For this reason, A-Shell uses memory mapping on the qflock.sys and jobtbl.sys files under Unix. 

There are, however, two downsides to memory mapping. The biggest one only affects Windows, where the memory "view" of a file is not kept coherent with the disk "view" of the file. Thus it is not a good idea to use this technique in multi-user mode, unless you are only planning to read from a file. 

The second downside is that it causes a lot of memory to be allocated, which may decrease overall efficiency of the system if it is used too much. (If the total size of memory mapped files exceeds available memory, the system will begin to "thrash", which is not a pretty sight.) 

A-Shell Reference 

Page 1836 

## **NO IDX LOCK** 

This was implemented mainly as a test to see if ISAM access in a non-LOKSER environment could be significantly improved by not bothering to place a lock on the IDX "rock" when performing an ISAM operation. In theory, this simulates the way it works under AMOS when LOKSER is not on. In our experience so far, it does not seem to have that much of an effect. It was implemented as a file-oriented switch rather than a global option (like OPTIONS=ISAM_IDXLOK) because it is probably only practical, if at all, with files that are only going to be scanned and not updated. 

**Warning** :  using this option with a file that is being updated may lead to IDX corruption, unless you have some other mechanism in place to make sure two users are updating the IDX at once! 

## **History** 

- 2006 March, A Shell 4.9.952:  In ISAM 1.0, when `ASFLAG,32` is used to turn off all locking of the IDX file, if an error other than key-not-found (erf 33) occurs, A-Shell now retries the operation after doing a normal index lock. The theory here is that it may make it safer to use the no-lock mode in certain read-only situations (mainly in a peer-to-peer LAN environment) where normal locking has a high overhead and speed is the main consideration. 

A-Shell Reference 

Page 1837 

## **LOCAL COPY** 

This only applies to Windows, and provides yet another way of speeding up access to a file that is only going to be read. When turned on, all random OPEN file operations result in a local copy being made of the file in the workstation's "TEMP" directory. (It uses the TEMP environment variable definition to locate this directory.) The local copy is then accessed, rather than the network copy. When the file is closed, the local copy is deleted (and any updates to the file are lost!) 

The Local Copy option provides nearly as much performance improvement as memory mapping and even loading files into memory, and has the advantage of not requiring any extra physical memory. So it can work just as well with a 100MB file as with a 500K file (provided you have sufficient disk space). As with all of the related schemes for getting around the performance penalty of peer-to-peer shared file access, it makes the most sense in situations where you are going to be accessing a large part, or all, of the file. (It would not make much sense to transfer a 100MB file from the server to the workstation and then only access a few records from it.) Unlike memory mapping and the MEM: device, this technique works with ISAM files as well, and is immune to concerns over how well Windows supports it (since all we ask out of Windows here is the ability to copy a file). 

A-Shell Reference 

Page 1838 

## **FORCE CTRL+C TO PARENT** 

This allows SBX Subroutines to mimic a common behavior in traditional subroutines which do not do their own handling of CTRL+C. The trick is to add the following to the error trap routine of the SBX module: 

```
TRAP:
```

```
if err(0)=1 then
```

```
xcall ASFLAG,128      ! set ^C in parent
```

```
END                   ! exit SBX
```

```
Endif
```

If the _flag_ argument is supplied as a 2 byte binary variable, then the previous flags settings will be returned in the variable, after the new settings are updated from the variable. This technique would be important when using ASFLAG to change the settings for just one file, returning to the original settings thereafter. 

A-Shell Reference 

Page 1839 

## **SBX AS RUN** 

When set within an SBX, any files opened subsequently within that SBX will be auto-closed when this SBX returns. The _flag_ name comes from the idea that in some kinds of menu architectures, you may use SBXs to execute programs that might otherwise have been executed with RUN. The difference is that in the case of a RUN, on exit, all files (and most other resources) are automatically closed or released, whereas with SBXs, files opened in the SBX remain open and accessible to the parent, as well as to other SBXs called by the parent or by the original SBX. 

## **See Also** 

- File Auto-Close Behavior 

## **History** 

- 2012 October, A Shell 6.1.1319: _Flag_ added to ASFLAG 

A-Shell Reference 

Page 1840 

## **ASHELL** 

_Updated July 2024; see History_ 

## **xcall ASHELL, cmd {,qflag, pflag, chainto}** 

ASHELL (previously known as and equivalent to AMOS) allows a program to execute a system command (e.g. DIR, LOG, COPY, 

etc.) or an ASB program (e.g. RUN XYZ) almost as if it were a subroutine. It is similar to HOSTEX except that instead of 

executing host operating system commands, which differ from one operating system to the next, it executes A-Shell system Commands which behave identically among A-Shell's different platforms. 

Note that prior to A-Shell 7.0.1761 of July 2024, ASHELL was known as AMOS. The older term still works—i.e., AMOS and ASHELL are two names for the same function. 

_cmd_ (String)  [in] 

A-Shell command to be executed 

_qflag_ (Any)  [in]  (Num) 

If non-zero and non-blank (i.e. 1 or "Q"), it causes the subroutine to run "quietly"—i.e., generally invisibly. 

_pflag_ (Num)  [in] 

If 1, forces the subroutine to run as if the ASHELL_RUNSBR flag had been set. If _pflag_ is 2, it forces the subroutine to run as if ASHELL_RUNSBR had NOT been set. 

Value (+4) allows the child RUN program to pass its updated command file status to the parent. There are two main consequences. The first is that any command file inputs that were absorbed by the child program will not be available to the parent. (This is almost always preferable.) The second is that any attempt by the child program to CHAIN will effectively pass the chain information back to the parent, so that when the parent ENDS, it will then execute the chain requested by the child. This may or may not be desirable, but it is the only way that an attempted CHAIN by the child will have any effect. 

A-Shell Reference 

Page 1841 

Value (+8) prevents the normal reset of the auto parent setting at the start of the called program. This makes it easier to launch programs designed to operate in the default or main window and instead force them to operate within a dialog created by the calling program. 

Any other value causes the normal ASHELL_RUNSBR setting as specified in miame.ini or SET.LIT command to prevail. 

## _chainto_ (String) 

May be specified (along with the +4 option in the _pflag_ parameter) to return the command line that the child program attempted to chain to. The CHAIN operation is always trapped by xcall ASHELL, forcing the child to return to the parent; this feature allows the parent to effectively carry out the requested CHAIN operation via a subsequent xcall ASHELL call. _Chainto_ is a string of sufficient length to retrieve the CHAIN statement argument. If the +4 option in _pflag_ is not specified, or if the child program does not CHAIN, _chainto_ will return "". Also note that this is only possible when the child executes in-process, so unless you have that option forced on globally, you should also specify the +1 option in _pflag_ . 

ASHELL may work in one of three ways, depending on whether the SBR=ASHELL_RUNSBR switch is set, and depending on the command line specified. 

• If `SBR=ASHELL_RUNSBR` is not set in miame.ini, or if the command does not begin with "RUN" or "ORUN", or the _pflag_ parameter is specified as 2, then unless it is one of the special cases listed below, ASHELL will spawn a new instance of A-Shell with the -e (exit-upon-completion) switch, forcing the new instance to execute the specified command. The calling instance of A- Shell is suspended until the second instance completes the command, as you would expect for a subroutine call. This is - essentially the same as using HOSTEX and passing it a command line starting with "$ASHELL -e " (see Launching A Shell with HOSTEX). Note that under Windows, any screen output within the subroutine will not affect the calling process, since they have separate screen windows, but under Unix, even though the subroutine executes as a separate process, it shares the screen device with the caller and thus any output by the subroutine will remain on the caller's screen—although the calling program will not be aware of it and its cursor will not be advanced as you might otherwise expect. 

• If the _pflag_ parameter is set to 1, or if SBR=ASHELL_RUNSBR is set and the command begins with "RUN" or "ORUN", then the command will be executed as a true subroutine within the current instance of A-Shell. The current program is suspended, as you would expect for a subroutine call, and a new memory partition is allocated for the subroutine, but it shares the calling job's process and job environment. Any screen output, and any changes to the job environment, such as the current ppn, will remain 

A-Shell Reference 

Page 1842 

when the command completes and the subroutine returns. See the ASHELL_RUNSBR switch for important information on limitations and tricks related to this switch. 

• If a second instance is going to be launched, then if the optional second argument is specified, an attempt is made to execute the second instance "quietly." Under A-Shell/Windows, this is accomplished by making the new instance run in minimized mode. Under Unix, it uses the –q startup switch. 

In most cases, the A-Shell implementation of ASHELL will achieve the same result as the typical implementation of AMOS under AMOS. Actually, there are several versions of this subroutine created and distributed by various parties in the AMOS community. But most if not all work by making the child instance run as if it were a subroutine called by the parent. If you do not set the ASHELL_RUNSBR switch, or if the command cannot otherwise be run within the current process, then the fact of it running in a separate process can lead to some subtle differences in the outcome which may be significant to some applications. For example, if the purpose of the child process is to make some change to the job status (e.g. via the SET command) then any such change will be discarded when the subroutine returns if the subroutine ran in a separate process. Another example would be where the child process uses its job name to generate a file or key, assuming that its job name is the same as the parent. 

To minimize the chance of misunderstanding, ASHELL tries to be smart by looking at the command and deciding if it is possible or more desirable to execute that command _in-process_ (as a true subroutine) rather than by launching a new process. Some examples of this are: 

```
xcall ASHELL,"LOG <dev:[p,pn]>"
```

Since this is clearly a case where the intent is to change the PPN of the calling job, A-Shell intercepts this and turns it into `xcall LOG,"<dev:[p,pn]>."` 

```
xcall ASHELL,"LOOK <fspec>"
```

This one could be handled as a separate process with little harm, but since the new process would just turn around and use `xcall EZTYP,<fspec>` (MicroSabio’s EZTYP utility being deemed the appropriate replacement for Micro Concept’s LOOK.LIT), it seems more efficient to just call it directly. 

```
xcall ASHELL,"VUE <fspec>"
```

The reasoning here is similar to that used above. Under A-Shell, VUE.LIT is actually just a front end to the VUE function which is embedded within the A-Shell executable, so it makes just as much sense to call that function within the current instance as it does to start a new one. 

A-Shell Reference 

Page 1843 

ASHELL will launch the new instance of A-Shell (if necessary) using the same initialization file and executable command pathname with which the current instance was launched. 

The child job can determine its parent jobname from the _jobatt_ parameter of either GETJTB or PLYJOB. 

The configuration file option switch, SBR=AMOSJOB1, will cause JOBNAM to return the name of the parent job rather than the child job. 

- 2024 July, A Shell version 7.0.1761: Name changed from AMOS to ASHELL 

- 2014 February, A Shell version 6.1.1377: Add _chainto_ 

- 2014 February, A Shell version 6.1.1374: Add _pflag_ =8. 

A-Shell Reference 

Page 1844 

## **ATEAPX** 

_New documentation May 2016_ 

## **xcall ATEAPX, hostspec, pcdir, pcfile, flags, status** 

ATEAPX.SBX transfers a file from application server to ATE client PC. It supports multiple protocols, pre/post verification, logging, etc. 

## **Parameters** 

_hostspec_ (String)  [in] 

File spec of source file on server; AMOS-style or native; may contain embedded %env% variables) 

_pcdir_ (String)  [in] 

Destination directory on PC using Windows native syntax; default %ate%\dsk0\001004 

## _pcfile_ (String)  [in] 

File.ext for destination. May be left blank to use same file.ext from source. May also contain complete path, in which case _pcdir_ should be empty. Note that if _pcdir_ blank, and _pcfile_ contains format file.ext and file is longer than 10 characters, you should prepend a ".\" to eliminate ambiguity. 

_flags_ (Num) ( [in] 

One or more of the following options. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|APXF_BINARY|&h0000|binary transfer|
|APXF_ASCII|&h0002|ascii transfer|



A-Shell Reference 

Page 1845 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|APXF_NULL|&h0004|'null' printer mode, always set; see Comments|
|APXF_FTP|&h0008|use FTP if server not Windows|
|APXF_NOPOSTVERIFY|&h0010|skip post-transfer verification|
|APXF_PREVERIFY|&h0020|pre-verify; skip transfer if destination already matches source|
|APXF_NOVER|&h0040|ignore version 0 when comparing versions|
|APXF_LOGCURDIR|&h0080|writeateapx.logentries to current ppn rather than opr: directory|
|**Definition file:**ashinc:ateapx.def|||



## _status_ (Signed Num) [out] 

|**Value**|**Description**|
|---|---|
|>0|file transferred / number of bytes transferred|
|0|File transfer not needed or applicable|



A-Shell Reference 

Page 1846 

|**Value**|**Description**|
|---|---|
|-1|ATE required|
|-2|host file doesn't exist|
|-3|file transferred but failed to verify afterwards|
|-4|FTP transfer error|
|-98|A-Shell version on server not high enough for binary transfer|
|- 99|ATE version not high enough|



## **Comments** 

If running in a local Windows environment—i.e. A-Shell/Windows standalone, P2P or remote desktop—then ATEAPX does nothing and returns status 0; file transfer not applicable. 

If the APXF_PREVERIFY flag is set, ATEAPX uses the MX_FILESTATS function to compare the source and destination files to determine if the transfer is actually needed. The small overhead of the pre-verification is almost always worth the chance to omit the transfer, except when the file to be transferred is very small or the chance of the destination matching the source is very slim. 

If APXF_FTP flag is set and the server is not Windows/ATSD, then ATEAPX first attempts to transfer the file using FTP protocol via the AG_FTP command sequence. If the FTP operation fails, it will retry one time before giving up and returning status -4. 

A-Shell Reference 

Page 1847 

If not using FTP, then instead it uses the existing ATE terminal channel to transfer the file—aka the 'null' auxiliary printer protocol. 

The ateapx.log file in OPR: or the current directory, depending on the APXF_LOGCURDIR flag, provides useful information about the success or failure of transfers. To increase the level of detail in the log file, use SET DEBUG prior to the transfer. 

## **See Also** 

- ATSYNC.LIT to transfer/sync many files from server to client 

- AG_FTP: invoke FTP from client directly 

- FTP2: invoke FTP from server directly 

- ATEGFK: retrieve file from ATE client via keyboard channel 

- Source, samples and related functions, including the source for ATEAPX, can be found in SOSLIB:[907,33]. 

A-Shell Reference 

Page 1848 

## **ATEGFK** 

_Updated January 2018; see History_ 

## **xcall ATEGFK, hostspec, pcspec, flags, status** 

ATEGFK.SBX retrieves a file from the PC via the ATE terminal connection. This is useful in situations where FTP isn't available or isn't practical. 

## **Parameters** 

_hostspec_ (String)  [in] 

is the destination (native or AMOS-style) 

_pcspec_ (String)  [in] 

is the source (PC native) 

_flags_ (Num) ( [in] 

may contain zero or more of the following: 

|**Value**|**Definition**|
|---|---|
|16|skip post-transfer verification|
|32|pre-verify (skip transfer if destination matches source)|
|64|ignore version 0 in pre-verification|
|128|putategfk.login current directory rather than OPR:|



A-Shell Reference 

Page 1849 

## _status_ (Signed Num)  [out] 

returns status of operation: 

|**Value**|**Definition**|
|---|---|
|>0|file transferred|
|0|transfer not required|
|-1|ATE required|
|-2|source file doesn't exist|
|-3|file transferred but failed to verify afterwards|
|-4|transfer failure|



## **See Also** 

- Test program TSTATEGFK.BP in SOSLIB:[907,33]. 

- MX_ATEFILEXFR 

- Source, samples and related functions can be found in SOSLIB:[907,33]. 

## **History** 

A-Shell Reference 

Page 1850 

- 2018 January 2018, A Shell 6.4.1556, ATEGFK.SBX 1.0(105): eliminate a five second delay in the case where the source file exists but has zero bytes. 

- 2016 April, A Shell 6.3.1510:  Routine added to A-Shell 

A-Shell Reference 

Page 1851 

## **ATELGI** 

## **xcall ATELGI, name, pw, status, pkpw, host, cfg** 

ATELGI.SBX provides the means for creating a customized ATE login script. If BAS:ATELGI.SBX exists and the automatic login doesn't succeed, ATE will call it instead of the internal generic login dialog to get the login credentials. Source, samples and related functions can be found SOSLIB:[907,50]. 

## **Parameters** 

|**Name**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|login|String|in/out|login name|
|pw|String|out|password|
|pkpw|String|in/out|private key passphrase|
|status|Num|in/out|status: OK/CONNECT=1, CANCEL=0|
|host|String|in/out|host{:port}|
|cfg|String|in|name of current ATE configuration|



A-Shell Reference 

Page 1852 

## **AUI** 

AUI, an acronum for "A-Shell User Interface," serves as a organizing wrapper for most of the primary classes of functions of the AUI Toolkit. 

## **xcall AUI, CLASS, parameters** 

We use the object-oriented "class" terminology not to claim that these meet every definition of an object class, but to promote an object orientation to the understanding and use of the functions. Adopting this mind set early on in a text-to-GUI conversion project will reinforce good design and contribute to better results. 

CLASS is a string which names the class of interface "object" from the following table. 

|**Class**|**Description**|
|---|---|
|AUI_CONTROL|Display and input controls. Properties include the control type (button, checkbox,<br>etc.), size and position (using the row/col coordinate system), etc. Methods include<br>create, modify, delete, save, restore, clear, etc. Same asMX_WINCTL.|
|AUI_EVENTWAIT|Abstract class whose purpose is to provide methods for waiting for an interface<br>event (typically a button to be clicked). Used as an alternative toINFLDor other<br>input routine. Same asMX_EVENTWAIT.|
|AUI_ENVIRONMENT|Properties related to the interface environment.|
|AUI_MENU|Menu items. Methods for adding, deleting, and enabling/disabling items. Same as<br>MX_WINMNU.|
|AUI_IMAGE|Special case of control for images. Same asIMAGE.|



A-Shell Reference 

Page 1853 

|**Class**|**Description**|**Description**|
|---|---|---|
|AUI_WINDOW|Main display window configuration. Properties include number of rows and columns,<br>status lines, colors. Methods include PRINT and Tab.||
|AUI_HTMLHELP|Interface with HTML/CHM help files.||
|other|Other classes can be implemented asSBX<br>modules<br>`. xcall APL,CLASS$,...`will<br>be treated internally as<br>`VXCALL CLASS$,...`||



Note that there are some other class-level objects which could probably be in this table but are not. These controls were either developed before those noted in the table, or were deemed sufficiently important enough to have their own stand-alone function and documentation. Those topics are: 

- INFLD, the control for handling data input and output. 

- XTREE, the control for managing trees and listboxes. 

- XTEXT, the control for managing text functions. 

A-Shell Reference 

Page 1854 

## **AUI_CONTROL** 

## **xcall AUI, AUI_CONTROL, opcode, ctlid, ctext, cstate, ctype, cmd, func, cstatus, srow, scol, erow, ecol, fgc, bgc, fontattr, fontscale, fontface, tooltip, parentid, winclass, winstyle, winstylex, ctype2** 

The AUI_CONTROL class provides methods for creating a wide range of Windows GUI "controls", such as buttons, static text objects, listboxes, etc. 

This class is supported under Windows (and ATE) only, although there is nothing prohibiting an ambitious programmer from implementing a "super class" that provides similar capabilities in a text environment. In fact, it is generally recommended that developers create their own wrappers for these low level functions in order to standardize and accelerate their development. 

## **Subtopics** 

- AUI_Control Parameters 

- Control Types 

- Other Control Topics 

A-Shell Reference 

Page 1855 

## **AUI_CONTROL PARAMETERS** 

All of the parameters are optional except for the first two, _opcode_ and _ctlid_ , which together are sufficient to delete the control. Even when adding a new control, the last several parameters are only needed when you want to do something slightly unusual or fancy. Refer to the documentation on the individual parameters below for deciding how many you need to specify for a particular effect. 

In the case of _opcode_ CTLOP_INFO, all of the parameters besides _opcode_ may be updated. The indicators in the I/O column ignore this case and apply only to the _opcodes_ other than CTLOP_INFO. 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|opcode|Num|in|Determines the "method" or operation to perform.|
|ctlid|Num|in/out|Control ID: an integer starting from 1, or an alphanumeric name, that<br>uniquely identifies each control.|
|ctext|String|in/out|Text associated with the control. For most typical controls (buttons, static<br>text, checkbox, etc.) this is the text that appears in the control.|
|cstate|B,4|in|State of the control (enabled, disabled, hidden, etc.).|
|ctype|B,4|in|Control type and attributes. For more exotic controls, leave this zero and<br>use_winclass_,_winstyle_,_winstylex_.|
|cmd|String|in|Specifies the command or keyboard string which is invoked when the<br>control is clicked.|



A-Shell Reference 

Page 1856 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|func|Num|in/out|When the cmd type is DLL, this can specify a function within the DLL to<br>execute. For checkboxes,_func_is a 1-byte binary which gets set and<br>cleared along with the display state of the checkbox.|
|cstatus|Signed<br>Num|in/out|Returns status indicating success of operation. For some opcodes, it is used<br>as an input also.|
|srow, scol,<br>erow, ecol|Num|in|Coordinates of the control.|
|fgc, bgc|Num|in|Foreground and background color palette numbers for the control.|
|fontattr|B,4|in|Used to override the default font attributes for the control.|
|fontscale|Num|in|Scales the font to the specified percentage.|
|fontface|String|in|Overrides the default font selection.|
|tooltip|String|in|Defines a "tooltip" (popup message)|
|parentid|Num|in|If specified, new control becomes child of specified control.|
|winclass|String|in|May be used as an alternative to_ctype_to create a control using the|



A-Shell Reference 

Page 1857 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
||||standard Windows control classes and styles.|
|winstyle|B,4|in||
|winstylex|B,4|in||
|ctype2|B,4|in|Extension of_ctype_; control type and attributes.|



A-Shell Reference 

Page 1858 

## **OPCODE** 

_Updated November 2013; added opcodes 13, 14Para_ 

## Parameter _opcode_ specifies one of the "methods" or operations from the following table. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|CTLOP_INFO|0|Query Control|
|CTLOP_ADD|1|Add Control|
|CTLOP_CHG|2|Change Control|
|CTLOP_DEL|3|Delete|
|CTLOP_CLR|4|Clear Control|
|CTLOP_QRYCB|5|Query Checkbox<br>or Retrieve Date from Month Calendar Control|
|CTLOP_SVA, CTLOP_RSA|6, 7|Save/Restore Controls|
|CTLOP_SBCH, CTLOP_EBCH|8, 9|Batch Operations|
|CTLOP_GETID|10|Get Control ID|
|CTLOP_PANE|11|Set Current Tab Pane|



A-Shell Reference 

Page 1859 

|**Symbol**|**Value**|**Description**|
|---|---|---|
||||
|CTLOP_REPL|12|Internal use only.|
|CTLOP_IMGLST|13|Attach an image list to a toolbar control|
|CTLOP_TABSET, CTLOP_TABCLR|14, 15|Set/Clear MBF_TABSTOP Property|
|CTLOP_REPAINT|16|Force refresh/redraw of specified control and its children|
|**Definition file: ashell.def**|||



A-Shell Reference 

Page 1860 

## **QUERY CONTROL** 

Use CTLOP_INFO to query the details of a control by its _ctlid_ . This is mainly useful in three kinds of situations: 

- You need to determine if a control (with a specific _ctlid_ ) still exists (perhaps upon return from a subroutine that may or may 

- not have cleared the screen). 

- You have a _ctlid—_ perhaps returned from AUI_EVENTWAIT—but your program does not keep track of controls by their _ctlids_ 

- so you need to find out more information about the control to decide what to do. 

- You have a _ctlid_ and you know what control it is, but the control has changeable text and you want to determine what text is 

- currently associated with the control. This would mainly apply to a control designed to be modified by the user (such as an edit control), and in that case, you would probably use INFLD and keep track of the text a different way, but this capability may be useful in an advanced situation. 

To query a control, you need to specify the _ctlid_ . The contents of all the other parameters are ignored on input, and are returned with updated values based on the control specified. If the control exists, _cstatus_ will be set >= 0. If the control is not found, it will set to –2. Other negative values correspond to errors (see cstatus above for a table of error codes). You must specify at least the parameters up to _cstatus_ (and it must be a real variable); all others are optional (but will be updated if passed). 

## **Comments** 

Beginning with A-Shell 1751 of November 2023: when used on a TABX control, CTLOP_INFO returns the current panel number (starting from 1) in the _cstatus_ parameter if the control is found. Previously it returned the control id. This affects only the Windows client (or ATE), not the server side. Also, the current panels' command string will be return in the _ctext_ parameter. 

## **Example** 

```
ctlid = "btnTest"     ! id of control to query
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, ctlid, ctext, cstate, ctype, cmd, func, cstatus, srow, scol, erow, ecol
if cstatus >= 0 then
```

- `! control exists; ctext, cstate, etc. will be updated` 

```
else
```

A-Shell Reference 

Page 1861 

- `! control does not exist` 

```
endif
```

## **History** 

- 2023 November, A Shell 1751:  When used on a TABX control, CTLOP_INFO returns the current panel number (starting from 1) in the _ctext_ parameter if the control is found, and the current panel's command string in _ctext_ . 

A-Shell Reference 

Page 1862 

## **ADD CONTROL** 

_Rewritten Feburary 2013_ 

To add or create a control, use CTLOP_ADD and specify at least all the parameters up through the _ecol_ parameter. The rest are optional. 

The following simple example creates a button occupying the rectangle from 5,10 to 6,20 (in the grid units of the current parent window), displaying "Process", and transmitting exitcode -107 when clicked: 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, ctlid, "Process", MBST_ENABLE, MBF_BUTTON + MBF_KBD, "VK_xF107", "",
cstatus, 5, 10, 6, 20
```

In this slightly more complex example, we create a clickable static text control, specifying an alphanumeric id and a variety of other attributes. See _Comments_ . 

```
fontattr = FS_ITALIC + FA_HEAVY
```

```
fontscale = 250
```

```
fontface$ = "Impact"
```

```
tooltip$ = "Click for more information"
```

```
parentid$ = "gbMessages"
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "txtWarning", "Warning! Meltdown Imminent!", MBST_ENABLE, MBF_STATIC +
MBF_LFJUST + MBF_AUTOGROW + MBF_KBD, "VK_xF108", NUL_FUNC$, NUL_CSTATUS, 2, 10, 3, 20, &h0000ff,
RGB_TRANSPARENT, fontattr, fontscale, fontface$, tooltip$, parentid$
```

## **Comments** 

• If the _ctlid_ parameter is numeric, it is ignored on input and set to the new control's numeric id on output. But if _ctlid_ is alphanumeric, it is used as-is, and does not change. The numeric equivalent (or an error code < 0) will be returned in the _cstatus_ parameter, assuming the parameter is numeric. The second example uses NUL_CSTATUS, defined as "" in ashell.def, which eliminates the return status; this is a significant performance optimization in the case of ATE where each control created would otherwise require waiting for the client's return status packet to arrive before the next control could be created. 

A-Shell Reference 

Page 1863 

• If the _parentid_ parameter is not specified, as in the first example, the new control will be a child of the current window: either a modal dialog, if one exists, or else the main window. The coordinates specified will be taken as relative to the parent control. 

• For most child controls, if the new control has the same starting position as an existing child control, the existing control will be removed. In the case of the GUI_SPC_IND system option, this rule is expanded slightly to allow a new control to replace a pre-existing one that overlaps the new one. In both cases, the intent is to simplify automated strategies for migrating from plain text to GUI. See AUTOTPRINT, MX_DEFTABXYZ, and INFLD's _type_ **|G** ). 

• Normally, the control type is determined by the _ctype_ parameter, but in certain circumstances you can set _ctype_ to 0 and specify the control type in the _winclass_ , _winstyle_ , and _winstylex_ parameters. This technique is generally only useful for control types that do not require any interactivity -besides a click action), with the main example being Lines, Rectangles and Frames, although it may also provide a way to create a control type for which no _ctype_ flags have been defined. 

A-Shell Reference 

Page 1864 

## **CHANGE CONTROL** 

_Rewritten February 2013_ 

CTLOP_CHG ( _opcode_ 2) can be used, in conjunction with various MBST_xxx flags in the _cstate_ parameter, to change virtually any of the attributes of an existing control (such as the displayed text, state, command, etc.) For example, consider the following sample dialog: 

The Connect button is disabled because the user hasn't entered enough information to even justify attempting a connection. Once they do so, we want to enable the Connect button, which we can do with something like the following: 

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, btnid, NUL_CTEXT, MBST_ENABLE
```

The key parameters here were the button identifier and the MBST_ENABLE flag. We're not changing the button text, so we just supply NUL_CTEXT (defined as "" in the ashell.def) for the _ctext_ parameter, and none of the other parameters are required. If we wanted to know what the prior state of the control was, we could pass the _cstatus_ parameter (and those prior to it), but in most cases, we don't care about the prior state. 

To take another example, let's say we want to change the label associated with the second field, depending on the Database Connector - for MySQL, "Host/Server" seems appropriate, but for ODBC, "Data Source" might be better. To accomplish that, we can use a slight variation of the CTLOP_CHG operation: 

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, btnid, "Data Source", MBST_CHANGE + MBST_TEXTONLY
```

The combination of the MBST_CHANGE and MBST_TEXTONLY flags in the _cstate_ parameter causes the operation to only affect the text of the control, for which we supplied the string "Data Source". 

Depending on which MBST_xxx flags are specified, you may need to specify more parameters, with the extreme case being MBST_CHANGEX which replaces all of the attributes of the control (essentially deleting and recreating it). Virtually all of the MBST_xxx _cstate_ flags can be used with CTLOP_CHG, but the following ones apply uniquely to CTLOP_CHG and are therefore worth noting: 

A-Shell Reference 

Page 1865 

|**Symbol**|**Description**|
|---|---|
|MBST_CHANGE|Change ctext and cmd.|
|MBST_TEXTONL<br>Y|Add to MBST_CHANGE to limit the changes to the ctext|
|MBST_STYLE|Change the style and alignment flags (ctype)|
|MBST_POS|Change the position (coordinates)|
|MBST_CHANGE<br>X|Change everything|
|MBST_NORMALI<br>ZE|Change a maximized dialog back to normal state|



A-Shell Reference 

Page 1866 

## **DELETE CONTROL** 

_Updated February 2014_ 

CTLOP_DEL (opcode 3) is used to delete a control or set of controls. Typically you only need to specify the _ctlid_ , e.g. 

```
xcall AUI, AUI_CONTROL, CTLOP_DEL, CTLID
```

As a special convenience, you can delete the current dialog without even knowing its id by specifying a _ctlid_ of 0 and putting MBF_DIALOG in the _ctype_ field: 

```
CTLID = 0
```

```
xcall AUI, AUI_CONTROL, CTLOP_DEL, CTLID, NUL_CTEXT$, NUL_CSTATE, MBF_DIALOG
```

You have to specify the _ctext_ and _cstate_ parameters prior to the _ctype_ parameter, but since we don't care about them, we use the symbols NUL_CTEXT$ and NUL_CSTATE, defined in ashell.def as "" and 0, respectively, as placeholders. 

The other way to delete controls is by setting _ctext_ to "*" and using the _srow_ , _scol_ , _erow_ , and _ecol_ parameters to specify a region. In this case it is essential to specify the _parentid_ (typically a dialog) unless referencing controls directly in the main window. _ctlid_ should be set to 0. For example, to delete all of the controls within the region bounded by 1,1 and 3,30 within the dialog whose id is "dlgOne": 

```
CTLID = 0 : DLGID = "dlgOne" : srow = 1 : scol = 1 : erow = 3 : ecol = 30
```

```
xcall AUI, AUI_CONTROL, CTLOP_DEL, CTLID, "*", cstate, ctype, cmd, func, cstatus, srow, scol, erow, ecol,
NUL_FGC, NUL_BGC, NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$, DLGID
```

As mentioned above, the various NUL_xxx symbols are defined in ashell.def as 0 or "", and are used here for clarity as placeholders for the "don't care" parameters. 

A third way to delete controls is with TAB(-1,0), which deletes everything, including dialogs, unless the MX_AUTOPARENT is set, in which case the action is confined to the children of the specified parent. 

To delete all the controls but leave untouched the plain text in the main window, specify ctlid 0 without any other parameters: 

A-Shell Reference 

Page 1867 

```
xcall AUI, AUI_CONTROL, CTLOP_DEL, 0
```

## **Comments** 

Deleting a control will automatically delete any child controls of that control.If you want to delete just the children but leave the target control alone, you can use _opcode_ 4 (see Clear Control) or by specifying the _parentid_ with all of the other parameters set to null, e.g.: 

```
xcall AUI, AUI_CONTROL, CTLOP_DEL, NUL_CTLID, NUL_CTEXT$, NUL_CSTATE, NUL_CTYPE, NUL_CMD$, NUL_FUNC$,
NUL_CSTATUS, NUL_SROW, NUL_SCOL, NUL_EROW, NUL_ECOL, NUL_FGC, NUL_BGC, NUL_FONTATTR, NULL_FONTSCALE,
NUL_FONTFACE$, NUL_TOOLTIP$, parentid
```

## **History** 

- 2014 February, A Shell 6.1.1377: Several improvements and doc modifications. 

- 2012 October, A Shell 6.0.1261: Support _ctlid_ =0 to clear all of the controls, leaving plain text alone: 

```
xcall AUI, AUI_CONTROL, CTLOP_DEL, 0
```

A-Shell Reference 

Page 1868 

## **CLEAR CONTROL** 

CTLOP_CLR (opcode 4) is just like opcode 3, except for the following differences: 

• If _ctlid_ is specified, then only the children of that control are deleted. This is most useful with Tab controls, where, as you change panes, you need to remove the children previously displayed on the old pane and create the ones corresponding to the new one. If _ctlid_ does not refer to a control with children, then it is ignored (i.e. treated as if zero), in which case it identifies the controls to be deleted by the coordinates (assuming _ctext_ = "*"). See XTREE/XTEXT Tab Performance for an alternative to clearing and recreating XTREE and XTEXT controls within Tab panes. 

• It only deletes "unprotected" controls. By default static text controls are unprotected (as are those created with EPRINT), while most other types are protected. (You can, however, remove protection from protected controls by adding MBF_UNPROTECTED when the control is created.) To add protection to text controls, you have to add the dim attribute and also enable protection just like you would with regular text, using Tab(-1,13). For text controls created with AUI_CONTROL, you add protection by specifying MBF_DIM when creating the control. For text controls created via TPRINT commands, the MBF_DIM attribute is set automatically if the current text mode is dim (i.e., if Tab(-1,11) was issued previously.) The point of all this is to allow you to perform the same "trick" that is possible with dumb terminals, whereby you can protect the background of a form and clear the foreground with just a couple of commands. If it just seems confusing, you can probably ignore it. 

Note: In order for CTLOP_CLR to clear the controls from the Tab control pane, those controls must be children of the Tab control! A common mistake when working with Tab controls is to fail to explicitly set the parentid of the controls appearing within the active pane; typically this results in those controls being children of the outer dialog—siblings of the Tab control—and thus outside the scope of the CTLOP_CLR operation on the Tab control. An easy way to visualize this problem is to generate a Control Dump,  which clearly shows the parentid of each control. 

Tab(-1,10) (clear to end of screen) and Tab(-1,9) internally perform an opcode 4 for the region in question. 

## **History** 

- 2012 October, A Shell 6.0.1261: AUI_CONTROL refinement: When using opcode CTLOP_CLR, you may now set the MBST_TEXTONLY flag in the _cstate_ parameter to cause it to clear the text from any affected control, rather than delete the control entirely. This is mainly useful with controls containing data in a form, where you want to clear the data but leave the form. Note that in such a case, you will probably want to protect the label controls from being cleared, which you can do by creating them with the MBF_DIM attribute set, and using TAB(-1,13) to enable protection immediately prior to the AUI_CONTROL, CTLOP_CLR operation. Use TAB(-1,14) afterward to disable protection. 

A-Shell Reference 

Page 1869 

For example, to clear the text from the unprotected controls, and leave the protected controls alone (in the region of rows 1-24 and cols 1-80): 

```
? tab(-1,13);   ! enable protection
```

```
xcall AUI, AUI_CONTROL, CTLOP_CLR, NUL_CTLID, "*", MBST_TEXTONLY, NUL_CTYPE, NUL_CMD$, NUL_FUNC$, 1, 1, 24,
80
```

```
? tab(-1,14);   ! disable protection
```

Note that the "*" in the _ctext_ parameter is required to select all the controls. 

A-Shell Reference 

Page 1870 

## **QUERY CHECKBOX** 

CTLOP_QRYCB (opcode 5) may be used to query the current value of a checkbox or radiobutton. The value (returned in the _cstatus_ parameter) may be one of: 0 (unchecked), 1 (checked), or 2 (indeterminate, for MBF_3STATE checkboxes). 

The ability to query the value of a checkbox is useful when you want to present a bunch of checkboxes and let the user click on them in any order, or TAB around them, without having to code the INFLD logic necessary for handling individual field exitcodes and immediate validation. Instead, you can just let EVENTWAIT handle the operation until the user triggers the event requiring that you retrieve the values. 

Note that in the local A-Shell/Windows environment, a special operation to query a checkbox isn't really necessary, since the AUI system will automatically and immediately update the checkbox value variable (specified in the _func_ parameter when the checkbox was created). But in the ATE environment (where the checkbox is on the client and the variable is on the server), direct updating of the value variable isn't possible. The CTLOP_QRYCB method described below, will work in all environments and thus is recommended. 

As an example, consider the following simple dialog containing several checkbox options: 

The program creates the dialog, then waits in an EVENTWAIT loop to either click the green button (which triggers the checkbox query routine and displays the results in the trace window), or to close the dialog (by clicking the red X or hitting ESC). 

```
program qrycb,1.0(100)  ! simple example of querying checkboxes
```

```
++include ashinc:ashell.def
```

```
define MAX_CB = 7       ! number of checkboxes
define DLG_ID$ = "dlg1" ! id of main dialog
```

A-Shell Reference 

Page 1871 

```
map1 cb(MAX_CB)
    map2 cb'id$,s,20    ! control id
    map2 cb'dsc$,s,20   ! display text
    map2 cb'val,b,1     ! checkbox value
```

```
map1 misc
    map2 i,f
    map2 row,b,4
    map2 col,b,4
    map2 evw'parentid$,s,24
    map2 evw'ctlid$,s,24
    map2 evw'flags,b,4
    map2 exitcode,f
    map2 status,f
```

```
data "cbAPEX",      "APEX"
data "cbASQL",      "ASQL"
data "cbATE",       "ATE"
data "cbATS",       "ATS"
data "cbISAMA",     "ISAM-A"
data "cbPDFX",      "PDFX"
```

A-Shell Reference 

Page 1872 

```
data "cbPolyShell", "PolyShell"
```

```
    ! create the dialog
    xcall AUI, AUI_CONTROL, CTLOP_ADD, DLG_ID$, "A-Shell Options", &
        MBST_ENABLE, MBF_DIALOG + MBF_ALTPOS + MBF_SYSMENU, &
        NUL_CMD$, NUL_FUNC$, NUL_CSTATUS, 2000, 5000, 8000, 25000
```

```
    ! create the checkbox controls
```

```
    for i = 1 to 7
        read cb'id$(i), cb'dsc$(i)
```

```
        ! divide into two columns
```

```
        if i <= 4 then
            row = (i + 1) * 1000  ! millirows
            col = 3000
        else
```

```
            row = (i - 3) * 1000
            col = 12000
        endif
```

A-Shell Reference 

Page 1873 

```
        cb'val(2) = 1   ! (initialize one of the checkboxes to checked)
```

```
        xcall AUI, AUI_CONTROL, CTLOP_ADD, cb'id$(i), cb'dsc$(i), &
```

```
            MBST_ENABLE, MBF_CHKBOX + MBF_LFJUST + MBF_TABSTOP, &
```

```
            NUL_CMD$, cb'val(i), NUL_CSTATUS, row, col, row+1000, col+7000, &
```

```
            NUL_FGC, NUL_BGC, NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, &
```

```
            NUL_TOOLTIP$, DLG_ID$
```

```
    next i
```

- `! create qry/exit buttons` 

```
    xcall AUI, AUI_CONTROL, CTLOP_ADD, "btnQry", "checks::ashico1", &
```

```
        MBST_ENABLE, MBF_BUTTON + MBF_ICON + MBF_KBD, &
```

- `"VK_xF101", NUL_FUNC$, NUL_CSTATUS, 5500, 14000, 6500, 16000, & NUL_FGC, NUL_BGC, NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, &` 

- `"Query the current checkbox values", DLG_ID$` 

```
    xcall AUI, AUI_CONTROL, CTLOP_ADD, "btnExit", "delete::ashico1", &
```

```
        MBST_ENABLE, MBF_BUTTON + MBF_ICON + MBF_KBD, &
```

- `"VK_ESC", NUL_FUNC$, NUL_CSTATUS, 5500, 17000, 6500, 19000, &` 

```
        NUL_FGC, NUL_BGC, NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, &
```

- `"Exit dialog", DLG_ID$` 

A-Shell Reference 

Page 1874 

```
    ! wait for user to click Query or Exit
    evw'parentid$ = "dlg1"
    evw'ctlid$ = cb'id$(1)
    evw'flags = 0
```

```
    do
```

```
        xcall AUI, AUI_EVENTWAIT, evw'parentid$, evw'ctlid$, exitcode, evw'flags
```

```
        switch exitcode
            case -101            ! clicked ok
                trace.print "Querying checkboxes..."
                for i = 1 to MAX_CB
                    xcall AUI, AUI_CONTROL, CTLOP_QRYCB, cb'id$(i), NUL_CTEXT$, &
                        NUL_CSTATE, NUL_CTYPE, NUL_CMD$, NUL_FUNC$, status
                    cb'val(i) = status
                    trace.print "CB #"+i+" : "+cb'dsc$(i)+" = "+cb'val(i)
                next i
                exit
        endswitch
    loop until exitcode = 1     ! (escape)
```

A-Shell Reference 

Page 1875 

```
    xcall AUI, AUI_CONTROL, CTLOP_DEL, DLG_ID$      ! close dialog
```

```
end
```

## **Comments** 

The program above uses alphanumeric IDs for the checkbox controls, which eliminates the need for the CTLOP_ADD operation to return the numeric ID of each newly-created checkbox. This speeds up creation of the dialog in the ATE environment (where otherwise the server would have to wait for the return status of each checkbox before creating the next one). But it doesn't help the CTLOP_QRYCB operation, which would require a round-trip (server to client and back) for each checkbox queried. For a small dialog like this it wouldn't be an issue, but if you have a dialog with hundreds of checkboxes, you may want to consider optimizing the ATE performance either using Batch Operations or perhaps organizing the checkboxes into an XTREE. 

## **See Also** 

Get Control ID for an example scenario involving the need to query a radio button in order to enable/disable another control. 

A-Shell Reference 

Page 1876 

## **SAVE/RESTORE CONTROLS** 

CTLOP_SVA (opcodes 6 and 7) are normally only used internally by A-Shell, in conjunction with command which save and restore full or partial screen areas (e.g. TCRTs 148, 149, 202, 203, plus pop-up subroutines like MSBOXX, INMEMO, etc.) If for some reason you wanted to do this directly, note the following: 

- You must specify up through the _ecol_ parameter. 

- The _func_ parameter should be set to the string representation of a numeric ID (e.g. "1"). The same ID must be specified on 

- the restore operation as for the save (this is how the correct set of saved controls is located.) 

A-Shell Reference 

Page 1877 

## **BATCH OPERATIONS** 

**Note** : Batch operations are now deprecated, as the original motivation (improved ATE performance) has been satisfied in a simpler way by using numeric Control names. The remainder of the discussion below is retained here for historical purposes only. 

CTLOP_RSA (opcodes 8 and 9) offer increased efficiency for creating many controls at a time, and may be of interest when the application server and workstation are not the same machine. In that environment, for each control created, the application server sends the request to the workstation, which creates the control and sends back the control ID and status. Although the amount of information transferred is minimal, the delay introduced by the server having to wait for a response to each command before issuing the next can add up to noticeable delays, particularly on a slow network. 

There are two general techniques for minimizing those delays: activating the "ATE Reverse Channel" (described elsewhere), and creating controls in a batch. When controls are created in a batch, the return information (ID and status) for each control is buffered on the workstation until the batch is complete, after which it sends all the return information in a single packet. The main drawback of this approach is simply that it takes two extra steps for each batch – one command to start the batch and another to finish it. 

To start a batch, use opcode 8, as follows: 

```
xcall AUI, AUI_CONTROL, CTLOP_SBCH, cstatus
```

The normal return _cstatus_ is 0. If a batch has already been started, _cstatus_ will be set to –12. Other values all correspond to errors. 

Once the batch is started, you can proceed to issue commands to create or query controls as you normally do, but do not bother checking for returned _ctlid_ or _cstatus_ values, as they are buffered by the ATE client. (You do need to specify valid ctlid and cstatus parameters, just as if you were getting those parameters back on every call; otherwise the return status is not added to the buffer for later return.) 

To complete the batch and retrieve the buffered values, use opcode 9: 

```
COUNT = <maximum number of controls in batch>
```

```
XCALL AUI, AUI_CONTROL, CTLOP_EBCH, CSTATUS, COUNT, ID(1), CB(1)
```

```
If CSTATUS # <number of controls requested> then goto Error
```

A-Shell Reference 

Page 1878 

The parameters should be mapped something like the following: 

```
MAP1 ID(20),B,2    ! array of control IDs (sized large enough for the batch)
```

```
MAP1 CB(20),B,1    ! array of status codes (or checkbox values)
```

```
MAP1 CSTATUS,F,6   ! returns number of controls actually created in batch
```

```
MAP1 COUNT,B,2     ! number of controls expected (max)
```

The _count_ parameter must be set to the maximum number of controls in the batch (and no larger than the arrays.) Typically you would set this to the actual number of controls you attempted to create in the batch, although it might also be set to the maximum size of the arrays. (It just sets an upper limit on the amount of information returned.) 

_cstatus_ will be updated to the actual count of controls created in the batch. If it does not agree with the number you tried to create, then there was a problem. 

The _id()_ array receives the _ctlid_ values of the controls created in the batch. 

The _cb()_ array receives the status codes that would have otherwise been returned in the _cstatus_ parameter for each control creation operation. Note that it must be mapped as an array of B,1 (as shown above), so negative cstatus values will appear as 255 (-1), 254 (-2), etc. (Mainly you only care if the status is 0 or not.) 

Note that you normally specify the first element of each array in the parameters passed to the subroutine as shown in the example above. But if you have one large array of control Ids, yet for some reason you use multiple batches to create your controls, you could specify a different starting value for a subsequent batch, e.g. _cb(10)_ instead of _cb(1)_ , as long as the array is big enough. 

As an example of using a batch, we will recode the example given for opcode 5 above, this time using a batch operation to create the checkboxes, and another to query them. See the sample program TSTBMN in SOSLIB:[907,24] for a complete working version of this logic. 

```
MAP1 CID(7),B,2     ! control Ids for the checkboxes
```

```
MAP1 CB(7),B,1      ! chkbox state (0=unchecked, 1=checked)
```

A-Shell Reference 

Page 1879 

```
MAP1 OPTDLGID,B,2   ! ID of dialog box
```

```
MAP1 STATUS,F,6
```

```
MAP1 NOSTATUS$,S,1,""  ! use when we do not care about status or ID
```

```
CREATE'DIALOG:
```

```
OPTDLGID = 0
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO,OPTDLGID, "Eventwait Option Flags", MBST_ENABLE, MBF_DIALOG + MBF_SYSMENU,
"", "", STATUS, 2, 2, 11, 23
```

```
if OPTDLGID = 0 then goto ERROR'OUT
```

```
!(assume that CB(7) values have been initialized appropriately)
```

```
! Start a batch:
```

```
xcall AUI, AUI_CONTROL, CTLOP_SBCH, STATUS
```

```
if STATUS # 0 goto ERROR'OUT
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CID(1), "Start on next control (1)", MBST_ENABLE, MBF_CHKBOX +
MBF_LFJUST, "", CB(1), STATUS, 2, 3, 2, 21, -2, -2, 0, 0, "", "", OPTDLGID
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CID(2), "Do not wait for event (2)", MBST_ENABLE, MBF_CHKBOX +
MBF_LFJUST, "", CB(2), STATUS, 3, 3, 3, 21, -2, -2, 0, 0, "", "", OPTDLGID
```

A-Shell Reference 

Page 1880 

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CID(3), "Do not wrap (4)", MBST_ENABLE, MBF_CHKBOX + MBF_LFJUST, "",
CB(3), STATUS, 4, 3, 4, 21, -2, -2, 0, 0, "", "", OPTDLGID
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CID(4), "Do not set focus (8)", MBST_ENABLE, MBF_CHKBOX + MBF_LFJUST, "",
CB(4), STATUS, 5, 3, 5, 21, -2, -2, 0, 0, "", "", OPTDLGID
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CID(5), "Allow numeric input (16)", MBST_ENABLE, MBF_CHKBOX + MBF_LFJUST,
"", CB(5), STATUS, 6, 3, 6, 21, -2, -2, 0, 0, "", "", OPTDLGID
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CID(6), "Descend into child groups (32)", BST_ENABLE, MBF_CHKBOX +
MBF_LFJUST, ", CB(6), STATUS, 7, 3, 7, 21, -2, -2, 0, 0, "", "", OPTDLGID
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CID(7), "Allow focus on siblings of parent control (64)", BST_ENABLE,
MBF_CHKBOX + MBF_LFJUST, ", CB(7), STATUS, 8, 3, 8, 21, -2, -2, 0, 0, "", "", OPTDLGID
```

- `! finish the batch` 

```
COUNT = 7   ! number of controls in the batch
```

```
Xcall AUI,AUI_CONTROL, CTLOP_EBCH,STATUS,COUNT,CID(1),CB(1)
```

```
If STATUS # 7 then goto ERROR'OUT
```

- `! Add the buttons (they could have been part of the batch, but` 

- `! here we decided to leave them out because we do not need to` 

A-Shell Reference 

Page 1881 

```
! reference then directly later anyway)
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, 0, "OK", BST_ENABLE, MBF_BUTTON + MBF_KBD, %VK_F2%", "", NOSTATUS$, 9, 4,
9, 10, -2, -2, 0, 0, "", "", OPTDLGID
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, 0, "Cancel", BST_ENABLE, MBF_BUTTON + MBF_KBD, %VK_ESC%", "", NOSTATUS$,
9, 13, 9, 19, -2, -2, 0, 0, "", "", OPTDLGID
```

## To query the checkboxes later, we can also use a batch operation: 

```
xcall AUI,AUI_CONTROL, CTLOP_SBCH, STATUS   ! start a batch
```

```
If STATUS # 0 goto ERROR'OUT
```

```
COUNT = 7        ! send 7 query commands...
```

```
For I = 1 to COUNT
```

```
xcall AUI, AUI_CONTROL, CTLOP_QRYCB, CID(I), "", 0, "", "", STATUS
```

```
Next I
```

```
xcall AUI,AUI_CONTROL,CTLOP_EBCH,STATUS,COUNT,CID(1),CB(1)   ! finish batch
If STATUS # COUNT then goto ERROR'OUT
```

```
! CB(I) array is now set with the status of each checkbox
```

A-Shell Reference 

Page 1882 

## **GET CONTROL ID** 

CTLOP_GETID retrieves the ctlid of a control by its coordinates. This is useful when you know a control's coordinates, but not its ID, and you need the ID to perform some operation on it (like enable/disable). For example, you might have a form which includes INFLD fields depending on certain radio buttons, as in the example below. Here is the initial form, with the INFLD controls enabled: 

And here, after we change the radio button to the XLS option, we disable the controls associated with the printer: 

The code sample below illustrates the creation of the "Cópias" edit control (using INFLD) and obtaining its ID: 

## `COPIES:` 

```
xcall INFLD,2,8,XMAX,XMIN,TYPE$,ENTRY,INXCTL,1,GRPID2+1,OPCODE,EXITCODE
```

```
! now get ID by its coordinates
```

```
xcall AUI,AUI_CONTROL, CTLOP_GETID,0,"",0,0,"","",CSTATUS,2,8,2,8+XMAX-1
```

```
IF CSTATUS > 0 THEN
```

```
COPIES'ID = CSTATUS
```

## `ELSE` 

```
PRINT "UNABLE TO OBTAIN ID OF COPIES EDIT CONTROL"
```

```
ENDIF
```

Note that the only parameters of interest in the AUI AUI_CONTROL opcode 10 are the CSTATUS (which returns the ID of the control, if found), and the coordinates. Furthermore, the control will be matched if either the starting coordinates (2,8) or the ending coordinates (2,8+ _xmax_ -1) match the actual control. 

A-Shell Reference 

Page 1883 

The fact that the control can be matched by either the starting or ending coordinates is useful with INFLD controls, whose ending coordinates may be automatically adjusted due to the nature of the control type, and also with controls whose position may be based on some alignment logic, i.e. where you only know the position of the left or right edge. 

Note that for debugging purposes, you can determine the internal coordinates and other parameters of all the controls by positioning the mouse on an empty spot in the current dialog or main window and using CTRL+SHIFT+DOUBLE-RIGHT-CLICK. This will create and launch a spreadsheet containing the details of all the controls currently defined to A-Shell. 

In the above example, as the radio buttons change in the first group, we query the "Impressora" radio button to see if it is selected. If so, we enable the related INFLD controls; if not, we disable them. The logic for this (focusing just on the Copies edit control) would be similar to the following: 

```
UPDATE'CONTROL'STATUS:
```

- `! first, query the Impressora radio button, whose ID happens to be RBID(1)` 

```
xcall AUI,AUI_CONTROL, CTLOP_QRYCB, RBID(1), "", 0, "", "", CSTATUS
```

- `! if checked (CSTATUS=1) then enable the copies edit, else disable` 

```
If CSTATUS = 0 then CSTATE = MBST'DISABLE else CSTATE = MBST'ENABLE
```

```
xcall AUI,AUI_CONTROL, CTLOP_CHG, COPIES'ID, "", CSTATE
```

## **Comment** 

While the example above does effectively illustrate the use of CTLOP_GETID to retrieve the _ctlid_ of an INFLD control, the need for it could be eliminated by assigning an alphanumeric _ctlid_ for the INFLD control when it is created (via INFLD's _parentid_ parameter). 

A-Shell Reference 

Page 1884 

## **SET CURRENT TAB PANE** 

_Rewritten January 2013_ 

CTLOP_PANE (opcode 11) is only used with Tab controls, in order to select the current pane. There are two variations, one for the traditional (standard Windows) Tab control, and one for the TabX control. 

Traditional Tab (or TabX) Control: 

## **xcall AUI, AUI_CONTROL, CTLOP_PANE, tabid, "", pane** 

TabX Control: 

## **xcall AUI, AUI_CONTROL, CTLOP_PANE, tabid, paneid, cstate, NUL_CTYPE, NUL_CMD$, NUL_FUNC$, cstatus** 

## **Parameters** 

_tabid_ (Num or String)  [in] 

id of the Tab or TabX control 

_pane_ (B,4)  [in] 

is the pane number (starting with 1) 

_paneid_ (String)  [in] 

the alphanumeric identifier for the desired pane, which may be either the pane's command string (e.g. "VK_xF302"), or the pane's label text (e.g. "&History"), or the pane number (e.g. "2"). Note that with TabX, since it is possible to insert and delete panes after the control has been created, the pane number could be subject to change, and thus the command string or label text is a more robust identifier. 

## _cstate_ (B,4)  [in] 

may specify the optional flag MBST_SAVRES in which case the current panel's controls will be saved; if there is a previously saved set of controls for the new panel, it will be restored, and the number of restored controls will be returned in the _cstatus_ 

A-Shell Reference 

Page 1885 

parameter, allowing you to conditionally recreate the controls. For backwards compatibility, if _paneid_ = "", you can specify the new panel number in the low word of the _cstate_ parameter. 

Note: Since the MBST_SAVRES flag signals both the save operation (for the current panel) and the restore operation (for the new panel), if you only want one of the operations, you will have to use the two step method (CTLOP_CLR followed by CTLOP_PANE) so that you can specify the MBST_SAVRES flag on just the one operation. 

_cstatus_ (Signed Num)  [out] 

will return the number of controls restored if MBST_SAVRES was specified and there was a previously saved set of controls for the new panel. Otherwise it will return 0 for success, or < 0 for an error. See _Comments_ for more details about using _cstatus_ with MBST_SAVRES. 

## **Comments** 

In the traditional Tab control, clicking a new pane automatically selected it, so that the CTLOP_PANE operation is technically redundant, except for the need to clear the old controls from the panel. The click operation only highlights the new panel label; since all the labels share the same panel, it doesn't actually do anything to the panel itself). You may use CTLOP_CLR to clear the controls from the pane, but CTLOP_PANE also clears the controls, and thus is a better choice for compatibility with the TabX control. 

In the TabX control, clicking a new pane does **not** automatically select it or change the display in any way. It only sends the click string, leaving it to your application to decide whether to follow through or take some other action. Unlike the traditional Tab control, the TabX control supports different colors on each panel, so auto-selecting the panel on click would cause visual confusion if the application decided to delay or prevent the panel switch (due to some data validation issue on the current panel). To follow through the with panel switch, the application must use the CTLOP_PANE operation. 

In the standard/traditional scenario, switching panels always involved recreating all the controls for the new panel. However, for panels with many or complex controls, this can slow down the panel switching operation. The MBST_SAVRES option streamlines the panel switch operation by automatically restoring the controls if the target panel had previously been displayed. Rather than trying to keep track of which panels have been displayed and saved, the easiest programming approach is use the returned cstatus value to determine whether the controls need to be recreated, e.g.: 

```
xcall AUI, AUI_CONTROL, CTLOP_PANE, tabid, paneid$, MBST_SAVRES, NUL_CTYPE, NUL_CMD$, NUL_FUNC$, cstatus
    if cstatus < 1 then   ! (no controls restored)
```

A-Shell Reference 

Page 1886 

```
        < (re)create controls for the new panel >
```

```
endif
```

This way, the first time you switch to a panel, the application will have to create the controls, but subsequently if you switch back to that panel, the controls will be automatically restored, allowing the application to skip recreating them. 

If you don't want to use the restored controls and prefer instead to recreate them from scratch, you can use the CTLOP_CLR operation after CTLOP_PANE to remove the restored controls, then recreate them. 

Since the MBST_SAVRES flag triggers both the save operation for the current panel, and the restore operation for the new panel, in order to use the save/restore feature on only some of the panels, you would have to break up the panel switch operation into two parts: CTLOP_CLR followed by CTLOP_PANE. Both operations support the MBST_SAVRES flag, but in the case of CTLOP_CLR, it only performs the save operation, while in the case of CTLOP_PANE, if the panel is already clear, the save operation is ignored and only the restore operation is attempted. So for example, to switch from a panel whose controls you do want to save, to a panel whose controls you want to recreate from scratch (i.e. not restore), use this sequence: 

```
! save controls and then clear panel
```

```
xcall AUI, AUI_CONTROL, CTLOP_CLR, tabid, NUL_CTEXT$, MBST_SAVRES
```

```
! switch to new panel without restore
```

```
xcall AUI, AUI_CONTROL, CTLOP_PANE, tabid, paneid2$
```

To reverse the sequence, i.e. to switch back from the panel whose controls are not being saved, to the one whose controls you do want to restore: 

- `! clear panel without save` 

```
xcall AUI, AUI_CONTROL, CTLOP_CLR, tabid
```

```
! switch to new panel, requesting restore
```

```
xcall AUI, AUI_CONTROL, CTLOP_PANE, tabid, paneid1$, MBST_SAVRES, NUL_TYPE, NUL_CMD$, NUL_FUNC$, cstatus
```

A-Shell Reference 

Page 1887 

```
if cstatus < 1 then   ! if no controls restored
```

```
    <recreate controls>
```

```
endif
```

## **History** 

- 2013 January, A Shell 6.1.1333: CTLOP_PANE now supports one-step panel switch, with optional save/restore. 

A-Shell Reference 

Page 1888 

## **SET/CLEAR MBF_TABSTOP PROPERTY** 

_Added November 2013_ 

The opcodes CTLOP_TABSET and CTLOP_TABCLR are used for setting and clearing the MBF_TABSTOP property of a control: 

## **xcall AUI, AUI_CONTROL, CTLOP_TABSET, ctlid     ! set MBF_TABSTOP for ctlid** 

## **xcall AUI, AUI_CONTROL, CTLOP_TABCLR, ctlid     ! clr MBF_TABSTOP for ctlid** 

AUI_EVENTWAIT should skip over controls that do not have the MBF_TABSTOP property when using the keyboard navigation controls. 

Note: the rules for auto-initializing the MBF_TABSTOP property when creating new controls are a bit vague; these opcodes allow you to be explicit. 

Also note: the control dump contains a column making it more obvious which controls have the tabstop property, which show up with a numeric value of the control number offset by 5000. Currently there is no way to change this table order, which generally matches the order in which the controls were created. 

## **History** 

- 2013 November, A Shell 6.1.1368:  Added opcodes to A-Shell. 

A-Shell Reference 

Page 1889 

## **CTLID** 

When a control is created (CTLOP_ADD), an internal numeric ID is assigned to it and returned to you. For all other operations on the control (change, delete, etc.) you typically need to specify the ID value in order to identify the control. The standard data type for a control ID is B,2. For controls that are never manipulated after creation, such as static text controls, and which will be deleted indirectly by deleting the parent dialog or group, or by using Tab(-1,0), you may not have any use for the control ID and can just specify a literal zero in its place when creating the control. 

It is also possible to use alphanumeric control identifiers, in which case you can pre-establish your own ID's, possibly eliminating the need to save the ID returned from the control creation operation. Alphanumeric ID's can be up to 23 characters long, are case-sensitive, must start with a letter, and may contain letters, numbers, dashes and apostrophes. They also must be unique across all controls that exist at one time. 

When you specify an alphanumeric control identifier in the _ctlid_ parameter, the value is not updated on return from the CTLOP_ADD operation. But a numeric control ID is nonetheless assigned internally. Subsequent uses of the alphanumeric ID are internally converted to the equivalent numeric ID. Although most routines allow either the numeric or alphanumeric ID, there are some which only support the numeric ID. In that case, you can get the numeric ID by one of these methods: 

- On return from the CTLOP_ADD operation, the _cstatus_ variable will be set to the numeric ID. If successful; a value less than zero 

- indicates an error. 

- Opcode CTLOP_INFO may be used: specify the alphanumeric ID in the _ctlid_ parameter; the corresponding numeric ID will be 

- returned in the _cstatus_ parameter. 

See Control names for additional information on this topic. 

A-Shell Reference 

Page 1890 

## **CTEXT** 

Parameter _ctext_ specifies the primary text (and/or an image specification) that will appear on or in the control. This applies mainly to simple controls like buttons, static text controls, checkboxes, edit boxes, etc. Some controls have no text (such as a rectangle or image), or have so much text (like a Tab control or dialog), that ctext or may used for some other purpose, such as to specify a title or an encoded string of additional parameters. Refer to the topics on specific control types for ctext specifications relative to those controls, in particular: 

- Image Control 

- Button Icon Control 

- Command Link Button 

- Progress Bar Control 

- Tab Control 

Also see the opcode table for other specific exceptions based on the opcode. 

As a convenience when deleting or clearing controls, you may set _ctext_ to "*" to delete or clear all within the specified _srow_ , _scol_ , _erow_ , _ecol_ coordinates. Or you may specify the control purely by its _ctlid_ and omit all the remaining parameters. 

To assign an Accelerator to the control, precede the desired character with an & (e.g. ctext = "Self &Destruct") 

The limit on size of the _ctext_ parameter is approximately 3500 bytes. The actual limit is about 4K, less the space used for all of the other AUI_CONTROL parameters. The larger limit will be mainly useful with very large Tab controls, i.e. those having many tab panes). 

If _ctext_ does not contain a trailing null byte, and it is followed immediately in physical memory by the _func_ parameter, the last byte of _ctext_ will be truncated. 

A-Shell Reference 

Page 1891 

## **CSTATE** 

_Updated June 2016; see History_ 

Parameter _cstate_ indicates the initial state of the control (when adding) and flags which affect the change operation. The symbols come from ashell.def. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBST_ENABLE|&h0000000|Enabled.|
|MBST_DISABLE|&h0000001|Disable (grayed out).|
|MBST_HIDE|&h0000004|Hidden (invisible).|
|MBST_SHOW|&h0000008|Make visible (if hidden).|
|MBST_MINIMIZE|&h0000010|Create minimized modeless dialog. SeeDialog Positioning Tip<br>.Works withCTLOP_CHGand<br>CTLOP_ADD.|
|MBST_CENTER|&h0000020|Equivalent to MBST_HCENTER + MBST_VCENTER, which see below.|
|MBST_MAXIMIZE|&h0000040|(For MBF_ALTPOS dialogs only) Maximize dialog. Also see MBF_MAXBUTTON.|
|MBST_CHANGE|&h0000080|Change_ctext_and_cmd_. Use this with_opcode_2 to update the_ctext_and_cmd_parameters<br>associated with an existing button. Otherwise, only the button state is updated.|



A-Shell Reference 

Page 1892 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBST_TEXTONLY|&h0000200|May be added to MBST_CHANGE to cause only the text of the control to be modified. This<br>can eliminate the "flicker" that might otherwise appear as all of the attributes of the control<br>are reset, especially when updating the title bar of a dialog.|
|MBST_CLREDITS|&h0000400|Operate on edit controls only.|
|MBST_PLAY|&h0004000|Start an AVI playing. SeeAnimated Graphics<br>.|
|MBST_STOP|&h0008000|Stop an AVI playing.|
|MBST_POS|&h0010000|Causes the position and size of the specified control to be updated.|
|MBST_STYLE|&h0020000|Used withCTLOP_CHGto change the style and alignment flags for an existing control.|
|MBST_CHANGEX|&h0040000|This is related to MBST_CHANGE, MBST_POS and MBST_STYLE. It affects those attributes<br>(font, color, etc.) that were not covered by the other bits, and permits changing virtually<br>everything about most controls (tooltips, associated images, and in most cases even the<br>control type).|
|MBST_SELECT|&h0080000|This "selects" the control if the control has the design mode flag set. (Just ignore this<br>comment as "design mode" is a long way from being usable.) Note that to unselect a<br>control, use CTLOP_CHG with MBST_CHANGE and don't specify the MBST_SELECT flag.|
|MBST_ZTOP|&h00200000|These may be used to force the control to be at the top or bottom, respectively, of the "Z-|



A-Shell Reference 

Page 1893 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||order." (The "Z-order" determines the display order of controls that otherwise have the<br>same precedence. In general, controls created later are farther down the Z-order than<br>those created earlier. These flags would mainly be of use in situations where you have<br>overlapping sibling controls.)|
|MBST_ZBOTTOM|&h00400000||
|MBST_HCENTER|&h00800000|These allow controls to be centered just horizontally or just vertically. (Specifying both is<br>equivalent to MBST_CENTER.) Note that this kind of centering positions the current control<br>relative to its parent control, or, in the case of a dialog without a parent, relative to the<br>desktop. For example, MBST_HCENTER specified on a button within a dialog would<br>horizontally center the button within the dialog, effectively using the_scol_and_ecol_<br>parameters only to determine the button width. See the MBF_?CENTER flags inctype<br>for<br>options controlling the centering of text (or image) displayed within the control—as opposed<br>to the centering of the control relative to its parent. Note that for many control types,<br>particularly image controls, effective centering generally requires both the MBST_?CENTER<br>and MBF_?CENTER flags, i.e. centering of the image within the control and centering of the<br>control within the parent.|
|MBST_VCENTER|&h01000000||
|MBST_CHGTIPMNU|&h02000000|May be used with CTLOP_CHG to change just the context menu for the control. You could<br>also do this with MBST_CHANGEX, but it effectively deletes and re-adds the entire control,<br>creating a possible "flicker", and also requiring that you pass all of the parameters. With<br>MBST_CHGTIPMNU, other parameters such as the coordinates, type, etc. are ignored and<br>left alone. See sample program ICOMNUBAR[908,27] for an example of using the feature to<br>change the enabled/disabled state of icon context menus.|
|MBST_NOREDRAW|&h04000000|May be specified in a CTLOP_CHG operation to prevent the normal refresh/redraw of the<br>client area of the TabX control. This is mainly useful for eliminating "flicker" when<br>enabling/disabling panels other than the current one, since those operations do not really<br>require a full refresh.|



A-Shell Reference 

Page 1894 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBST_NORMALIZE|&h10000000|May be used with CTLOP_CHG to change the state of a minimized or maximized window<br>back to normal.|
|MBST_SAVRES|&h80000000|Improve performance when switching between panels.|



- Hex Decimal Values 

## **History** 

- 2016 June, A Shell 6.2.1427:  Centering of caption-less (MBF2_DLGNOCAP) dialogs within a parent dialog now supported. 

A-Shell Reference 

Page 1895 

## **DIALOG POSITIONING TIP** 

When MBST_MINIMIZE flag is specified (to create a minimized dialog), the normal position for the minimized dialog will be at the bottom left of the parent window. However, you also can force the minimized dialog to appear at the same position as the normal sized dialog by also setting the MBST_POS flag and putting the desired coordinates of the upper left corner of the minimized dialog into the upper 16 bits of the SROW and SCOL parameters. For example, if the normal position of the dialog is 8500,15 to 16500,60, but you want to initially display it minimized at 2500,62, then set your coordinates as follows: 

```
SROW = (2500*65536) + 8500
```

```
SCOL = (62*65536) + 15
EROW = 16500
```

```
ECOL = 60
```

```
CTYPE = MBF_DIALOG + MBF_MODELESS + MBF_SYSMENU
```

```
CSTATE = MBST_MINIMIZE + MBST_POS
```

Note that this technique is mainly relevant for modeless dialogs with the sysmenu option (for minimize/normalize/exit buttons). 

A-Shell Reference 

Page 1896 

## **MBST_SAVRES** 

_Added January 2013; see History_ 

The _cstate_ flag MBST_SAVRES can be applied to the CTLOP_CLR and CTLOP_PANE operations operations when operating on TabX controls to have the client module save the contents of the panel being cleared, and restore the previously saved contents of the new panel (if available). 

When switching from one TabX panel to another, the traditional protocol is to first call CTLOP_CLR to clear the controls from the current panel, then call CTLOP_PANE to establish the new panel, and finally (re)create the controls on the panel. The new feature doesn't change that logic, except as follows: 

To request that the existing contents of the panel be saved before the panel is cleared, specify the _cstate_ parameter with the MBST_SAVRES flag in the CTLOP_CLR call: 

```
xcall AUI, AUI_CONTROL, CTLOP_CLR, tabid$, NUL_CTEXT$, MBST_SAVRES
```

To request that the previously saved controls for the new panel be restored, specify the _cstate_ parameter with the MBST_SAVRES flag in the CTLOP_PANE call. To confirm whether any controls were actually saved, you should also specify up to the _cstatus_ parameter (which will return the count of the number of controls restored): 

```
xcall AUI, AUI_CONTROL, CTLOP_PANE, tabid$, paneid$, MBST_SAVRES, NUL_CTYPE, NUL_CMD$, NUL_FUNC$, status
```

```
if status <= 0 then   ! if no controls restored
```

```
   <(re)create the controls for the new panel>
```

```
 endif
```

## **Notes** 

• You need to identify the panel to switch to by putting the panel's label text or cmd string into the _paneid$_ parameter (i.e. ctext), rather than putting the panel number into the _cstate_ parameter (as in the traditional Tab control). This leaves the _cstate_ parameter available for the MBST_SAVRES flag. 

A-Shell Reference 

Page 1897 

- By checking the returned _status_ parameter, you can determine whether the restore operation was successful without actually 

- having to keep track of whether that panel has previously been displayed and saved (or even whether the ATE client version is sufficient to support the feature). 

- You must perform the CTLOP_CLR first, then the CTLOP_PANE. The reverse order is possible, but not when using MBST_SAVRES. 

- The motivation behind the MBST_SAVRES feature is not to simplify your application coding; in fact, it makes it slightly more 

- complex. Instead, the motivation is to improve the performance of switching between panels, particularly with ATE and with complex controls like XTREE and XTEXT. 

## **History** 

- 2013 January, A Shell 6.1.1332:  Flag added to A-Shell 

A-Shell Reference 

Page 1898 

## **CTYPE** 

Parameter _ctype_ specifies any valid combination of options from the following table. The symbols come from ashell.def. 

Also see the ctype2 parameter. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBF_BUTTON|&h00000000|(default control type) A rectangular button, which displays a text string and is virtually always<br>associated with a click action. SeeButton Control<br>.|
|MBF_CMDLIN|&h00000000|(default_cmd_type) Clicking the control causes the contents of_cmd_to be executed as a Windows<br>command line, as if it had been executed viaxcall HOSTEX. See thecmd<br>topic.|
|MBF_DLL|&h00000001|DLL. Clicking the button causes the function (_func_) with the associated DLL (defined in_cmd_) to be<br>loaded and executed.|
|MBF_CHKBOX|&h00000004|Checkbox. Clicking on the button toggles the checkmark display, as well as the value of the one-byte<br>parameter (0 for unchecked, 1 for checked) in func. SeeCheckbox Control<br>.|
|MBF_3STATE|&h00000008|Three-state checkbox. Same as a regular checkbox except it has three states: unchecked (0),<br>checked (1), and indeterminate (2).|
|MBF_AUTORADIOBTN|&h00000010|Radio button. Used in a group (see MBF_GROUPBOX) of two or more radio buttons. Similar to<br>MBF_CHECKBOX except that only one may be selected at a time. Although popular in Windows<br>forms, from a programming standpoint, they are more complex and less efficient than andINFLD<br>combo box (which otherwise accomplishes the same task of allowing the selection of just one from a<br>short list of choices. SeeCheckbox Alignment, Justification<br>.|



A-Shell Reference 

Page 1899 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBF_RADIOBTN|&h00000010|Same as MBF_AUTORADIOBTN.|
|MBF_HCENTER|&h000000C0|Horizontal centering of control text (at top). Applies to static (MBF_STATIC), button (MBF_BUTTON)<br>controls only, with text or images (MBF_BITMAP). For horizontal MBF_TOOLBAR controls, centers the<br>buttons horizontally in the toolbar. SeeControl Alignment<br>. Also see the MBST_?CENTER flags in<br>cstate<br>.|
|MBF_CENTER|&h000000E0|Centering along both axes. See above comment for MBF_HCENTER.|
|MBF_VCENTER|&h00000020|Vertically center text or image within the control. Applies mainly to static text controls, which<br>otherwise default to top alignment. Also see MBST_CENTER incstate<br>for centering an entire control<br>on its parent, andControl Alignment<br>.|
|MBF_LFTEXT|&h00000020|For controls such as checkboxes, that contain a text element and some other element, specifies that<br>the text element appear to the left of the other element. (Default is to the right.)|
|MBF_DLGNOPARENT|&h00000020|Force dialog box to be a child of the desktop (sibling of the main A-Shell window) rather than a child<br>of the main A-Shell window (both of which involve setting the_parentid_parameter to 0). For non-<br>dialog controls, also seeMBF2_NOAUTOPARENT<br>.|
|MBF_LFJUST|&h00000040|Left justify text. (Default is center.) Note that for checkboxes, this affects only the justification of the<br>text within the space allotted to it, not whether the text is to the left or right of the checkbox. See<br>MBF_LFTEXT above.|
|MBF_RTJUST|&h00000080|Right justify text. (Default is centered.) See MBF_LFJUST above. Note that for MBF_TOOLBAR,|



A-Shell Reference 

Page 1900 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||justifies the buttons within a horizontal toolbar (buttons are left-justified by default).|
|MBF_BITMAP|&h00000100|Use with buttons (MBF_BUTTON) or static text controls (MBF_STATIC) to display an image instead of<br>text in the control._ctext_is interpreted as the filespec (either AMOS or native) or a DLL bitmap<br>resource (resname::dllname); supported types are BMP, JPG, TIF, PCX, PNG. For buttons, the image<br>will be stretched to fill the button. For static controls, see MBF_NODISTORT, MBF_HCENTER,<br>MBF_VCENTER and MBF_CENTER, andImage Control<br>.|
|MBF_SYSMENU|&h00000100|For dialogs (MBF_DIALOG), this causes the dialog to sport an "X" (aka system menu) in the upper<br>right corner allowing it to be closed by clicking on it. SeeModal Dialog Box<br>.|
|MBF_ICON|&h00000200|Icon. Applies to both button (MBF_BUTTON) and static (MBF_STATIC) control types. SeeIcon<br>Control<br>.|
|MBF_TABSTOP|&h00000400|Indicates that the control is part of the group of controls that may receive the focus by tabbing<br>between them. This is automatic for MBF_BUTTON, but may optionally be applied to MBF_CHKBOX,<br>MBF_3STATE, MBF_AUTORADIOBTN and MBF_STATIC controls. Currently this is only applicable in<br>conjunction with the AUI EVENTWAIT class.|
|MBF_MAXBUTTON|&h00000400|For dialogs with MBF_ALTPOS and MBF_SYSMENU options set, enables the maximize button.|
|MBF_SEP|&h00000800|Separator.|
|MBF_DLGNOCREEP|&h00000800|Dialog No Creep<br>applies to nested dialogs, forcing their coordinates to be interpreted relative to the<br>main window, rather than to the parent dialog.|



A-Shell Reference 

Page 1901 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBF_AUTOGROW|&h00000800|For static text controls (MBF_STATIC), causes the control to automatically grow as needed to contain<br>the text.  For left justified text (MBF_LFJUST), the left edge will be determined by scol, while ecol is<br>treated only as a minimum size.  (The actual right edge of the control will be shifted to the right as<br>needed to contain the text.)<br>For right justified text (MBF_RTJUST), the right edge is set by ecol and expands to the left as needed<br>(with scol establishing the minimum).  The bottom edge of the control will also be shifted if<br>necessary to contain the height of the text.  MBF_AUTOGROW is not compatible with MBF_WRAP.|
|MBF_SUNKEN|&h00001000|For static text controls (MBF_STATIC), causes them to appear with an "sunken" edge.|
|MBF_READONLY|&h00001000|Read only (with MBF_EDIT).|
|MBF_XCLASS|&h00002000|Set internally for certain special control classes.|
|MBF_UPDOWN|&h00004000|This is a special-purpose option. Generally you would not use this flag directly, unless you wanted to<br>create an Up-Down control independent ofINFLD. In that case, use MBF_EDIT + MBF_UPDOWN (+<br>any other relevant flags); set WINCLASS$ = "ASHEDIT", and WINSTYLE to any valid ES_xxx flags<br>(Windows Edit control styles). Such a control will allow the user to change the value by clicking on<br>the Up-Down buttons, independent of any signals or actions by the application. You would need to<br>use theAUI_CONTROLCTLOP_INFO function to retrieve the current value of the field.|
|MBF_TOOLBAR|&h00008000|TheToolbar Control<br>creates a Windows-typical toolbar across the top of the parent window.|
|MBF_KBD|&h00010000|Keyboard. Clicking on the control causes the contents of_cmd_to be forced into the keyboard buffer.|



A-Shell Reference 

Page 1902 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||See cmd<br>for specifications and hints on how to use this technique effectively. Note that MBF_KBD is<br>ignored if MBF_SHLEXC, MBF_CMDLIN, or MBF_DLL are set.|
|MBF_SHLEXC|&h00020000|Shell execute. Clicking the button causes the contents of_cmd_to be interpreted as an object (file or<br>URL) to be opened using the associated application defined in the Windows Registry. Seecmd<br>notes.|
|MBF_STATIC|&h00040000|Static control, normally used for text prompts, but also may be used for graphic lines and images.<br>For images,_ctext_is interpreted as the filespec (either AMOS or native) or a DLL bitmap resource<br>(resname::dllname) ; supported types are BMP, JPG, TIF, PCX, PNG. See example underAdd<br>Control<br>.|
|MBF_EDIT|&h00080000|Edit control (reserved forINFLDuse). SeeIcon Control<br>.|
|MBF_ALTPOS|&h00100000|Adjusts the way in which a control is positioned, with the specific effect varying by the type of<br>control. For buttons (MBF_BUTTON) and group boxes (MBF_GROUPBOX) it causes a slight vertical<br>adjustment (usually an improvement) in the way they are positioned and sized on the screen. See<br>Groupbox + MBF_ALTPOS<br>. For horizontal lines, it moves them from the center of the row to the<br>bottom of the row. For dialogs, it switches the entire dialog (and all its child controls) to the<br>Alternate Dialog Coordinate System<br>.|
|MBF_WORDELLIPSIS|&h00200000|For static text controls (MBF_STATIC), if the text in ctext does not fit within the control, an ellipsis<br>(...) will be displayed.|
|MBF_PATHELLIPSIS|&h00400000|For static text controls (MBF_STATIC), if the text in_ctext_does not fit within the control, it is<br>interpreted as a path, and an ellipsis will be used for the middle portion of the path to shrink it to fit.|



A-Shell Reference 

Page 1903 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBF_WRAP|&h00400000|Applies to buttons (MBF_BUTTON) only, causing text within them to wrap to multiple lines (assuming<br>the button is tall enough). This is automatic for static controls.|
|MBF_NODISTORT|&h00400000|Applies to images (MBF_ICON or MBF_BITMAP) within controls (MBF_STATIC or MBF_BUTTON) only,<br>causing the aspect ratio of the original image to be preserved when scaling it to the size of the<br>control. Otherwise, the image will be stretched to completely fill the control.|
|MBF_MODELESS|&h00400000|Mode-less dialog (with MBF_DIALOG).|
|MBF_DIM|&h00800000|For static text controls (MBF_STATIC), applies the equivalent of the "dim" attribute. This affects the<br>interpretation of the foreground color (_fgc_) and also makes the text behave like normal fixed-pitch<br>text with respect to protection and clearing.|
|MBF_LISTBOX|&h01000000|List box control. (Reserved for internal use byXTREE)|
|MBF_GROUPBOX|&h02000000|Creates a "groupbox", which can be used to group other controls. (Do not set MBF_STATIC!) See<br>Groupbox Control<br>.|
|MBF_FRAME|&h02000000|When used with MBF_STATIC, creates a variation of static control that has a "frame" edge, making it<br>stand out from the background (sort of the reverse of the sunken effect.)|
|MBF_COMBOBOX|&h04000000|Combo box control (reserved forINFLDuse)|
|MBF_UNPROTECTED|&h08000000|May be applied to buttons and other controls which are normally protected, to allow them to be|



A-Shell Reference 

Page 1904 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||cleared by opcode 4. SeeClear Control<br>.|
|MBF_PROGRESS|&h10000000|Progress bar control. SeeProgress Bar Control<br>.|
|MBF_DIALOG|&h20000000|Dialog box. SeeModal Dialog Box|
|MBF_TAB|&h40000000|Tab control. SeeTab Control<br>,and the MBF2_TABX entry in thectype2<br> table.|
|**Definition file: ashell.def**|||



- Hex Decimal Values 

A-Shell Reference 

Page 1905 

## **DIALOG NO CREEP** 

This option ( _ctype_ MBF_DLGNOCREEP) applies only to dialogs, causing them to be positioned relative to the main window rather than relative to the parent dialog. Such nested dialogs with the same starting coordinates will have the same upper left corner position. Otherwise, dialogs are positioned relative to the parent, and are offset down and to the right by 2 times the thickness of the border, so that a series of nested dialogs will "creep" (or cascade) down to the right. 

Note that MBF_ALTPOS causes the same effect (among others), as does selecting the "Windows desktop font size" option in the Dialog Sizing dialog. 

Dialogs with the MBF_SYSMENU flag offer additional choices for how it responds to the user clicking on the "X" to close it. By default, that sends an ESCAPE and leaves it to the application to close the dialog (using AUI_CONTROL opcode 3). This requires setting the MBF_KBD flag. If you set that flag and put something in the _command_ parameter, then that string will be sent instead of the standard ESCAPE. If you set the MBF_KBD flag but leave the _command_ parameter empty, then dialog will close itself without sending anything to the application. This might actually be very convenient for status/info/debug dialogs that are just outputting auxiliary messages, perhaps via SCRSTS.SBX; in which case further output would just be thrown away. 

SCRSTS.SBX 1.0(105) supports this capability; see the updated TSTSCR sample program (edit 104+) in [907,20] to experiment with it.) 

A-Shell Reference 

Page 1906 

## **ALTERNATE DIALOG COORDINATE SYSTEM** 

The standard A-Shell coordinate system is based on dividing the main window size by the currently defined number of rows and columns. To put it another way, the basic unit of the coordinate grid is the text-based coordinate cell size. This fact helps facilitate the coexistence of text and GUI elements on the same window, but it has two shortcomings for GUI development: 

• The grid size is dependent on the actual size of the main A-Shell window, which can be easily adjusted, thus leading to a grid size that may be vastly too big or too small for a particular screen environment 

- It is based on fixed-pitch fonts which have little to do with the proportional fonts used in GUI environments. 

The problems become particularly noticeable with dialogs, which are typically designed to be a certain size relative to the information contained within, and not dependent on the size of the window that called the dialog. Yet, with the normal A-Shell grid system, the dialog, being just another control, uses the same grid as the parent window, making the dialog layout helplessly dependent on the user setting the main window to a reasonable size. 

To overcome these shortcomings, the MBF_ALTPOS option may be specified when a dialog is created in order to have the dialog use a more flexible coordinate system which is independent of the A-Shell main window and which self-adjusts to provide a "constant logical size." This is accomplished by basing the alternate grid on the current standard GUI font size. In addition to being independent of the size of the main window, it also adjusts to the "DPI" of the Windows desktop. 

The units of the alternate grid are still based on individual characters, which allows you to lay out the dialog almost as if it was a traditional text screen (where one character equals one column). Only here, we are using an "average character width." So while you can count the actual number of characters in your dialog labels to determine the sizes needed for the controls, as with "standard Windows dialogs", you need to allow enough room for the variability in character widths of variable text, since capital letters are on average twice as wide as lower case in the typical GUI font. So you cannot count on a 20 character string fitting in 20 "columns" of the dialog. But if you use mostly lower case, it should be a rough approximation, and if you allow a little extra space, your dialogs should be pretty resilient to local environment settings. 

As an added bonus, this coordinate system is reasonably compatible with the old one, meaning that adding MBF_ALTPOS to an existing dialog will probably not break it, and may improve it. 

There is one significant difference that must be noted when using the MBF_ALTPOS option, involving the way the height of the dialog is calculated. In the original dialog implementation, the total dialog height was based on multiplying the row height of the main window by the number of requested rows in the dialog coordinates. But this calculation included the dialog border and title bar, which reduced the usable number of rows of the dialog. A margin was added to the bottom, but the net effect is that normal 

A-Shell Reference 

Page 1907 

dialogs have one less usable row than they ought to. And when the dialog gets too small, even that last row may be truncated. Arguably this should be fixed since it is confusing, but doing so now would probably affect too many programs. 

However, when the MBF_ALTPOS flag is specified, the dialog height is calculated to take into account the border and title bar, so that you always get the full number of rows specified. For example, if a dialog was coded to start at row five and end at row fifteen, you get eleven usable rows.(In addition, there is a half-row margin at the bottom, which gives buttons placed on the bottom row of a dialog a little breathing room.) 

TRMCHR is aware of this distinction, and returns the full number of rows in WINROWS when the MBF_ALTPOS flag was used to create the dialog. Otherwise, it returns one row less, which generally works but is still an approximation since the amount of space lost due to the border and title bar could amount to more than one row if the rows are short enough. 

This "correction" to the height calculation of dialogs may cause your existing dialogs to appear to have an extra row at the bottom (or, if you used the BTNMNU. SBX option to put buttons on the bottom row, then the extra space will appear above that.) The sample program TSTEVW in EXLIB:[908,20] has been upgraded to deal with this by subtracting one from the height of the dialogs if you select the MBF_ALTPOS option. Another way to deal with the "correction" is to check the option on the Dialog Sizing dialog labeled "Included caption in dialog height." This, however, only applies to dialogs that were forced to use the alternate grid system (aka Windows desktop font size grid) by means of the radio button choice in the Dialog Sizing dialog. (The 

combination of the two options allow you to experiment with switching to the alternate grid without actually modifying any code. Once you decide you like it, you can explicitly add the MBF_ALTPOS option to your dialog settings in your code, and adjust the dialog height at the same time.) 

Another minor difference when using the MBF_ALTPOS option, is that the starting row/col coordinates of the dialog are interpreted as relative to the main window, and not to the parent dialog. This only matters for nested dialogs, and allows you more flexibility in positioning such nested dialogs (which otherwise cannot start up or to the left of the previous dialog.) But since dialogs can be dragged around the screen by the user, it probably will not have any significant deleterious effect on existing dialogs that are converted to the new grid system. 

Note that a nested dialog will automatically inherit the ALTPOS grid size from its parent dialog (if the parent dialog had the ALTPOS option). But it will not automatically inherit the alternate positioning logic or height calculation. That is, if the parent dialog uses MBF_ALTPOS, then any nested child dialog will automatically use the same spacing. But unless the child dialog also uses MBF_ALTPOS, its upper left corner will be positioned relative to its parent, and its bottom row usability will be related to the relationship between the row height and title bar height. Otherwise, if the child dialog does use MBF_ALTPOS, then its upper left 

A-Shell Reference 

Page 1908 

corner will be relative to the main window and use the same height logic, and thus if it has the same coordinates as the parent dialog, it will exactly overlay it. 

One additional advantage of the Alternate Dialog grid is that it allows you to create maximized dialogs, either under program (MBST_MAXIMIZE) or user control (MBF_MAXBUTTON). When such a dialog is maximized (or normalized), all of the controls scale accordingly. If the size difference between the normal and maximized state is more than 10% in each direction, the fonts will be scaled as well, as will the column sizes of any XTREE columns which have _Dspmin_ or _Dspwid_ Advanced Coldef Options. The fonts within XTREE controls, however, will not be resized. 

A-Shell Reference 

Page 1909 

## **CMD** 

Parameter _cmd_ , a string of up to 199 characters, specifies the command, DLL, keystrokes, or object reference (according to _ctype_ ) associated with clicking on the control. The choices are: 

- Windows Command Line 

- Keyboard Commands 

- Shell execute 

- Subroutine (SBX) 

## **See Also** 

- The discussion on how to use an Accelerator key 

- The commentary in Modal Dialog Box Control about customizing the "X" button behavior. 

A-Shell Reference 

Page 1910 

## **WINDOWS COMMAND LINE** 

(MBF_CMDLIN) When launching a Windows command line (unrelated to A-Shell, such as the Windows calculator), it is often problematic to know the fully qualified path. If the command cannot be assumed to be in the default PATH (like NOTEPAD or CALCULATOR) or in the Registry (typical for newer installations of Office applications), then you will probably have to use an environment variable and insist that it be defined. For example, you might put your utilities in an arbitrary folder but require as part of the installation procedure that an environment variable, say, ASHUTIL, be defined, then you can specify it in your command lines (e.g. " `%ASHUTIL%\MYUTIL.EXE` "). Or you can just require that the PATH environment variable be extended to include the directory where your special utilities are found. 

Another idea would be to install any such custom utilities in a directory with a known relation to the DSKn directories. Then you can refer to it using relative notation, e.g. " `..\..\ashutils\myutil.exe.` " This would assume that the "ashutils" folder as a sibling to the DSKn folders. 

If you are using the command line to launch another instance of A-Shell, as with xcall HOSTEX, you can refer to the current A- Shell executable (and its current miame.ini) via the macro symbol `$ASHELL` , and you can use the suffix characters available to HOSTEX. For example, `"$ASHELL –e run armenu $"` would launch a new A-Shell instance, run the program armenu, and suspend the current session until armenu exited. 

A-Shell Reference 

Page 1911 

## **KEYBOARD COMMANDS** 

(MBF_KBD) Although you might find it convenient in menus to set your button or other control cmd strings to mimic what might otherwise be keypunched by the operator to make a menu selection, care must be taken to prevent the user from sending such "ordinary text" commands in the wrong context. The best way to avoid that problem is to define your keyboard _cmd_ strings to send pseudo function key sequences. These will automatically be converted by INFLD (and other routines which wait for events, such as BTNMNU and AUI AUI_EVENTWAIT) into exitcodes, and can be processed relatively easily by other character-level input routines. 

There are several formats for defining pseudo-function key sequences: 

```
chr(7) + chr(n)
```

or 

```
chr(7) + chr(250) + "####."
```

or 

```
"VK_xF####"
```

or 

```
"VK_xrF####"
```

The first format is limited to values of (n) from 1 (for F1) to 249. The last three provide a nearly unlimited range of pseudofunction key numbers and are therefore preferable. (The #### shown can actually be any number of digits. In the second format it must be terminated with a period, but not in the symbolic formats which start with "VK_".) So you can theoretically assign a different pseudo function key to every single control in an entire application, or at the very least to every control in a program. Note that in either case, if converted by INFLD or a similar routine into an exitcode, the exitcode will be the negative of the pseudo-function key number. So in the first case, the range is from –1 to –249, while in the others it is from –1 to – - 9999999. See Event driven Programming for more details on how to use this form of keyboard command string to allow a program to respond to a user clicking randomly on controls. Also see the highlighted note below. 

A-Shell Reference 

Page 1912 

The last format example above is equivalent to the third one, except that the presence of the "r" indicates that a right click on the field is also allowed, and if so, the exitcode value will be positive rather than negative. So, for example "VK_xrF421" will generate exitcode -421 for a left click, and +421 for a right click. 

The symbolic notation is preferable to the chr(x)... notation, both for readability, and because in the ATE environment, certain control characters may have trouble passing through the data stream to the client without being filtered. 

Besides the pseudo-function key sequences, there are also symbolic equivalents for most standard control character sequences. For example, a CTRL+X can be represented by "^X" rather than chr(24). An escape character can be represented by "VK_ESC" instead of chr(27). See Virtual Key Symbolic Names for a table of all the symbolic control key definitions, and also for information on how to combine multiple control codes into a single command string. 

When assigning pseudo-function key sequences to controls, avoid using exitcodes in the range of -100 to +100. Many of these are used for internal navigation and other event codes by routines such as INFLD, EVENTWAIT, XTREE and XTEXT. Exitcodes -1 thru -32 are possible exceptions. They are not used by A-Shell, but have been typically used in the past to represent function keys F1 thru SHIFT+F16. If you want to equate, say, a button to F5, then it might be appropriate to set cmd string to VK_xF5. The downside is that some users may have expectations for function key actions that don't match yours, which could cause them confusion. For example, some people expect F1 to bring up help, so defining a button which says "Cancel" with cmd = "VK_xF1" might not be the best idea. 

A-Shell Reference 

Page 1913 

## **SHELL EXECUTE** 

(MBF_SHLEXC) For launching Windows commands, this method is often preferable to the Windows Command Line method discussed above, since it eliminates the problem of determining the fully qualified path for the command. Instead, you just specify the file or object reference (or URL) and Windows launches the necessary program (or gives the user a chance to specify what program goes with that file or object type.). For example, if _cmd_ = "http://www.microsabio.com", then clicking it would launch the browser and go to the specified web page. If _cmd_ = mydata.xls, clicking the button would launch whatever the user’s preferred spreadsheet program was to open the spreadsheet. 

If the file object specified in _cmd_ does not contain a drive or directory specifier, then it will be assumed to be in A-Shell’s "DOC" subdirectory (e.g. c:\vm\miame\doc). Otherwise, you need to specify a native pathspec (unless the file is in the system search PATH). See MX_FSPEC. 

A-Shell Reference 

Page 1914 

## **SUBROUTINE (SBX)** 

(MBF_CMDLIN) If the command line starts with "SBX:", instead of treating it as an ordinary Windows command line, the specified SBX subroutine is called with the specified arguments.  The complete syntax is as follows: 

## **SBX: sbxnam, arg1, arg2,...argN** 

## **Example** 

```
"SBX:EVTMSG,Hello World"
```

## **Notes** 

Other than the "SBX:", this is essentially equivalent to the XFUNC() syntax, but unlike XFUNC, the return value of the SBX is ignored. 

Do not include any extra spaces before or after the colon and comma delimiters. 

All arguments will be passed to the specified SBX module as strings. For SBXs that expect numeric arguments, this is usually not a problem because the standard parameter conversion routine will convert strings to numbers, but there could be some SBXs that make decisions about the calling arguments based on the types passed. (EVTMSG happens to be one of them; if the first argument is numeric, it is treated as the event level, else it is treated as the message.) 

The current state of A-Shell or ATE is suspended while waiting for the SBX to return, so it is probably only a good idea to use this with modal functions that are reasonably limited in scope. (Using it to launch an entire application, which in turn may get nested by subsequent launches is likely to burn up a lot of stack space; using the traditional CMD = "$ASHELL ..." to launch a new instance would be preferable in that case. 

A-Shell Reference 

Page 1915 

## **ACCELERATOR** 

_Updated October 2013; see History_ 

Controls that have a click action associated with them, such as cmd, may define an accelerator character by inserting a "&" in front of the desired character in the display text of the control. For example, if a button displays "Open", you can make the "O" be the accelerator character by setting the label to "&Open." Such an accelerator character allows the control to be "clicked" by the key combination ALT+<CHAR> where <char> is the designated accelerator character. (In the example just described, hitting ALT+O would act the same as clicking on the button.) 

Accelerator characters will be indicated on the screen by underlining, although the underlines may not initially appear until the user hits the ALT key. 

Note that in order for the accelerator to have a practical effect, the control must define some kind of action in its _cmd_ parameter and its ctype flags must include MBF_KBD. 

## **History** 

- 2013 October, A Shell 6.1.1363: AUI_CONTROL refinement: controls without text, such as icons with no labels, can now still have an accelerator key by inserting it at the start of the tooltip string. For example, to use the accelerator key "H": 

```
TOOLTIP$ = "&H Show History"
```

or: 

```
TOOLTIP$ = ">&H Show History\<menu def>"
```

Note that the accelerator key will not display in the tooltip, so you may want to include some kind of textual hint, i.e. 

```
TOOLTIP$ = "&H Show History (Alt+H)"
```

A-Shell Reference 

Page 1916 

## **FUNC** 

Parameter _func_ has two purposes. For type 1 (MBF_DLL), it must be a string containing the name of the function to execute within the DLL whose name was specified in cmd. For types 4 and 8 (checkboxes), it should be a B,1 variable whose value will be tied to the state of the checkbox (0=unchecked, 1=checked, 2=indeterminate). The initial value of _func_ upon creating the checkbox will determine its initial check status. Thereafter, the value of the variable will change automatically and immediately as the checkbox is checked/unchecked. 

The above technique of tying a variable directly to the checkbox state only works when the variable in memory is maintained in the same environment and context as the checkbox control. In the case of ATE, the checkbox control is on the client and the variable is on the server, so the link only works to establish the initial value of the control. After that, it is harmlessly broken, requiring you to query the checkbox value using opcode CTLOP_QRYCB. 

A particular situation to avoid is creating a checkbox within an SBX, using a B,1 variable for the _func_ parameter. When the SBX exits, the checkbox control will remain linked to the variable's address, even though that memory will have been relinquished by the SBX. To avoid this, just specify a null string ("") for the _func_ parameter when creating a checkbox, and use CTLOP_QRYCB to query it. 

Checkboxes can also be created and managed by INFLD, in which case it handles the details just described internally and interfaces with the application as if the checkbox were a Yes/No field. 

A-Shell Reference 

Page 1917 

## **CSTATUS** 

## Parameter _cstatus_ (signed num) returns a code indicating the result of the operation: 

|**Value **|**Description**|
|---|---|
|>=0|OK, or for_opcode_2 indicates control was previously enabled. For_opcode_1,<br>if an alphanumeric_ctlid_parameter is specified,_cstatus_will return the<br>numeric ID of the new control.|
|1|OK, or for_opcode_2 indicates control was previously disabled|
|-1|Add or delete control function failed|
|-2|Button (_ctlid_or_ctext_) not found during change or delete operation|
|-3|Out of memory (unable to allocate control storage buffers)|
|-4|Exceeded maximum number of added controls. Note that in A-Shell 1166 of<br>21 Nov 09, the limit of 600 controls was eliminated; the control table<br>expands as needed, without limit. This value should therefore not occur.|
|-5|No control buffer allocated|
|-6|Illegal_opcode_|
|-7|Control already exists|



A-Shell Reference 

Page 1918 

|**Value **|**Description**|
|---|---|
|||
|-8|Control update operation failed|
|-9|Unable to load bitmap or icon file. Note the common error of mismatching<br>the_ctype_flag (256 or 512) with image file type (BMP or ICO)|
|-10|Incorrect control type for operation|
|-11|No batch in progress|
|-12|Illegal tab request or duplicate batch request|
|-13|Parent dialog not found|



## **ATE performance notes** 

If you do not care about the returned _cstatus_ or _ctlid_ , you can specify the _cstatus_ variable as a null string ("") or eliminate it entirely if you do not need any of the other parameters. This prevents the routine from returning any information, eliminating the network turnaround latency (in the case of ATE) that would otherwise accompany each AUI_CONTROL operation. While small, these round-trip delays can add up, so that a screen consisting of many items might take seconds, as opposed to milliseconds, to display. Technically, each control creation operation could fail, but in practice, it is rare, as well as unlikely that your application would have a meaningful recovery planned anyway. So other than the case where you need the returned control ID for future 

A-Shell Reference 

Page 1919 

reference, there is little practical value to the returned status. And even in the case of needing the returned control ID, you can eliminate that necessity by supplying an alphanumeric control name in place of the ID; see Control names. 

A-Shell Reference 

Page 1920 

## **SROW, SCOL, EROW, ECOL** 

_Updated April 2015; see History_ 

(Num)  These coordinate parameters determine the position and size of the control, based on the grid according to the following options and considerations. For controls in the main window, the units are normally based on the main window grid. For controls within dialogs, the units are normally based on the parent Dialog Grid Units. In either case, they may be specified in rows and columns (whole units), or for more precision, Millirows and Millicolumns. There are two notable exceptions, triggered by the MBF2_PIXCOORDS and/or MBF2_PIXSIZE flags in ctype2. In the case of MBF2_PIXCOORDS, the coordinates are interpreted in units of display pixels, and negative values for _erow_ and _ecol_ are taken as relative to the bottom and right edge of the parent control. MBF2_PIXSIZE (with or without MBF2_PIXCOORDS) causes _erow_ and _ecol_ to be interpreted as the height and width, respectively, of the control in pixels. 

See History below for details on using negative grid coordinates to specify the control position relative to the right/bottom edges of the parent control, rather than the top/left edges. 

Regardless of the units, child control positioning is always relative to the client area of the parent control, which may be determined implicitly or by an explicit _parentid_ . Many different control types can serve as a parent control, including the Groupbox Control, Static Text Control, Tab Control as well as all kinds of dialog controls. For the main window and dialogs, there may be a small amount of internal margin, such that srow and/or scol values of 1 (or 1000 milli-units) may not be flush against the top or left edge of the parent client area. To rectify that, use the MBF2_STICKY flag. To make the right or bottom edge of the child control extend to the right or bottom edge of the parent, set the erow and/or ecol values slightly larger than necessary and MBF2_STICKY will adjust them as needed. 

The position of dialog controls may be relative to the main window or to the physical screen; see Dialog Positioning for details. 

For the Toolbar Control, the coordinates should be set to all zero for them to auto-adjust to the dimensions of the main window. The one exception is if you want to split a horizontal toolbar into left and right parts, in which case set ecol the ending column for the _left_ toolbar and _scol_ to the starting column for the right toolbar. 

## **See Also** 

Alternate Dialog Coordinate System 

## **History** 

A-Shell Reference 

Page 1921 

- 2015 April, A Shell 6.1.1407:  AUI refinement: the logic that auto-deletes controls with conflicting coordinates now ignores controls belonging to a TAB control parent. The main purpose of the auto-deletion is to accommodate automatic conversion of text-based programs to GUI, but such program would not involve a TAB control, for which there is no text-based analog. On the other hand, some programs involving TAB controls might purposefully create child controls for multiple panels and AUI would have no way of distinguishing these because all the panels share the same effective parent ID. 

- 2014 February, A Shell 6.1.1377: AUI_CONTROL enhancement / behavioral change: negative grid coordinates are now interpreted as relative to the bottom/right edges of the parent control. When using grid coordinates, _srow/scol_ values < 0, and/or _erow/ecol_ values <=0 are interpreted as relative to the bottom and right edge of the parent control. This was already the case for MBF2_PIXCOORDS but now works for grid coordinates. Note that this does eliminate an ancient but probably unused feature in which negative coordinate values were assumed to be pixels. If you want to use pixel coordinates, you should use MBF2_PIXCOORDS. 

2013 November, A-Shell 6.1.1368:  Introduce support for split toolbars, allow for negative _erow_ and _ecol_ values with with MBF2_PIXCOORDS. 

A-Shell Reference 

Page 1922 

## **MILLIROWS** 

When the start row or end row coordinate of a control (created by AUI_CONTROL, AG_CONTROL, INFLD, etc.) is greater than 200, it is assumed to be in units of "millirows" (1000 to the row) rather than rows. This allows the vertical position and size of a control to be more finely adjusted than is possible with integer rows or even with the MBF_ALTPOS option. 

In general you will get the same results whether you specify an _srow_ value in units of rows or multiply it by 1000. There are some exceptions, though, where the default position of a row is adjusted up or down based on some internal logic, and in such cases, switching to millirows may defeat the internal logic, causing the line position to change more than expected. For example, with single row horizontal line controls, the default position is in the middle of a row. If you switch from, say, row 5 to millirow 5000, the second line will be half a row higher than the first. In general though, if you want to move a control up or down by a slight amount, multiply the _srow_ value by 1000 and then offset it by some fraction of 1000. To convert _erow_ to millirows, first add 1 and then multiply by 1000 (e.g. _erow_ 5 is equivalent to millirow 6000). 

In order for a control to occupy a single "row", its _erow_ coordinate should be 1000 millirows higher than the _srow_ coordinate. Some examples will make this clear: 

|**Coordinates**|**Result**|
|---|---|
|_srow_=2 :_erow_=2|Control is one row high.|
|_srow_=2000 :<br>_erow_=3000|This is equivalent to the previous example. Note that<br>when converting_erow_from standard rows to millirows,<br>add 1 and then multiply by 1000. When converting_srow_,<br>just multiply by 1000.|
|_srow_=2100 :<br>_erow_=3100|This is equivalent to the previous example, except that it<br>is shifted down by 1/10 of a row (100 millirows).|
|_srow_=2400 :|This control is only 1 millirow high, which only makes<br>sense in the case of lines, i.e. (SZCLASS="STATIC",|



A-Shell Reference 

Page 1923 

|**Coordinates**|**Result**|
|---|---|
|_erow_=2400|DWSTYLE=SS_BLACKRECT or SS_GRAYRECT or<br>SS_WHITERECT).|



The system used here makes millirows logically analogous to pixel coordinates, except for the fact that the external leading is still subtracted from the bottom coordinate of the control. For example, consider two controls in adjacent rows. The first is specified as _srow_ =3000 : _erow_ =4000 and the second is _srow_ =4000 : _erow_ = 5000. Do the two controls touch? Normally, no. This is because we subtract the external leading from the resulting bottom coordinate. So if the external leading was 6, the two controls would still be separated vertically by 6 pixels, even though the bottom coordinate of the top control matches the top coordinate of the bottom control. This is a bit strange perhaps, but is very handy if your purpose in using millirows is simply to shift an object up or down by a small amount. 

To cancel the automatic adjustment of the bottom coordinate to account for the external leading, specify the MBF_ALTPOS flag in the ctype parameter. When used in conjunction with an _erow_ specified in millirows, the usual interpretation (i.e., causing an "aesthetic adjustment" to the size or position of certain control types) is changed to simply disable the automatic subtracting of the leading from the bottom coordinate. 

The 1.0(103) update of the sample program GUILIN in EXLIB:[908,24] illustrates this difference by drawing a pair of columns made up of lines 1000 millirows high in the lower right corner of the screen. The first column has gaps between the lines due to the leading; the second column uses MBF_ALTPOS to eliminate them. Note that we could also have eliminated them by just adding more to the _erow_ coordinate; this is less convenient though since we would have had to query the current leading value (see MX_WINSETTINGS) and then converted from pixels to millirows (see  AUI_WINDOW). (Overlapping would not matter for lines but it might for some other controls.) 

## **Notes** 

• Millirow 1000 is the top of the usable area of a dialog. It might have been more logical for millirow 0 to have been the top, but this offset does provide some advantages. One is that it seems more consistent with the fact that the first row in standard coordinates is 1, not 0. This makes it somewhat easier to mentally convert from row _x_ to the equivalent millirow (1000 _x_ ), and dovetails nicely with the fact that static text is currently aligned at the top of the control area. Consequently, if you want to shift 

A-Shell Reference 

Page 1924 

a text label up by 1/4 row, just multiply the _srow_ by 1000 and subtract 250. Another advantage is that it eliminates the ambiguity that would otherwise arise if trying to position a control within 200 millirows of the top of a dialog. (If you needed to use a millirow value of between 1 and 200 to do that, it would have been otherwise interpreted as a standard row.) 

• In the main window (i.e. not a dialog), there will be left, top, right and bottom margins which are made up of the pixels left over after determining the largest integer grid size that will accommodate the rows and columns into which the main window is divided (via Tab(-5,rows) or Tab(-6,cols)). Thus, millirow 1000, just like row 1, will not necessarily be the very top of the window. You can specify a millirow value of between 200 and 1000 to shift the control up into that margin space, although it may get clipped if your adjustment is more than the margin. 

A-Shell Reference 

Page 1925 

## **MILLICOLUMNS** 

Most controls support "millicolumns". When the starting column or ending column coordinate of a control (created by AUI_CONTROL, AG_CONTROL, INFLD, etc.) is greater than 200, it is assumed to be in units of "millicolumns" (1000 per standard column) rather than standard columns. This allows the horizontal position and size of a control to be more finely adjusted than was previously possible. 

To convert a starting column coordinate to millicolumns, simply multiply by 1000. (Then add or subtract as needed to make your fine adjustments.) 

To convert an ending column coordinate to millicolumns, first add 1, then multiply the total by 1000. 

For example, the millicolumn equivalent of scol=5, ecol=9 is scol=5000, ecol=10000. (A coordinate whose starting and ending column is the same will be effectively one column wide when using standard column coordinates, but only one millicolumn wide when using millicolumn coordinates, hence the need for adding 1000 to the ending coordinate during the conversion.) 

In the case of INFLD, which uses a maximum width ( _xmax_ ) rather than ending column coordinate, you can still specify _xmax_ in millicolumns, but the threshold is 1000 rather than 200. (That is, any _xmax_ value less than 1000 will be considered as a number of standard columns.) 

A-Shell Reference 

Page 1926 

## **FGC, BGC** 

_Revised and reviewed July 2020_ 

Num  These parameters allow you to override the default control foreground (text) and background colors, in some cases. Some controls do not allow the applicatioin to override colors, and in other cases Windows Themes may override your attempts to do so. Specify these values as –1 to use the "current" colors (if applicable to the control type), or –2 to use the default Windows colors. (The "current" colors are those that would apply to ordinary PRINT statements, i.e those set by TAB(-2,x) and TAB(-3,x) or SET TERM FCOLOR and SET TERM BCOLOR.) 

To request an override of the foreground and background colors when Windows Themes are not in effect, you may specify a palette color number in the range of 0-15 (same as would be used with the TAB(-2,x) and TAB(-3,x) commands.) 

To override the foreground and background colors even when Themes are active (assuming this is even possible for the control type and Theme), do one of the following: 

- Add +64 to the palette index value. For example, if 3 is the palette index for magenta, to request magenta even when it 

- contradicts the default for the Theme, specify 3+64. 

• Instead of a palette index value, specify an RGB value. RGB values are made up of 3 bytes, with the low byte representing the Red, the second byte the Green, and the third byte, the Blue values. This is most easily accomplished using hex notation, i.e. &h00bbggrr where rr, gg, and bb are the red, green and blue values, each ranging from 00 to FF. Note that this may appear to reverse the order of the rr, gg, and bb, values, but is necessary for direct compatibility with the Windows RGB format, which uses the least significant byte for the red. Also note that since an overall RGB value of between -2 and 15 might be confused with a palette index, to avoid confusion, make sure that either the blue value > 0, or the green value is > 0, or the red value > 128. You can also experiment with the RGB values and corresponding colors via the Settings..Colors dialog (click on one of the color buttons, then the "Define Custom Colors" button; as you move the pointer and slider bar, you will see the Red, Green and Blue values appear in the boxes. 

## **History** 

- 2011 June, A Shell 5.1.1220.1:  New pseudo RGB symbol RGB_TRANSPARENT (&h02020202) may be specified with static and checkbox/radiobutton controls to create a transparent background, providing an alternate method for making those controls blend into non-standard window background colors. 

A-Shell Reference 

Page 1927 

## **FONTATTR** 

Parameter _fontattr_ (Num) May be used to override the default font attributes for the control. Again, as with colors, this is probably used most effectively only with static text controls. Choose one or more (sum) from the following tables. Note that these are only requests to the font mapper; if it cannot supply an exact match for the given _fontface_ , _fontscale_ , and _fontattr_ values, if will supply the "closest" match. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|FS_UPRIGHT|&h00|Normal upright|
|FS_ITALIC|&h01|Italic|
|FS_UNDERLIN<br>E|&h02|Underline|
|FS_STRIKEOU<br>T|&h04|Strikeout|



|**Symbol**|**Value**|**Description**|
|---|---|---|
|FA_DONTCARE|0|Do not care|
|FA_THIN|1600|Thin|



A-Shell Reference 

Page 1928 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|FA_EXTRALIG<br>HT|3200|Extra Light|
|FA_LIGHT|4800|Light|
|FA_NORMAL|6400|Normal|
|FA_MEDIUM|8000|Medium|
|FA_SEMIBOLD|9600|Semibold, demibold|
|FA_BOLD|11200|Bold|
|FA_EXTRABOL<br>D|12800|Extrabold, ultrabold|
|FA_HEAVY|14400|Heavy|



Note the difference between the FA_xxx symbols used here, and the similar FW_xxx symbols used by the SETFONT GDI printing directive; the FA_xxx symbols are shifted up 4 bits (16 times) from the FW_xxx symbols. 

**Symbol** 

**Value Description** 

A-Shell Reference 

Page 1929 

|ll Reference|||
|---|---|---|
|FA_GRIDWIDT<br>H|&h000080<br>00|This flag may be added to FONTATTR to tell the font matcher to try<br>to match the average character width to the grid cell width. This<br>probably only makes sense when specifying a fixed pitch font, in<br>which case it should make the selected font match pretty closely in<br>width to the standard non-GUI text.|
|FA_SYMBOL|&h000200<br>00|Use symbol character set (instead of the ansi character set). This<br>normally would only make sense with a fontface like "Wingdings" or<br>"Symbol." Symbol fonts are mainly used in the context of AUI as a<br>trick for creating buttons with graphic, without having to find or<br>create an icon or bitmap. See the sample programSYMBOL in<br>EXLIB:[908,24]<br>for an example.|



- Hex Decimal Values 

A-Shell Reference 

Page 1930 

## **FONTSCALE** 

Parameter _fontscale_ (Num)  If specified, causes the font for the control to be scaled by the specified percentage (100=100%). This factor is applied in addition to the global font scale factor found in the Misc. Settings menu, so should only be used to adjust the font size of a particular control relative to the others. 

Note that what is being scaled in this case is the point size of the font, and that may not correspond linearly to what you might expect. For example, if you want to create a static text control with double-high characters, and have specified coordinates with _erow_ = _srow_ + 1, you may find that a _fontscale_ factor of 200 is bigger than you want. (Or it might fit the height but be too wide.) Some experimentation is in order here, and it is also highly recommended to be conservative (i.e. go for something smaller than the maximum size that will fit), because different resolution screens and other display parameters outside of your application’s control may affect the sizing. (It is better for a message to be slightly smaller than you wanted, than for it to be so big that it does not fit, or wraps inappropriately.) 

A-Shell Reference 

Page 1931 

## **FONTFACE** 

Parameter _fontface_ (String)  If specified, it is added to the request to the font mapper to help determine the font to be used. If left blank, the default is the font that is specified as the "GUI (Control)" font in the A-Shell Settings menu. If that is also blank (as it usually is), then the default becomes the standard Windows dialogs (aka "MS Dialog"). If a font face is specified but there is no such font defined to the system, the Windows font mapper will use its own reasoning to decide what font to use. To avoid the uncertainties that might entail, it is best to stick with fonts that are nearly universal, such as "Arial", "Times New Roman", etc. Note that a particular font face is generally either fixed pitch (e.g. "Courier New", "Lucida Console") or proportional ("MS Dialog", "Arial", etc.) Note that to request a special symbol font, such as Wingdings or Symbol, you should also set the FA_SYMBOL bit in the fontattr parameter. 

A-Shell Reference 

Page 1932 

## **TOOLTIP** 

_Updated December 2013_ 

If _tooltip_ (String) is specified, and if the control is clickable, then the specified string will appear automatically just above or below the control when the mouse hovers over it for about one second. This is useful for additional explanation about what will happen when the control is clicked. 

If you want to associate a tooltip with a static text control, it must have the MBF_KBD style flag and a click string defined in the ctype parameter. Otherwise the control is not really "clickable", or more precisely, the click action is ignored and so is the tooltip feature. If you want to have a tooltip even though there is no click action, the workaround is to use "VK_NULL" from the Virtual Key Symbolic Names table. 

## **Update: Context and Hover Menus** 

With A-Shell 6.1.1335 of January 2013, the syntax of _tooltip_ has been expanded for static image controls to allow for context and "hover" menus. 

Tooltip only (original syntax): 

## **tooltip** 

Menu only: 

## **\menudef** 

Tooltip and menu: 

## **>tooltip\menudef** 

This scheme, with > and \ leadins, follows the general syntax relating to tooltips and context menus supported by INFLD's _hlpidx_ parameter. 

The menudef syntax is: 

## **\{@<attrib>\} <text>,<cmd>; ... <text>,<cmd>;** 

A-Shell Reference 

Page 1933 

It must start with a leading backslash, followed by an optional list of attributes (which must begin with "@" and end with "\"), followed by one or more <text>,<cmd> pairs, each terminated with a semicolon. This also matches the syntax used for INFLD menu definitions, and XTREE PopupMenu definitions, except that the attribute list is new, and there are no special $cmds yet defined. 

The only attribute currently supported is: 

```
@Hover{=##}
```

Where the optional =## may be used to specify the millisecond hover time before the menu appears. 0 indicates that the menu should appear immediately with no hover delay; omit the =## clause for the system default  hover delay (typically 400ms). If the Hover attribute is not specified, then the context menu acts like a typical one, i.e. doesn't appear unless you right click on the control. 

Each <text> field contains the text to display in the menu, with an optional image specification, enclosed in vertical bars, i.e.: 

```
|imagespec{=##}|display text
```

This is identical to the format supported by the AUI_MENU _mnutxt_ parameter. 

The optional =## clause at the end of the image spec specifies the size of the displayed image in pixels. The width and height of the image will be the same, so only one size value is needed. 

The imagespec may be a native or AMOS-style filespec, or a DLL library reference, e.g.: images:sunshine.ico, "exit::ashico1", c: \img\new.png. Under ATE, if the image is not found in the specified location or default path, it will also be looked for in the atecache and atepermcache directories. 

## **Submenus** 

The context menus just described may also contain submenus, i.e. multi-level menus. To define a submenu, set the <cmd> string for the parent item to "[SUB]". Indicate the end of the submenu by defining a dummy item whose <text> is "[ENDSUB]" and whose command is empty. See examples below. 

## **Examples** 

Standard right-click context menu with two options and a separator between them: 

A-Shell Reference 

Page 1934 

```
TIP$ = "\Option 1,VK_xF101;-------,;Option 2,VK_xF102;"
```

Same menu, but with instant display as soon as mouse enters control: 

```
TIP$ = "\@Hover=0\Option 1,VK_xF101;-------,;Option 2,VK_xF102;"
```

Same menu, appearing after the standard hover time: 

```
TIP$ = "\@Hover\Option 1,VK_xF101;-------,;Option 2,VK_xF102;"
```

Same menu, appearing after 100 ms, and with an icon (in its default size) from the ashico1 library next to the first option and the separator removed: 

```
TIP$ = "\@Hover=100\|gear::ashico1|Option 1,VK_xF101;Option 2,VK_xF102;"
```

Same as above, but with a different icon image spec, including an explicit size of 24 pixels: 

```
TIP$ = "\@Hover=100\|gear.ico=24|Option 1,VK_xF101;Option 2,VK_xF102;"
```

Standard context menu and tooltip together: 

```
TIP$ = ">Right click for options\Option 1,VK_xF101;Option 2,VK_xF102;"
```

Note that combining a tooltip and a menu only makes sense for the standard right-click menus. Those with the Hover option (that appear automatically) will end up clobbering the tooltip display. 

Two-level context menu: The following tooltip string will define a two-level menu with the following structure: 

Item 1 

Item 2 > Sub-Item 1a 

Sub-Item 1b 

Item 3 

Item 4 > Sub-Item 2a 

Sub-Item 2b 

A-Shell Reference 

Page 1935 

```
TIP$ = ">tooltip string\"                                    &
    + "Item 1,VK_xF101;Item 2,[SUB];"                        &
    + "Sub-Item 1a,VK_xF201;Sub-Item 1b,VK_xF202;[ENDSUB],;" &
    + "Item 3,VK_xF103;Item 4,[SUB];"                        &
    + "Sub-Item 2a,VK_xF301;Sub-Item 2b,VK_xF302;[ENDSUB],;"
```

Note that any or all of the above menu items can contain icons, just as in previous examples. 

## **History** 

- 2014 March, A Shell 6.1.1377:  Tooltips will now automatically wrap at 600 pixels, and you now have the option of manually breaking the lines by inserting chr(13) characters. The display time for a tooltip, normally about five seconds, is also now extended by four seconds for every 100 characters past the first 100. You may extend the display time to the maximum value of 32 seconds by inserting a "+" at the start of the tooltip string. Note that the maximum tooltip length remains 400 characters.Added support for submenus within context menus. 

- 2013 October A Shell 6.1.1363: Added support for submenus within context menus, and also for adding an accelerator key definition within the tooltip for controls with no _ctext_ . See Accelerator. 

- 2013 February, A Shell 6.1.1337: The tooltip/context menu feature supports the ability to create disabled menu items by prefixing the item's definition with "!", e.g. 

```
TIP$ = "!Disabled item,VK_xF101;"
```

```
TIP$ += "Enabled item,VK_xF102;"
```

```
TIP$ += "!|image.ico|Disabled item with image,VK_xF103;"
```

A-Shell Reference 

Page 1936 

There is no way to individually enable/disable such menu items without redefining the entire menu, which may call into question, what ois the point—i.e., why not just recreate the menu without the disabled items? A possible rationale would be in order to preserve the layout of the menus so as to make it easier for users to memorize the menu layouts. 

A-Shell Reference 

Page 1937 

## **PARENTID** 

_Updated July 2025_ 

If _parentid_ (Integer) is specified when creating a new control, the new control becomes a child of the specified control. This has two primary ramifications: 1) the coordinates of the child control are taken to be relative to the client area of the parent, and 2) such child controls will be automatically deleted when the parent is deleted or cleared. 

If parentid is not specified (or is zero), it defaults to the current modal dialog (if any), provided that the MBF2_NOAUTOPARENT flag is not specified. 

_Parentid_ , like _ctlid_ , may also be expressed as an alphanumeric string. 

Dialogs created with AUI_CONTROL may specify a parent ID of -1 to signify that the dialog is a child of the main window. The default (0) makes the new dialog a child of the current dialog, if any. 

## **See Also** 

- ctlid 

- Control names 

- MBF2_NOAUTOPARENT 

A-Shell Reference 

Page 1938 

## **WINCLASS** 

Parameter _winclass_ (String) may be used, along with _winstyle_ and _winstylex,_ as an alternate way of specifying a control type. Note that this technique is only practical for controls that do not require special processing by A-Shell. (For example, it can be used safely to create a new style of button or static text control, since these do not require any special handling other than to process their click command. But it cannot be used to create a complex control like a spreadsheet, up-down, or property sheet, since in order to be used effectively, these would require integration with other A-Shell operations.) See Lines, Rectangles and Frames and Animated Graphics. 

A-Shell Reference 

Page 1939 

## **WINSTYLE** 

Parameter _winstyle_ (integer) May be used in conjunction with _winclass_ or _ctype_ to specify window-style flags. This is equivalent to the _dwStyle_ parameter in the WIN32 API CreateWindowsEx() function; consult the Microsoft documentation for details. As with _winclass_ , these flags are only practical if they affect the appearance or other characteristic of the control without changing the way it interacts with the application. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|WS_VISIBLE|&h1000000<br>0|The window is initially visible.|
|WS_CHILD|&h4000000<br>0|The window is a child window. A window with this style cannot have a menu<br>bar. This style cannot be used with WS_POPUP. .|
|WS_OVERLAPPE<br>D|&h0000000<br>0|The window is an overlapped window. An overlapped window has a title bar<br>and a border.|
|WS_POPUP|&h8000000<br>0|The windows is a pop-up window. This style cannot be used with the<br>WS_CHILD style.|
|WS_CLIPSIBLIN<br>GS|&h0400000<br>0|Clips child windows relative to each other; that is, when a particular child<br>window receives aWM_PAINT<br> message, the WS_CLIPSIBLINGS style clips all<br>other overlapping child windows out of the region of the child window to be<br>updated. If WS_CLIPSIBLINGS is not specified and child windows overlap, it is<br>possible, when drawing within the client area of a child window, to draw within<br>the client area of a neighboring child window.|



A-Shell Reference 

Page 1940 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|WS_CLIPCHILDR<br>EN|&h0200000<br>0|Excludes the area occupied by child windows when drawing occurs within the<br>parent window. This style is used when creating the parent window.|
|WS_MAXIMIZE|&h0100000<br>0|The window is initially maximized.|
|WS_CAPTION|&h00C000<br>00|Adds a title bar. Includes the WS_BORDER style.|
|WS_BORDER|&h0080000<br>0|Adds a thin-line border.|
|WS_DLGFRAME|&h0040000<br>0|The window has a border of a style typically used with dialog boxes. A window<br>with this style cannot have a title bar.|
|WS_SYSMENU|&h0008000<br>0|The window has a window menu on its title bar. The WS_CAPTION style must<br>also be specified.|
|WS_MINIMIZEBO<br>X|&h0002000<br>0||
|WS_MAXIMIZEB<br>OX|&h0001000<br>0|The window has a maximize button. The WS_SYSMENU style must also be<br>specified.|
|WS_VSCROLL|&h0020000|Used to support vertical scrolling in dialogs. The scroll bar is initially disabled,|



A-Shell Reference 

Page 1941 

|**Symbol**|**Value**|**Description**|
|---|---|---|
||0|but is automatically enabled and configured as fields are added to the dialog<br>that extend beyond the bottom of the visible dialog. Users can scroll the<br>dialogs using the scroll bar. AUI_EVENTWAIT will also auto-scroll the dialog as<br>needed to bring the newly focused control into view. SeeDialog Scrolling<br>.|



- Hex Decimal Values 

A-Shell Reference 

Page 1942 

## **WINSTYLEX** 

_Updated February 2015_ 

Parameter _winstylex_ (Integer) provides another set of flags of the same type as _winstyle_ . These correspond to the _dwStyleEx_ parameter in the WIN32 API CreateWindowsEx() function. 

For what it’s worth, the addition of this second set of flags is what distinguishes CreateWindowEx() from the earlier CreateWindow(); even Microsoft is guilty of not seeing far enough into the future to prevent having to add more parameters to functions over time. We have the advantage, though, of being able to use variable length argument lists, so at least we do not have to create a whole new "Ex" version of a function just to add another parameter. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|WS_EX_DLGMODALFR<br>AME|&h0000000<br>1|The window has a double border; the window can, optionally, be created<br>with a title bar by specifying the WS_CAPTION style in the_dwStyle_<br>parameter.|
|WS_EX_NOPARENTNO<br>TIFY|&h0000000<br>4|The child window created with this style does not send the<br>WM_PARENTNOTIFY message to its parent window when it is created or<br>destroyed.|
|WS_EX_TOPMOST|&h0000000<br>8|The window should be placed above all non-topmost windows and should<br>stay above them, even when the window is deactivated. To add or remove<br>this style, use the SetWindowPos function.|
|WS_EX_ACCEPTFILES|&h0000001<br>0|The window accepts drag-drop files.|
|WS_EX_TRANSPARENT|&h0000002<br>0|The window should not be painted until siblings beneath the window (that<br>were created by the same thread) have been painted. The window appears|



A-Shell Reference 

Page 1943 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||transparent because the bits of underlying sibling windows have already<br>been painted.|
|WS_EX_TOOLWINDOW|&h0000008<br>0|The window is intended to be used as a floating toolbar. A tool window has a<br>title bar that is shorter than a normal title bar, and the window title is drawn<br>using a smaller font. A tool window does not appear in the taskbar or in the<br>dialog that appears when the user presses ALT+TAB. If a tool window has a<br>system menu, its icon is not displayed on the title bar. However, you can<br>display the system menu by right-clicking or by typing ALT+SPACE.|
|WS_EX_WINDOWEDGE|&h0000010<br>0|The window has a border with a raised edge.|
|WS_EX_CLIENTEDGE|&h0000020<br>0|The window has a border with a sunken edge.|
|WS_EX_CONTEXTHELP|&h0000040<br>0|Adds a "?" button to the right end of the capture bar of a dialog; clicking the<br>button sends exitcode -70. Note that in order to use this feature, you must<br>specify MBF_SYSMENU but not either of the min/max buttons.|
|WS_EX_STATICEDGE|&h0020000<br>0|The window has a three-dimensional border style intended to be used for<br>items that do not accept user input.|
|WS_EX_STATICEDGE|&h0080000<br>0|The window is layered.  (This is an advanced Windows variation mainly<br>relevant for windows with complex drawing requirements, shape, blending,<br>etc.   Consult the Windows API documentation for more details.|



A-Shell Reference 

Page 1944 

- Hex Decimal Values 

## **History** 

- 2015 February, A Shell 1403: Improve operation of WS_EX_CONTEXTHELP. 

A-Shell Reference 

Page 1945 

## **CTYPE2** 

_Updated December 2018; see History_ 

Parameter _ctype2_ is an extension of the _ctype_ parameter, and specifies any valid combination of options from the following table. The symbols come from ashell.def. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBF2_STICKY|&h000000<br>01|Causes child control to "stick" to the edge of the parent container, if otherwise close to<br>or overlapping the edge. Starting with A-Shell 6.0.1261, it also applies to<br>MBF2_DLGNOCAP dialogs. Prior to 6.1.1355, to activate, the_scol_coordinate must be 1.<br>After 1355, this is still true for the left edge but stickiness can now apply to the right<br>edge independent of the left. To stick the right edge to the parent's right edge, the ecol<br>coordinate must be larger than the maximum coordinate of the parent.|
|MBF2_DLGICON|&h000000<br>10|May be used with MBF_DIALOG to cause the dialog to display the application icon on its<br>title bar. This is equivalent to MBF_DLGNOPARENT except without the other aspects of<br>MBF_DLGNOPARENT (i.e. retains the parent child relationship).|
|MBF2_PIXCOORDS|&h000000<br>20|Allows the coordinates of a control to be specified in pixels rather than in row/col units.|
|MBF2_PIXSIZE|&h000000<br>80|Causes_erow_and_ecol_to be interpreted as the desired control height and width<br>(respectively) in pixels. May be combined with MBF2_PIXCOORDS, in which case_srow_<br>and_scol_are interpreted as coordinates while_erow_and_ecol_are interpreted as_height_<br>and_width_. As of A-Shell build 5.1.1176, may also be used with dialogs. Previously was<br>only supported for child controls. If used with MBF_DIALOG and MBF_ALTPOS, the<br>dialog borders and caption dimensions will be added to_erow_and_ecol_so that the<br>resulting dialog's client area will be of the requested size; otherwise the_erow_and_ecol_<br>will determine the outer dimensions of the dialog.|



A-Shell Reference 

Page 1946 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBF2_NOTHEME|&h000001<br>00|Disables theme (visual style) for the control. In the case of MBF_GROUPBOX, this also<br>causes the control to be manually drawn by A-Shell rather than by Windows, allowing<br>the FGC and BGC values to be taken into account. (Otherwise, the themed version of a<br>groupbox ignores the FGC value, and only applies the BGC value to the background of<br>the text.) Note that for the new implementation, you must use an RGB value for FGC<br>and/or BGC if you want custom colors. (For black, you should use &h00010101 rather<br>than &h00000000 to avoid any confusion with palette color numbers, which range from<br>0-15.)|
|MBF2_CUSTDRAW|&h000002<br>00|Causes A-Shell to draw the control, rather than let Windows draw it. Generally this is a<br>bad idea (a lot of work, guaranteed never to match the way Windows does it). But,<br>sometimes it is useful, in order to implement a visual variation that Windows does not<br>support. Currently there are only two control types this applies to: MBF_GROUPBOX<br>(see notes for MBF2_NOTHEME) and MBF_STATIC. In the case of MBF_STATIC, the<br>MBF2_CUSTDRAW flag allows us to create variations of the standard rectangular static<br>control (rounded corner rectangles, ellipses, circles, and controls with a border<br>matching the text color.) To get any of these effects, combine MBF2_CUSTDRAW with<br>MBF2_ROUNDRECT or MBF2_ELLIPSE.|
|MBF2_ROUNDRECT|&h000004<br>00|Causes the corners of the static control be slightly rounded. This is only noticeable if<br>the BGC parameter is set to an RGB value, or if the WS_BORDER flag is used.|
|MBF2_DLGNOCAP|&h000008<br>00|Creates a dialog with no caption. Such a dialog is effectively anchored to its parent, as<br>if it were a child control, except that it can host its own child controls. These dialogs are<br>positioned using the same logic as for child controls.|
|MBF2_ELLIPSE|&h000008<br>00|Causes the control to have an elliptical rather than rectangular shape. As with<br>MBF2_ROUNDRECT, the effect is invisible unless you define a non-standard BGC value|



A-Shell Reference 

Page 1947 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||or use the WS_BORDER flag.<br>If the display width and height of an ellipse are equal, you have a circle. Unfortunately,<br>at present, there is no good way to calculate how many columns are needed to match a<br>particular number of rows or millirows, so circles may end up as ellipses. (Actually, you<br>could use the MBF2_PIXCOORD flag to specify the dimensions in pixels, and that would<br>work, but leads to a different problem which is how to calculate the desired number of<br>pixels. (We may need to add another flag to force the width of the ellipse to match the<br>height so that you end up with a perfect circle, regardless of the window aspect ratio or<br>resolution.)|
|MBF2_RESIZE|&h000010<br>00|May be used with an MBF_ALTPOS dialog to allow it to be resized with the mouse. The<br>range of resizing is from 50% of the original dialog size to maximized.|
|MBF2_STATICWIN|&h000040<br>00|Creates a static child control window that looks something like a dialog box but can be<br>used as a variation of a group box.|
|MBF2_TABX|h00008000|Combine with MBF_TAB (ctype) for theTabX Control<br>variation of the Tab control. Set<br>SBR=AUTO_TABX to automatically convert all Tab controls to TabX controls.|
|MBF2_NOMOVE|&h000400<br>00|Prevents a dialog from being moved. This does not interfere with the ability to<br>minimize, maximize or resize the dialog, which are controlled by other options<br>(MBF_MODELESS, MBF_MAXBUTTON, and MBF2_RESIZE, respectively). See History<br>note below.|
|MBF2_MINBUTTON|&h000080<br>000|Used with MBF_SYSMENU to add a minimize button to a modal dialog. A minimize<br>button is not normally allowed in this case, because if the dialog is minimized, it may<br>make the parent window appear to be unresponsive. But if you are sure that won't be a|



A-Shell Reference 

Page 1948 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||problem (perhaps you've made the dialog's parent invisible already), you can force the<br>minimize button option with this flag (in the cflag2 parameter).|
|MBF2_FNTPTSIZE|&h001000<br>00|Interpret font scale factors as points (x 10) rather than as a percentage.|
|MBF2_DLGMWFNTG<br>RID|&h001000<br>00|May be used with captionless dialogs based on the main window grid (i.e. without<br>MBF_ALTPOS) to force the text controls within the dialog to use the same font scaling<br>logic as the main window uses. This is mainly of use when the Misc Settings font<br>scaling option is non-zero—i.e. when the main window controls use a font scaled to the<br>main window grid. In particular, if you are using theMX_AUTOPARENTand<br>AUTOTPRINT features to run a non-GUI-aware program in a dialog, this allows you to<br>scale the dialog and the fonts within it to the main window size. Note: due to context,<br>this function does not conflict with the one above having the same value.|
|MBF2_DLGSTATE|&h002000<br>00|Can be specified with MBF_DIALOG to cause the previous last state (normal or<br>maximized) and position of the dialog to override the state and position specified in the<br>AUI_CONTROLstatement. The saved state is keyed to the combination of the current<br>program name and the dialog control name, so you must use an alphanumeric control<br>name.MBF2_DLGSTATEoverrides the MBST_xxxx options relating to dialog positioning—<br>e.g. MBST_CENTER, etc. The system parameterOPTIONS=AUTODLGSTATEallows you<br>to make the MBF2_DLGSTATE option be the default for all dialogs. Dialogs with the<br>MBF2_DLGSTATE option are moved back to the default position if the previously saved<br>position is no longer visible due to a monitor configuration change. The dialog is<br>considered visible if enough of its caption bar is visible to reasonably be able to spot it<br>and drag it. This allows you to deliberately set the dialog's initial position so that only a<br>fraction of its title bar is visible. Note that saved coordinates are ignored—i.e. reset<br>back to the design coordinates—if the design coordinates have changed since the dialog|



A-Shell Reference 

Page 1949 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||was last saved, or if the dialog no longer fits entirely within the virtual desktop space.|
|MBF2_GDIPLUS|&h004000<br>00|Set for images using the GDI Plus library. Set automatically for some image types and<br>mainly of internal interest; may be set manually to force images with <32 bpp to use<br>the GDI. SeeDisabled and Hot Images<br>.|
|MBF2_GLOBAL|&h008000<br>00|May be specified for a clickable control to make it active even when not part of the<br>current modal dialog. It has the additional effect of changing the default parent from<br>the current modal dialog to the main window, if applicable. This is the only way you can<br>create a control outside of the current modal dialog.|
|MBF2_NOAUTOPAR<br>ENT|&h010000<br>00|Overrides the normal logic for defaulting the parent of a new control that doesn't<br>specify an explicit parent. Normally, if the new control does not specify a parent and a<br>modal dialog exists, the new control is assigned that dialog as its parent. With this flag<br>set, the main window (ctl #0) would instead become the default parent.|



- Hex Decimal Values 

## **History** 

- 2018 December, A Shell 6.4.1651:  the MBF2_NOMOVE flag may now be set when creating the control to stifle the logic which otherwise shifts the control up and/or to the left as needed so that it fits in within the parent window. 

- 2014 Feburary, A Shell 6.1.1376: Added MBF2_DLGMWFNTGRID 

- 2013 July, A Shell 6.1.1356: Added MBF2_NOAUTOPARENT 

- 2012 May, A Shell 6.0.1250: Added MBF2_DLGSTATE 

- 2012 May, A Shell 6.0.1249: Added MBF2_FNTPTSIZE 

A-Shell Reference 

Page 1950 

A-Shell Reference 

Page 1951 

## **CONTROL TYPES** 

See the Table of Contents at left for individual topics in this section, and click on the highlighted title to expand or condense that portion of the TOC. 

A-Shell Reference 

Page 1952 

## **STATIC TEXT CONTROL** 

_UpdatedDecember 2013; see History_ 

Static text controls are the simplest kind of controls, consisting just of a text string formatted within a rectangular area, with an optional click notification. You may adjust the font and color, but in most cases, will just want to use the default font and color to get the most uniform, Windows-like look. 

In the main window, static text controls correspond to PRINT statements and use the same coordinate system. In dialogs, ordinary PRINT statements are not permitted, and multiple coordinate systems are available (see Dialog Positioning) but otherwise the following discussion applies to static text controls in all contexts unless otherwise noted. 

The simple PRINT statement: 

```
PRINT TAB(10,5);"Customer Name:";
```

would correspond to this static text object: 

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, ID, "Customer Name:", MBST_ENABLE, MBF_STATIC + MBF_LFJUST, "", "",
STATUS, 10, 5, 10, 19
```

This probably seems like overkill, but before addressing that, we should first clarify some subtle distinctions between the standard text and static text control implementations. 

• Because the text and GUI layers in the main window use the same coordinate system, in both cases, the message starts in the same location (row 10, column 5). Also, since we set the ending column of the GUI version to 19, both will occupy the same amount of space. (This fact is important in converting from the fixed pitch to proportional font layouts. But, although the static text control occupies the same amount of space as the text counterpart, some of that space may appear blank (depending on the size of the font and how much difference there is between the fixed and proportional font metrics for this particular string. Typically, lower case characters will take up much less space in a proportional font than in a fixed pitch font, but the reverse may be true with all upper case. So if your text prompts are all upper case, you may need to allow more room (or convert them to lower case, or add the font parameters to the AUI CONTROL call to adjust the font to fit.) 

• Because the proportional version of the character string will not appear to take up the same amount of space as the fixed pitch text version, attempts to position adjacent messages based on columnar calculations will not work very well in the proportional environment. See the section on Text Message Tokenization for further comments. 

A-Shell Reference 

Page 1953 

- In the above example, we did not define a command to be associated with clicking on this static text object, but we easily 

- could, in which case the static text object acts like a button. To define a click event, add the MBF_KBD (or MBF_CMDLIN or MBF_SHLEXC flag) to the ctype parameter and put the string to be sent (or executed) in the cmd parameter.  You may also want to add a tooltip so the user knows what to expect when clicking. 

- Although (in the main window) the static text object exists in a layer above the standard text layer (and thus would obscure 

- anything below it), as a convenience, it may be deleted by the same kinds of Print Tab operations that would delete the text version. 

- If your screen prompts are parameterized (loaded from a file and output using a centralized routine), then converting from 

- the PRINT version to the AUI CONTROL version will be simple. But if you have thousands of literal PRINT statements throughout your programs, you might want to consider one of the following shortcuts: 

- PRINT statements may be replaced one-to-one with TPRINT statements, which, when compiled with the /X:2 switch, are 

- equivalent to the AUI CONTROL shown above. That is, every segment or argument to a TPRINT statement will be converted to a separate static text control starting in the position it would have in the fixed pitch environment, and occupying the same frame space (although likely with some trailing space at the right edge of the frame.) When compiled without /X:2, TPRINT statements revert to PRINT. 

- PRINT statements may also be replaced with DPRINT or EPRINT statements, which are similar to TPRINT except use the 

- MBF_SUNKEN and MBF_EDIT styles, respectively, both of which work well to separate data fields from labels. 

- SET AUTOTPRINT may be used prior to running a program to automatically treat all PRINT statements like TPRINT. This 

- method provides the fastest way to see how well your screen layouts behave with proportional fonts. 

- `PRINT TAB(-10,AG_CONTROL); TEXT$; chr(127)` is equivalent to `TPRINT TEXT$` . The advantage of the AG_CONTROL 

approach is that it eliminates any compiler dependency (i.e. you could compile under AMOS, or use the same RUN under both AMOS and A-Shell). You would probably need to modify your AMOS terminal driver to filter out the trailing chr(127), or perhaps ideally, to send the necessary escape sequence so that an ATE client could understand the command just as A-Shell/Windows would have. 

- Tab(x,y);expr$ statements may be replaced with Tab(x,y,z);expr$ where the _z_ parameter can be used to invoke a previously 

- defined set of attributes to associate with the string expression (converting it into a GUI control object). See MX_DEFTABXYZ for details. 

A-Shell Reference 

Page 1954 

## **Additional Static Text Control Notes** 

**Justification:** When using AUI_CONTROL, the default justification is centered, but all of the shortcuts listed above automatically set left justification. The AG_CONTROL option supports a second two-character argument of which the first character sets the style ("T" for TPRINT or "D" for DPRINT), and the second character sets the justification ("L", "C", or "R"). 

**Auto-expand:** When using AUI_CONTROL to create a static text control, you can add the MBF_AUTOGROW flag to ctype to allow the control to grow as needed (both to handle the case of unexpectedly wide characters or a dynamic/unpredictable amount of text.) 

**Wrap:** Static text controls automatically wrap, although this is typically only applicable when using the AUI_CONTROL syntax, since it allows you to adjust the height to make room for multiple rows of text. 

**Font:** If not specified explicitly, via the fontface _,_ fontattr or fontscale parameters of AUI_CONTROL, the font face is set according to the global Settings > Font > Control menu option. The size (for main window static text controls) is determined by the Settings > Misc Settings Proprtional font scaling option. (If 0, it uses the standard Windows desktop font, otherwise it applies the specified scale to the grid cell size.) For static text controls within dialogs, the Settings > Dialog Sizing > Font Scaling factor is applied to the standard Windows dialog font size. 

## **History** 

- 2013 December, A Shell 6.1.1371:  Static text controls without images can now have context menus attached, with or without the hover/auto-show feature. Use the same syntax as documented in the _tooltip_ parameter for image controls. 

A-Shell Reference 

Page 1955 

## **LINES, RECTANGLES AND FRAMES** 

These controls share the same STATIC class with static text controls, and are even simpler than their cousins, except that creating them requires the use of the _winclass_ , _winstyle_ , and _winstylex_ parameters, which are otherwise not commonly needed. 

The sample program GUILIN in EXLIB:[908,24] illustrates most of the combinations of these control types (see the sample screen shot below), all of which are created with variations of the following code: 

```
xcall AUI,AUI_CONTROL,CTLOP_ADD, NUL_CTLID, NUL_CTEXT$, NUL_CSTATE, ctype, NUL_CMD$, NUL_FUNC$, NUL_CSTATUS,
srow,scol,erow,ecol,NUL_FGC, NUL_BGC, NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$,
NUL_PARENTID,"STATIC", ss'style, NUL_WINSTYLEX
```

In this example we make extensive use of NUL_xxx placeholder parameters, including for the _ctlid_ and _cstatus_ return parameters which we don't care about here. 

The different styles of lines and boxes are accomplished by setting DWSTYLE to one of the following values (defined in ashell.def): 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|SS_BLACKRECT|4|Black rectangle.|
|SS_GRAYRECT|5|Gray rectangle.|
|SS_WHITERECT|6|White rectangle.|
|SS_BLACKFRAME|7|Black frame.|
|SS_GRAYFRAME|8|Gray frame.|



A-Shell Reference 

Page 1956 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|SS_WHITEFRAME|9|White frame.|
|SS_ETCHEDFRAM<br>E|12|Etched frame.|



## These maybe be combined with the above: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|SS_TYPEMASK|&h000F|Mask for extracting type.|
|SS_CENTERIMAG<br>E|&h0200|Static option, sunken.|
|SS_SUNKEN|&h1000|Center image with static control.|



The second set (with the "sunken" look) is accomplished by adding SS’SUNKEN to one of the above: 

Note that MBF_ALTPOS can be used with horizontal line controls to shift their position from the middle of the cell to the bottom of the cell. Millirows can also be used for finer adjustments; see the GUILIN sample for details. 

A-Shell Reference 

Page 1957 

## **BUTTON CONTROL** 

After static text controls, buttons are the next simplest. Essentially they can be viewed as nearly equivalent to a static text control except that it gets drawn with a box around it, and you are more obligated to define a command string to go with it. The command string is option with static text controls, since users do not necessarily demand that all text be clickable. 

Buttons do have a couple of additional features over static text controls. One is that they have a more obviously different appearance when enabled vs. disabled, and when they have the focus, where as static text pretty much appears the same all the time. This example illustrates the different appearance of enabled, disabled, and focused buttons in the standard Windows Theme. 

A second special feature of buttons is that they may display a bitmap (BMP) or icon (ICO) file in place of text. The following example shows a button displaying an icon. Note that when a button displays a BMP or ICO, the image is automatically expanded to fill the button. To help users understand what the button pictures represent, use the _tooltip_ parameter to define a tooltip (as shown in this example). 

The code to create the icon button in the above screen shot looks like this: 

```
xcall AUI,AUI_CONTROL, CTLOP_INFO,CID,"ctlpan.ico", 0, MBF_BUTTON + MBF_KBD + MBF_ICON, "%VK_xF2%", "",
STATUS, 3, 72, 4, 75, -1, -1, 0, 0, "", "Click for additional options"
```

Bitmap and icon images for buttons may also be loaded from DLL resources. See the topic Button Icon Control for more details. 

Buttons are often grouped together using groupbox controls (which see next). 

A chr(13) character embedded in the text of a button (MBF_BUTTON) will automatically enable multi-line mode (eliminating the need to remember to set MBF_WRAP at the same time). 

## **Subtopics** 

- Command Link Button 

- Add Icon or Bitmap to Button 

A-Shell Reference 

Page 1958 

· Auto-Countdown Buttons 

A-Shell Reference 

Page 1959 

## **COMMAND LINK BUTTON** 

Command link buttons are a button type, introduced in Windows Vista, which are typically rather large and contain three subcomponents: 

- Main Text: a short text string comparable to the normal button text. 

- Secondary Text: a longer text string with additional explanation of what the button does. This string appears in a smaller font 

- beneath the Main Text. 

- An icon: either the default green arrow pointing to the right, or a custom icon you specify. The icon appears at the left side of 

- the button. 

For example: 

See the Microsoft documentation for examples and usage guidelines. 

Command Link buttons are distinguished from regular buttons in AUI_CONTROL purely by the syntax of the _ctext_ parameter, which must be as follows: 

```
ctext = maintext$ + "|" + secondarytext$ + "~" {+ iconspec$}
```

The iconspec$ can be a .bmp file, an .ico file (with the standard search path, which includes the %miame%\icons directory), or an iconname::dllname spec. It may also be omitted (to use the default icon), but the tilde must then be the last character in the _ctext_ string. Do not specify the MBF_ICON or MBF_BITMAP flags. The icon or bitmap will be displayed at the larger of 16x16, 32x32 or 48x48, depending the height of the button. 

If the Command Link button style is not supported by the version of Windows (i.e. prior to Vista), then the iconspec will be ignored, and the "|" will be converted to a chr(13) and the MBF_WRAP flag turned on, so as to display the secondarytext$ below the maintext$. (So the button will still appear at least functional, if not beautiful.) 

See the sample program CMDLINK in EXLIB:[908,51] for an example. 

A-Shell Reference 

Page 1960 

## **ADD ICON OR BITMAP TO BUTTON** 

In Windows Vista and above, you can add an icon or bitmap to any button. The concept is similar to the Command Link button, except without the secondary text (and thus may be suitable for more "normal" sized buttons.) As with Command Link buttons, they are requested purely by means of the syntax of the _ctext_ parameter contents, which must be: 

```
ctext = text$ + "~" + iconspec$
```

The syntax options for iconspec$ are the same as for Command Link buttons. 

If the version of Windows does not support the feature, the iconspec$ will just be ignored. 

Note that as with the Command Link buttons, the image displays on the left of the text. But here the image is allocated the entire left half of the button, while the text gets the right half. And the right side of the image will be adjacent to the left edge of the text. If you prefer some spacing between them, add space(s) to both ends of the text$ string. (The leading space provides the separate with from the image, but the trailing space will help maintain centering of the text within the button if the image option is not supported.) 

See the sample program IMGTXTBTN in EXLIB:[908,51] for an example. 

A-Shell Reference 

Page 1961 

## **- AUTO COUNTDOWN BUTTONS** 

_Revised May 2023; added Example_ 

To enable this feature, append "<##>" to the text of a button ( _ctype_ MBF_BUTTON), where ## is the desired length of the countdown in seconds. The button display will be updated each second with the remaining length of the countdown until it reaches zero. At that time, the "<##>" suffix will be removed entirely, and one of the following two events will occur: 

- If the button was initially disabled (MBST_DISABLE), then it will become enabled. This might make sense in a situation where you 

- want to prevent the user from prematurely or accidentally triggering an action with serious consequences. 

- If the button was initially enabled, then the click event will be triggered. 

## **Example** 

```
++include ashinc:ashell.def
```

```
++include ashinc:xcall.def    ! (needed if using named parameters)
```

- `! std text button; auto-clicks itself after 15 seconds` 

```
    xcall AUI, AUI_CONTROL, CTLOP_ADD, ctlid="btn1", ctext="&OK <15>", &
```

```
        ctype=MBF_BUTTON+MBF_KBD, cmd="VK_xF100", srow=3, scol=5, erow=4, ecol=17
```

- `! button with discrete ico image; enables itself after 3 seconds` 

```
    xcall AUI, AUI_CONTROL, CTLOP_ADD, ctlid="btnTV", ctext="   Watch &TV <3>~tv.ico", &
```

```
        cstate=MBST_DISABLE, ctype=MBF_BUTTON+MBF_KBD, cmd="VK_xF101", &
```

```
        srow=3, scol=20, erow=4, ecol=32
```

- `! button with discrete bmp image; enables itself after 6 seconds` 

```
    xcall AUI, AUI_CONTROL, CTLOP_ADD, ctlid="btnCoffee", ctext="Drink &Coffee <6>~coffee.bmp", &
```

A-Shell Reference 

Page 1962 

```
        cstate=MBST_DISABLE, ctype=MBF_BUTTON+MBF_KBD, cmd="VK_xF102", &
```

```
        srow=3, scol=35, erow=4, ecol=47
```

- `! button with icon from ashico1.dll; enables itself after 9 seconds` 

```
    xcall AUI, AUI_CONTROL, CTLOP_ADD, ctlid="btnExit", ctext="&Exit <9>~exit::ashico1", &
```

```
        cstate=MBST_DISABLE, ctype=MBF_BUTTON+MBF_KBD, cmd="VK_xF103", &
```

```
        srow=3, scol=50, erow=4, ecol=62
```

- `! command link button; enables itself after 12 seconds` 

```
    xcall AUI, AUI_CONTROL, CTLOP_ADD, "btnPrint", &
```

- `"&Print <12>|Prompt for printer; options for email, PDF~printer3::ashico1", &` 

```
        MBST_DISABLE, MBF_BUTTON+MBF_KBD, "VK_xF104", NUL_FUNC$, NUL_CSTATUS, &
```

- `6,5,8,35` 

## **Notes** 

- The "<##>" which triggers the countdown feature must be at the end of the ctext parameter (for text-only buttons), or 

- immediately prior to "~" separating the text from the image spec (for buttons with both text and an image), or immediately prior to the "|" separating the two text lines (for Command Link buttons) 

- Do not include the MBF_ICON or MBF_BITMAP flags 

- The use of named parameters in the first four AUI calls relies on this DEFXCALL definition in xcall.def : 

A-Shell Reference 

Page 1963 

```
defxcall AUI+AUI_CONTROL, opcode, ctlid {, ctext="", cstate=MBST_ENABLE, ctype, cmd="", func="",
cstatus=NUL_CSTATUS, srow, scol, erow, ecol, fgc=NUL_FGC, bgc=NUL_BGC, fontattr=0, fontscale=0, fontface="",
tooltip="", parentid=0, winclass="", winstyle=0, winstylex=0, ctype2=0}
```

## **History** 

- 2017 January, A Shell 6.3.1542:  added to A-Shell 

A-Shell Reference 

Page 1964 

## **GROUPBOX CONTROL** 

A groupbox is a hollow rectangle with rounded corners used to group a collection of related control. In the following sample, the three buttons are grouped within a groupbox titled "Test Group." 

The controls belonging to the groupbox must specify the groupbox _ctlid_ as their parent when they are created, and their coordinates are relative to the upper left corner of the groupbox. 

Groupboxes are useful in several ways: 

- They provide visual organization. 

- The fact that the child controls use relative coordinates allows you to adjust the position of the entire group by changing the 

- position of the groupbox. 

- The AUI_EVENTWAIT class allows the user to move among the buttons within a group, providing a simple way to wait for one 

- of a group of option buttons. 

- Grouping controls together using a groupbox allows them all to be deleted in a single step by deleting the groupbox. 

- Groupboxes are needed to define more than one set of radio buttons. 

Groupboxes do not have to be visible to offer all of the above features (except for the first one). Also, the child controls do not have to be confined geometrically within the groupbox. The groupbox above would work just as well if the box were invisible, and even if it was reduced to a one by one block in the upper left corner. Also, child controls may be placed on top of the border (whether visible or not). These facts come in handy when you want to have a group of buttons for control purposes, but you do not want to waste any screen space for it. For example, you can make the groupbox invisible and one row high, then put a row of buttons on that same row. Or, another common arrangement is to put a row of buttons at the bottom of a window, with just a line above it: 

In the example above, an invisible group was probably created, occupying the bottom two rows of the screen. On top of the invisible group, a single line was drawn (see Lines, Rectangles and Frames), along with the buttons below it. BTNMNU.SBX can be used to create groups of buttons like this.) 

A-Shell Reference 

Page 1965 

A groupbox one row high still contains 4 sides, so if you want a single line like in the above example, you have to use the rectangle technique. 

## **Subtopics** 

- Groupbox + MBF_ALTPOS 

A-Shell Reference 

Page 1966 

## **GROUPBOX + MBF_ALTPOS** 

In the standard groupbox layout, the top border is positioned at the very top of row 1, and the bottom border is about in the middle of the bottom row. This is not always ideal, particularly when you want to put controls on every row within the groupbox. The illustration below shows what can happen. In each of the three groupboxes, the first control within is on row 2 (relative to the groupbox), and the last control is on the bottom line of the groupbox. For example, the last groupbox (Predefinir) is four rows high, with controls on rows two, three, and four. The "profile" text control and edit box on row four share the row with the bottom border of the box. The problem is that we have plenty of room between the top border and the controls in row two, but almost no room between the bottom border and the controls on the bottom row. In fact, the parts of the border are being obscured by the controls "Pré-visualizar", "Paisagem", and "Profile." Also, the buttons on the bottom are not centered vertically very well in the space between the bottom of the dialog and the bottom of the groupbox. (Note that the difference between this and the previous example above which shows a set of four buttons below a horizontal line, is that the horizontal line is positioned vertically near the top of the row, whereas the whereas the bottom border of the groupbox is closer to the bottom. 

Adding the MBF_ALTPOS option to both the groupboxes and the buttons at the bottom shifts the spacing and sizing of the groupboxes and buttons, resulting the in the example below. The top border of the groupboxes has been moved down by about 1/3 of a row, and the bottom border has been down slightly less than that, resulting in more even vertical spacing between the borders and the controls within. Also, for the buttons, MBF_ALTPOS causes them to take up the entire row height, including the inter-row (aka "leading") area, and to be shifted down to take advantage of some of the margin which is added to the bottom of dialogs. 

A-Shell Reference 

Page 1967 

## **CHECKBOX CONTROL** 

Checkboxes are the Windows GUI equivalent of yes/no questions. 

Typically several checkboxes are presented as a group, either within a groupbox, or in a dialog as in this example below: 

When the group of checkboxes has no other input fields which require real-time support by the application, the easiest way to implement them may be to just display them, then use the EVENTWAIT class to wait for a button action (Apply or Cancel in the above dialog), then query the buttons to see which ones are checked. In the Windows environment, you do not even need to query them, since one of the parameters passed to AUI CONTROL to create the checkbox is the actual variable which gets updated automatically as the box is checked/unchecked. But in the ATE environment, direct linkage between the checkbox on the screen and the control variable is not possible, so the technique of querying the checkboxes is more universal. See the following topic for sample code showing how to create a query a group of checkboxes like is shown above. 

The other way to manage checkboxes is INFLD, which makes them act like yes/no fields from the point of view of the application. To turn an existing INFLD yes/no field into a checkbox, just add the _type_ code **||c** . In this case, you will need to process exitcodes like for any other field in order to allow the user to move up and down or among the fields. 

Note that although INFLD does a reasonable job of hiding the idiosyncrasies of checkboxes from the application (making them act like yes/no fields), it is hard to overlook the fact that unlike other field types, with a checkbox, the label or prompt is actually part of the control, so you need to specify it to INFLD if you want it to create the checkbox with the text. To do so, put the label text in the _setdef_ parameter, and you must set the field width to accommodate the text plus the checkbox. However, as a convenience to programs that are used to displaying the field prompts in one operation, and editing the fields in another, when INFLD is given a standard one-character-wide yes/no setup with the **||c** option added, it will scan the existing controls to see if this matches the left or right edge of an existing checkbox, and if so, uses the existing one rather than creating a new one. This allows you to create the checkboxes as part of your screen layout operation, but then edit them as if they were simply yes/no fields. 

## **Subtopics** 

· Checkbox Alignment, Justification 

A-Shell Reference 

Page 1968 

## **CHECKBOX ALIGNMENT, JUSTIFICATION** 

There are two parts to a checkbox control (the text label and the checkbox itself), and six ways to arrange them, as shown here (from the sample program TSTCBZ in EXLIB:[908,41]). 

## The checkboxes in the upper group were created with these AUI_CONTROL calls: 

```
xcall AUI, AUI_CONTROL, OPCODE, ID(1), "Left Text; Left Justify",  MBST_ENABLE, MBF_CHKBOX + MBF_LFTEXT +
MBF_LFJUST, CMD$, CB1,  STATUS, 2, 2, 2, 24, 67, -2,  0, 0, "",  "", GRPID1
```

```
xcall AUI, AUI_CONTROL, OPCODE, ID(2), "Left Text; Right Justify",  MBST_ENABLE, MBF_CHKBOX + MBF_LFTEXT +
MBF_RTJUST, CMD$, CB2,  STATUS, 3, 2, 3, 24, 67, -2,  0, 0, "",  "", GRPID1
```

```
xcall AUI, AUI_CONTROL, OPCODE, ID(3), "Right Text; Left Justify",  MBST_ENABLE, MBF_CHKBOX + MBF_LFJUST,
CMD$, CB3,  STATUS, 5, 2, 5, 24, 67, -2,  0, 0, "",  "", GRPID1
```

```
xcall AUI, AUI_CONTROL, OPCODE, ID(4), "Right Text; Right Justify",  MBST_ENABLE, MBF_CHKBOX + MBF_RTJUST,
CMD$, CB4,  STATUS, 6, 2, 6, 24, 67, -2,  0, 0, "",  "", GRPID1
```

```
xcall AUI, AUI_CONTROL, OPCODE, ID(5), "Left Text; Center Justify",  MBST_ENABLE, MBF_CHKBOX + MBF_LFTEXT,
CMD$, CB5,  STATUS, 8, 2, 8, 24, 67, -2,  0, 0, "",  "", GRPID1
```

```
xcall AUI, AUI_CONTROL, OPCODE, ID(6), "Right Text; Center Justify",  MBST_ENABLE, MBF_CHKBOX, CMD$, CB6,
STATUS, 9, 2, 9, 24, 67, -2,  0, 0, "",  "", GRPID1
```

## The checkboxes in the lower group were created with INFLD, which only supports four of the six possible alignments: 

```
xcall INFLD, 2, 2, 23, 0, "||c", CB$(1), INXCTL, GRPID2+1, 2, EXITCODE, 0, 0, -1, -1, -1, "Left Text; Left
Justify"
```

A-Shell Reference 

Page 1969 

```
xcall INFLD, 3, 2, 23, 0, "||c|J", CB$(2), INXCTL, GRPID2+1, 2, EXITCODE, 0, 0, -1, -1, -1, "Left Text; Right
Justify"
```

```
xcall INFLD, 5, 2, 23, 0, "||cR", CB$(1), INXCTL, GRPID2+1, 2, EXITCODE, 0, 0, -1, -1, -1, "Right Text; Left
Justify"
```

```
xcall INFLD, 6, 2, 23, 0, "||cR|J", CB$(2), INXCTL, GRPID2+1, 2, EXITCODE, 0, 0, -1, -1, -1, "Right Text;
Right Justify"
```

_type_ code legend: **||c** is for checkbox; **R** reverses the normal alignment (putting the checkbox on the left and the text on the right), and **|J** right justifies the text. **|J** is the same as setting SBR=INFLDCBRJ but has the advantage of being easy to change from one field to the next. 

INFLD uses the _setdef_ parameter for specifying the text associated with checkboxes. 

A-Shell Reference 

Page 1970 

## **RADIO BUTTON CONTROL** 

Radio buttons are similar to checkboxes, except that within a group, only one can be set at a time, as shown in the example below: 

This is a typical way of presenting a choice among several mutually exclusive options, and can be implemented using either of the techniques described above for checkboxes. (If using INFLD, use **||r** rather than **||c** to create a radio button field.) However, despite the obvious parallel to checkboxes, radio buttons do not correspond neatly to any legacy data entry INFLD construct, because it breaks the normal one data field to one input field correspondence. 

For example, consider a payroll application that needs to know the marital status, with the choices being single, married filing together and married filing separately. Since this information is going to be stored as a single data item (probably coded as a number), it would be easiest to just prompt for the code number (1-3) while displaying a menu. To present this as a series of radio buttons, we need more screen real estate and logic to check each of the fields to see which one was selected. So, while they may look neat, they may not be that practical to implement, especially when migrating from, or trying to preserve compatibility with a text implementation of the same application. A much more natural, and legacy-friendly way to present such a choice is via a combo box. 

A-Shell Reference 

Page 1971 

## **ANIMATED GRAPHICS CONTROL** 

Animated icons or graphics are typically used to entertain the user during an operation that takes more than a couple of seconds. They are usually stored in AVI files, which internally are made up of multiple frames of a similar image, which when "played", give the impression of a moving image. The example below shows two such frames of an AVI file that presents the appearance of the letter moving from one computer to the other: 

Another common example is the "flying files" that appear when transferring a lot of files to the recycle bin. You can acquire such AVI files from various sources on the Internet, or build them yourself with AVI toolkits which are also available on the Internet. Once you have the desired AVI file in hand, you can display it using a standard AUI_CONTROL call with the following particulars: 

- Set the _ctype_ parameter to 0 

- Set the _winclass_ parameter to "SysAnimate32" 

- Set the _winstyle_ parameter to a combination of zero or more of the following flags: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|ACS_CENTER|&h000<br>1|Center the graphic in the specified rectangle; instead of putting it in<br>the upper left corner. (Animated graphics do not scale.)|
|ACS_TRANSPARE<br>NT|&h000<br>2|Use a transparent background. (This is almost always desirable.)|
|ACS_AUTOPLAY|&h000<br>4|Start the graphic "playing" automatically|



```
CTYPE = 0    ! use winclass instead of type
```

A-Shell Reference 

Page 1972 

```
xcall AUI,AUI_CONTROL, CTLOP_ADD,ID,AVIFILE$, MBST_ENABLE, CTYPE, "","",STATUS,SROW,SCOL,EROW,ECOL,-2,-
2,0,0,"","",0, "SysAnimate32",ACS_TRANSPARENT+ACS_AUTOPLAY,0
```

You can stop and start it using the CTLOP_CHG opcode with the special cstate flags MBST_PLAY and MBST_STOP, for example: 

```
xcall AUI,AUI_CONTROL, CTLOP_CHG,ID,"", MBST_STOP
```

## or 

```
xcall AUI,AUI_CONTROL, CTLOP_CHG,ID,"", MBST_PLAY
```

A-Shell Reference 

Page 1973 

## **ICON CONTROL** 

Icon controls may be created as a variation of either the STATIC or BUTTON control types. In general you would use the STATIC type for icons that are just decorative, and the BUTTON type for icons meant to be clicked on. The following subsections deal with the specifics of each type. 

## **Subtopics** 

- Button Icon Control 

- Icons: Static vs. Button 

A-Shell Reference 

Page 1974 

## **BUTTON ICON CONTROL** 

Button icon controls are typically used for icons intended to be clicked on to perform some action, as in this sample (TSTICB, which uses the subroutine ICOBAR. SBX): 

Button icons use the _ctype_ combination MBF_BUTTON + MBF_ICON. In most cases, you would also add the MBF_KBD type to specify a string to be sent when the button is clicked. 

Button icons can be loaded individually from .ICO files, or via resource names from a DLL. (As of build 919, they do not support the Windows internal icon resources such as "#question.") To load an icon into a button from an ICO file, just specify the ICO filespec in the _ctext_ parameter, either using AMOS or native syntax, for example: 

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, id, ".\control panel.ico", MBST_ENABLE, MBF_BUTTON + MBF_ICON, cmd$, "",
status, srow, scol, erow, ecol, -2, -2,  0, 0, "",  "", grpid1
```

To use an icon resource from a DLL, use the same syntax as for static icons, i.e.: 

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, id, "navigate_down::ashico1.dll", MBST_ENABLE, MBF_BUTTON + MBF_ICON,
cmd$, "", status, srow, scol, erow, ecol, -2, -2, 0, 0, "",  "", grpid1
```

Unlike static icons, button icons are scaled to fit the button. However, this can sometimes result in a distorted look if the button is not square. (In the example above, the buttons are slightly taller than they are wide, which results in a slightly "squeezed" look.) To prevent that kind of distortion, you can add the flag MBF_NODISTORT, which forces it to retain the original square aspect ratio. The example below illustrates some icons from the ashico1.dll displayed as buttons with the MBF_NODISTORT flag (all except the last icon, which illustrates what it would look like without the MBF_NODISTORT. 

## **See Also** 

The sample dialogs under Groupbox + MBF_ALTPOS for a good example of how using an icon on a button can be much easier to understand than text in a foreign language (which may be how your application appears to even native users.) 

## STATIC ICON CONTROL 

A-Shell Reference 

Page 1975 

The STATIC version of the icon control gives you a non-scaled icon with no border, which is appropriate for displaying as a sort of logo in a dialog. This example shows a dialog with several icons, just for illustration purposes: 

Static icons are created by setting ctype to MBF_STATIC + MBF_ICON, and ctext to the resource name of the icon. There are four possible sources of icon resources, each with its own syntax: 

- **System icon resources.** These are embedded in Windows, and are referenced with a name starting with "#". As of build 

- 919, the only ones available are shown in the example above and listed in the following table (the names are not case sensitive): 

|**ICONAMES**|**Description**|
|---|---|
|#HAND|Same as the MBICON'stop icon inMSGBOX. This normally appears as an X in a red<br>circle.|
|#QUESTION|Same as the MBICON'question icon inMSGBOX.|
|#EXCLAMATI<br>ON|Same as the MBICON'exclamation inMSGBOX. This normally appears as a yellow<br>triangle with an exclamation mark in it.|
|#INFO|Same as the MBICON'info icon inMSGBOX. This normally appears as an "i" in a<br>white caption bubble.|
|#WINPTR|A generic printer icon.|



For example: 

A-Shell Reference 

Page 1976 

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, ctlid, "#question", MBST_ENABLE, MBF_STATIC + MBF_ICON, "", "", cstatus,
srow, scol, erow, ecol2
```

• **A-Shell internal icon resources.** These are icons embedded in the ashw32.exe executable, and consist of icons used internally by A-Shell, plus any third-party application icons that have been sent to us for embedding in ashw32.exe. The syntax for these is just a string name, without the "#", such as "ACORNICON", or #dddd where dddd is the decimal icon numbe (1000+). (If we embedded an icon specially for you, we will tell you the name and/or number.) 

• **Icons loaded from external DLLs.** In this case the syntax for _ctext_ is "resourcename::modulename" where resourcename is a string name, such as "stop", and modulename is the name of the DLL (or other loadable module). For DLL’s, you do not need to specify the DLL extension, but the DLL file must be located in the same directory as the copy of ashw32.exe that is being launched, or else in the WINDOWS or SYSTEM32 directory. Such modules can also be located in the ATEPERMCACHE directory. For example, an icon source named "document_check" in the ashico1.dll library would be referenced as " `document_check::ashico1".` 

- **ICO files.** In this case the syntax for ctext is simply the filespec of the .ICO file (either in AMOS or native Windows format). 

Static icons are generally not scaled to the size of the control; see next paragraph for exception. Instead, they are fixed by Windows, according to characteristics of the desktop environment. In almost all cases, this means they are 32 x 32 pixels. The two consequences of this are that the _erow_ and _ecol_ parameters do not matter (by convention they should probably be set to match the _srow_ and _scol_ parameters), and that you need to allow for adequate space for the icons in cases where the number of pixels in the window is smaller than what you designed with. For example, if the window size is about 800 x 500, a 32 x 32 icon will occupy about 1.5 rows in height and 3.2 columns in width. But the same icon in a window of 1200 x 1000 will occupy less than one row in height and about two columns in width. 

The exception to the above rule is that you can force the icon to display at a particular size by setting _erow_ and _ecol_ to the desired height and width **in pixels** , and specifying the MBF2_PIXSIZE flag in the _ctype2_ parameter. Note that for best results, you should use standard sizes, such as 64x64, 128x128, or 256x256, since icons are typically optimized for these sizes. 

Static icons in dialogs interpret a starting row of 0 as a special flag to position it with about ½ row of top margin below the title bar of the dialog. This is just about right for the typical case. (Row one puts the icon right up against the title bar, and row two would waste too much space.) The sample dialog showing the five built-in icons above illustrates this. The first four icons are positioned with _srow_ = 0, while the last one uses _srow_ = 1. 

A-Shell Reference 

Page 1977 

## **Icon Library** 

_Reviewed July 2020_ 

MicroSabio provides an icon library in ashico1.dll, which contains the icons shown and listed below. These have been purchased by MicroSabio so they can be used, royalty-free, by A-Shell developers. While these icons are free to use, most icons are copyrighted and/or licensed and should not be used without the explicit permission of their owner. Icon collections, such as MicroSabio's, are available for purchase from many icon vendors and developers. 

The library may be displayed with the sample program ICODLG in EXLIB:[908,27], which makes use of the subroutine BTNMENU.SBX in SOSLIB:[907,24]. A text listing of the available icons is given after the images. 

Here is a listing of the icons' names, grouped by category where appropriate. 

## miscellaneous 

about, add, add2, copy, cut, delete, delete2, door, door2, edit, error, exchange, exit, export1t, first_aid, fit_to_size, font, forbidden, garbage, help, help2, history, import1, information, music, paste, printer3, preferences, question and answer, redo, refresh, replace, replace2, signpost, star_blue, stop, transform, transform2, undo, unknown, view, warning 

## arrow 

down_blue,  left_blue, right_blue, down_green, left_green, right_green, up_blue, up_green, 

bookmark 

add, delete, down, new, up 

check 

A-Shell Reference 

Page 1978 

check, check2, checks 

disk_blue 

disk_blue, error, ok, warn 

document 

add , certified, chart, check, cup, edit, error, exchange, find, heart, info, lock, ok, out, preferences, text, view, documents 

find 

find, again, next, previous, text 

folder 

folder, folder_add 

gear 

gear, error, ok, pause, refresh, stop, time, gears 

lightbulb 

off, on, 

media 

beginning, end, fast_foward, pause, play, play_green, rewind, step_back, step_forward, stop, stop_red 

navigate 

beginning, up, up2, left, left2, end, down, down2, right, right2 

notebook 

notebook, notebook_preferences 

photo 

A-Shell Reference 

Page 1979 

portrait, scenery 

text 

text, bold, find, italics, normal, speaker, tree, underline 

window 

colors, environment, gear, preferences 

zoom 

in, out 

A-Shell Reference 

Page 1980 

## **ICONS: STATIC VS. BUTTON** 

The distinctions between icons implemented as static controls (MBF_STATIC + MBF_ICON) and those implemented as buttons (MBF_BUTTON + MBF_ICON) are summarized here: 

• Icons on buttons are scaled to the size of the button, whereas icons in static controls display in their "natural" size (which in most cases is 32x32 pixels, although on an extremely low res or high res screen, or if you tinker with the Windows system parameters, it may be as small as 16x16 or as big as 64x64). Although the icon size (for static controls) is not affected by the _erow_ and _ecol_ parameters, we recommend setting them equal to _srow_ and _scol_ . 

- Only buttons can load icons from individual files, whereas only static controls can load them from the internal system 

- resources (e.g. "#INFO"). Either type of icon can load the image from a DLL. 

- Static controls, including icons, may have click actions defined, but they cannot get the focus while waiting in the EVENTWAIT 

- routine. 

A-Shell Reference 

Page 1981 

## **BITMAP CONTROL** 

Bitmap controls are very similar to icon controls, and come in the same two flavors – static (MBF_STATIC + MBF_BITMAP) and button (MBF_BUTTON + MBF_BITMAP). The main differences between bitmaps and icons are: 

- Icons (whether stored in an ICO file or in a resource) typically contain variations of themselves with different color depths and 

- grid sizes, from which Windows will usually select the most appropriate one. Bitmaps, on the other hand, are stored with only one size, and are typically converted internally to a format appropriate for the display device. 

- Icons are square, whereas bitmaps can be in any rectangular shape. 

- The MBF_NODISTORT flag only applies (as of build 919) to icons. 

For both bitmap and icon controls, the _ctext_ parameter must be set to either the filespec of the image file, or a DLL resource identifier (in the format resname::dllname). 

Note that both bitmaps and icons can be contained in DLL resource files. 

## **Examples** 

- `! clickable button with JPG bitmap loaded from file` 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "btnCoffee", "IMAGES:COFFEE.JPG", MBST_ENABLE,
MBF_BUTTON+MBF_BITMAP+MBF_KBD, "VK_xF101", NUL_FUNC$, CSTATUS, SROW, SCOL, EROW, ECOL
```

- `! static with bitmap loaded from resource called "logo1" within images.dll` 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "stcLogo1", "logo1::images", MBST_ENABLE, MBF_STATIC+MBF_BITMAP, NUL_CMD$,
NUL_FUNC$, CSTATUS, SROW, SCOL, EROW, ECOL
```

- `! static clickable using PNG bitmap loaded from file` 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "stcBrain", "brain.png", MBST_ENABLE, MBF_STATIC+MBF_BITMAP+MBF_KBD,
NUL_CMD$,"VK_xF02", NUL_FUNC$, CSTATUS, SROW, SCOL, EROW, ECOL
```

A-Shell Reference 

Page 1982 

## **EDIT CONTROL (INFLD)** 

An edit control is a rectangle in which text may be edited. Most commonly they are used to input just a single field, limited to one line of text and a certain number of characters. Although it is possible to use the AUI CONTROL class to create an edit box (using the _winclass_ parameter), as a practical matter, edit boxes are handled by INFLD, which takes care of the details of creating and managing the edit control and providing a single interface to the application which works in both text and GUI - modes; see INFLD's _type_ table of GUI Related Codes. For convenience, the GUI-related TYPE codes are excerpted here. For information about other INFLD control types, see Groupbox + MBF_ALTPOS, Checkbox Alignment, Justification, Date Picker Control (INFLD), Time Picker Control (INFLD), Combo Box Control (INFLD) and Up/Down Control (INFLD). 

INFLD supports several TYPE codes which activate various graphic user interface features within the A-Shell/Windows (or ATE) version of INFLD. 

When in GUI mode, INFLD typically assumes the form of a Windows edit control when editing, and a static text control (with sunken edges) when not currently being edited. For date and time fields, a date or time "picker" (e.g. calendar /clock) control - may be used, and for fields with certain kinds of SETDEF lists, a combo box may be used. See the INFLD GUI Related Codes for more details. 

## **Comments** 

- The height of an INFLD control is normally a single row, except for the Multi line Edit Control (INFLD), but the precise calculation of that row height depends on some factors which bear explaining. Mostly these involve options set in the Misc Settings and Dialog Sizing dialogs, or alternatively via the MX_WINSETTINGS function. If the Force edit box height to match combo| topic=Force Edit Boxes to Match Combo Height option is set, then A-Shell will determine the height of a standard combo box (see next paragraph) and use that for the edit box. Otherwise, the raw row height is based on the grid for the main window or dialog; see Dialog Grid Units. Then if the Allow Edit Boxes to Use Leading Space|topic=Allow Edit Boxes to Use Leading Space option is not checked, the External Font Leading will be subtracted from the height. 

Unlike the edit box whose height is independent of the font, the height of combo box is determined by the height of the font associated with it. To avoid this difference resulting in differing heights for your standard edit and combo box controls, you can use the Force Edit Boxes to Match Combo Height Height option to force the height of edit boxes to match the height of combo boxes. The combo box reference height is determined initially based on the default font for the window. However, as of 6.1.1380.0, the reference height is updated whenever an actual combo box is created. This provides the possibility of a workaround for a problem in which the font or scale characteristics of the actual combo boxes in use do not match the default 

A-Shell Reference 

Page 1983 

font and scale. To completely take advantage of the feature, if you are using a different font or scale for your combo boxes than for your edit boxes, you should create one of the combo boxes (or a dummy, if necessary) before creating the edit boxes. This will ensure that the combo and edit box heights match. 

A-Shell Reference 

Page 1984 

## **UP/DOWN CONTROL (INFLD)** 

The Up/Down or "Spin" (or "Spinner") control is like a regular numeric edit control, except that it in addition to the normal keyboard method of data entry, there is also a pair of up/down arrows on the right edge which allow the user to increment/decrement the value by a predetermined amount. 

To create an Up/Down control, use the field _type_ **||U** along with a numeric _type_ such as **#** . By default the increment is 1, and the range extends from 0 to 100, with the down arrow increasing the value of the field. You can change the range by specifying a string in the _setdef_ parameter, formatted as follows: 

```
/n1/n2//
```

or 

## `/n1/n2/n3//` 

where n1 and n2 are the low and high limits of the range, and n3, if specified, is the increment (the amount of change you get with each arrow/click). Normally, the down arrow increases the value of the field, but if you want to reverse this, reverse the n1 and n2 values in SETDEF so that the high value is first. 

If the preloaded value you specify in ENTRY does not fit in the range, it will be changed to the nearest range limit. 

Increment values must be positive integers, but the either or both of the range limits may be negative. 

Note that the increment value only affect that amount of change when you click on the arrow; it does not prevent numbers that are within the range but not multiples of the increment from being entered. For example, if SETDEF = "/-20/50/10//", the range is from -20 to 50, and the increment is 10. But the user may keyboard in a value such as 13. In that case clicking on the up/down arrows will increment/decrement the field by 10 (i.e. to 3 or 23 in this case). 

Up/Down controls revert to the form of a regular edit control when not active. 

Note that the Up/Down control is internally separate from the edit control. This is probably of no concern to anyone except that it will show up in a control dump, independent of the associated edit control. 

## **Comments** 

A-Shell Reference 

Page 1985 

Up-Down controls preserve their Up-Down buttons even when the field is not active. Note that if you click on one of the Up-Down buttons while the field is not active, it will trigger the click string for the field, but not increment or decrement the field value. This is deliberate to avoid the possibility that your application may decide not to respond to the click string by enabling the field, thus giving the user the false impression that the field value had actually been updated. 

A-Shell Reference 

Page 1986 

## **- MULTI LINE EDIT CONTROL (INFLD)** 

A multi-line edit control is a special case of the standard edit control. See types **|M** and **||M** and **||H** in the table above for notes on implementing one. A sample is shown below. Note that although this is a convenient way of editing and displaying a free format block of text, it is suitable for a maximum of about 4000 characters and has various other limitations. For a more powerful text editing control, see XTEXT. 

The SCRSTS.SBX subroutine uses a multi-line edit control in display-only mode to implement a scrolling status window. Source code is available, along with sample programs, in the SOSLIB:[907,20]. 

Note that when INFLD is in multi-line mode ( **|M** or **||M** ) and up/down exits are enabled (3 and 5), and is not using Windows keyboard conventions (i.e. not specifying **|K** ), then the UP/DOWN-ARROWS will cause INFLD to exit if used when the cursor is already on the first or last line of the control. Note that the last line is defined as the line containing text. 

A-Shell Reference 

Page 1987 

## **COMBO BOX CONTROL (INFLD)** 

A combo box is another compound control type, made up of an edit control and a drop-down list box. As with other variations of edit controls, they are managed by INFLD rather than by the AUI CONTROL class. The example below shows two combo boxes, one in the display state and the other being edited and with the drop-down list extended. 

Thanks go to Jorge Tavares for the example above, which besides illustrating combo boxes, also illustrates the use of a button as the label or prompt associated with the combo box. In this case, clicking on the button pops up a dialog, allowing the qualified user to edit the list of items available to be chosen in the drop down list. 

There are a number of variations of combo boxes. In the default state, you can freely type in the edit box. (Whether or not INFLD allows you to exit the field after entering a value not in the list depends on whether you add the _type_ **||s** , or include a wildcard "*" in your SETDEF list.) As with other INFLD fields, _type_ O may be added to make the field optional, i.e. to allow a blank entry. If you want to limit the operator to just selecting values from the list (either by displaying it and clicking on an option, or by typing one or more characters and using the auto-selection logic), then add _type_ code **||S** . 

The width of the drop-down list will be increased beyond the _xmax_ value, if necessary to accommodate the longest choice (as specified in the _setdef_ parameter). This allows you to have longer, more descriptive choices in the drop-down list than the field allows for. A good example of this would be a 2-character state abbreviation field, which you can now link to a list of choices such as ",CA California, MN Minnesota,," etc. In this case the user will be able to see the full descriptions, but the data returned to the program will be limited by _xmax_ (i.e. to just the 2 character state abbreviation). 

There is no set maximum to the number of characters (or number of choices) that can be displayed in the drop-down list, but once it gets beyond a few thousand bytes or a few hundred entries, you will probably want to consider another method, such as XTREE, or perhaps a Self Service Combo Box. 

Also see the comments below Edit Control (INFLD) for details on how the height of a combo box is determined. 

## **Subtopics** 

- Text Mode Compatibility 

- Coded Lists 

A-Shell Reference 

Page 1988 

- Self Service Combo Box 

A-Shell Reference 

Page 1989 

## **TEXT MODE COMPATIBILITY** 

INFLD supports most of the combo box-related _type_ codes even in text mode, only in that case, instead of a combo box like shown above, you get a normal looking field, with a display of the list of options along the bottom line of the screen. (The display can be turned off with TYPE S.) This is a good example of a GUI enhancement that you get with INFLD without any programming changes, simply by activating GUI mode (with **|G** ). 

A-Shell Reference 

Page 1990 

## **CODED LISTS** 

_Updated May 2021; see History_ 

Often, if a list has only a limited number of items, and especially if the description of those items might be lengthy, it makes more data processing sense to store the selected item as a coded number, rather than as text. For example, the program shown above (Combo Box Control (INFLD)) actually stores the choices for the Zona field as a B,1 value, maintaining a table which translates the numeric codes into the descriptions which are seen above. Rather than having to do this work separately, you can let INFLD manage the table by adding _type_ **||L** , and specifying SETDEF as a list of pairs, i.e. 

```
SETDEF=",01,Norte,02,Centro,03,Sul,04,Pink Zone,05,Hot Zone,06,Ozone,,"
```

In this case, INFLD displays just the descriptions, but returns to the program the numeric codes (in other words, letting the user and the programmer have it their own way.) 

A sub-variation of the above causes INFLD to return both parts of the pair, i.e. "04,Pink Zone" if _type_ **||l** (lower case L) is used instead of **||L** . 

Since INFLD typically trims the _xmax_ value to be no greater than the physical size of the _entry_ parameter, you may need to map the variable used for the _entry_ parameter large enough to display the descriptions in the coded list (rather than just large enough to hold the coded values). 

## **History** 

- 2021 March, A Shell 6.5.1701:  List substitution (INFLD _type_ code **||l** or **||L** ) now supports matching an empty field to a key entry in the list consisting of just blanks, provided that the _xmin_ parameter is not zero and the **O** (optional) _type_ code is not set. For example, in the list 

- `/  /Nowhere/01/Up/02/Down/03/Middle/` 

passing an empty field to INFLD will now match against the Nowhere entry in the list provided XMIN>0 and field not optional. Previously, null fields were not initially matched against the list, resulting in the initial field display defaulting to nothing. 

A-Shell Reference 

Page 1991 

## **SELF SERVICE COMBO BOX** 

Another variation of a combo box is where you want to present the user with the appearance of there being a combo box to select from, but you do not want to specify the choices in advance. One reason might be that the choices are actually all the records in a file, and rather than fetch them in advance, you want to allow the user to enter a couple of characters to limit the number of choices, then presenting them in an XTREE control (which is equipped to handle thousands of entries, unlike the combo box). To get this effect, specify SETDEF="..." (3 dots). INFLD will then return EXITCODE 29 to the application when the user clicks on the DOWN-ARROW button or hits a key that would normally display the list (including the DOWN-ARROW key) 

A-Shell Reference 

Page 1992 

## **DATE PICKER CONTROL (INFLD)** 

A date picker is a special kind of edit control designed only for the input of dates. It is created automatically by INFLD when called on to edit a date field ( _type_ **D** ) in GUI mode ( **|G** ). (It is not activated in the "lesser GUI mode", which you get with _type_ **| g** .) In the first example below, the field is being edited, but unlike with a normal field, the control selects one sub-field (month, day, or year) to edit at a time. You can either type digits, or use the UP/DOWN-ARROWS, or use the PLUS / MINUS keys on the numeric pad, to increment/decrement the value. Use the RIGHT-ARROW to move to the next sub-field. 

If the date is optional (XMIN=0), a checkbox will appear. If unchecked, the date is grayed out and unavailable. To change it, first check the checkbox: 

To display the calendar, click on the DOWN-ARROW button, or hit ALT+DOWN-ARROW: 

The format used by the date picker for editing and display is based on the localization settings of the client PC. But the format returned to the application is based on the INFLD _type_ codes and _xmax_ value. With _xmax_ =6, only 2 digits of the year are turned. With _xmax_ =8, the entire CCYY is returned. TYPE D uses American format (MM/DD/{CC}YY), TYPE U forces European 

(DD/MM/{CC}YY) format, and TYPE U selects the format from the language definition file (e.g. englsh.ldf[1,6]). TYPE > forces the date to be returned in CCYYMMDD format (most convenient for sorting, independent of country format). 

See Month Calendar Controlfor information on using the calendar control independently of an INFLD date field. 

## **Comment** 

If you would like to implement your own date picker (i.e. your own calendar display associated with the INFLD date field), use the "lesser GUI mode" ( **|g** ) and set the _setdef_ parameter to "...", which will give you an INFLD date control which returns to you with EXITCODE=29 if the user clicks on the DOWN-ARROW button. You can then pop up whatever kind of display you like to help the user select a date. 

A-Shell Reference 

Page 1993 

Or, to use the edit part of the date picker control, but replace the drop-down calendar part, use **|G** with **||v** (and set setdef = "..." as above). 

A-Shell Reference 

Page 1994 

## **TIME PICKER CONTROL (INFLD)** 

A time picker is similar to a Date Picker Control except for time rather than dates. (Use INFLD _type_ **t** or **||t** .) As with the date picker, the editor selects one sub-field at a time for editing (hour, minute, second) and you can edit it either by typing or by clicking on the UP/DOWN ARROWS. 

. 

The format used by the control for editing and display is based on the localization settings for the workstation, but the format in which the field is returned is determined by the _type_ code and _xmax_ values. With _type_ **t** , the time is returned in military (24 hour) format. With _type_ **||t** , the time is returned in 12 hour format with AM/PM appended. In both cases, setting _xmax_ to 5 will eliminate the seconds from the returned time string. (Otherwise 8 is the normal _xmax_ value.) 

## **Notes** 

The time picker control bases its format on MAXCHARS rather than _xmax_ , allowing you to use _xmax_ to set the physical display width of the field. In this case you may want to use _type_ **||]** to defeat the automatic widening of the field to accommodate the extra formatting features of the time picker. This behavior matches the date picker and other field types as well. 

If _type_ **O** (optional) or XMIN=0, the time field will have a check box allowing you to select whether the field is to be valid or not. 

A-Shell Reference 

Page 1995 

## **MONTH CALENDAR CONTROL** 

_Updated December 2018; see History_ 

The month calendar control is essentially the same as the calendar that appears in a date picker when you press the dropdown button, but is not associated with an input field, thus making it suitable to just place in a window/dialog as a convenience to the user in applications that involve dates (like scheduling). In comparison to the generic date/time dialog (the one you get by double-clicking on the system time display), this one has the advantage of being visually more compact, as well as providing some degree of application control. For example, you can: 

- generate a key click string/exitcode when the user changes the date 

- query or set the selected date (independent of the system date) 

- you can set limits on the range of dates that can be selected or displayed 

- highlight individual dates 

To create a calendar control, use the following syntax: 

## **xcall AUI, AUI_CONTROL, CTLOP_ADD, ctlid, ctext$, cstate, ctype, cmd$, func$, cstatus, srow, scol, erow, ecol, fgc, bgc, fontattr, fontscale, fontface$, tooltip$, parentid, winclass, winstyle, winstylex, ctype2** 

## **Parameters** 

|**Option**|**Description**|
|---|---|
|ctlid|standard control identifier.|
|ctext$|generally ignored when creating a calendar, unless you specify a_winstyle_that creates a title bar.<br>_ctext$_is however used with the CTLOP_CHG opcode to set the date or day states.|



A-Shell Reference 

Page 1996 

|**Option**|**Description**|
|---|---|
|cstate|standard control state options; normally set to MBST_ENABLE.|
|ctype|may be set to 0, unless you want to enable a click string, in which case specify the MBF_KBD flag.|
|cmd$|may specify a standard key click string (if MBF_KBD specified). If so, then clicking on a date will<br>send the click string. Unless the MCS_DAYSTATES option is specified in_winstyle_, advancing to<br>another month does not trigger the click string.|
|func$|ignored|
|cstatus|standard return codes (0=ok)|
|position|See topic of this name.|
|<ignored<br>>|fgc, bgc, fontattr, fontscale, fontface$|
|tooltip$,<br>parentid|work as usual.|
|winclass|must be specified as "ASHMONTHCAL". This replaces the fact that we didn't specify a control type<br>in_ctype_.|
|winstyle|may be used to specify additional style options relating to the window wrapper for the control, as|



A-Shell Reference 

Page 1997 

|**Option**|**Description**|
|---|---|
||well as options specific to the calendar. See_winstyle_table for options, values and descriptions.|
|winstyle<br>x|may optionally have additional extended window styles: use WS_EX_TOPMOST (&00000008) to<br>force on top (of its siblings)|
|ctype2|If you plan to modify the color attributes (see Modify section below), you must specify the<br>MBF2_NOTHEME bit here.|



Once the calendar control is created, there are several additional operations you may want to perform on it, such as highlighting, setting and retrieving dates, modifying colors, etc.  See the sub-topic Operations for details. 

## **Example** 

See the sample program MONCAL.BP in EXLIB:[908,42] for a simple working example. 

## **History** 

- 2018 December, A Shell 6.4.1651:  the MBF2_NOMOVE flag may now be set when creating the control to stifle the logic which otherwise shifts the control up and/or to the left as needed so that it fits in within the parent window. 

- 2011 April, A Shell 5.1.1212:  The month calendar control now supports multiple calendars in a single control—i.e. multiple months showing at a time. Because it is difficult to know how big the control coordinates must be in order to display a specific number of calendars, you may now replace the lower right coordinate (erow,ecol) with the number of rows and columns, respectively, of calendars to display, provided that the MBF2_PIXSIZE flag is specified in the _ctype2_ parameter. For example, srow=1, scol=50, erow=1, ecol=2 will create a control with two calendars side by size, starting at position 1,50. (If the two calendars would extend off the edge of the parent window, the starting coordinates will be adjusted so that the entire calendar fits in the window.) 

A-Shell Reference 

Page 1998 

Note that the day states feature (MCS_DAYSTATES) is not compatible with multiple calendars. 

The sample program MONCAL.BP in EXLIB:[908,42] has been enhanced to illustrate the new technique. 

## **Subtopics** 

- Position 

- Winstyle 

- Operations 

A-Shell Reference 

Page 1999 

## **POSITION** 

Because the control size is fixed by the system (based on system display parameters), it doesn't make much sense to specify an arbitrary rectangle—although you can, with unpredictable results. Typically, you want the control to be stuck in one of the four corners of the window or dialog, or at least up against an edge. To accomplish this, A-Shell will apply certain logical rules to the coordinates given. The first rule is that if you ask for a size that is less than the minimum width and height needed to display one month, it will be automatically expanded as needed. To take full advantage of this, just set the _erow, ecol_ parameters to match the _srow, scol_ . For example, to put it in the upper left, set the coordinates to 1,1,1,1. The second rule is that if the starting position specified is beyond the width or height of the window, it will be moved to fit. So to position the control in the bottom corner, specify numbers that you know are larger than the size of the window, like 100,100,100,100. (Note that if you specify a row greater than 200, millirows are assumed, which means you would need to specify a much larger value.) With these rules, you can position the control in each of the four corners as follows: 

|**Position**|**Values**|
|---|---|
|Top left|1,1,1,1|
|Top right|1,100,1,100|
|Bottom left|100,1,100,1|
|Bottom right|100,100,100,10<br>0|



Even with this simplification, you still need to deal with the fact that the actual size may be smaller or larger than you are expecting in terms of the row/column coordinates used for other controls. (This problem is minimized if you use MBF_ALTPOS since at least then the units are based on the font size and resolution, giving the calendar a predictable size of about 6 rows and 17-20 

A-Shell Reference 

Page 2000 

columns, depending on the display options.) But if your dialog grid is based on the main window, then the size of the main window will determine how many rows and columns are actually occupied by the calendar.) 

If you specify a rectangle that fits in the window and is large enough to show more than one month, the control will display as many months as it can. (This is not recommended though, as no consideration has yet been given to the special issues that may arise. In particular, the day states option only works for single-month-at-a-time calendars.) 

A-Shell Reference 

Page 2001 

## **WINSTYLE** 

This parameter may be used to specify additional style options relating to the window wrapper for the control, as well as options specific to the calendar: 

|**Option**|**Value**|**Description**|
|---|---|---|
|MCS_DAYSTATE|&h0000001|Enable day state highlighting; see next topic|
|MCS_MULTISELECT|&h0000002|(not yet supported)|
|MCS_WEEKNUMBERS|&h0000004|Show week numbers in calendar.|
|MCS_NOTODAYCIRCLE|&h0000008|Don't circle today's date|
|MCS_NOTODAY|&h0000010|Don't show today's date at bottom of calendar.|
|MCS_NOTRAILINGDATES|&h0000040|Disable display of dates in prev/next month|
|MCS_SHORTDAYSOFWEEK|&h0000080|Display short day names in header|
|MCS_NOSELCHANGEONNAV|&h0000100|Don't change selection when navigating next/prev|
||||
|WS_BORDER|&h0800000|Put a thin border around it.|



A-Shell Reference 

Page 2002 

|**Option**|**Value**|**Description**|
|---|---|---|
||||
|WS_DLGFRAME|&h0400000|Put a dialog-style border around it.|
|WS_CAPTION|&h0C00000|Add a title bar; allows dragging.|
|WS_SYSMENU|&h0080000|Add an X button to close calendar.|
|WS_VSSCROLL|&h0200000|Adds a vertical scroll bar to the dialog; seeDialog Scrolling<br>.|



WS_THICKFRAME may be added to the _winstyle_ parameter when creating static controls to give them a raised panel effect. This is the visual reverse of WS_EX_CLIENTEDGE. It isn't clear whether any other control types can benefit from this option, but it probably won't hurt to try. 

A-Shell Reference 

Page 2003 

## **OPERATIONS** 

## **Retrieve Date** 

To retrieve the selected date (either in response to receiving the click string or exitcode, or whenever you like), use _opcode_ CTLOP_QRYCB (5) to query the control. This opcode was previously only used for querying a checkbox, but takes on a slightly different meaning here: 

## **xcall AUI, AUI_CONTROL, CTLOP_QRYCB, id, ctext$, cstate, ctype, cmd$, "", cstatus** 

Set _id_ to the id number of the control (as returned from the CTLOP_ADD) operation. The currently selected date will be returned in _cstatus_ as a number with the following format: CCYYMMDD. (You can convert it to a string and parse it out into subfields as you like.) The ctext$, cstate, _ctype_ , and _cmd$_ parameters are ignored. 

## **Set Date** 

To set the date in the calendar, use the CTLOP_CHG opcode and put the date (in CCYYMMDD format) into the _ctext$_ parameter, as if you were changing the text of a control. Set the _cstate_ parameter to MBST_TEXTONLY: 

## **xcall AUI, AUI_CONTROL, CTLOP_CHG, id, ctext$, MBST_TEXTONLY** 

## **Set Limits** 

To limit the calendar to a range of dates, Use the CTLOP_CHG operation as for setting the date, except format the _ctext$_ parameter as a 17 byte string of two dates in CCYYMMDD format with a dash in between, for example: 

```
CTEXT$ = "20230120-20250630"   ! range of 20-Jan-23 thru 30-Jun-25
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ID, CTEXT$, MBST_TEXTONLY
```

## **Set Day States** 

As an added feature, you can force selected dates to be shown in bold. To do so, specify the MCS_DAYSTATES flag (in the _winstyle_ parameter) when creating the control. You must then send a string of 0's and 1's to the control to update the day states for the current month when the control is first displayed and whenever the month changes (which will require you to respond to the click code). Set the _ctext$_ parameter to a string 31 digits long, representing the days 1-31 of the current month. (Set any 

A-Shell Reference 

Page 2004 

extra days to 0). 0 indicates the normal state, and 1 the bold state. Then use the same CTLOP_CHG format as shown above for setting the date. The control will determine which attribute you are setting by the fact that the _ctext$_ string is exactly 31 bytes long. For example:: 

```
CTEXT$ = "1000000000000010000000000000000"  ! bold 1st & 15th
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ID, CTEXT$, MBST_TEXTONLY
```

Note that this mechanism currently is only supported for one month at a time; see the discussion above about specifying the coordinates to make sure that the control is not big enough to show multiple months. 

## **Set Color Attributes** 

There are two standard style/color variations of the calendar control, depending on whether the _ctype2_ MBF2_NOTHEME bit is set when the control is created: 

Standard themed version (Win11) 

Standard non-themed version 

To change the color scheme for the non-themed version, use the following: 

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid, ctext$, MBST_TEXTONLY
```

where _ctext$_ should set to the an attribute name string followed by a colon followed by hex representation for the blue, green and red color values, e.g. 

```
AttributeID:&hbbggrr
```

The available attributes (not case sensitive) for which colors can be set are as follows: 

**AttributeID Description** 

A-Shell Reference 

Page 2005 

|ell Reference||
|---|---|
|SETCOLOR_BACKGROUND|Background (area outside the calendars but inside the control<br>borders)|
|SETCOLOR_MONTHBK|Background for the calendar(s)|
|SETCOLOR_TEXT|Color of the text within a month (days)|
|SETCOLOR_TITLEBK|Background of the title area|
|SETCOLOR_TITLETEXT|Title text color|
|SETCOLOR_HDRTRAILINGTEX<br>T|Text color for the display header day and trailing day text (leading<br>and trailing days from previous and following months)|



## **Example** 

```
ctext$ = "SETCOLOR_MONTHBK:&heecc88"
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid, ctext$, MBST_TEXTONLY
```

## **Visibility Issues** 

The calendar control, when positioned on top of another control in the same window, allows the control underneath to "bleed" through (both visually and when processing mouse clicks). (This is just a Windows quirk of that control.) The normal way to avoid such problems with it is to not position on top of another control (seems reasonable), or, if you insist, then first enclose it in a separate dialog. However, if neither of those options is desirable, yet another possibility is to remove the child flag from the control, so that it acts like a top-level popup or overlapped window. To do so, add the WS_VISIBLE flag, and optionally, the WS_POPUP flags in the _dwStyle_ parameter. (e.g. DWSTYLE = WS_CAPTION + WS_SYSMENU + WS_VISIBLE). This essentially turns the calendar control 

A-Shell Reference 

Page 2006 

into its own dialog, which has its own downsides (affecting the positioning and also making it difficult to use in conjunction with another control to receive the date clicked on), but for cases where you just want to have a floating calendar handy, this may be an easier technique than manually creating your own modeless dialog to house the calendar control. 

The reason why adding WS_VISIBLE removes the child flag (WS_CHILD) is that if neither WS_VISIBLE nor WS_CHILD are specified, both are turned on by default. Turning on the visible flag explicitly removes the default. 

## **History** 

- March 2024, A Shell 7.0.1757:  ASHMONTHCAL control enhancement: you can now set various color attributes for the control. 

A-Shell Reference 

Page 2007 

## **MODAL DIALOG BOX CONTROL** 

_Updated December 2013; see History_ 

A "modal" dialog (MBF_DIALOG) is a popup window that holds on to the keyboard focus, making it impossible to type in any other window owned by the current application, until the modal dialog is closed. You can, however, drag the dialog around, access the main A-Shell menu bar, and even pop up nested modal dialogs. They are quite handy when you want to interrupt the context of the current operation to display or input a collection of related fields. 

When creating a dialog box, you should save its _ctlid_ parameter so that it can be used later with _opcode_ CTLOP_DEL to delete the dialog box. Deleting the dialog box will automatically delete the controls within it. 

Once a modal dialog is opened with A-Shell, any subsequently created child controls (buttons, static text, edit prompts, etc.) will be, by default, owned by the dialog box, and their coordinates will be taken as relative to the dialog box. (In other words, the _parentid_ parameter will automatically be set to the dialog box _ctlid_ .) However, it is probably still a good idea for you to manually set the _parentid_ , as it probably will make your programs easier to follow, and will be indispensable if you want to implement a text version of a dialog using MSBOXX. Ordinary text output (e.g. PRINT statements, unless SET AUTOTPRINT is enabled) will ignore the dialog box and appear in the main A-Shell window. (In other words, you can only place Windows control-objects within these dialog boxes.) 

Typically, a dialog box should have one or more buttons which notify the program (via a keyboard sequence) to close the dialog (for example, "OK", and "CANCEL"). You may also include an "X" in the upper right corner of the dialog by adding the MBF_SYSMENU flag to _ctype_ , which the user can click on to close the dialog. 

Note that clicking on the "X" to close a dialog does not directly close it. Instead, it sends a click string to the keyboard buffer, which should generate an _exitcode_ in the dialog's event handler or input routine, allowing the application to close the dialog (with _opcode_ CTLOP_DEL). By default, the click string is a single escape character, i.e. chr(27), which generally translates to _exitcode_ 1. But as of 6.1.1355.0 you can override it by putting the desired click string (e.g. VK_xF999 for exitcode 999) into the _cmd_ parameter and _not_ setting the MBF_KBD flag in the _ctype_ parameter. If you set the MBF_KBD flag, then clicking anywhere on the dialog will send the click string, as if it were a button or other clickable control. 

To simplify programming, if the dialog also has a CANCEL button, you might as well program it to send the same click string so that pressing on the CANCEL button or "X" has the same effect. Also note that you are not obligated to close the dialog just because the user clicked on either of these buttons; if there is a problem needing resolution by the user, you can ignore the clicks or pop up a message box to tell the user what they must do before closing the dialog. 

A-Shell Reference 

Page 2008 

To display a dialog by itself, without the main window behind it, using one of the following techniques: 

• You can launch a new session of A-Shell with either of the Command Line Switches -z or -zi (both of which make the main window invisible) and use a startup command that launches a program which shows a dialog. Note however, that the dialog should be created with MBF_ALTPOS flag or else it will likely be sized inappropriately. 

• You can hide the main window on demand using `XCALL AUI,` AUI_WINDOW `, SW_HIDE` and then proceed to create a dialog normally. 

## **History** 

- 2013 December, A Shell 6.1.1368: WS_VSCROLL flag in the _winstyle_ parameter allows creation of vertically scrollable dialogs. 

- 2013 July, A Shell 6.1.1356: Clicks on controls belonging to windows not within the current modal dialog are normally ignored, unless they come from a modeless dialog. The idea is that modeless dialogs operate outside of the normal dialog hierarchy. This rule has now been modified slightly to ignore clicks from a modeless dialog which is a parent of the current modal dialog. In other words, if a modeless dialog launches a modal child dialog, the user will have to terminate that modal child dialog prior to interacting again with the original modeless dialog. 

- 2013 March, A Shell 6.1.1340:  New ctype2 flag MBF2_GLOBAL allows a control to be clickable even if not part of the current modal dialog. 

## **Subtopics** 

- Dialog Options 

- Dialog Positioning 

- Dialog Scrolling 

A-Shell Reference 

Page 2009 

## **DIALOG OPTIONS** 

_Updated December 2013_ 

## The following _ctype_ and _ctype2_ flags relate specifically to dialogs: 

|**Symbol**|**Description**|
|---|---|
|MBF_ALTPOS|Changes the grid units used to size the dialog and position the controls within it,<br>from the main window grid, i.e. the original text R rows by C columns system used<br>by TAB(R,C), to units that are based on the Windows desktop font and resolution.<br>SeeDialog Positioning<br>.|
|MBF_DLGNOCREEP|Applies to nested dialogs which don't use MBF_ALTPOS, eliminating the cascading<br>(aka "creeping") effect by making the dialog interpret its position relative to the<br>main window rather than to the parent dialog.|
|MBF_DLGNOPARENT|Forces dialog box to be a child of the desktop (sibling of the main A-Shell window)<br>rather than a child of the main A-Shell window. SeeDialog Positioning<br>.|
|MBF_MAXBUTTON|Enables the maximize dialogs button (requires MBF_SYSMENU)|
|MBF_MODELESS|Creates aModeless Dialog<br>.|
|MBF_SYSMENU|Adds the "X" button to the dialog.|
|||
|MBF2_DLGICON|Display the dialog icon in the dialog title bar.|



A-Shell Reference 

Page 2010 

|**Symbol**|**Description**|
|---|---|
|||
|MBF2_DLGNOCAP|Creates a dialog with no caption. Such a dialog is effectively anchored to its parent,<br>as if it were a child control, except that it can host its own child controls.|
|MBF2_DLGSTATE|Causes A-Shell to remember and re-use the last size/position/state of the dialog,<br>ignoring the specified coordinates/state.|
|MBF2_MINBUTTON|Used with MBF_SYSMENU to add a minimize button to a modal dialog.|
|MBF2_NOMOVE|Prevents a dialog from being moved.|
|MBF2_PIXCOORDS|Allows you to specify all the coordinates of the dialog in pixels. SeeDialog<br>Positioning<br>.|
|MBF2_PIXSIZE|Allows you to specify the size of the dialog in pixels. SeeDialog Positioning<br>.|
|MBF2_RESIZE|May be used with MBF_ALTPOS to allow the dialog to be resized with the mouse.|



## Use the following _winstyle_ options to further define the dialogs: 

WS_BORDER &h00080000 Adds a thin border. Is normally only applicable with MBF2_DLGNOCAP. 

A-Shell Reference 

Page 2011 

|WS_VSCROLL|&h00200000|Used to support vertical scrolling in dialogs. The scroll bar is initially disabled,<br>but is automatically enabled and configured as fields are added to the dialog<br>that extend beyond the bottom of the visible dialog. Users can scroll the<br>dialogs using the scroll bar. AUI_EVENTWAIT will also auto-scroll the dialog<br>as needed to bring the newly focused control into view. SeeDialog<br>Scrolling<br>.|
|---|---|---|



## **History** 

2013 December: Added two winstyle symbols in separate table. 

2012 November: This topic added. 

A-Shell Reference 

Page 2012 

## **DIALOG POSITIONING** 

The size of a dialog is based on interpreting the specified scol, srow, ecol and erow coordinates according to one of following grid systems: 

• **Main window grid:** If the dialog is a child of the main A-Shell window and neither the MBF_ALTPOS nor MBF2_PIXSIZE options are specified (and the Settings > Dialog Sizing > Dialog Grid Units option is not set to "Main window grid size"), then the dialog coordinates will be interpreted using the grid of the main window. For example, if the main window is divided into 24 rows and 80 columns, and the dialog coordinates are 12, 40, 26, 90, then the dialog will be positioned with the upper left corner roughly in the position of the main windows' row 12, column 40, and will extend approximately two rows and ten columns beyond the bottom and right edge of the main window. (The positions are somewhat approximate due to some internal margins in both the dialog and main window, the thickness of the dialog border, etc.) Note that these main window grid units are calculated dynamically based on the size of the main window at the time the dialog is created, which raises the risk of the resulting dialog being too big or too small. 

- **Altpos grid:** If the MBF_ALTPOS flag is specified (or the Settings > Dialog Sizing > Dialog Grid option is set to "Windows 

- desktop font size"), then the "altpos" (alternate positioning) grid is used. The units of this grid are based on the resolution and size of the Windows desktop font, about 120% of that font's character height and average character width. This grid system makes it easy to lay out controls in standard rows and columns that adjust automatically to the desktop resolution, which is the way most Windows dialogs work. 

- **Pixels:** If you specify the MBF2_PIXSIZE or MBF2_PIXCOORDS flags, then you can specify the height and width (or all the coordinates, 

- if MBF2_PIXCOORDS) in pixels. 

Although the Altpos grid system is the most convenient of the three, in all cases you can use the AUI_WINDOW function to query the details of the grid system and monitor configuration in order to size and position the dialog relative to the available space. 

You can also center the dialog, using the _cstate_ flags MBST_HCENTER and MBST_VCENTER (in which case you might was well set the left and top coordinates of the 1,1 and the right and bottom to the desired width and height). 

See the sample programs DLGCTR, DLGCTR2 and DLGCTR3 in EXLIB:[908,28] for various examples of these techniques. 

## **History** 

2012 November: This topic added. 

A-Shell Reference 

Page 2013 

A-Shell Reference 

Page 2014 

## **DIALOG SCROLLING** 

_Added December 2013_ 

Dialogs can be made vertically scrollable by specifying the WS_VSCROLL in the _winstyle_ parameter when the dialog is created. For example: 

... 

- `! create dialog with vertical scroll bar` 

```
winstyle = WS_VSCROLL
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "dlg1", "Scrolling Dialog", &
```

- `MBST_ENABLE, MBF_DIALOG, NUL_CMD$, NUL_FUNC$, NUL_CSTATUS, &` 

```
    4000, 10000, 10000, 40000, NUL_FGC, NUL_BGC, &
```

```
    NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$, &
```

```
    NUL_PARENTID, NUL_WINCLASS$, winstyle, NUL_WINSTYLEX, NUL_CTYPE2
```

- `! create a bunch of fields that extend arbitrarily below bottom of dialog` 

```
row = 500
```

```
for fno = 1 to num'fields
```

```
    row += 1000
```

```
    xcall SBXINP, "<2>"+label$(fno), INFOP_DISPLAY, row, 8, xmax(fno), &
```

A-Shell Reference 

Page 2015 

```
        field$(fno), "|GA||C]g123T", setdef$, 50, fno+100, tooltip$, "dlg1", &
```

```
        exitcode, -1, 0, 0, -1
```

```
next fno
```

The scroll bar will be automatically configured / calibrated as fields are added to the dialog, and the EVENTWAIT routine will automatically scroll the currently focused field into view. 

Note that this works for all types of dialogs, including MBF_DLGNOCAP dialogs, which can be positioned within parent windows or panels (such as Tab panels), allowing you to effectively creating scrollable regions within a larger window. 

To produce this dialog, we modify the code from the first example as follows: 

- `! main dialog (not scrollable)` 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "dlg0", "Dialog with scrollable region", &
```

```
    MBST_ENABLE, MBF_DIALOG, NUL_CMD$, NUL_FUNC$, NUL_CSTATUS, &
```

```
    4000, 10000, 12000, 40000, NUL_FGC, &hffeeee
```

- `! ok and cancel buttons at top, in non-scolling region` 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "btnOK", "OK", &
```

```
    MBST_ENABLE, MBF_BUTTON+MBF_KBD, "VK_xF5", NUL_FUNC$, NUL_CSTATUS, &
```

```
    1500, 13000, 3000, 20000
```

A-Shell Reference 

Page 2016 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "btnCancel", "Cancel", &
```

```
    MBST_ENABLE, MBF_BUTTON+MBF_KBD, "VK_ESC", NUL_FUNC$, NUL_CSTATUS, &
```

```
    1500, 22000, 3000, 29000
```

- `! scrollable borderless dialog within main dialog` 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "dlg1", NUL_CTEXT$, &
```

```
    MBST_ENABLE, MBF_DIALOG, NUL_CMD$, NUL_FUNC$, NUL_CSTATUS, &
```

```
    3000, 0, 8500, 31000, NUL_FGC, &hffdddd, &
```

```
    NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$, &
```

```
    NUL_PARENTID, NUL_WINCLASS$, WS_VSCROLL+WS_BORDER, NUL_WINSTYLEX, &
```

```
    MBF2_DLGNOCAP+MBF2_STICKY
```

- `! create a bunch of fields that extend arbitrarily below bottom of window` 

- `! <same as before, fields owned by dlg1 which is now a captionless dialog within dlg0` 

A-Shell Reference 

Page 2017 

## **MODELESS DIALOG** 

_Updated August 2015; see History_ 

A "modeless" dialog is like a Modal Dialog Box Control except that it does not command the focus and does suspend the operation of the main program or other dialogs). To create, use MBF_DIALOG+MBF_MODELESS. The ending row and column of a modeless dialog may be beyond the limits of the screen or window. These dialogs are mainly useful for displaying information that is not critical to the main window, allowing the user to push it out of the way if desired. 

Unlike a modal dialog, a modeless dialog can be minimized, in which case it sits just above the Task Bar rather than within it. 

See the sample program DLGMODLES in EXLIB:[908,20] for an example of creating and managing a modeless dialog. 

## **History** 

- 2015 May, A Shell 6.1.1408: AUI refinement: when a modeless dialog is created in an initial minimized or maximized state (see cstate), the min/max buttons MBF2_MINBUTTON and MBF_MAXBUTTON are now automatically added. This is a follow-up revision to 1402.7 which removed the buttons when the corresponding flags were not specified, but it doesn't make sense to create a minimized or maximized dialog without buttons to normalize it. 

A-Shell Reference 

Page 2018 

## **PROGRESS BAR CONTROL** 

_Updated August 2017_ 

A progress bar control is used to graphically indicate progress—or at least the suggestion of some activity—to the user. There are two variations. The standard version (shown below on the left) indicates the percent complete, and requires the application to make successive calls to progressively fill the bar appropriately. An alternate "Marquee" version (shown below on the right), updates itself, suggesting activity to the user without any indication of the percent complete. 

In both cases, the _ctype_ must be set to MBF_PROGRESS, and the coordinates should indicate the desired rectangle. The only parameters of interest are the _ctlid_ (needed to reference the control for updating), _ctype_ (must be set to MBF_PROGRESS), _ctext_ (used to set the percentage or animation frequency), and the coordinates. And in the case of the marquee version, you must set the _winstyle_ parameter to PBS_MARQUEE (&h0008). The parameters relating to colors, fonts, tooltips, and click events are not applicable. Additional details on each of the two versions follows. 

## **Standard Progress Bar** 

Once the progress bar is created, you update the progress bar via repeated AUI_CONTROL calls using _opcode_ = CTLOP_CHG opcode, _cstate_ = MBST_CHANGE, and with the percentage in the _ctext_ field. For example: 

```
map1 percent,b,1
```

```
map1 pbid$,s,24,"prgbar1"
```

```
! create the control
```

```
percent = 0   ! starting at 0%
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, pbid$, str(percent), MBST_ENABLE, MBF_PROGRESS, "", "", "", srow, scol,
erow, ecol
```

```
! update it as we process
```

```
do while not done
```

A-Shell Reference 

Page 2019 

```
    <some processing>
```

```
    percent = <some calculation>
    xcall AUI, AUI_CONTROL, CTLOP_CHG, pbid$, str(percent), MBST_CHANGE
```

```
loop
```

```
! destroy it when done
xcall AUI, AUI_CONTROL, CTLOP_DEL, pbid$
```

## **Marquee Progress Bar** 

The marquee version of the progress bar does not require updating, and instead of the _ctext_ parameter indicating the percent complete, it is used to specify the animation update frequency, in milliseconds. 0 turns off the animation. You can change the animation frequency via a CTLOP_CHG call, but typically you just set it when creating the control. For example: 

```
map1 freq,b,2
```

```
map1 pbid$,s,24,"prgbar2"
```

```
! create the control
```

```
freq = 100     ! update marquee every 100 ms (1/10 sec)
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, pbid$, str(freq), MBST_ENABLE, MBF_PROGRESS, "", "", "", srow, scol, erow,
ecol, NUL_FGC, NUL_BGC, NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$, parentid$, PBS_MARQUEE
<some time-consuming operations here>
```

```
! destroy the control
xcall AUI, AUI_CONTROL, CTLOP_DEL, pbid$
```

**Comments** 

A-Shell Reference 

Page 2020 

As with any control update operation, the _ctlid_ passed to, or returned from, the CTLOP_ADD operation (pbid$ in the above example), must be preserved for the subsequent CTLOP_CHG and CTLOP_DEL operations. 

For the standard progress bar, you can set the initial percentage when creating the control to any value from 0 to 100; starting at 0 would be the most typical. 

There is some overhead in updating the control, especially in the ATE environment, so you don't want to do it excessively.  For example, if processing 100,000 records, it would be much more efficient to update the progress once per 1000 records—i.e., every 1%—than for every record. 

The particular aesthetics and some aspects of the behavior are dependent on the Windows environment, theme, etc. 

In some Windows environments, the bar is updated asynchronously via a background thread which may lag slightly behind the application. This may be more efficient for the PC, but the case of a fast-moving bar, the CTLOP_DEL operation to remove the bar may preempt the final updates, i.e. it may appear to go from 0 to 90% and then terminate without ever showing the final few percent. To eliminate this effect, you can add a small sleep—say, 0.5 seconds—prior to the CTLOP_DEL. 

Often a progress bar is displayed inside of a dialog box which contains a message indicating the nature of the activity, and possibly a CANCEL button. As a convenience, there is a higher-level subroutine, PROGRS.SBX in SOSLIB:[907,21] , which combines the elements text message, progress bar, optional cancel button, within a dialog box. 

## **History** 

- 2012 August, A Shell 1255:  Marquee version implemented. 

A-Shell Reference 

Page 2021 

## **TAB CONTROL** 

A Tab control looks something like a series of file folders, where you can see the "tabs" for all of them (unless they scroll out of view) but can see the contents of only one at a time. Another way to conceptualize a Tab control is as a combination of a Groupbox and a row of buttons ("tabs") along the top. Clicking on one of the buttons or tabs sends a keyboard command notification allowing the program to replace the contents of the current groupbox with new contents, depending on which tab was clicked. 

The coordinates specified are for the outer rectangle, which includes the space occupied by the tabs. The "client area" of the tab control (the usable area bounded by the tabs at the top and the left, right and bottom edges) acts like a groupbox. Controls placed in this area must specify the ID of the tab control in the _parentid_ parameter, and their coordinates are treated as offsets from the upper left corner of this client area. If the number and style of tabs is such that there are multiple rows of tabs, the client area is further reduced by the space taken up the extra row(s) of tabs, so you should allow extra space if this is a possibility. 

As with a groupbox, deleting the tab control deletes all of the controls within it. Perhaps more importantly, using _opcode_ CTLOP_CLR to clear the tab deletes all the controls on the current tab page, a necessary step in switching to a new tab page. 

Variations of the basic tab control can be specified by adding one or more of the following to the _winstyle_ parameter: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|TCS_FLATBUTTONS|&h0008||
|TCS_FORCELABELLEFT|&h0020|Tab labels are left justified within each tab. This only makes sense with<br>the TCS_FIXEDWIDTH style. Otherwise they are centered.|
|TCS_BUTTONS|&h0100|Tabs appear as buttons and no border is drawn around the display area.|
|TCS_MULTILINE|&h0200|If the tabs do not fit on one row, multiple rows are used. Otherwise, a<br>scroll button is placed at the edge of the one row of tabs to allow it to|



A-Shell Reference 

Page 2022 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||be scrolled horizontally.|
|TCS_FIXEDWIDTH|&h0400|All tabs are made the same width; otherwise the width of each tab is<br>based on the text in that tab.|



- Hex Decimal Values 

The tabs are defined by specifying _ctext_ in the following format: 

## **CTEXT=Label1~Cmd1~~Label2~Cmd2~~...LabelN~CmdN** 

In the above specification, Label1 through LabelN represent the text strings displayed in each tab, and Cmd1 through CmdN represent the keyboard command strings each tab sends. As an example: 

```
CTEXT="&Receivables~" + chr(7) + chr(250) + "101." + "~~&Payables~" + chr(7) + chr(250) + "102." + "~~General
&Ledger~" + chr(7) + chr(250) + "103."
```

This would define a set of 3 tabs, "Receivables", "Payables" and "General Ledger" (with corresponding Accelerator keys R, P, and L). Clicking on the "Receivables" tab (or keying ALT+R) would generate exitcode –101 (pseudo function key F101), etc. A program using this arrangement would have to check for these exitcodes (or raw key sequences if your input routine did not provide automatic exitcode conversions), and on receipt, display the appropriate options within the display area of the tab control, according to which tab clicked. 

## **See Also** 

- TabX Control for an extended version of the Tab control. 

## **Subtopics** 

- XTREE/XTEXT Tab Performance 

A-Shell Reference 

Page 2023 

- Tab Control Example 

A-Shell Reference 

Page 2024 

## **XTREE/XTEXT TAB PERFORMANCE** 

This section discusses a performance refinement for Tab controls containing XTREE and XTEXT controls. It is primarily an ATE refinement, but could also apply to local Windows environments where you have large XTREE or XTEXT controls within TABs. 

The idea is to avoid deleting and recreating the XTREE or XTEXT control when switching from one Tab pane to another, by just hiding the XTREE/XTEXT control and later reactivating it rather than recreating it. 

Normally, the procedure for switching between TABs is to use CTLOP_CLR with the TAB's control ID to clear all of the controls on the pane before switching to the new pane and recreating all the controls for that pane. Destroying and recreating controls is usually just as fast as hiding/restoring them. But in the case of very large and complex controls, like XTREE and XTEXT, and especially in the ATE environment (where a lot of data must be sent from the server to the client to create and load the control), it would be more efficient to just make those controls disappear when switching to another pane, and then make them reappear when switching back to the pane containing them. 

To accomplish that, you may now specify the code "!XT" (meant to suggest no XTREE or XTEXT) in the Txt parameter of the CTLOP_CLR call, e.g.: 

```
xcall AUI, AUI_CONTROL, CTLOP_CLR, TABID, "!XT"
```

This causes any XTREE or XTEXT controls on the current Tab pane to be merely hidden instead of deleted. 

Later, when you switch back to the pane containing the XTREE or XTEXT control(s), you just need to use CTLOP_CHG with the MBST_ENABLE and MBST_SHOW cstate flags to redisplay the control, rather than recreating it. 

As a practical matter, to do this robustly, you will need the _ctlid_ of the XTREE and/or XTEXT controls, which you would have from the `XTR.CTLID` and/or `TXC.CTLID` variables of the respecting routines. This assumes you are saving the _xtrctl_ and/or _txtctl_ parameter blocks for each XTREE/XTEXT control separately. If the _ctlid_ parameter is non-zero, that implies that you must have previously created the control, and thus you may be able to just redisplay it with CTLOP_CHG. The returned cstatus value from the CTLOP_CHG operation will be >=0 if it succeeds, else it failed and you will need to recreate the control. For example: 

## `if XTR.CTLID > 0 then` 

```
    xcall AUI, AUI_CONTROL, CTLOP_CHG, XTR.CTLID, NUL_CTEXT$, MBST_ENABLE+MBST_SHOW, NUL_CMD$, NUL_FUNC$,
CSTATUS
```

A-Shell Reference 

Page 2025 

```
else
```

```
    CSTATUS = -1
```

```
endif
```

```
if CSTATUS < 0 then   ! we failed to redisplay the XTREE so recreate it
```

```
    ...
```

```
endif
```

Note: this is a client-side enhancement. (If an app tries to use the feature in an older client that doesn't support it, the CSTATUS parameter will indicate an error and you will be able to recreate the control as before.) 

A-Shell Reference 

Page 2026 

## **TAB CONTROL EXAMPLE** 

See the sample program TABDLG.BP in SOSLIB:[908,22] for a good example of the tab control. Here’s a screen shot of it, showing a Tab control inside of a modal dialog box: 

The colored strip across the top of the dialog is a bitmap file, displayed on the dialog using the AUI "IMAGE" class. 

A-Shell Reference 

Page 2027 

## **TABX CONTROL** 

_Updated October 2020; see History_ 

The TabX control was introduced in A-Shell 6.1.1321 as an alternate version of the standard Tab control, with several extended features, including: 

- Many different styles of tab labels 

- Ability to set the label font style/size 

• Extensive color options (background, • Ability to put the labels on the left, right, text, flyby, active, inactive, etc) for each or bottom, as well as the top tab 

- Options relating to the scroll buttons • Transparency of the area around the 

- position and style labels (cleaner look) • Add and delete tab labels • Enable/Disable tab labels 

- Tooltips for each tab label 

   - Optional close ("x") button 

- Options relating to arrangement of the • Option to have just labels (no panel) 

- labels 

In its basic/default configuration, it supports the same configuration syntax as the standard Tab, except that you must also specify the MBF2_TABX flag in the ctype2 parameter (or the SBR=AUTO_TABX global flag); in this mode it looks and behaves similarly to the standard Tab. To take advantage of some of the extended features, set your ctext parameter according to the following syntax shown below. 

Creating a new TabX control ( _opcode_ CTLOP_ADD): 

A-Shell Reference 

Page 2028 

## **ctext = {@globalattribs~~} {labeldef~~labeldef~~...labeldef~~}** 

Modifying a TabX control ( _opcode_ CTLOP_CHG): 

## **ctext = {@globalattribs~~}{+|-|={labelid}:}{labeldef~~}...{+|-|={labelid}:}{labeldef~~}** 

where: 

_globalattribs_ define attributes for the tab control as a whole 

_labeldefs_ define each individual tab/label 

_labelid_ identifies a tab/label to modify, or the position in which to insert a new one. It may be either the tab label number, starting from 1, or the label text or command field defined in the _labeldef._ It must begin with "+", "-", or "=", and end with ":" 

|**Value**|**Description**|
|---|---|
|**+**_labelid:_|insert a new label at the specified position, or at the end (if no_labelid_)|
|**+:**|(no labelid specified) append a new label at the end|
|**-**_labelid:_|delete the specified label|
|**=**_labelid:_|modify specified label, e.g. enable/disable it|



## **History** 

- 2020 October 2020, A Shell 6.5.1690:  You can now specify any of the label RGB attributes in the global attributes section of the configuration string (passed in the _ctext_ parameter). Any attributes thus specified will be used as the default for any labels that 

A-Shell Reference 

Page 2029 

do not specify their own RGB attributes. This eliminates the redundancy of having to specify the same RGB attributes on every label. 

- 2014 December, A Shell 6.1.1399:  TabX refinement/workaround: If the user somehow manages to click on a tab label in such a way that the event code trigger is bypassed and consequently the application doesn't know to switch panels, resulting in a mismatch between the actual panel displayed and the highlighted label, you can now rectify the situation by just re-clicking on the correct label. This is a rare situation, generally only possible if clicking rapidly on the labels while other control updating operations are occurring within the TABX control. When it did occur, it previously caused more headache because clicking on the correct label typically caused confusion in the application, which thought that the specified panel was already the active one, thus rejecting the click. 

- 2012 November, A Shell 6.1.1321:  TabX control added to A-Shell 

## **Subtopics** 

- globalattribs 

- labeldefs 

- TabX Style Examples 

- TabX Operations / Examples 

A-Shell Reference 

Page 2030 

## **GLOBALATTRIBS** 

## _Changed July 2013_ 

Global attributes are signaled by a leading "@", followed by one or more clauses of the form attrib=value~, and ending with an extra ~ (two in a row). If the first character of ctext is not "@" then it is assumed there are no global attributes and parsing proceeds with the _labeldefs_ . 

|**Attribute**|**Value**|**Description**|**Description**|
|---|---|---|---|
|style|Number|sets the overall style; see descriptions in the following table (not this one)||
|scrollstyle|Number|sets style of scroll buttons, from following table:||
|||"none"|No scroll buttons|
|||0|Windows 3.1 style|
|||1|Windows 95 style|
|||2|Standard style|
|||3|Windows 95 alternate style|
|||4|Theme buttons|
|||5|Theme/scroll|



A-Shell Reference 

Page 2031 

|**Attribute**|**Value**|**Description**|**Description**|
|---|---|---|---|
|||6|Hover|
|||7|Theme/scroll alternate|
|bold|0/1|if 1, current label text is to be displayed in bold||
|xbtnVisibl<br>e|0/1|if 1, an "x" button will be visible, theoretically to close the current tab. When<br>clicked, it sends exitcode -69.||
|xbtnEnabl<br>ed|0/1|Controls whether the "x" button is enabled or disabled||
|xbtnTip|text|tooltip for the "x" button||
|xbtnAlign|near|far|<br>center|controls how close the "x" button is to the last tab label||
|themes|0/1|use visual themes or not.  (using them may disable a number of other<br>features relating to color)||
|sbtn|Number<br>(default = 1)|scroll button options (sum of):+1=scrollable (and visible), +2=conditional<br>visibility (only if needed), +4=buttons displayed at start/left instead of at<br>right/end||



A-Shell Reference 

Page 2032 

|**Attribute**|**Value**|**Description**|
|---|---|---|
|sbtnAlign|near|far|<br>center|same idea as xbtnAlign but for the scroll buttons|
|forcedSize|Number|forced height (if horizontal) or width (if vertical). Units are {milli}rows or<br>columns, unless MBF2_PIXSIZE, in which case units are pixels.|
|ClientArea|0/1|determines if the tab control has a client area (attached panel). See<br>TABSTRIP.BP in SOSLIB:[908,22]<br>for example with ClientArea=0.|
|rows|Number|Number of rows of labels; may require sbtn=0; see Note1 below.|
|rowTabs|Number|Number of tabs per row (if fixed tabs); may require sbtn=0; see Note1 below.|
|fixedTabs|0/1|fixed width tabs. If fixedTabs=0, tab size will be based on the text in each<br>tab; othewise all tabs will be same width. If rowTabs=0, tab width will be<br>determined by actual number of tabs, spread evenly to fill the panel width. To<br>make tab width smaller, set rowTabs larger.|
|multiLine|0/1|if 1, tab labels may have multiple lines using chr(13) for line break.|
|panelBord<br>er|0/1|controls if panel/client area has a border|
|font|facename|_Font=facename{,fontattr}_and_fontAttr=#_provide alternate ways of<br>specifying the same exact set of font attributes. Use which ever form you|



A-Shell Reference 

Page 2033 

|**Attribute**|**Value**|**Description**|**Description**|**Description**|
|---|---|---|---|---|
|fontAttr|{,fontattr}<br>Number|prefer with values from the following table.|||
|||**Symbol**|**Value**|**Description**|
|||FS_UPRIGHT|&h00|Normal upright|
|||FS_ITALIC|&h01|Italic|
|||FS_UNDERLINE|&h02|Underline|
|||FS_STRIKEOUT|&h04|Strikeout|
|fontFace|facename|alternate method of specifying the label text font.|||
|fontScale<br>or scale|<percent>|optional font scale to use for the label text|||
|RGBxxx|r,g,b|All RGBxxx attributes defined forlabeldefs<br>may be used here as well.|||



Note1: Unlike the traditional Tab Control style option TCS_MULTILINE, which results in a variable number of rows of tab labels (as required to display them all), the TabX control requires, if you want multiple rows of labels instead of a single scrolling row, that you explicitly specify the number of label rows ( `rows=#` ). This is actually a sensible limitation, since each additional row of labels 

A-Shell Reference 

Page 2034 

subtracts from the client/display area available to the panels. Without knowing how much space is available in the client/display area, it would be difficult to lay out your child controls. In situations where the number of tab labels is unknown at design time, it is probably best to stick with scrolling labels; see sbtn. 

## **Style** 

The style parameters sets the overall style, using values as shown in the following table. See the TabX Operations / Examples section. Also note the following symbol naming conventions: 

- _ L = Tab labels on left side (instead of default which is top) 

- _R = Tab labels on right side 

- _LR = Tab labels on left and right (requires even number of tab rows) 

- _TB = Tab labels on top and bottom (requires even number of tab rows) 

- _V = Labels rotated (vertical, not compatible with multiLine attribute) 

The source of these values and symbols is the included file TABX.DEF in SOSLIB:[907,16]. 

|**Symbol**|**Value **|**Description**||**Symbol**|**Value **|**Description**|
|---|---|---|---|---|---|---|
|TBXSTY_STD|0|Standard style, labels on<br>top||TBXSTY_SQ_L_V|38||
|TBXSTY_STD_L|1|||TBXSTY_SQ_R|39||
|TBXSTY_STD_L_V|2|||TBXSTY_SQ_R_V|40||
|TBXSTY_STD_R|3|||TBXSTY_SQ_B|41||



A-Shell Reference 

Page 2035 

|hell Reference|||||||
|---|---|---|---|---|---|---|
|TBXSTY_STD_R_V|4|||TBXSTY_SQ_TB|42||
|TBXSTY_STD_B|5|||TBXSTY_SQ_LR_V|43||
|TBXSTY_STD_II|6|Standard style II, labels on<br>top||TBXSTY_SQ2|44|Square style with edge|
|TBXSTY_STD_II_L|7|||TBXSTY_SQ2_L|45||
|TBXSTY_STD_II_L_<br>V|8|||TBXSTY_SQ2_L_V|46||
|TBXSTY_STD_II_R|9|||TBXSTY_SQ2_R|47||
|TBXSTY_STD_II_R_<br>V|10|||TBXSTY_SQ2_R_V|48||
|TBXSTY_STD_II_B|11|||TBXSTY_SQ2_B|49||
|TBXSTY_WIZARD|12|(Invisible)||TBXSTY_SQ2_TB|50||
|TBXSTY_SIMP|13|Simple, top labels||TBXSTY_SQ2_LR_V|51||
|TBXSTY_SIMP_B|14|Simple, bottom labels||TBXSTY_LSQ|52|Another square style|



A-Shell Reference 

Page 2036 

|hell Reference|||||||
|---|---|---|---|---|---|---|
|TBXSTY_MOD_I|21|Modern style I, labels on||TBXSTY_LSQ_L|53||
|TBXSTY_MOD_I_L_V|22|||TBXSTY_LSQ_L_V|54||
|TBXSTY_MOD_I_R_<br>V|23|||TBXSTY_LSQ_R|55||
|TBXSTY_MOD_I_B|24|||TBXSTY_LSQ_R_V|56||
|TBXSTY_MOD_I_L|25|||TBXSTY_LSQ_B|57||
|TBXSTY_MOD_I_R|26|||TBXSTY_LSQ_TB|58||
|TBXSTY_SIMP_II|27|Simple II, top||TBXSTY_LSQ_LR_V|59||
|TBXSTY_SIMP_II_B|28|||TBXSTY_MOD_II|60|Modern style II|
|TBXSTY_SIMP_III_B|29|Simple III, bottom||TBXSTY_MOD_II_L_<br>V|61||
|TBXSTY_STD_TB|30|Standard style, top/bottom<br>labels||TBXSTY_MOD_II_R_<br>V|62||
|TBXSTY_STD_LR|31|||TBXSTY_MOD_II_B|63||



A-Shell Reference 

Page 2037 

|hell Reference|||||||
|---|---|---|---|---|---|---|
|TBXSTY_STD_LR_V|32|||TBXSTY_MOD_II_TB|64||
|TBXSTY_MOD_TB|33|Modern style I, top/bottom<br>labels||TBXSTY_MOD_II_LR<br>_V|65||
|TBXSTY_MOD_LR|34|||TBXSTY_BTNS|66|Buttons style|
|TBXSTY_MOD_LR_V|35|||TBXSTY_BTNS_L|67||
|TBXSTY_SQ|36|Square style||TBXSTY_BTNS_L_V|68||
|TBXSTY_SQ_L|37|||TBXSTY_BTNS_R|69||



A-Shell Reference 

Page 2038 

## **LABELDEFS** 

As with the global attributes, each set of label definitions is made up of one or more _attrib=value_ clauses, separated by a tilde. Two consecutive tildes are used to separate the clauses for one label from those of another label. The **cmd** and **label** clauses are mandatory; the rest are optional: 

|**Option**|**Description**|
|---|---|
|cmd=<cmdstring>|(mandatory) click string to send when label clicked, e.g. VK_xF101|
|label=<text>|(mandatory) text to display in label|
|enabled=0/1|disable/enable the tab|
|RGBbg=r,g,b|background color for the unselected tab labels.|
|RGBbgSel=r,g,b|background color for the currently selected tab label|
|RGBbgClient=r,g,b|background color for the client panel. Also sets RGBbgSel to match, if<br>not already set.|
|RGBbgClientStart=r,g,b~RGBbgClientEnd<br>=r,g,b|alternative to RGBbgClient; creates a gradient background|
|RGBfg=r,g,b|foreground color for the unselected tab label text.|
|RGBfgFlyby=r,g,b|foreground color for the tab label text when the mouse is over it.|



A-Shell Reference 

Page 2039 

|**Option**|**Description**|
|---|---|
|||
|RGBfgSel=r,g,b|foreground color for the text in the currently selected tab label|
|tip=<text>|tooltip text for the label|



A-Shell Reference 

Page 2040 

## **TABX STYLE EXAMPLES** 

Many of the style variations are limited to particular sets of attributes, or are variations of each other (e.g. tab labels on bottom instead of on top, or on right instead of left). Here are some examples of variations with labels on the top and on the left. (The TSTTABX program in [908,22] allows you to cycle though the variations.) 

A-Shell Reference 

Page 2041 

## **TABX OPERATIONS / EXAMPLES** 

See the sample program TSTTABX for a working example of many of the operations discussed in the following sections. 

## **Creating a TabX Control** 

```
map1 tabdefs$,s,0
map1 tabid$,s,24,"tbx1"
```

```
! start with TABX global options
```

```
tabdefs$ = "@style=0~"           ! std modern style
tabdefs$ += "XbtnVisible=1~"     ! "x" (close) button visible
tabdefs$ += "XbtnEnabled=1~"     ! close button is enabled
tabdefs$ += "XbnTip=Close current tab~"  ! tool tip for close btn
tabdefs$ += "themes=0~"          ! themes disabled
tabdefs$ += "~"                  ! end of global options
```

```
! add tabs (each with individual options)
```

```
tabdefs$ += "Label=&One~"
```

```
tabdefs$ += "Cmd=VK_xF101~"
tabdefs$ += "id=One~"
```

```
tabdefs$ += "RGBbgClient=200,180,160~"  ! active panel/lbl (light beige)
tabdefs$ += "RGBbg=140,130,120~"        ! inactive lbl (darker gray/beige)
tabdefs$ += "tip=this is the tab one tip~"
```

A-Shell Reference 

Page 2042 

```
tabdefs$ += "~"                         ! end of tab 1 options
```

```
tabdefs$ += "Label=&Two~"
tabdefs$ += "Cmd=VK_xF102~"
tabdefs$ += "id=Two~"
```

```
tabdefs$ += "tip=this is the tab two tip~"
tabdefs$ += "RGBbgClient=150,200,250~"
tabdefs$ += "RGBbg=140,130,120~"        ! inactive lbl (darker gray/beige)
tabdefs$ += "~"                         ! end of tab 2
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, TABID$, tabdefs$, MBST_ENABLE, MBF_TAB, NUL_CMD$, NUL_FUNC$, NUL_CSTATUS,
tsrow,tscol,terow,tecol, NUL_FGC,NUL_BGC,NUL_FONTATTR,NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$, parentid$,
NUL_WINCLASS$, NUL_WINSTYLE,NUL_WINSTYLEX, MBF2_TABX
```

## **Selecting a Panel** 

When first creating a Tab (or TabX) control, the first tab label will automatically be selected. To select a different label/panel, use the CTLOP_PANE opcode, specifying either the pane/label number in the _cstate_ parameter (and leaving ctext empty), or the pane/label text or click string (as defined by the label or cmd attributes) in the _ctext_ parameter and setting _cstate_ to 0. For example: 

```
tabno = 3            ! select panel #3 (Tab or TabX control)
```

```
xcall AUI, AUI_CONTROL, CTLOP_PANE, ctlid$, "", tabno
```

```
! (the following methods only work with the TabX control)
```

A-Shell Reference 

Page 2043 

```
labelid$ = "&One"       ! select panel with label text "&One"
xcall AUI, AUI_CONTROL, CTLOP_PANE, ctlid$, labelid$, 0
```

```
labelid$ = "VK_xF402"       ! select panel with click str "VK_xF402"
xcall AUI, AUI_CONTROL, CTLOP_PANE, ctlid$, labelid$, 0
```

## **Switching Panels** 

Typically, the user will signal the desire to switch to another panel by clicking on the label, which will transmit the label's click string, which will typically generate an exitcode in the application. To respond (or to switch panels purely according to the whim of the application), you might first want to start by validating or storing the contents of the current panel (if applicable), then proceed by clearing the panel with the CTLOP_CLR opcode, followed by selecting the new panel with the CTLOP_PANE opcode (as described above). In the example below, we use the exitcode returned by clicking on the label to identify the label (assuming that the exitcode was generated by the standard click string syntax of VK_xF###): 

```
switch exitcode
```

```
…
  case -102                           ! user clicked label #2
```

```
<validate current panel contents>
```

```
if <ok to switch to new panel> then
```

```
xcall AUI, AUI_CONTROL, CTLOP_CLR, ctlid$     ! clear current panel contents
labelid$ = "VK_xF"+str(exitcode)
```

```
xcall AUI, AUI_CONTROL, CTLOP_PANE, ctlid$, labelid$, 0
```

```
<display contents of panel>
```

```
else
```

A-Shell Reference 

Page 2044 

```
<display a message saying why switch is not allowed>
```

```
! now we must re-select the current panel
```

```
labelid$ = <id of previous panel>
```

```
xcall AUI, AUI_CONTROL, CTLOP_PANE, ctlid$, labelid$, 0     ! select new panel
```

```
endif
```

```
endif
```

If you don't want to allow the user to switch panels, then you must explicitly use CTLOP_PANE to re-establish the label/panel you were previously on, else the control will display the clicked-on label as if it were the current label. An alternate approach would be to disable the other panels until you wanted to allow the user to switch to them. 

## **Disabling/Enabling a Panel/Label** 

To disable or enable panels, use the CTLOP_CHG opcode and cstate MBST_CHANGEX, identifying the labels to be enabled/disabled using "=labelid:" clauses in the ctext parameter (either by # or by the alphanumeric id), e.g. 

```
ctext$ = "=1:~Enabled=0~~"       ! disable the first panel
```

```
ctext$ += "=Th&ree:Enabled=1~~"  ! and enable the panel "Th&ree"
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid$, ctext$, MBST_CHANGEX
```

## **Adding a Panel/Label** 

To add a new panel to the end, specify the panel's label definition, preceded by "+:", e.g. 

```
ctext$ = "+:label=New~cmd=VK_xF405~~"   ! add new panel "New"
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid$, ctext$, MBST_CHANGEX
```

A-Shell Reference 

Page 2045 

Inserting a panel in another position is the same except that you must specify the panel's labelid (number or label text or click string).  Here we insert the new label in position 2: 

```
ctext$ = "+2:label=New~cmd=VK_xF405~~"   ! insert new panel "New" at position 2
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid$, ctext$, MBST_CHANGEX
```

Here we insert it prior to the panel whose cmd click string is "VK_xF402": 

```
ctext$ = "+VK_xF402:label=New~cmd=VK_xF405~~"
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid$, ctext$, MBST_CHANGEX
```

Note that inserting or deleting a label in the middle causes the pre-existing labels to be renumbered. 

## **Deleting a Panel** 

To delete a panel, specify the panel's label identifier preceded by a "-" and followed by the ":". Note that as with the other operations, the label identifier can be a number (the panel's ordinal position), or the panel's text label string, or its command string. Also note that although we are deleting a panel, we are not deleting the entire control, so we are using the CTLOP_CHG opcode (rather than CTLOP_DEL). For example: 

```
ctext$ = "-2:~~"   ! delete panel #2
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid$, ctext$, MBST_CHANGEX
```

```
ctext$ = "-Th&ree:~~" ! delete panel whose label is "Th&ree"
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid$, ctext$, MBST_CHANGEX
```

A-Shell Reference 

Page 2046 

```
ctext$ = "-VK_xF101:~~" ! delete panel whose command string is "VK_xF101"
```

```
xcall AUI, AUI_CONTROL, CTLOP_CHG, ctlid$, ctext$, MBST_CHANGEX
```

Finally, note that deleting a panel effectively renumbers all of the panels to its right, which is why the panel label text or command text might be generally more useful than the ordinal position for identifying the panel. 

A-Shell Reference 

Page 2047 

## **IMAGE CONTROL** 

A-Shell supports the following five internal methods for displaying images: 

• AUI_IMAGE (e.g. xcall AUI, AUI_IMAGE, or xcall IMAGE) . This method doesn't actually create a "control"; it just displays the image at the specified row/col coordinates, and may be used in both traditional text screens as well as fully GUI windows and dialogs. The main disadvantage of this method is that the images don't act like controls, so they don't integrate as well into GUI screens. 

• Icon Controls, which come in both static and button flavors too, and are essentially just a particular variation of an image type. The term "icon" has both a technical meaning (referring to the ICO file format, which contains multiple versions of the image in different sizes and bit depths) and a more common meaning (referring to a small image of a somewhat standardized size which either acts as a kind of logo to identify a program or represents some kind of action that will occur when you click on it). It is important to note that other types of image formats (besides ICO, e.g. BMP) can serve as icons in the latter sense. In fact, so called "icon libraries" often contain both ICO and other file formats. 

- Images can be displayed inside of XTREE cells. 

- Static controls (MBF_STATIC + MBF_BITMAP), where the _ctext_ parameter specifies the image file, which may be in JPG, BMP, PCX, 

- TIF or PNG format. 

• Button controls (MBF_BUTTON + MBF_BITMAP), where the _ctext_ parameter specifies the image file, same formats as above. Button controls displaying an image are very similar to static controls displaying an image - both support the same range of image types and both can have click events associated with them. The differences are mainly in the way the border of the control looks, and in the way scaling and alignment work. 

Static and Button controls can also specify bitmap resources contained inside DLLs using the syntax: 

## `resname::dllname` 

The first three of the above five categories are already covered elsewhere in this document; so we will focus here on the last two, which we will refer to as the "Static Image Control" and the "Button Image Control". 

## **Subtopics** 

- Static Image Control 

A-Shell Reference 

Page 2048 

- Button Image Control 

- Hover/Context Menus 

A-Shell Reference 

Page 2049 

## **STATIC IMAGE CONTROL** 

Static image controls are created with XCALL AUI_CONTROL, with _ctype_ set to MBF_STATIC + MBF_BITMAP (plus optional flags such as MBF_NODISTORT, MBF_CENTER, MBF_KBD, etc.) For example: 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, NUL_CTLID, imgfile$, MBST_ENABLE, ctype, NUL_CMD$, NUL_FUNC$, NUL_CSTATUS,
srow, scol, erow, ecol, NUL_FGC, NUL_BGC, NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$,
parentid$, NUL_WINCLASS$, winstyle
```

Here are a few examples, using the above code with different values for ctype, winstyle, and the coordinates. In each case, we draw a groupbox just outside the image control so that you can easily see the true size of the control (which doesn't always match the size of the image). 

## **Stretched to fit, no border** 

```
ctype = MBF_STATIC + MBF_BITMAP
```

```
winstyle = 0
```

## **No distortion, thick frame border** 

```
ctype = MBF_STATIC + MBF_BITMAP + MBF_NODISTORT
```

```
winstyle = WS_THICKFRAME    ! &h0004000 (border)
```

The WS_THICKFRAME flag puts a border around the static control, making it look more like a button. (You can make it act like a button, in the sense of giving it a click event, by adding the MBF_KBD flag and specifying a click string in the _cmd_ parameter.) 

When the MBF_NODISTORT flag is used, the image is scaled only as much as it can be without changing the aspect ratio. So if the original static control shape is relatively taller or wider than the image shape, you end up with extra vertical or horizontal space within the control. The question then becomes how to position the image within the space provided, the default being as shown above, in the upper left. You can use the MBF_HCENTER, MBF_VCENTER or MBF_CENTER flags to force horizontal and/or vertical alignment, as in the example below: 

A-Shell Reference 

Page 2050 

```
ctype = MBF_STATIC + MBF_BITMAP + MBF_NODISTORT + MBF_CENTER   ! H+V centering
```

```
winstyle = WS_THICKFRAME    ! &h0004000 (border)
```

By default, after computing the maximum image size and position of the scaled image, the static control is then shrunk to fit. This probably makes no difference unless the border option is used, but to see the effect of not shrinking the control to fit the image, add the SS_CENTERIMAGE flag, as shown below: 

```
ctype = MBF_STATIC + MBF_BITMAP + MBF_NODISTORT + MBF_CENTER
```

```
winstyle =  WS_THICKFRAME + SS_CENTERIMAGE  ! &h0004000 + &h00000200
```

See the program STIMGT in EXLIB:[908,32] for illustrations of many of these static image alignment options. 

A-Shell Reference 

Page 2051 

## **BUTTON IMAGE CONTROL** 

Button image controls are nearly identical to static image controls. To create them, use the same code as you would for static image controls, but replace MBF_STATIC with MBF_BUTTON, and the eliminate WS_THICKFRAME flag and any SS_xxx flags from the _winstyle_ parameter. (Buttons always have borders, which makes them look very similar to the static controls with the WS_THICKFRAME option.) 

Another subtle difference is that buttons are not by default shrunk to fit the non-distorted scaled image, unless one of the MBF_CENTER, MBF_HCENTER, or MBF_VCENTER flags is used. Plus, the default alignment is centered. For example: 

```
ctype = MBF_BUTTON + MBF_BITMAP + MBF_NODISTORT
```

In the above example, the images are centered in the button. The image is not stretched to fit the button because of the MBF_NODISTORT flag, and the button is not subsequently shrunk to fit the image because none of the alignment flags were used. If we add MBF_CENTER to the above, we get the following: 

```
ctype = MBF_BUTTON + MBF_BITMAP + MBF_NODISTORT + MBF_CENTER
```

Note that in the above case, the effect is virtually identical to the corresponding static control. 

See the routine TSTICB in SOSLIB [907,23] for an example of using intermixing icons and other image types on buttons. 

A-Shell Reference 

Page 2052 

## **HOVER/CONTEXT MENUS** 

_Added November 2013_ 

Hover/context menus, associated with image controls and any static text controls, may contain submenus. To indicate the start of a submenu, set the command string for the parent item to "[SUB]". To indicate the end of a submenu, define a dummy menu item whose text is "[ENDSUB]" and whose command field will be ignored. 

For example, to define a two level hover/context menu similar to the following: 

```
Item 1
```

```
Item 2 > Sub-Item 1a
```

```
         Sub-Item 1b
```

```
Item 3
```

```
Item 4 > Sub-Item 2a
```

The definition string in the tooltip parameter should be coded something like: 

```
TOOLTIP$ = ">tooltip string\"                                &
```

```
    + "Item 1,VK_xF101;Item 2,[SUB];"                        &
    + "Sub-Item 1a,VK_xF201;Sub-Item 1b,VK_xF202;[ENDSUB],;" &
    + "Item 3,VK_xF103;Item 4,[SUB];"                        &
    + "Sub-Item 2a,VK_xF301;Sub-Item 2b,VK_xF302;[ENDSUB],;"
```

Sub menus may be nested up to nine levels deep, and a single hover/context menu may contain up to 99 total sub menus. 

## **History** 

A-Shell Reference 

Page 2053 

- 2013 November, A Shell 6.1.1368:  Added ability to contain submenus, and added this section to doc. 

A-Shell Reference 

Page 2054 

## **TOOLBAR CONTROL** 

_Updated November 2013; see History_ 

The toolbar control ( _ctype_ MBF_TOOLBAR) is a standard Windows control which acts as a container for buttons. It is attached to one of the four edges of the parent window. Although created with the standard AUI_CONTROL function, toolbars differ from other controls in the following ways: 

- The coordinates specified when creating a toolbar are ignored; position is determined by the CCS_xxx option set in the _winstyle_ 

- parameter, which selects the edge of the parent window to which the toolbar will be attached. The thickness of the bar is determined by the size of the images, labels, and style. 

- Toolbars do not scale with changes in size to the parent window. Instead, they only stretch to match the length of the window 

- edge to which they are attached. 

- Toolbars do not take up space within the main window grid. Instead, the grid itself adjusts to make room for the toolbar. 

- Toolbars are not removed by the tab(-1,0) command, unless they were created with the MBF_UNPROTECTED flag. They must be 

- removed explicitly by AUI_CONTROL with the CTLOP_DEL opcode. 

- There is a maximum of four toolbars per parent window, one for each edge. 

- Currently, toolbars may only be created in the main window. This restriction may be lifted later. 

You can also create toolbar-like controls or panels using standard buttons or icons, either positioned manually in a row along one edge of the screen, or contained within a floating dialog (i.e. a floating tool panel). 

Several example programs and PNG images are included in the EXLIB:[908,58]. 

## **Examples** 

See A-Shell Screen Elements for an extreme example with all four toolbars in use. Other examples: 

16x16 buttons in top 

toolbar with tooltips: 

A-Shell Reference 

Page 2055 

24x24 buttons in bottom toolbar with labels beneath (TBSTYLE_FLAT): 

24x24 buttons with labels to side (TBSTYLE_LIST), with one disabled button: 

Like the TabX Control, the Toolbar is largely configured via the AUI_CONTROL ctext parameter using the following syntax: 

## **ctext = {@toolbarattribs~~}{opcur}{btndef~~btndef~~...btndef~~}** 

## _opcur_ 

identifies the operation and button when modifying an existing toolbar. If present it must start with a "+" or "=" and end with a ":", according to the following: 

|**opcur**|**Description**|
|---|---|
|_+:_|Append subsequent_btndef_s to the end of the toolbar|
|_-labelid_<br>_:_|Modify the button whose_id_or_cmd_attribute matches the<br>specified l_abelid_.|



A-Shell Reference 

Page 2056 

## _toolbarattribs_ 

defines attributes of the toolbar as a whole, most importantly the image size info. Starts with a @ and ends with ~~, between which you may have any number of <attrib>=<value> pairs separated a single tilde, i.e.: 

```
@<attrib>=<value>~<attrib>=<value>~...<attrib>=<value>~~
```

|**Attrib**|**Value**|**Description**|
|---|---|---|
|ImgSiz|<width>,<height>,<b<br>pp>|width, height (in pixels), bits per pixel. All images for the toolbar will be<br>scaled to the specified size (although the quality will be best if the original<br>images are already of the specified size). For bpp < 32, you must specify the<br>MBF2_GDIPLUS_ctype2_flag when creating the control in order to support<br>some of the more advanced options, like the automatic transparency and<br>ImgDis/ImgHot features.|
|ImgDir|<default directory><br>or<br>standard icon set id|(optional) Default location for images, which avoids need to specify the full<br>directory for each individual image. May be in native format (e.g. ImgDir=c:<br>\images\toolbars) with or without %env% variables, or DevPPN format.<br>Note that A-Shell and ATE will also look in their own default locations if not<br>found here. To use one of the standard icon sets built in to Windows, specify<br>the id # here in place of a directory; see Using Windows Native Icons below.|
|ImgCoun<br>t|# of images to expect|(optional) estimate of the number of images in the toolbar. Simply improves<br>the efficiency of memory allocation operations.|
|ImgDis|<rop>{,<suffix>}|(optional) Rendering OPtion and suffix for disabled version of images. Rop 0<br>is the standard Windows scheme; 1 uses an A-Shell alternate algorithm for<br>generating the disabled/gray version of the image. If the suffix is specified,<br>A-Shell looks for an alternate image file to use for the disabled image. For<br>example, if the img file isclickme.pngand <suffix> is _d, then it will look|



A-Shell Reference 

Page 2057 

|**Attrib**|**Value**|**Description**|
|---|---|---|
|||forclickme_d.png. See following topicDisabled and Hot Images<br>.|
|ImgHot|<rop>{,<suffix>}|(optional) Rendering OPtion and suffix for hot version of images. Same<br>concept as for ImgDis except for the "hot" version of the image (displayed<br>when the mouse is hovering over it). See following topicDisabled and Hot<br>Images<br>.|



## _btndefs_ 

define each individual button. Each _btndef_ clause is made up of a series of <attrib>=<value> pairs, each delimited by a single tilde with the entire clause terminated by a double tilde, i.e.: 

```
<attrib>=<value>~<attrib>=<value>~...<attrib>=<value>~~
```

|**Attrib**|**Value**|**Description**|
|---|---|---|
|img|Image specification<br>or<br>standard icon id|The image to load for the button. If no directory specified, the default<br>directory (see ImgDir in the_toolbarattribs_) is used. Note that only discrete<br>PNG files are properly supported. If using standard built-in icons, specify the<br>icon id number instead of the image file specification; see Using Windows<br>Native Icons below.|
|cmd|command string|May be any of the following:<br>keyboard client string (e.g. VK_xF201, VK_ESCAPE, etc.)|



A-Shell Reference 

Page 2058 

|**Attrib**|**Value**|**Description**||
|---|---|---|---|
|||MENUID:<menu identifier> (seeEdit Menu Control<br>)<br>CMDLIN:<windows command line> (seeHOSTEX)<br>SHLEXC:<url or file object> (seeMX_SHELLEX)||
|lbl|Label text|(optional) If specified, text will display either under the button (for toolbar<br>_winstyle_TBLSTYLE_FLAT) or to the side of the button (_winstyle_<br>TBSTYLE_LIST). Note that in the typical toolbar aesthetic style, label text for<br>the buttons is omitted, relying instead of tooltips to clarify the function of<br>each button. You cannot have both labels and tooltips, so either specify the<br>_lbl_attribute or the_tip_attribute, but not both.||
|tip|Tooltip text|(optional) If specified (and lbl not specified), establishes the tooltip to<br>display when the mouse hovers over the button.||
|id|Button ID|(optional) unique identifier for the button. Mainly used as a way to identify<br>the button later for the purpose of enabling/disabling or otherwise altering<br>it. You may also use the cmd string or the ordinal button position, but this<br>approach probably makes for more readable and robust code.||
|enabled|0,1|(optional) state. Defaults to 1 (enabled)||
|type|SEP|(optional) type of button. Currently the only available type is SEP<br>(separator). Separators require no other attributes, and normal buttons do<br>not require the_type_attribute.||



A-Shell Reference 

Page 2059 

|**Attrib**|**Value**|**Description**|**Description**|**Description**|
|---|---|---|---|---|
|opaque|0,1|(optional) If set to 1, the image background will be displayed as opaque;<br>otherwise it will be transparent. For images with bpp < 32, requires the<br>MBF2_GDIPLUS flag when creating the toolbar. Note that 32 bit PNG images<br>are assumed to be pre-configured with the alpha channel controlling<br>transparency; for other image types, the first pixel determines the<br>background color, which is converted to match the toolbar background.|||
|nd_winstylex_<br>m the_toolbarattribs_in the_ctext_parameter, other global attributes of the toolbar control are set via bits<br>tylex<br> parameters, including:<br>**Winstyle Symbol**<br>**Value**<br>**Description**<br>TBSTYLE_EX_MIXEDBUTTONS<br>&h00000007<br>Mixture of tips and labels<br>TBSTYLE_EX_HIDECLIPPEDBUTTONS<br>&h00000010<br>Hide truncated buttons<br>TBSTYLE_TOOLTIPS<br>&h00000100<br>Display tooltips<br>TBSTYLE_WRAPABLE<br>&h00000200<br>Wrap-able text labels (applies only with horizontal<br>toolbars)<br>TBSTYLE_FLAT<br>&h00000400<br>Standard toolbar style; any button labels appear|||||
|**Winstyle Symbol**|||**Value**|**Description**|
|TBSTYLE_EX_MIXEDBUTTONS|||&h00000007|Mixture of tips and labels|
|TBSTYLE_EX_HIDECLIPPEDBUTTONS|||&h00000010|Hide truncated buttons|
|TBSTYLE_TOOLTIPS|||&h00000100|Display tooltips|
|TBSTYLE_WRAPABLE|||&h00000200|Wrap-able text labels (applies only with horizontal<br>toolbars)|
|TBSTYLE_FLAT|||&h00000400|Standard toolbar style; any button labels appear|



## _winstyle_ and _winstylex_ 

Aside from the _toolbarattribs_ in the _ctext_ parameter, other global attributes of the toolbar control are set via bits in the winstyle _and_ winstylex parameters, including: 

A-Shell Reference 

Page 2060 

|**Winstyle Symbol**|**Winstyle Symbol**|**Winstyle Symbol**|**Value**|**Description**|
|---|---|---|---|---|
|||||beneath the buttons|
|TBSTYLE_LIST|||&h00001000|Alternate style; labels appear to right of buttons|
|CCS_TOP|||&h00000001|Horizontal toolbar along top of window (default)|
|CCS_BOTTOM *|||&h00000003|Horizontal toolbar along bottom of parent window|
|CCS_LEFT *|||&h00000081|Vertical toolbar along left edge of parent window|
|CCS_RIGHT *|||&h00000083|Vertical toolbar along right edge of parent window|
|WS_BORDER*|||&h00800000|Gives toolbar a thin black border|
|**Winstylex**<br>**Symbol**<br>**Value**<br>**Description**<br>WS_EX_CLIENTED<br>GE *<br>&h0000020<br>0<br>gives toolbar a beveled edge|||||
|**Winstylex**<br>**Symbol**|**Value**|**Description**|||
|WS_EX_CLIENTED<br>GE *|&h0000020<br>0|gives toolbar a beveled edge|||



A-Shell Reference 

Page 2061 

* "CCS" stands for "Common Control Style," and "WS" for Window Style. These terms are borrowed directly from the Windows API symbols; the fact that multiple types of style bits could apply to a compound control like a toolbar is not unusual. 

Note that attempting to add a toolbar in a position already occupied by a toolbar automatically deletes the prior toolbar. 

This sample program creates a top toolbar with various types of 16x16x32 buttons It illustrates using CTLOP_CHG mode to disable buttons, and CTLOP_DEL to remove the toolbar. 

```
++include ashinc:ashell.def
```

```
map1 ctext$,s,0
```

```
map1 winstyle,b,4
map1 a,b,1
```

```
! global attributes
```

```
ctext$ = "@"            ! beginning of global options
```

```
ctext$ += "ImgDir=C:\vm\miame\images~"
```

```
ctext$ += "ImgSiz=16,16,32~"
```

```
ctext$ += "ImgCount=5~"
```

```
ctext$ += "ImgDis=1~"   ! alternate rendering of disabled images
ctext$ += "~"           ! end of global options
```

```
! buttons that simulate menu items
```

```
ctext$ += "id=copy~img=copy_16.png~tip=Copy to clipboard~" &
        + "cmd=MENUID:"+IDM_COPY+"~~"
```

A-Shell Reference 

Page 2062 

```
ctext$ += "id=paste~img=paste_16.png~tip=Paste from clipboard~" &
        + "cmd=MENUID:"+IDM_PASTE+"~~"
```

```
ctext$ += "type=SEP~~"
```

```
! buttons that simulate keyboard keys
```

```
ctext$ += "id=up~img=nav_up_16.png~tip=Up one field~" &
        + "cmd=VK_UP~~"
```

```
ctext$ += "id=down~img=nav_down_16.png~tip=Next field~" &
        + "cmd=VK_DOWN~~"
```

```
ctext$ += "type=SEP~~"
```

```
! buttons that generate pseudo-function exitcodes
```

```
ctext$ += "id=bskip~img=nav_left2_16.png~tip=Back 10 recs~" &
        + "cmd=VK_xF501~~"
```

```
ctext$ += "id=fskip~img=nav_right2_16.png~tip=Forward 10 recs~" &
        + "cmd=VK_xF502~~"
```

```
ctext$ += "type=SEP~~"
```

```
! button to launch a windows app
```

```
ctext$ += "id=calc~img=calc_16.png~tip=Calculator~" &
        + "cmd=CMDLIN:calc.exe $~~"  ! note $ so as not to wait for it
```

A-Shell Reference 

Page 2063 

- `! button to launch a URL` 

```
 ctext$ += "id=home~img=house_16.png~tip=MicroSabio Home Page~" &
```

```
         + "cmd=SHLEXC:http://www.microsabio.com~~"
```

```
winstyle = TBSTYLE_FLAT or CCS_TOP
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, "tb1", ctext$, &
```

```
     MBST_ENABLE, MBF_TOOLBAR, NUL_CMD$, NUL_FUNC$, NUL_CSTATUS, &
```

```
     0, 0, 0, 0, NUL_FGC, NUL_BGC, &
     NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$, &
```

```
     NUL_PARENTID, NUL_WINCLASS$, winstyle, NUL_WINSTYLEX, &
     NUL_CTYPE2
```

```
input "Enter to disable '^' and '<<' buttons...",a
```

```
ctext$ = "=up:enabled=0~~=bskip:enabled=0~~"
xcall AUI, AUI_CONTROL, CTLOP_CHG, "tb1", ctext$, MBST_CHANGEX
```

```
input "Enter to delete the toolbar ",a
xcall AUI, AUI_CONTROL, CTLOP_DEL, "tb1"
```

A-Shell Reference 

Page 2064 

It is also possible to create toolbars using one of the sets of button images which are built in to Windows. Each toolbar can contain images from one of these built-in sets, or can contain discrete images loaded from PNG files, but not a mixture. To use one of the built-in image sets, include the file TOOLBARSTD.DEF in SOSLIB:[907,16], set the ImgDir= attribute to the identifier for one of the sets (e.g. IDB_STD_SMALL_COLOR), and each img= attribute to the identifier for one of the buttons within that set (e.g. STD_FILEOPEN). For example: 

```
! toolbarattributes:
```

```
ctext$ =  "@"
```

```
ctext$ += "Imgdir="+IDB_STD_SMALL_COLOR+"~"     ! std small color images
ctext$ += "ImgSiz=16,16,24~~"                   ! 16x16, 24 color
```

```
! buttons
```

```
ctext$ += "id=fnew~img="+STD_FILENEW+"~tip=New file~cmd=VK_xF601~~"
```

```
ctext$ += "id=fopen~img="+STD_FILEOPEN+"~tip=Open files~cmd="VK_xF602~~"
```

- 2013 November, A Shell 6.1.1368: MBF_TOOLBAR enhancement: it is now possible to split the top and bottom toolbars into two separate toolbars so as to left justify one set of buttons and right-justify the other. Within any single toolbar, all of the buttons get justified as a group. To accomplish this, set the _ecol_ parameter to the desired ending column (main window column grid units) for the left toolbar, and _ecol_ to the starting column for the right toolbar. All the other coordinates should remain zero, as they do for the normal toolbar configuration. Note that to avoid a seam in the middle where the two toolbars meet, you may want to set the TBSTYLE_FLAT option in the _dwstyle_ parameter. 

- 2013 August, A Shell 6.1.1359:  ImgDis and ImgHot toolbarattributes added. Bottom toolbar position moved to above bottom status and session lines. 

A-Shell Reference 

Page 2065 

- 2013 July, A Shell 6.1.1358: Background transparency is now automatic for all image formats; previously it only worked with PNG ARGB images. To force the background to remain opaque, you can add the new _btndef_ (button definition) clause: `opaque=1` . For example: `tbdef$ += "img=clickme.bmp~opaque=1~lbl=Click me~" ...` 

- 2013 July, A Shell 6.1.1355: MBF_TOOLBAR added to A-Shell 

A-Shell Reference 

Page 2066 

## **DISABLED AND HOT IMAGES** 

_Added October 2013_ 

Note: These are the release notes that accompanied the introduction of new button attributes to improve rendering of disabled and hot images: 

```
ImgDis=<rop>{,<suffix>}
```

```
ImgHot=<rop>{,<suffix>}
```

The _rop_ parameter (short for Rendering OPtion) determines the algorithm used when automatically rendering the button images in the disabled (gray) or hot (highlighted) states. Set _rop_ to 0, or omit the clause entirely, for the default effect applied by Windows, or set it to 1 for an alternate effect applied by A-Shell. 

The optional suffix clause may be used to specify separate images for the disabled and/or hot version of each button. A-Shell will look for image files matching the base image, with the specified suffix. For example: 

```
Img=clickme.png~ImgDis=0,_d
```

In the above case, the file clickme.png will supply the normal image. A-Shell will look for clickme_d.png for an alternate image 

to use when the button is in the disabled state. If the clickme_d.png file is not present, the disabled version will use the same base image as the enabled version, with the standard Windows disabled/gray effect. 

Note: _rop_ option 1 requires GDIPlus, which is activated automatically for 32 bpp images; see _toolbarattribute_ ImgSiz=w,h,bpp. Otherwise you must explicitly specify the MBF2_GDIPLUS option in the AUI_CONTROL ctype2 parameter when creating the toolbar. 

A-Shell Reference 

Page 2067 

## **OTHER CONTROL TOPICS** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- ATE Optimization 

- Control names 

- Scaling Logic 

- Height of Controls 

- Control Alignment 

- NUL_xxx Parameters 

A-Shell Reference 

Page 2068 

## **ATE OPTIMIZATION** 

In the ATE environment, any operation that requires a return status or other response from the client workstation introduces a small delay. The delay is not significant when doing just a few operations, but it can add up when large numbers of operations are performed in sequence. The simplest way to minimize the problem is to not ask for a returned status (see cstatus) or _ctlid_ when creating controls (assuming that you do not need to use the _ctlid_ later.) But when you do need a return status or control ID, then an alternative way to speed up the communication with the client is to create a batch. See Batch Operations. 

A-Shell Reference 

Page 2069 

## **CONTROL NAMES** 

Controls may be given names, which can then be used instead of the ID numbers to reference them. To assign a name to a control when creating it, specify a string parameter with the desired name in place of the CTLID parameter, i.e.: 

```
CTLNAME$ = "Cus-cbTaxExampt"
```

```
PARENTNAME$ = "dlgCustomer"
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, CTLNAME$, CTEXT$, CSTATE, CTYPE, CMD$, FUNC$, CSTATUS, SROW, SCOL, EROW,
ECOL, FGC, BGC, FONTATTR, FONTSCALE, FONTFACE, TOOLTIP, PARENTNAME$, WINCLASS, WINSTYLE, WINSTYLEX, CTYPE2,
CAUXDATA
```

In the example above, the string variable CTLNAME$ is being used in place of the normal numeric CTLID parameter (which normally returns the ID of the newly created control). Since we are assigning the name "Cus-cbTaxExempt" to the control, we probably don't need to get back the numeric control ID, but in case you do want to save it, it will be in the CSTATUS parameter. (Previously CSTATUS was set to 0 for success; now, if a string name is used in place of the CTLID parameter, CSTATUS will return the ID #.) 

Similarly, the PARENTID parameter may be replaced with a string name in order to reference the parent by its name rather than number. 

Control names should be unique across all controls used within a single program. You may want to adopt a naming standard which includes a prefix for the dialog and perhaps another prefix to identify the control type, as in our example above, where "Cus-cbTaxExempt" is meant to indicate that it is part of the Cus dialog, and it is a checkbox (cb). Names may be up to 23 characters long, plus a trailing null. 

You can retrieve the control ID # associated with a control name, or vice versa, using the CTLOP_INFO opcode. To get the ID # associated with the name, just use CTLOP_INFO with the name in place of the CTLID parameter; the ID # will be returned in CSTATUS (just as when the control was created). For example: 

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CTLNAME$, CTEXT$, CSTATE, CTYPE, CMD$, FUNC$, CSTATUS
```

```
   if CSTATUS > 0 then CTLID = CSTATUS
```

A-Shell Reference 

Page 2070 

To get the name associated with a control ID #, specify a string variable in place of the CTLID parameter, that contains the string representation of the control ID #, e.g.: 

```
CTLNAME$ = str(CTLID)   ! e.g. "7"
```

```
xcall AUI, AUI_CONTROL, CTLOP_INFO, CTLNAME$, CTEXT$, CSTATE, CTYPE, CMD$, FUNC$, CSTATUS
```

In this case, the CTLNAME$ parameter will be updated on return, with the name of the control. 

A new "Name" column has been inserted into the Control Dump, providing a convenient way for you to verify how your control names and numbers are matching up. 

Note that although you may specify a name for the PARENTID parameter, the name is converted to the equivalent number at the time the control is added. So the PARENTID name doesn't show in the control dump. But the CTLOP_INFO command will return the PARENT control name if you specify a string variable in place of the PARENTID parameter. 

Also note that for controls and functions that do not currently support a convenient means of specifying a symbolic name for the control ID or parent ID when creating the control (e.g. XTREE, XTEXT, EVENTWAIT), you have to convert the control names to ID numbers (using CTLOP_INFO if necessary). 

The symbolic names are currently supported in all forms of AUI_CONTROL, AG_CONTROL, MX_AUTOPARENT and AUTO_PARENT. 

A-Shell Reference 

Page 2071 

## **SCALING LOGIC** 

Scaling logic applies to dialogs immediately, and the ALTPOS grid basis has changed slightly. Unfortunately this will likely have a minor effect on the width of existing dialogs using ALTPOS, but the new formula is slightly more natural, and virtually eliminates the need for the strange 160 default width scale in the Dialog Sizing dialog. Consequently, existing dialog sizing scale factors will be reset to 100 for existing .ash files. (Once you re-save any settings, your saved settings will be preserved.) 

For dialogs using the ALTPOS grid, the grid basis continues to be the size of a character in the default GUI font. The actual grid row height is equal to the height of a combo box plus the external leading, and the grid column width is about half way between the "average" and maximum character width for the default GUI font. Unlike before, the default GUI font is scaled according to the scale factor in the Misc. Settings dialog. Since scaling that font also affects the height of combo boxes and the average character width, the entire grid scales along with the font scale factor. 

For example, with the font scale factor set to 0 or 100, the dialog grid will be based on the default size of the default GUI font. (This is the font you see in menu bars and in most standard Windows dialogs.) If you change that to, say, 90, then the dialog and everything in it should get about 10% smaller. (Scaling isn't entirely linear or orthogonal, but that's approximately the idea.) 

Related to this, the Dialog Sizing dialog offers a new option of whether to include the dialog caption in the dialog height when forcing dialogs to use the grid based on Font Size (i.e. ALTPOS units). Normally, dialogs using the font-size or ALTPOS grid are sized so that they have the expected number of rows not counting the caption bar. For example, if SROW = 1 and EROW = 10, then there will be room for 10 logical rows inside the dialog. This is quite convenient and logical, but conflicts with the way nonALTPOS (main-window based) dialogs are sized, since they include the caption in the height. So in our example of SROW=1 and EROW=10, the outer height of the dialog would be equivalent to 10 rows in the main window, but since that includes the caption, you will probably end up with something closer to 9 rows. 

This causes a problem when trying to convert dialogs to the ALTPOS grid, because you almost always end up with the equivalent of one extra row in the dialog. The new option in the Dialog Sizing dialog to include the caption in the dialog height should help you counteract that. Note however, that it only has an effect on dialogs that weren't explicitly coded to use MBF_ALTPOS. (The theory is that if you coded the dialog to use the ALTPOS grid, then you were counting on the number of rows. But if you coded it to use the main window grid, and then we force it to use the ALTPOS grid via the option on the Dialog Sizing dialog, then you probably don't want the extra row. 

Another side effect of the new scaling logic is that you can indirectly resize an active dialog by resizing the main window behind it. 

A-Shell Reference 

Page 2072 

## **HEIGHT OF CONTROLS** 

_Updated May 2018_ 

When row coordinates are converted to pixels, the height of the visible control is often shortened slightly—i.e. the bottom coordinate shifted up—to allow for some space between rows, i.e. external leading. This topic describes the rules for this adjustment in more detail. 

When the _erow_ coordinate is expressed using regular rows, not millirows or pixels, then the control height will not include the external leading; i.e. it will be shortened by the number of pixels in the External Font Leading value. The one exception to this rule is for Edit Controls (INFLD) when the Allow Edit Boxes to Use Leading Space option is checked. 

Conversely, when the _erow_ coordinate is expressed in millirows or in pixels, then the height of the control will be as specified without adjustment, i.e. the height will include the external leading. 

This sounds confusing but makes sense, based on the following reasoning: 

• When using regular row units, it is common to put controls in adjacent rows, particularly when converting from a text-based layout. In order for these to not appear too crowded, especially for buttons and other controls that have their own borders, it seems logical to preserve the same external leading area that would appear between text rows. 

• But, when using millirows, the idea is that row N occupies millirows N*1000 to (N+1)*1000-1—e.g., row five spans millirow 5000 to 5999.) Thus, if you actually asked for a control to occupy millirows 5000 to 5999, you would expect it to be right up to the edge of another control that started in millirow 6000. It would seem too confusing if the system automatically converted your request for a control spanning millirows 5000-5999 into one spanning millirows 5000-5850 in order to preserve the leading area. The same goes for coordinates specified in pixels. 

A-Shell Reference 

Page 2073 

## **CONTROL ALIGNMENT** 

The sample program ALIGN.BP in EXLIB:[908,24] illustrates the use of the various alignment options for text within static and button controls. 

The tooltip for each control shows details about the _ctype_ and _winstyle_ flags, and of course the source code reveals all, but here are the relevant flags from ctype: 

|**Flag**|**Description**|
|---|---|
|MBF_LFJUST|Left justify text|
|MBF_RTJUST|Right justify text|
|MBF_HCENTER|Horizontally center text|
|MBF_VCENTER|Vertically center text|
|MBF_CENTER|Vertically and horizontally center text|



BS_TOP, BS_BOTTOM, BS_VCENTER can be added to the WINSTYLE parameter for buttons to adjust the vertical alignment of the text within the button. The horizontal alignment can be adjusted by the traditional MBF_RTJUST and MBF_LFJUST flags. Note: default alignment for buttons is centered in both directions. 

SS_CENTERIMAGE can be added to the WINSTYLE parameter for static images (scaled with MBF_NODISTORT and without any other MBF_xxx alignment options) to center them within the static control, without changing the size of the control. See the sample program STIMGT.BP in EXLIB:[908,32]. 

A-Shell Reference 

Page 2074 

See Image Control for an example of using these same flags for aligning images within Static Text controls, and see the cstate MBST_?CENTER flags for options relating to centering the control itself (relative to its parent). 

A-Shell Reference 

Page 2075 

## **NUL_XXX PARAMETERS** 

## _Written December 2023_ 

The AUI_CONTROL operation has many parameters, many of which are effectively optional but still need to be specified as placeholders (unless using Named Parameters in Subroutines syntax). As an aid to self-documenting code and to keeping the parameters in order, the following symbols are defined for specifying "don't care" parameters. 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|NUL_CTLID|0|Use when you don't need to refer to the control again by its id.|
|NUL_CTEXT$|""||
|NUL_CSTATE|0|Enabled, visible (i.e., normal).|
|NUL_CTYPE, NUL_CTYPE2|0|Mainly used for operations that do not affect the control type.|
|NUL_CMD$|""|For controls with no command string and/or function strings.|
||||
|NUL_CSTATUS|""|_cstatus_parameter normally numeric; this form disables any return status, which makes it<br>much faster in ATE environment.|
|NUL_SROW, NUL_SCOL,<br>NUL_EROW, NUL_ECOL|0|Use when coordinates are not being affected by the operation.|



A-Shell Reference 

Page 2076 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|NUL_FCG, NUL_BGC|-2|Default colors. Default foreground is based on the Windows theme text color, usually<br>black. Default background is transparent for text controls, else based on the Windows<br>theme for dialogs and other controls with solid backgrounds.|
|NUL_FONTATTR|0|Standard text attributes; upright, don't care which symbol set.|
|NUL_FONTSCALE|0|Standard/default font scale; equivalent to the Windows dialog font scale).|
|NUL_FONTFACE$|""|Standard/default Windows font face; probably Arial or something similar.|
|NUL_TOOLTIP$|""|No tooltip.|
|NUL_PARENTID|0|Default parent is either the current modal dialog, if there is one, else the main A-Shell<br>window.|
|NUL_WINCLASS$|""|Let window class be determined by_ctype, ctype2_. The only reason for using anything<br>else here is when creating special control types known to Windows but not A-Shell.|
|NUL_WINSTYLE,<br>NUL_WINSTYLEX|0|Standard/default control style flags.|
|**Definition file: ashell.def**|||



A-Shell Reference 

Page 2077 

For example, to create a reasonably standard button control that you didn't need to reference by ID and had no other special attributes, you could code it with just these parameters: 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, NUL_CTLID, "Click Me", NUL_CSTATE, MBF_BUTTON+MBF_KBD, "VK_xF101"
```

But if you want to add a tooltip, then you would need to specify several placeholder parameters; using the symbol names instead of literal values will make the code easier to read: 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, NUL_CTLID, "Click Me", NUL_CSTATE, MBF_BUTTON+MBF_KBD, "VK_xF101",
NUL_FUNC$, NUL_CSTATUS, 20, 50, 21, 60, NUL_FCG, NUL_BGC, NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, "Don't
bet on the horses"
```

Another approach, which eliminates the need for placeholder parameters, would be to use named parameter syntax (based on the DEFXCALL definitions in xcall.def), e.g.: 

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, NUL_CTLID, "Click Me", cmd="VK_xF101", ctype=MBF_BUTTON+MBF_KBD, srow=20,
scol=50, erow=21, ecol=60, tooltip="This is a tip"
```

## **Also See** 

- Named Parameters in Subroutines 

A-Shell Reference 

Page 2078 

## **AUI_EVENTWAIT** 

## **xcall AUI, AUI_EVENTWAIT, parentid, ctlid, exitcode {,opflags, timer}** 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|parentid|Num<br>or<br>String|in|Specifies a parent control to which the button controls of interest are children to. Leave<br>zero if not applicable.|
|ctlid|Num<br>or<br>String|in/<br>out|ID of the control which should start with the focus. If zero, the first control within the<br>group specified by_parentid_will start with the focus.|
|exitcode|Num|in/<br>out|(Signed Num)  Returns a code indicating the event received.|
|opflags|B,4|in|Flags affecting operation.|
|timer|Num|in|Optional numeric argument which can be set to the number of milliseconds to wait for an<br>event before the eventwait times out with exitcode 11.|



The AUI_EVENTWAIT class is really less of an independent "class" than a method relating to the CONTROL class, but is separated out for parameter organization convenience. Its purpose is simply to wait for an event, allowing the user to shift the focus 

A-Shell Reference 

Page 2079 

among a range of buttons (plus some other control types) until something is clicked which triggers an event. It could be implemented using an invisible INFLD call in a loop, but this is much simpler to program. 

The basic concept is analogous to the dialog manager in Windows or forms manager in VB, which allows the user to move around the form or dialog until some event is triggered that requires the dialog or forms manager to exit (temporarily or permanently) back to the application. In Windows/VB this is done by calling special event handler routines in the application. In A-Shell, this is done by returning from the routine with an exitcode and control ID and leaving it to the application to perform whatever action it deems suitable, after which the application can return to the eventwait (or not). 

Aside from simplifying the coding of event-driven programs, AUI_EVENTWAIT can often be useful for converting legacy programs which prompt the user to enter a field number to edit, or to choose among a handful of commands that might otherwise be represented as buttons. In the legacy case, the program would be waiting for only one kind of event (the entry of a field number or menu command.) With AUI_EVENTWAIT, the program logic is nearly the same, except that instead of keying in a command, the user can select a field to edit or operation to perform by either clicking on something that generates an exitcode, or by using the ARROWS and TAB and SHIFT+TAB keys to move the focus around a collection of buttons or other controls and hitting ENTER to generate the equivalent of a click. 

There are several options relating to managing which control gets the focus to start with, which controls can get the focus, and what kinds of events generate exitcodes. 

Although AUI_EVENTWAIT will exit on any click event that generates an INFLD-style exitcode, it only allows the focus to be moved (via ARROWS and TAB and SHIFT+TAB) to a limited subset of controls that can take the MBF_TABSTOP style. Standard pushbuttons automatically get this style, while it can be manually added to checkboxes and radio buttons when they are created. In the case of INFLD controls, there is no way to specify the MBF_TABSTOP style when creating them, but you can pass the EVW_INFLD flag to AUI_EVENTWAIT to temporarily confer that style on all INFLD controls in the scope. 

Note that this function was originally designated as MX_EVENTWAIT and MX_BTNIDLE. 

## **Comments** 

When converting from a traditional procedural program to an event-driven one, you will probably encounter situations where used to have an input prompt to wait for the user to select among many choices or confirm/cancel an operation. In the GUI model, such an input prompt may seem silly, since the layout of the screen (buttons, other things to click on) makes it obvious what the user needs to do without being prompted to type something. This EVENTWAIT class is perfect for such situations. Examples include: 

A-Shell Reference 

Page 2080 

- Menus, where in the text version you might have a prompt like "Enter Selection:" but now you have buttons. 

- At the bottom of an input form, where in the text version you might have had an "Any Change?" prompt, but now you have 

- buttons such as "OK" and "Cancel", with the implicit understanding that the user can just click on a field to edit it. 

- Dialogs, especially those containing checkboxes and radio buttons (which do not require any special procedural coding and 

- can instead just be queried upon exiting the dialog). 

Although you do not need to specify a parent group, this concept is generally much clearer if you do group the relevant buttons within a parent. The best way to do this is with a Groupbox Control. Note that the group box need not take up any extra space or even be visible. (You can set its initial state to MBST_HIDE and its size to one row high, and place the buttons right on top of it.) 

The BTNMNU.SBX routine encapsulates this logic in a wrapper making it easy to create and use (i.e. wait on) groups of buttons. 

The sample program TSTEVW in EXLIB:[908,20] provides detailed examples of using EVENTWAIT, both via BTNMNU and via AUI. 

EVENTWAIT only allows the focus to be moved amongst controls that have the MBF_TABSTOP property. This property is automatic for regular buttons, and may be applied manually to check boxes and radio buttons. No other control type currently supports the MBF_TABSTOP property, although the EVW_INFLD flag will cause EVENTWAIT to act as if all INFLD controls had the MBF_TABSTOP property. 

## **See Also** 

- AG_EVENTWAIT 

## **History** 

2011 February, A-Shell 5.1.1205: Support alphanumeric as well as numeric control IDs for _parentid_ and _ctlid_ . 

A-Shell Reference 

Page 2081 

## **PARENTID** 

The parentid parameter determines the scope of the controls to which the focus can be moved using the TAB and ARROW keys, while waiting for an event. Note that unless the flags EVW_DESCEND and/or EVW_SIBLINGS are set, the focus will be limited to direct children of the specified group or dialog. To clarify this, consider the dialog below: 

This dialog is made up of at least 3 groups. (The two buttons at the bottom may be direct children of the dialog, or they may be in their own invisible group, which is common but hard to detect visually.) If we set the parentid to the ID of the dialog, and do not set the EVW_DESCEND flag, then the user would not be able to move the focus to the radio buttons and edit boxes within the groups, because those are all grandchildren (rather than direct children) of the dialog. If the two icon buttons at the bottom were direct children of the dialog (not part of their own invisible group) then the focus would be limited to those two buttons. (That is, the TAB and ARROW keys would not permit the focus to be moved into any of the groupboxes.) The user, could, however, use the mouse to click on anything that generates an exitcode. 

Similarly, if the parentid was set to the ID of the group "Destinos", then, the user could ARROW or TAB around within that groupbox but not go directly to another groupbox without first existing from the event wait operation (unless the EVW_SIBLINGS flag was set.). 

## **History** 

- 2011 February, A Shell 5.1.1205: You can now pass alphanumeric IDs for the _parentid_ and _ctlid_ parameters. This eliminates one of the most common excuses for needing a numeric control ID. Note, however, that the updated _ctlid_ parameter will be returned as a number (although formatted as a string if you pass a string parameter). This shouldn't make any difference to your application as a string-formatted numeric control ID may be used anywhere an alphanumeric control ID may be used. 

A-Shell Reference 

Page 2082 

## **CTLID** 

The ctlid parameter is often set to zero, which causes EVENTWAIT to initially put the focus on the first control within the specified parentid. On exit, it will be automatically set to the ID of the control that last had the focus (or was just clicked on). Setting the ctlid to a specific control ID will cause the focus to start there. 

If the specified ctlid does not exist, EVENTWAIT returns exitcode 99. Also note that if ctlid does exist, but is not in the group you specified by parentid, then the results might be unpredictable. 

## **History** 

- 2011 February, A Shell 5.1.1205: You can now pass alphanumeric IDs for the _parentid_ and _ctlid_ parameters. This eliminates one of the most common excuses for needing a numeric control ID. Note, however, that the updated _ctlid_ parameter will be returned as a number (although formatted as a string if you pass a string parameter). This shouldn't make any difference to your application as a string-formatted numeric control ID may be used anywhere an alphanumeric control ID may be used. 

A-Shell Reference 

Page 2083 

## **EXITCODE** 

Exitcode returns a code indicating the event received. Typically this would be the exitcode associated with a mouse click on an object, or a particular keystroke or timer event. The actual values are generally consistent with INFLD, or XTREE, or both, to facilitate a single exitcode-handling routine that covers all three. 

To avoid confusion between control-identifying exitcodes (i.e. those generated via the click string associated with a control) and navigational exitcodes (such as those in the following table), you should avoid assigning control-identifying exitcodes in the range of -100 to 100. See the cmd parameter of AUI_CONTROL, the hlpidx parameter of INFLD, and the XTR.KBDSTR (xtrctl) parameter of XTREE for information on how control-identifying exitcodes are defined. 

Note that buttons with exitcode values -1 thru -32 may be used with EVW_EXCDINOUT. This allows buttons that emulate the standard function keys to be used with EVW_EXCDINOUT. 

|**Exit**<br>**Code**|**Flag(s)**|**Description**|
|---|---|---|
|0|EVW_NUMERIC|number + enter|
|0|EVW_RAW|any keystroke|
|1||Escape|
|2|EVW_HAREXIT|LeftArrow|
|3|EVW_NOWRAP|Attempt to navigate up/back from end of group (instead of wrap)|
|3|EVW_VAREXIT|UpArrow|



A-Shell Reference 

Page 2084 

|**Exit**<br>**Code**|**Flag(s)**|**Description**|
|---|---|---|
|4||PrevPage|
|5|EVW_NOWRAP|Attempt to navigate down/forward from end of group|
|5|EVW_VAREXIT|DownArrow|
|6||NextPage|
|7|EVW_TABEXIT|Tab|
|10||Ctrl C|
|11||Time out|
|12|EVW_HAREXIT|Right Exit|
|99||Invalid combination of parameter values (no matching control)|
|-35|EVW_TABEXIT|Shift Tab|
|-36|EVW_HAREXIT|Shift Left Arrow|



A-Shell Reference 

Page 2085 

|**Exit**<br>**Code**|**Flag(s)**|**Description**|
|---|---|---|
|-37|EVW_VAREXIT|Shift UpArrow|
|-38|EVW_HAREXIT|Shift Right Arrow|
|-39|EVW_VAREXIT|Shift Down Arrow|
|-45||Home|
|-46||End|
|-47||Del|
|-52|EVW_CTLARRO<br>W,<br>EVW_HAREXIT|Ctrl+Left Arrow|
|-53|EVW_CTLARRO<br>W,<br>EVW_VAREXIT|Ctrl+UpArrow|
|-54|EVW_CTLARRO<br>W,<br>EVW_HAREXIT|Ctrl+Right Arrow|



A-Shell Reference 

Page 2086 

|**Exit**<br>**Code**|**Flag(s)**|**Description**|
|---|---|---|
|-55|EVW_CTLARRO<br>W,<br>EVW_VAREXIT|Ctrl+Down Arrow|
|-56|EVW_CTLCLIPBD|Ctrl+C|
|-57|EVW_CTLCLIPBD|Ctrl+V|
|-58|EVW_CTLCLIPBD|Ctrl+X|
|-60|EVW_CTLCLIPBD|Ctrl+Z|
|-61|EVW_CTLARRO<br>W|Ctrl+-(numpad minus)|
|-62|EVW_CTLARRO<br>W|Ctrl+Plus (numeric keyboard)|
|-65||Shift+Tab|
|-66||Ctrl+Page-Down|



A-Shell Reference 

Page 2087 

|**Exit**<br>**Code**|**Flag(s)**|**Description**|
|---|---|---|
|-67||Ctrl+Page-Up|
|-68||Ctrl+Home|
|-75||File(s) dragged-and-dropped on to a control with the<br>WS_EX_ACCEPTFILES attribute. SeeMX_DRAGDROP<br>.|
|<= -100|EVW_EXCDINOU<br>T|No event, incoming exitcode passed through|
|-1 thru<br>-16||F1 thru F16|
|#||Right click on control with VK_xrF# clickstring|
|-#||Left click on control with VK_xF# clickstring|



A-Shell Reference 

Page 2088 

## **OPFLAGS** 

_Updated September 2018; see History_ 

## opflags specifies any sensible combination of the symbols below (symbols defined in ashell.def): 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|EVW_NEXT|&h00000001|Set initial focus on control following the one specified by ctlid. Generally not used,<br>particularly if_ctlid_= 0, since the focus will automatically be placed on the first<br>control within the specified parent group.|
|EVW_NOWAIT|&h00000002|Set the focus and return (do not wait for an event). This is a bit of an oxymoron,<br>since it directly contradicts the idea of waiting for an event, and thus is only useful<br>in very limited circumstances, where you just want to put the focus on a control<br>while doing some time consuming calculations.|
|EVW_NOWRAP|&h00000004|Exit from the wait operation with EXITCODE 3 or 5 rather than wrap.|
|EVW_NOFOCUS|&h00000008|This is another exotic switch, which eliminates the initial step of setting the focus<br>on an appropriate control when starting the eventwait. Probably the only situation<br>where it would be useful is if, due to the context of the program, the application<br>knew that it wanted to start with the focus where it currently was, without knowing<br>where that was..|
|EVW_NUMERIC|&h00000010|Allow keyboard input.|
|EVW_DESCEND|&h00000020|Expand scope to include grandchildren, great-grandchildren, etc.|



A-Shell Reference 

Page 2089 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|EVW_SIBLINGS|&h00000040|Expand scope to include siblings of parentid.|
|EVW_INFLD<br>(or)<br>EVW_EDIT|&h00000080|Allow navigation keys to move the focus to editable fields, such as EDIT, COMBO,<br>DATE/TIME andXTREEcontrols. Otherwise EVENTWAIT ignores controls except for<br>buttons and controls with the MBF_TABSTOP flag explicitly set. (Standard push<br>buttons get this flag automatically.) Note that unlike the case with buttons, when<br>EVENTWAIT puts the focus on an editable field, it actually returns to the application<br>with the same exitcode as if the field had been clicked (allowing the application to<br>take over the editing operation.)|
|EVW_PREV|&h00000100|This is the inverse of the EVW_NEXT option, and was provided mainly to satisfy<br>some arcane notion of symmetry.|
|EVW_SQUELCH|&h00000200|Squelch radio button exits on focus change.|
|EVW_TABEXIT|&h00000400|This option overrides the normal behavior of the Tab and Shift+Tab, so that instead<br>of advancing the focus, they simply exit, with exitcode 7 and -35, respectively.|
|EVW_ACCEL|&h00000800|Allow "accelerator" keys.|
|EVW_RAW|&h00001000|Raw keyboard input.|
|EVW_HAREXIT|&h00002000|Exit on horizontalARROWS. Exitcodes: Left=2, ShiftLeft=-36, Right=12,<br>ShiftRight=-38|



A-Shell Reference 

Page 2090 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|EVW_VAREXIT|&h00004000|Exit on verticalARROWS. Exit codes: Up=3, ShiftUp = -37; Down = 5; ShiftDown =<br>-39|
|EVW_EXCDFOCUS|&h00010000|Incoming exitcode overrides CTLID.|
|EVW_EXCDINOUT|&h00040000|Like EVW_EXCDFOCUS; see detailed description.|
|EVW_CTLARROWS|&h00080000|May be added to EVW_VAREXIT or VAR_HAREXIT to causeCTRL+ARROWto return a<br>unique exitcode (offset by -16 from theSHIFT+ARROWexitcodes). Without this<br>qualifier,CTRL+ARROWreturns the same exitcode values as the arrow keys by<br>themselves. EVW_CTLARROWS also causesCTRL+PLUSandCTRL+MINUS-(i.e.CTRL<br>in conjunction with thePLUSandMINUSkeys on the numeric keypad) to return<br>EXITCODEs -62 and -61, respectively.|
|EVW_CTLCLIPBD|&h00100000|Causes the normal Windows clipboard shortcuts to be returned as exitcodes:<br>^C=-56, ^V=-57, ^X=-58. Also causes ^Z to return EXITCODE -60.|
|EVW_NODELAY|&h00200000|Removes the timer filter that normal restricts click events for a single control to one<br>per 1/2 second. This is normally useful for preventing (click bounce), but in some<br>cases (like a scroll button), you may want to allow more rapid click response by<br>specifying this flag.|
|EVW_ENTER|&h00400000|Causes the ENTER key to return exitcode=33, instead of acting like a click on the<br>currently focused control. This might be useful to implement a default action that<br>was independent of the currently-focused button. Note that you can identify the<br>currently-focused button from the returned ctlid parameter.|



A-Shell Reference 

Page 2091 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|EVW_ULFOCUS|&h00800000|Clickable static text controls are highlighted to indicate when they have the focus.<br>The default highlight effect is a dotted line around the perimeter of the control. As<br>an alternative, you can specify this flag(EVW_ULFOCUS), which changes the highlight<br>effect to the combination of bold+underline. Note: PNG and GDIPLUS images are<br>excluded from this treatment on the theory that they are amenable to a more<br>sophisticated highlighting approach.|
|EVW_BGFOCUS|&h01000000|Provides an alternative way to highlight static text controls that have the eventwait<br>focus. Instead of underlining the text, as with EVW_ULFOCUS, it makes the<br>background color slightly lighter. This probably only makes sense with static<br>'buttons' that have colored backgrounds. Note that if the control is too light, it will<br>be darkened instead.|



- Hex Decimal Values 

## **History** 

- 2018 September, A Shell 6.5.1647:  Added EVW_BGFOCUS flag 

- 2013 November, A Shell 6.1.1368:  Added EVW_ULFOCUS flag 

A-Shell Reference 

Page 2092 

## **EVW_NOWRAP** 

This option controls what happens when keyboard navigation commands (ARROWS, TAB, SHIFT+TAB) are used to move the focus around within a group of controls and you hit the "edge". If the flag is not set, then the focus will "wrap" around to the first control in the group. Otherwise, the eventwait operation will exit, setting EXITCODE 3 (up, left) or 5 (down, right) depending on which direction the group was exited. (The _ctlid_ parameter will also be set to identify the last focused control, so the distinction between _exitcode_ 3 and 5 may not be that important.) 

As an example, consider the Tab Control Example dialog above, which features a groupbox containing three buttons. In the default case, without EVW_NOWRAP, hitting the LEFT/RIGHT ARROWS, or TAB/SHIFT+TAB keys, will just move the focus around in a circle between the buttons. The user will have to click on one, or hit ENTER to exit from the eventwait. If the user wanted to edit one of the fields in the tab pane, they could click the "Edit" button. As an alternative, you could use the EVW_NOWRAP flag, in which case, merely using the arrow keys would trigger an exit from the eventwait, allowing the program to refocus on one of the edit fields. (See EVW_SIBLINGS and EVW_DESCEND flags for other approaches to allowing the user to navigate around the dialog.) 

A-Shell Reference 

Page 2093 

## **EVW_NUMERIC** 

This switch allows you to also accept "events" consisting of a string of numeric digits followed by <ENTER> .  This is particularly useful when migrating from text-mode (or power-user) environments where users are accustomed to selecting fields or menu options by keying in the corresponding number and hitting <ENTER>.  When you start adding clickable controls to such screens, you may want to replace the "Enter Field #"  prompt with an EVENTWAIT operation, allowing the user the choice of  either clicking on a control (possibly generating an exitcode or a keyboard string simulating what the user could have typed to make that selection), or just typing the desired option # and hitting ENTER. 

Note that these numeric keyboard "events" are returned to the calling program with _exitcode_ set to 0, and _ctlid_ set to the numeric value entered.  Since the returned _ctlid_ may not have anything to do with a valid control ID, take care not to pass the value back as input to a subsequent EVENTWAIT operation (or else it will probably abort with _exitcode_ 99, meaning invalid control ID.)  In other words, after interpreting the returned _ctlid_ , set it back to either 0 or to the ID or a valid control on which you want to place focus for the next EVENTWAIT. 

See EVW_RAW for a similar option. 

A-Shell Reference 

Page 2094 

## **EVW_DESCEND** 

This flag allows the focus to be moved (via the keyboard ARROWS and TAB/SHIFT+TAB) into child subgroups of the _parentid_ . Otherwise keyboard navigation is limited to the immediate group. For example, in the sample dialog above (see parentid) there are three or four separate groups in the dialog. If you start an eventwait with parentid set to one of them but the EVW_DESCEND flag not set, the user will be able to navigate around the controls in that group, but not leave the group (except by clicking or some other event that triggers an exitcode). This might be useful if you wanted to do some validation logic on the group as a whole before moving to another group. On the other hand, if you wanted to allow the user to navigate around all of the groups without requiring program intervention, then you could set the parentid to the ID of the dialog itself and set the EVW_DESCEND flag. 

A-Shell Reference 

Page 2095 

## **EVW_SIBLINGS** 

This flag is similar in concept to the EVW_DESCEND, except that it extends the scope of controls which can be navigated to via keyboard navigation commands to groups and controls that have a sibling relationship to the _parentid_ . The effect is essentially the same as if instead of setting _parentid_ to a particular group, you set it to the parent of that group (or the dialog ID), and set the EVW_DESCEND flag. 

A-Shell Reference 

Page 2096 

## **EVW_SQUELCH** 

This oddly named feature, like its namesake in the world of radios, turns down "the noise" when navigating among a collection of radio buttons. With buttons and checkboxes, the focus can be moved from one control to the next without actually changing the selection. But with radio buttons, the act of changing the focus with the ARROWS also changes the selection, and thus is essentially the same as clicking on a button. If each button has an exitcode associated with it, then each time you hit the ARROW key to move to the next radio button, the eventwait will exit. This might be appropriate when, depending on which radio button is selected, you might need to enable/disable some other controls in the dialog. For example in the output dialog above (see parentid), if you select the printer option, then you would want to enable the combo box containing the list of printers, and set the focus on it. But if you selected, say, PDF output, then the printer selection combo box can be disabled, along with the Copies option. The immediate exitcode as you move the focus among the radio buttons allows the program to perform these actions. 

But if you do not need to perform any immediate action just because the radio button selection was changed by arrowing through the group, then use the EVW_SQUELCH option, and wait for some more important event to terminate the eventwait, after which you can go back and query the buttons. 

To advance the focus out of the current radio button group, without changing the currently selected radio button, use TAB (or SHIFT+TAB). 

A-Shell Reference 

Page 2097 

## **EVW_ACCEL** 

_Updated June 2013; see History_ 

This flag allows alphanumeric keystrokes to act as "accelerator" keys, automatically selecting and clicking on the matching control, if present. You can define an accelerator key association for a control by inserting a "&" in front of the desired character in the control's text. For example, a button defined using "E&xit" will use "x" as the accelerator key. (The & will not appear, but the subsequent character will be underlined.) In this case, hitting "x" will have the same effect as clicking on the button. 

Note that the standard Windows keyboard accelerator formula (ALT+key) does not require that EVW_ACCEL be specified. 

## **History** 

- 2013 June, A Shell 6.1.1354: When the EVW_ACCEL flag is set, underlining of the hot keys is now forced on. Previously, and otherwise, it follows the Windows convention, showing them if the last input event was a keyboard event and hiding them if it was a mouse event. 

A-Shell Reference 

Page 2098 

## **EVW_RAW** 

Causes nearly all keystrokes to be returned "raw" by setting the _ctlid_ to the ASCII value of the keystroke and _exitcode_ to 0. The only exceptions are the TAB, SHIFT+TAB, and ARROW keys, which retain their navigation function. This is similar to EVW_NUMERIC, in that the _ctlid_ parameter is used to return a user-input code which has nothing to do with an actual control ID. 

Since the returned _ctlid_ may not have anything to do with a valid control ID, take care not to pass the value back as input to a subsequent EVENTWAIT operation (or else it will probably abort with _exitcode_ 99, meaning invalid control ID.) 

A-Shell Reference 

Page 2099 

## **EVW_EXCDFOCUS** 

_Updated September 2018; see History_ 

When this option is set, AUI_EVENTWAIT gives preference to the incoming EXITCODE value in deciding which control to initially set the focus on, using the following rules: 

- If EXITCODE < 0 and not -35 through -42 (often used for SHIFT+TAB and SHIFT+ARROWS) then it is interpreted as if the CTLID 

- parameter had been set to the control whose click-string generates the specified EXITCODE. Provided that the control is of a type that is normally allowed to retain the focus by EVENTWAIT. If, for example, you define both a static text label and an INFLD field with the same EXITCODE click string, EVENTWAIT will skip over the label and activate the INFLD field. 

- Else if EXITCODE is 2, 3, -35, -36, -37, -40 or -42 (LEFT-ARROW, UP-ARROW, SHIFT+LEFT-ARROW, SHIFT+UP-ARROW, SHIFT+TAB and 

- shifted XTREE up/left) then the EVW_PREV flag is automatically set. 

- Else if EXITCODE is 5, 7, 12, -38, -39 or -41 (DOWN-ARROW, TAB, RIGHT-ARROW, SHIFT+RIGHT, SHIFT+DOWN, SHIFT+RIGHT in XTREE 

- then the EVW_NEXT flag is automatically set. 

- Else it acts as if the EVW_EXCDFOCUS flag had not been set. 

An example will make it clear why this is handy. Imagine a dialog containing some buttons and also several INFLD fields, where you are going to use AUI_EVENTWAIT. Previously, to start you might have set CTLID to the ID of a particular button. You can still do that, but since the logic of your application is probably built on the EXITCODE values rather than the control IDs, it will be easier to just set EXITCODE to the value corresponding to the desired control and use EVW_EXCDFOCUS. That's a minor improvement. But consider if you wanted to start on one of the INFLD fields. You would not call AUI_EVENTWAIT at all, rather you'd call INFLD. But this complicates your logic. If you just set EXITCODE to the value corresponding to the desired field (and specify EVW_EDIT) then AUI_EVENTWAIT will immediately return to you with the desired exitcode—which accomplishes nothing but simplifies your code since you do not have to have special logic for handling the initial focus. 

The main improvement comes as you return to the AUI_EVENTWAIT after calling INFLD (or XTREE). If the user exits from the INFLD operation by hitting UP-ARROW (returning EXITCODE 3), previously you would have had to figure out what the control ID was for the control prior to that INFLD control (or at the very least, have logic to set the EVW_NEXT or EVW_PREV flags). Now, with the EVW_EXCDFOCUS flag, you can just go right back to the AUI_EVENTWAIT operation and let it decide what the next control to get the focus should be. 

A-Shell Reference 

Page 2100 

In other words, your dialog loop can probably now be simplified down to something like: 

```
do
```

```
   xcall AUI,AUI_EVENTWAIT, CTLID, PARENTID, EXITCODE, OPFLAGS
```

```
   if <exitcode to exit dialog>
```

```
      exit
   else
      call <field handler based on exitcode>
```

```
loop
```

## **History** 

- 2018 September, A Shell 6.5.1647:  AUI_EVENTWAIT refinement: static 'buttons'—i.e. static controls with the MBF_KBD flag set so they act like clickable buttons—are now compatible with the EVW_EXCDFOCUS flag if the MBF_TABSTOP flag is also set. 

A-Shell Reference 

Page 2101 

## **EVW_EXCDINOUT** 

This flag is similar to EVW_EXCDFOCUS but just causes any incoming EXITCODE value of -100 or less to be "passed through" (i.e. returned directly) to the application. This is useful (in conjunction with EVW_EXCDFOCUS) for responding to button clicks that occur while INFLD has the focus. For example, you might have a structure like this: 

## `do` 

```
   xcall AUI,AUI_EVENTWAIT,CTLID,PARENTID,EXITCODE,OPFLAGS
```

```
   if <exitcode to exit dialog>
```

```
      exit
```

```
   else
```

```
      call <field handler based on exitcode>
```

```
loop
```

With just EVW_EXCDFOCUS alone, if the user clicks on a button while INFLD has the focus (in the "field handler" above), the subsequent EVENTWAIT would merely put the focus on the button without triggering it. (The first click would trigger an exit from the current INFLD, but it would take a second click on the button to invoke the "field handler" for the button, using the logic above.) With EVW_EXCDINOUT added to the OPFLAGS, the button click would cause the "field handler" to exit, as before, but now the EVENTWAIT would also exit, so that the new "field handler" for the button could be called. This is not an issue when clicking on an INFLD field, because the combination of EVW_INFLD+EVW_EXCDFOCUS would cause any attempt to put the focus on an INFLD field to just exit from the EVENTWAIT so that INFLD could be called. 

Note that one situation where you might not want EVW_EXCDINOUT is if you want to explicitly put the focus on a button by specifying its EXITCODE, without forcing the button to get clicked. 

A-Shell Reference 

Page 2102 

## **AUI_ENVIRONMENT** 

## **xcall AUI, AUI_ENVIRONMENT, opcode, guiflags** 

The AUI_ENVIRONMENT class keeps track of properties and capabilities of the interface environment that affect the kind of user interface a program should use. 

## **Parameters** 

## _opcode_ (Num)  [in] 

0 to retrieve the current attributes into guiflags, 1 to set them from guiflags. As a practical matter, you would probably never use opcode 1 since the flags are set automatically by A-Shell when the session is launched, and changing a flag isn't going to change the reality of the environment. Opcode 2 is a streamlined variation of 0 that skips the query of the ATE client to find out if it has Windows theme support or not. That detail is rarely of interest to applications; eliminating the query saves a few milliseconds for the round-trip query-and-response, although it probably makes little difference unless the application makes a lot of these calls. 

## _guiflags_ (Num) [in/out] 

Values for _guiflags_ are shown in the following table, and are defined in ashell.def. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|AGF_LWG|&h0001|Local Windows w/ GUI (e.g. PCTDVG)|
|AGF_LWN|&h0002|Local Windows w/o GUI (e.g. PCTDV)|
|AGF_ATE|&h0004|Running on server via ATE connection|
|AGF_RWN|&h0008|Remote windows (ATS)|



A-Shell Reference 

Page 2103 

|ell Reference|||
|---|---|---|
|AGF_TNT|&h0010|Telnet|
|AGF_ASH|&h0020|A-Shell|
|AGF_THEMES|&h0040|Windows Themes are active|
|AGF_HOLDKBD|&h0080|Client currently holding kbd|
|AGF_ATERES|&h0100|Currently waiting on ATE response|
|AGF_LOCWIN|&h0003|Local Windows (AGF_LWN or AGF_LWG)|
|AGF_ANYWIN|&h000B|Any windows platform (_LWN or _LWG or _RWN)|
|AGF_GUIEXT|&h0005|GUI extensions avail (AGF_LWG or AGF_ATE)|
|AGF_LWNATE|&h0007|Local Windows or ATE|
|AGF_ATECLI|&h0200|Running on ATE client (i.e. insideTELNET.LIT)|
|AGF_INPROC|&h0400|TAB(-10,x) command in progress|
|AGF_ATESBX|&h1000|We are in ATE-side SBX call|



A-Shell Reference 

Page 2104 

|ell Reference|||
|---|---|---|
|AGF_NOSTATUS|&h2000|Disable the return of_cstatus_information|
|AGF_DESIGN|&h10000|Design mode|



## **Comments and Examples** 

All of these would start with retrieving the current _guiflags_ as follows: 

```
xcall AUI, AUI_ENVIRONMENT, 0, GUIFLAGS       ! retrieve GUI flags
```

Before creating a graphical user interface with components from the AUI CONTROL class, you might want to check for either AGF_LWG or AGF_ATE. Since these are combined in AGF_GUIEXT, we can simply check it as follows: 

```
if (GUIFLAGS and AGF_GUIEXT) then ? TAB(-10,x);.....
```

If you wanted to display a file for the user, either using NOTEPAD (if applicable) or else EZTYP (if not), you might use the following logic: 

```
if (GUIFLAGS and AGF_LOCWIN) then
```

```
    xcall HOSTEX,"NOTEPAD "+F$
```

```
elseif (((GUIFLAGS and AGF_ATE)#0) and ((GUIFLAGS and AGF_TNT)#0)) then
```

```
    call XFER'TO'PC
```

```
    call LAUNCH'NOTEPAD'ON'CLIENT
```

```
else
```

```
    xcall EZTYP,F$
```

```
endif
```

A-Shell Reference 

Page 2105 

In the above example, if running Windows locally, we can just launch NOTEPAD using HOSTEX. Otherwise, if running ATE on the client over telnet, we could transfer the file to the PC and then launch NOTEPAD, both of which could be done via Tab(-10,x) commands. Otherwise, we could just use EZTYP on the server. (You might also want to test for other telnet emulators, such as ZTERM, which are capable of doing file transfers and launching commands on the client, but that exceeds the scope of this example.) Note that when testing multiple AND conditions, you need the extra set of parentheses and the #0 test as shown above to get the desired effect. Otherwise the confusion between the logical and arithmetic AND in BASIC will cause the test to fail. 

If you merely wanted to test whether you were running under A-Shell Windows or A-Shell/Unix (or some other platform, presumably AMOS), you could do this: 

```
if (GUIFLAGS and AGF_ASH) then       ! running A-Shell
```

```
if (GUIFLAGS and AGF_ANYWIN)      ! any Windows platform
```

```
? "A-Shell Windows"
```

```
else
```

```
? "A-Shell Unix"
```

```
endif
```

```
else
```

```
? "Non A-Shell (AMOS?)"
```

```
endif
```

## **History** 

- 2006 January, A Shell 4.9.949:  The following will return the ATE version if the fourth parameter is specified and the client is ATE. 

```
xcall AUI, AUI_ENVIRONMENT, 0, FLAGS {,ATEVER$}
```

A-Shell Reference 

Page 2106 

## **AGF_NOSTATUS** 

AGF_NOSTATUS may be set to disable the return of _cstatus_ information from AUI_CONTROL CTLOP_ADD operations. This may be useful in programs which contain many individual AUI_CONTROL calls but where you don't care about the return status (and don't need to reference the control IDs, or are using alphanumeric IDs). This is equivalent to specifying NUL_CSTATUS (or "") for the _cstatus_ parameter in each call, so it is mainly useful when you have a lot of code doesn't take that refinement into account (perhaps because it was originally written for a local Windows environment where there is no performance penalty for returning the status). 

Use AUI_ENVIRONMENT with opcode 1 to set this flag. It remains set for the duration of the session, or until specifically reset. Note that this is purely a server-side enhancement. 

A-Shell Reference 

Page 2107 

## **AUI_MENU** 

## **xcall AUI, AUI_MENU, opcode, menuid, mnutxt, mstate, mtype, cmd, func, mstatus {,dlgid, itemid}** 

## **xcall AUI, AUI_MENU, opcode, mdfspec, mstate, mstatus {,dlgid}** 

The AUI_MENU class deals with the A-Shell menu bar, offering methods for adding and deleting menu items. The first form of the syntax above (AUI_Menu Traditional Method) is the original method, which is still the most flexible, but most difficult to use. The second form (AUI_Menu Simplified Method) vastly reduces the amount of code you need to write. 

## Note: 

- When the GUI trace is active, AUI_MENU operations are traced. 

- This operation can only take place on a GUI-enabled client, either ATE or some form of A-Shell/Windows. 

- A-Shell permits an unlimited number of menu items; the menu table expands automatically as need. 

## **Examples** 

Several sample programs illustrating menu operations may be found in the EXLIB:[908,35]. 

## **Subtopics** 

- AUI_Menu Traditional Method 

- AUI_Menu Simplified Method 

- AUI_MENU Techniques and Tips 

A-Shell Reference 

Page 2108 

## **AUI_MENU TRADITIONAL METHOD** 

## **xcall AUI, AUI_MENU, Opcode, Menuid, Mnutxt, Mstate, Mtype, Cmd, Func {,Mstatus, Dlgid, Itemid}** 

For detailed info on each parameter, click on the parameter names above, or click through them using the table of contents, or navigate through them all with the "Next" button. 

A-Shell Reference 

Page 2109 

## **OPCODE** 

## _opcode_ (Num) should be one of the following: 

|**Symbol**|**Valu**<br>**e**|**Meaning**|
|---|---|---|
|MNUOP_CH<br>K|0|No change to the menus; just check to see if a menu item exists|
|MNUOP_AD<br>D|1|Add new menu items|
|MNUOP_ST<br>A|2|Change state of existing menu items|
|MNUOP_DE<br>L|3|Delete menu items|
|MNUOP_PO<br>P|4|Displays a previously defined context or popup menu, supports millirows:<br>`xcall AUI, AUI_MENU, mnuop_pop, menuid, "", row, col, "",`<br>`"", status {,dlgid}`|
|MNUOP_DS<br>P|6|Force menu to be redisplayed/updated (needed after adding menu items to a<br>dialog)|
|MNUOP_RS<br>T|7|Resets main A-Shell menu.|



A-Shell Reference 

Page 2110 

A-Shell Reference 

Page 2111 

## **MNUOP_RST** 

This _opcode_ , added in A-Shell 5.1.1129 of 31 Oct 08, can be used to reset the main A-Shell menu back to the way it was when A-Shell was first launched: 

## **xcall AUI, AUI_MENU, MNUOP_RST, 0, mnutxt, 0, 0, "", "", mstatus** 

As with other AUI_MENU commands, _mstatus_ will be set to 0 on success. But on failure, it will return the negative version of the OS error #, which you can translate using MX_ERRNOMSG. 

Mnutxt can be "" for the standard menu (aka "MIAMEMENU") or you may select a language specific menus by specifying "MIAMEMENU-xxx" where xxx is the LDF language definition (e.g. "SPA", "ITA", "POR", "FRE", "CDN" etc.) If there is no specific menu for the requested language, the default version (American English) will be used. In this case, the return status will be -2 (indicating that the requested menu was not found). 

In the case of ATE, the menu items will be reset to the way they are at the start of an ATE connection. 

A-Shell Reference 

Page 2112 

## **MENUID** 

_menuid_ (any type) specifies the top level menu number or its name, according to the following table: 

|**Value**|**Meaning**|
|---|---|
|< 0|Negative numbers are used to identify context menus. The number itself is arbitrary and only serves to<br>identify the menu (for the purpose of adding items to it, deleting it, or displaying it under program control).<br>SeeSample.mdf<br>.|
|0|Top level menu as a whole. Use this when adding or deleting an item that appears on the horizontal menu bar<br>(which starts with items "File", "Edit", "Settings", "Help".|
|1|The "File" menu. Use this to add or delete items to the drop down menu that appears when you click on<br>"File".|
|2|The "Edit" menu. Use this to add or delete items to the drop down menu that appears when you click on<br>"Edit".|
|3|The "Settings" menu. Use this to add or delete items to the drop down menu that appears when you click on<br>"Settings".|
|4|The "Help" menu. Use this to add or delete items to the drop down menu that appears when you click on<br>"Help".|
|5 or<br><name>|This would be the number of the first item added to the top level menu bar. You could also refer to it by the<br>same text that you specified as_mnutxt_when you added it. Use this to add or delete items to the drop down<br>menu that appears when you click on this menu.|



A-Shell Reference 

Page 2113 

|**Value**|**Meaning**|
|---|---|
|6 – 14 or<br><name>|Same idea as for five, but for the sixth through fourteenth items on the top menu bar.|
|1000+|Custom menu item identifier established by setting Itemid when the parent menu created. (This method of<br>associating menu items with the parent menu is more flexible than the position-based method, and allows for<br>multiple levels of submenu nesting.)|



A-Shell Reference 

Page 2114 

## **MNUTXT** 

_mnutxt_ (String) specifies the text that will appear in the menu item, and optionally, a bitmap or icon to display alongside the text. You may precede one letter with "&" to allow that letter to be used with the ALT key as a hot key for the menu. For example, "&Custom" would display as "Custom" and could be selected via ALT+C. You may append a right-justified suffix to the text by preceding it with a TAB character, i.e. chr(9). For example: 

```
MnuTxt = "Calculator" + chr(9) + "F6"
```

_mnutxt_ may also serve as the identifier for the menu item, allowing it to be selected for later deletion, so it should be a unique string. 

To include a bitmap or icon alongside the menu text, precede the text with the bitmap or icon specification enclosed in vertical bars. You may also specify a desired size in pixels by appending "=##" to the end of the image spec, where ## is a number between 10 and 99. (The images are assumed to be square. If no size is specified, for standalone BMP files, the actual size of the bitmap will be used; for icons, the size will be set to 16x16, which is the standard size of a menu icon). Best results will be obtained when the actual image size (or, in the case of icons, when one of the available images) matches the target size. 

The image specification can be in any of the formats accepted for standard Icon Control or Bitmap Control (AMOS-style or native fspec, and/or in the case of icons, a resourcename::dllname). In the case of ATE, the image file must be present on the ATE client; if not present in the specified location, ATE will also look in the %ATECACHE% and %ATEPERMCACHE% directories. A typical strategy is to copy all of the images needed by ATE into the %ATEPERMCACHE% directory, possibly using the ATSYNC.LIT utility. Some examples: 

```
mnutxt = "|images:fopen.bmp|Open File"
```

```
mnutxt = "|help.ico[7,57]=64|Help"
```

```
mnutxt = "|%MIAME%\images\exit.ico=32|Exit"
```

```
mnutxt = "|paste::ashico1v|Paste"
```

See Menu Icons for more details and examples of menus with images. 

A-Shell Reference 

Page 2115 

When modifying or deleting custom menu items, you must identify the item by setting _mnutxt_ to the text used when the menu was created. Using the ordinal position may work for modifications, but will fail to fully delete the item, making it impossible to re-add it later. _Menuid_ should identify the parent menu. See Adding/Deleting Internal Menu Items for details on dealing with the built-in menu items. 

## **History** 

- 2013 May, A Shell 6.1.1351: Icon images can now be attached to context menu items, just as they can for normal menu items, using the same "|image|text" syntax. 

- 2013 May, A Shell 6.1.1351: "\t" can now be embedded directly in mnutxt to signify a TAB, as an alternative to concatenating a chr(9) as described above. This is particularly convenient when menu item text is stored in a data file rather than assembled dynamically. For example, the menu items in the sample context menu above can now be created with the following: 

```
"Edit MIAME.INI \t F5"
```

```
"Calculator \t F6"
```

- 2009 July, A Shell 5.1.1155: You can also reference built-in menu items by setting _mnutxt_ to the string representation of the item’s internal command ID (in the range of 100-199); see the Internal Menu Modifiers table, above. 

2009 July, A-Shell 5.1.1154: You can specify a bitmap or icon to display next to the menu item; see Menu Icons. 

A-Shell Reference 

Page 2116 

## **MSTATE** 

## _mstate_ (Num) indicates the state of the menu item: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|MBST_ENABL<br>E|&h0000000<br>0|Enabled|
|MBST_DISAB<br>LE|&h0000000<br>1|Disable (grayed out)|
|MBST_CHECK<br>ED|&h1000000<br>0|Menu item is checked (see MBF_CHKMNU and MBF_RADIOMNU in<br>Mtype<br>)|
|MBST_HILITE|&h2000000<br>0|Adds visual highlighting to the item. Under Vista and later, the<br>effect is quite subtle, and basically the same as what you get when<br>the mouse hovers over an item.|
|MBST_DEFAU<br>LT|&h4000000<br>0|Menu item is the default|



- Hex Decimal Values 

A-Shell Reference 

Page 2117 

## **MTYPE** 

_mtype_ (Num) specifies any valid combination of options from the following table: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|MBF_CMDLIN|&h00000000|Normal. Selecting the menu item causes the contents of_cmd_to be executed as a<br>Windows command line, as if it had been executed viaHOSTEX. As withHOSTEX, you<br>can refer to the current A-Shell executable (and its currentmiame.ini) via the macro<br>symbol $ASHELL, and you can use the suffix characters available toHOSTEX. For<br>example, "$ASHELL –e run armenu" would launch a new A-Shell instance, run the<br>program armenu, and suspend the current session until armenu exited.|
|MBF_DLL|&h00000001|DLL. Selecting the menu item causes the function (_func_) with the associated DLL<br>(defined in_cmd_) to be loaded and executed.|
|MBF_CHKMNU|&h00000004|Menu item is "checkable".  See MBST_CHECKED inMstate|
|MBF_RADIOMNU|&h00000008|Menu item is part of a radio button group.  Same idea as MBF_CHKMNU except only<br>one item in a group of contiguous radio button items may be selected.|
|MBF_SUBMNU|&h00000010|Submenu. Selecting the menu item will cause a submenu to appear. As of 5.1.1154,<br>nested submenus are supported.  To create a nested submenu, assign a uniqueItemid<br>to the parent item, i.e. the one with the MBF_SUBMNU type, and then specify that<br>_itemid_in theMenuid<br> of the child items (one or more of which can themselves be<br>submenus).|
|MBF_SEP|&h00000800|Separator. Item displays a s horizontal separator bar. Separators cannot be selected<br>and only serve to visually organize submenus. Even though separators do not display|



A-Shell Reference 

Page 2118 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|||the_mnutxt_contents, they still need a unique_mnutxt_string to allow the item to be<br>deleted later.|
|MBF_KBD|&h00010000|Keyboard. Selecting the menu item causes the contents of_cmd_to be forced into the<br>keyboard buffer. This technique may minimize the impact on the program, since to it,<br>menu selections may appear just like ordinary keyboard responses, but you have to be<br>careful to disable such menus when the program context is not correct to interpret<br>such responses. See_cmd_for further notes on designing and encoding keyboard<br>sequences.|
|MBF_SHLEXC|&h00020000|Shell execute. Selecting the menu item causes the contents of_cmd_to be interpreted as<br>an object (file or URL) to be opened using the associated application defined in the<br>Windows registry. For example, if CMD="http://www.microsabio.com", then selecting it<br>would launch the browser and go to the specified web page. If CMD= "mydata.xls",<br>selecting the menu would probably launch Excel to open the spreadsheet.<br>If the file object specified in CMD does not contain a drive or directory specifier, then it<br>will be assumed to be in A-Shell’s "DOC" subdirectory (e.g.c:\vm\miame\doc).<br>Otherwise, you need to specify a native pathspec (unless the file is in the system<br>search PATH). Refer toMX_FSPEC<br>for converting AMOS directories to their native<br>equivalents.|
|MBF_MENUID|&h00040000|Internal menu command identifier.  This is the type of the internal or built-in menus.<br>When clicked, then just send a message with their ID to the A-Shell message handler.<br>SeeAdding/Deleting Internal Menu Items<br>for further details.|



- Hex Decimal Values 

A-Shell Reference 

Page 2119 

## **CMD** 

_cmd_ (String, in) should be set to the command, DLL, keystrokes, object, or internal ID, according to the _mtype_ . It is ignored for the submenu (MBF_SUBMNU) and separator (MNU_SEP) menu item types. 

Care should be taken so that your custom menu commands remain contextually compatible with the application.  For example, creating a menu item labeled "Help" with cmd = "?" + chr(13) might make sense in the context of a screen or menu which understands that keyboard sequence, but may make no sense in a text editing context where those would simply be ordinary characters. Any of the following strategies might be employed to avoid the problem: 

- Use menu types MBF_SHLEXC and MBF_CMDLIN, since they launch external windows without affecting the current application 

- context. 

- Disable or delete the menu items when switching to an application context where they no longer apply. This is usually a error 

- prone and tedious to program and thus not highly recommended. 

• For MBF_KBD menus, use universal control characters (that may be applicable everywhere, such as VK_ESC), or pseudofunction keys which are either context-independent or can be ignored by applications that don't recognize them. In either case, use Virtual Key Symbolic Names whenever possible, to avoid complications with the handling of literal control characters. (You can also encode them using the ^X notation, (where ^X is interpreted as CTRL+X, for any character A-Z or [, ], \, underline, or another caret). Thus the _cmd_ string "^GA" would be treated as CTRL+G followed by the letter A, and "Hello^M" would be treated as the word "Hello" followed by a CARRIAGE-RETURN (CTRL+M). 

## **Examples** 

```
mtype = MBF_KBD     : cmd = "VK_xF213"    ! virtual function key 213
```

```
mtype = MBF_KBD     : cmd = "^C"          ! Control C (using "^" notation)
```

```
mtype = MBF_CMDLIN  : cmd = "CALC.EXE"    ! launch calculator
mtype = MBF_SHLEXC  : cmd = "www.me.com"  ! launch browser
```

A-Shell Reference 

Page 2120 

## **FUNC** 

_func_ (String, in) must contain the name of the function to execute within the DLL whose name was specified in _cmd_ . It will be ignored except when the _mtype_ is MBF_DLL. 

A-Shell Reference 

Page 2121 

## **MSTATUS** 

_mstatus_ (Signed Num, out, optional) returns a code indicating the result of the operation: 

|**Valu**<br>**e**|**Meaning**|
|---|---|
|0|OK, or for opcode 2 indicates item was previously enabled|
|1|OK, or for opcode 2 indicates item was previously disabled|
|-1|Add or delete menu function failed|
|-2|Menu (_mnutxt_) not found during change or delete operation|
|-3|Out of memory (unable to allocate menu storage buffers)|
|-4|Exceeded maximum number of added menu items (currently<br>125)|
|-5|No menu buffer allocated|
|-6|Illegal opcode|
|-7|Menu (_mnutxt_) already exists|



A-Shell Reference 

Page 2122 

|**Valu**<br>**e**|**Meaning**|
|---|---|
|-8|Menuid<br> not found|
|-15|ATE failed to respond to the server request within the normal<br>time limit|



If the _mstatus_ parameter is omitted, or passed as a null string (if mapped, must be S,1), then no status will be returned. This will provide a speed improvement when setting up a lot of menu items (particularly over ATE), and is recommended especially if you aren't even bothering to check the returned status value anyway. 

The normal time limit for a response from ATE is five seconds for most commands, ten to fifteen seconds for a few. Sometimes commands that "should" respond almost instantly will take a long time, either because ATE is "locked up", or there is some other Windows hang-up, such as waiting on "elevation" or some other critical event. In such cases, we return -15 to indicate time out. 

A-Shell Reference 

Page 2123 

## **DLGID** 

_dlgid_ (Num, in, optional) adds a menu to the dialog. Note that: 

• For dialogs using MBF_ALTPOS, the dialog height will be increased by the height of the menu (so as to leave the amount of usable space within the dialog unchanged.  Otherwise (in the non MBF_ALTPOS case), the dialog height will remain fixed, but the addition of the menu will take away from the usable space within the dialog.  In either case, any controls currently within the dialog will be shifted down by the height of the menu. 

- It is not possible to delete the menu, once added. (In general, you would probably just delete the dialog.) 

- The dialog display does not get automatically refreshed to show the newly added menu. To force this to happen after you 

- have added all of your menu items, use AUI_MENU with opcode MNUOP_DSP: 

```
xcall AUI, AUI_MENU, MNUOP_DSP, 0, "", 0, 0, "", "", mstatus, dlgid
```

A-Shell Reference 

Page 2124 

## **ITEMID** 

_Updated May 2013_ 

_itemid_ (Num, in, optional) allows you to specify a unique ID (in the range of 1000-32767) to assign to the item being added, or to identify the item being modified or referenced. Items can also be identified by their ordinal position or text, but these are less satisfactory because either may change at runtime due to forces outside the developer’s awareness at the time of writing the code. The use of _itemid_ is also the only way to create nested submenus (i.e. assign an itemid to the parent of the submenu, then reference it as the Menuid of the child items). 

## **History** 

- 2013 May, A Shell 6.1.1351: ItemId no longer needs to be globally unique; it only needs to be unique relative to the DlgId—i.e., to the window to which the menu is attached. This makes it easier to generate menu item IDs when working with multiple dialogs, without having to worry about collisions. 

A-Shell Reference 

Page 2125 

## **AUI_MENU SIMPLIFIED METHOD** 

The simplified menu calling syntax uses just five parameters, as shown here: 

## **xcall AUI, AUI_MENU, opcode, mdfspec, state, status {,dlgid}** 

_opcode_ , _state_ , _status, dlgid_ have the same meaning and usage as for the traditional method, described above. 

_mdfspec_ (String) should contain the filespec (AMOS or native format) of a "Menu Definition File" which consists of lines of the following format: 

```
;(Blank lines and lines starting with semicolon are ignored)
```

```
;
```

```
MENUID,MNUTXT,TYPE,CMD
```

```
MENUID,MNUTXT,TYPE,CMD
```

```
etc.
```

By convention, the normal extension for such a file is MDF (Menu Definition File). If the _mdfspec_ parameter is "", then it is assumed to refer to A-Shell's help menu definition file, $miame\doc\ashelp.mdf. 

If running on a Unix server with an ATE client, the mdfspec will be resolved on the PC side and must reside there in advance of the call. (You can transfer it via FTP necessary.) If just a filename and optional extension given, it will be treated as being in the local ATE current ppn, which by default is DSK0:[1,4]. 

The file can specify any number of menu items (subject to the maximum of 125 custom menu items at any one time), all of which will be added, deleted, or enabled/disabled in one operation. 

Each of fields _menuid_ , _mnutxt_ , _type_ and _cmd_ have the same meaning as in the traditional calling format. As an added convenience, the TYPE field may also be specified as a three-character mnemonic: 

A-Shell Reference 

Page 2126 

|**Type**|**Mnemonic**|
|---|---|
|0|CMD|
|1|<not supported in MDF format>|
|16|SUB|
|2048|SEP|
|65536|KBD|
|131072|REG|



_menuid_ can also be specified as a mnemonic, as shown in the following table. Note that this is the same table with the same values as shown and as used in the "Traditional Method." In the "Simplified Method," however, the mnemonics are allowed, whereas in the "Traditional Method" they are not. 

|**MenuID**|**Meaning**|
|---|---|
|0 or<br>"Top"|Top level menu as a whole. Use this when adding or deleting an item that appears<br>on the horizontal menu bar (which starts with items "File", "Edit", "Settings",<br>"Help".|
|1 or|The "File" menu. Use this to add or delete items to the drop down menu that|



A-Shell Reference 

Page 2127 

|**MenuID**|**Meaning**|
|---|---|
|"File"|appears when you click on "File".|
|2 or<br>"Edit"|The "Edit" menu. Use this to add or delete items to the drop down menu that<br>appears when you click on "Edit".|
|3 or<br>"Settings"|The "Settings" menu. Use this to add or delete items to the drop down menu that<br>appears when you click on "Settings".|
|4 or<br>"Help"|The "Help" menu. Use this to add or delete items to the drop down menu that<br>appears when you click on "Help".|
|5 or<br><name>|This would be the number of the first item added to the top level menu bar. You<br>could also refer to it by the same text that you specified as_mnutxt_when you added<br>it. Use this to add or delete items to the drop down menu that appears when you<br>click on this menu.|
|6 – 14 or<br><name>|Same idea as for five, but for the sixth through fourteenth items on the top menu<br>bar.|



Any of the fields in the MDF may optionally be enclosed in quotes – this in only mandatory when the field itself contains a comma. 

See the notes in the TYPE table and under the CMD definition for the traditional method above for details about how to format the CMD string for the various TYPEs. 

A-Shell Reference 

Page 2128 

As an example, consider the following call and sample MDF file. The comments in the sample.mdf should hopefully make clear what it does. 

```
xcall MIAMEX, MX_WINMMU, 1, "sample.mdf", 0, STATUS
```

The Simplified Method does not support the more advanced capabilities added in 1154 (checked and radio button menus, nested submenus, menu icons.) 

## **Subtopics** 

- Sample.mdf 

A-Shell Reference 

Page 2129 

## **SAMPLE.MDF** 

```
;Add a separator bar to File menu:
```

```
FILE,"fs1",SEP
```

- `;Add item to "Select Source" (implemented my launching another` 

- `;  instance of A-Shell)` 

- `; (Note -e for auto exit) FILE,"Select Source...",CMD,"$ASHELL -e run selsrc"` 

```
;Next, add a new top level menu called "Tools"
```

```
TOP,"&Tools",SUB
```

- `;Add a calculator and a website link to it...` 

```
"&Tools","Calculator",CMD,"calc.exe"
```

```
"&Tools","Web Search",REG,"http://www.google.com"
```

```
;Add a separator and two PDF document files to Help menu
```

```
HELP,"fs2",SEP
HELP,"User Guide",REG,"UserGuide.pdf"
```

```
HELP, "Troubleshooting Reference",REG,"TroubleRef.pdf"
```

If an error occurs, the operation will abort at that point, which should hopefully help you pinpoint the cause. 

A-Shell Reference 

Page 2130 

It is usually necessary to delete menus in the reverse order from the way they were added (in order to avoid the confusion caused by later menus changing position due to the deletion of earlier ones). The simplified method takes care of this difficulty for you, but only within a single MDF file. If you use multiple MDF files and want to be able to delete them independently of each other, you should not have more than one MDF file add menu items to the same top level submenu, and you will need to refer to the top level submenus by name rather than number. 

See the sample program ASMENU.BAS in EXLIB:[908,35] for more details. 

A-Shell Reference 

Page 2131 

## **AUI_MENU TECHNIQUES AND TIPS** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Submenus 

- Context Menus 

- Menu Icons 

- Checked and Radio Button Menu Items 

- Deleting Menus 

- Adding/Deleting Internal Menu Items 

A-Shell Reference 

Page 2132 

## **SUBMENUS** 

To create a submenu, use the MBF_SUBMNU flag and specify a menuid other than 0. (Submenus whose parent menuid is 0 are toplevel drop-down menus.) To create the items within the submenu, set the menuid to match the itemid of the submenu itself. 

A-Shell Reference 

Page 2133 

## **CONTEXT MENUS** 

AUI_MENU supports the creation of popup menus (aka "right-click" or "context" menus) for the main window and for dialogs. The syntax is the same the same as for the Traditional Method above, with the following differences: 

• There can be only one context menu for the main window and one for each dialog. When the menu is created, if there is a dialog active, then it becomes associated with the dialog; otherwise it becomes associated with the main window. As of A-Shell build 5.1.1151.0, the _dlgid_ parameter may be specified to override the menu/dialog association rule just stated. 

- The menu ID of the context menu must be negative, although beyond that, the value is arbitrary and only serves to identify 

- the menu. One way of assigning a unique value for each dialog would be to take the dialog's numeric ctlid, add 1, and negate it. (The offset of 1 would preserve the menu ID -1 for a menu attached to the main window, whose _ctlid_ is effectively 0). 

- To add the clipboard operations Copy and Paste to the popup menu, use the MBF_CMDLIN format with the special commands 

- "$COPY" and "$PASTE". $CUT doesn't really apply in this context. 

- Defining a context menu does not automatically change the cursor to an arrow, but you can do that with the 

- AG_SETCURSOR;chr(32);chr(127); command and AG_SETCURSOR;chr(48);chr(127); to set it back to an I-beam. 

- You can delete the context menu with a single AUI_MENU call with opcode=MNUOP_DEL, mnutxt="*", and _menuid_ set to the 

- same value used when creating the menu. 

- The context menu will be active when the cursor is over the window or dialog, but not over a control which has its own click 

- processing. 

- To display the menu under program control (rather than waiting for the user to right-click), use AUI_MENU with 

- opcode=MNUOP_POP, e.g. 

```
xcall AUI, AUI_MENU, MNUOP_POP, MENUID, "", ROW, COL, "", "", STATUS
```

The ROW and COL parameters mark the position of the upper left corner of the popup menu (relative to the current dialog, if applicable, or else to the main window), in (milli) row and column units and replace what would otherwise be the _mstate_ and _mtype_ parameters. 

**See Also** 

A-Shell Reference 

Page 2134 

AUI_MENU can only add context menus to dialogs or the main window. To add context menus to other control types, see: 

- Static controls 

- XTREE 

- INFLD 

A-Shell Reference 

Page 2135 

## **MENU ICONS** 

You can specify a bitmap or icon to display next to the menu item, by prepending "| _imgspec_ {=size}|" to the text. 

_imgspec_ may be the filespec (native or AMOS-style) of a BMP or ICO file, or it may be in the " _name_ :: _library_ " format used by standard controls which may contain icons. ( _name_ is the name of the icon, and _library_ is the name of a DLL containing the icons, such as the ashico1.dll distributed with A-Shell.) The optional {=size} clause may be specified to request a specific size in pixels (menu images display as squares, so only one dimension is required). 

Under Windows Vista and later, menu images can be in any reasonable size (say, 10x10 to 99x99), and the menu spacing will adjust accordingly, and the size clause works for both bitmaps (BMP) and icons. The standard icon size is 16x16. Best results will be obtained when the natural size of the BMP file, or when one of the images contained within the ICO, match the default or specified size. 

Prior to Vista, the standard menu bitmap size was 13x13 and the resizing feature is not operable (and is essentially ignored). Icons will be automatically scaled to fit the standard space, while BMP files will be clipped. These BMP files are not recommended unless you have a specific set of them for Windows XP and prior that is naturally 13x13 or close to it. 

## **Example** 

The following code excerpt, from the sample program ASMNU4 in EXLIB:[908,35], adds a new top level menu "Custom" and then adds eight items to that menu, each with a different bitmap, illustrating most of the syntax and image type possibilities—BMP file, ICO file, icon resource in library module, with and without scaling: 

```
++include ashinc:ashell.def
```

```
map1 id'cusmnu,b,2,2000
map1 mstatus,f
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, 0,  "&Custom" , MBST_ENABLE, &
```

```
MBF_SUBMNU,"","",mstatus,0,id'cusmnu
```

A-Shell Reference 

Page 2136 

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'cusmnu, "|Back16.bmp|Back (16x16 bmp)", &
MBST_ENABLE, MBF_KBD,"VK_xF501",""
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'cusmnu, "|Back24.bmp|Back (24x24 bmp)", &
```

```
MBST_ENABLE, MBF_KBD,"VK_xF502",""
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'cusmnu, "|Clock24.bmp=16|Clock (24x24 as 16x16 bmp)", &
MBST_ENABLE, MBF_KBD,"VK_xF503",""
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'cusmnu, "|add2.ico|Add+ (ico file, default size)", &
MBST_ENABLE, MBF_KBD,"VK_xF504",""
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'cusmnu, "|coffee.bmp=64|Coffee (189x189 as 64x64 bmp)", &
MBST_ENABLE, MBF_KBD,"VK_xF505",""
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'cusmnu, "|back12.bmp|Back (12x12 bmp)", &
```

```
MBST_ENABLE, MBF_KBD,"VK_xF506",""
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'cusmnu, &
```

```
"|Arrow_left_green::ashico1v|Arrow_left_green (ashico1v, dft size)", MBST_ENABLE, &
MBF_KBD,"VK_xF507",""
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'cusmnu, &
```

```
"|Arrow_left_green::ashico1=32|Arrow_left_green (ashico1 =32)", MBST_ENABLE, &
MBF_KBD,"VK_xF508",""
```

Note that in the above examples, we did not specify the optional Mstatus parameter since we weren’t checking the result code anyway, and eliminating any delays waiting for response codes from remote ATE client workstations. 

Under Vista and beyond, the result looks something like the picture below. Note that the menu spacing adjusts to the size of the image, and furthermore that all the images can be displayed in a size other than the underlying native size. 

A-Shell Reference 

Page 2137 

Under older versions of Windows (see image below), the visual capabilities are more limited, with no image scaling, and with BMP images being truncated to 13x13. In that environment, either you need to have a set of custom bitmap images sized no larger than 13x13, or you should stick with icons, using either ICO files or taking them from an icon library (like ashico1). 

## **See Also** 

Icons in XTREE Popup Menu 

Icons in AUI_Control context menus 

A-Shell Reference 

Page 2138 

## **CHECKED AND RADIO BUTTON MENU ITEMS** 

Checked and radio button menu items are created using the Mtype flags MBF_CHKMNU and MBF_RADIOMNU, as shown in this example from the sample program ASMNU2 in EXLIB:[908,35]. 

To initialize the state of a checked or radio button menu item to checked (or selected), add the MBST_CHECKED flag to the Mstate parameter, as shown in the example below: 

```
xcall AUI, AUI_MENU, MNUOP_ADD, id'optmnu, "Option 1", MBST_ENABLE+MBST_CHECKED, &
```

```
MBF_CHKMNU,"","",mstatus, dlgid, id’option1     ! checked item
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id’optmnu, "Option 2", MBST_ENABLE, &
```

```
MBF_CHKMNU,"","",mstatus, dlgid, id’option2     ! unchecked item
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id’optmnu, "Radio 1", MBST_ENABLE+MBST_CHECKED, &
```

```
MBF_RADIOMNU,"","",mstatus, dlgid, id’radio1    ! selected radio item
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, id’optmnu, "Radio 2", MBST_ENABLE, &
```

```
MBF_RADIOMNU,"","",mstatus, dlgid, id’radio2    ! unselected radio item
```

In the above code sample, note that the Itemid is used to assign unique identifiers to each of the items, and to associate the items with the parent menu _id’optmnu_ . Also note that since we didn’t specify anything in the Cmd parameter, the items do not do anything on their own when clicked, other than change their state.  The application will have to query the items to determine their states as needed (see next). Alternatively, if we wanted to respond immediately with an action corresponding to the change in state of such a menu item, we could have had them generate exitcodes (as in the Menu Icons example above).  They can also execute command lines or launch documents (using MBF_CMDLIN or MBF_SHLEXC) just like other normal menu items. 

QUERYING ITEM STATE:  To query the current state of a checked or radio menu item, use MNUOP_CHK, identifying the item to query via the parent Menuid, Dlgid, and Itemid. The current state flags will be returned in the Mstatus parameter, as shown below: 

```
xcall AUI, AUI_MENU, MNUOP_CHK, id’optmnu, "", 0, 0, "","", mstatus, dlgid, id’option1
If (mstatus and MBST_CHECKED) ? "Option 1 is checked"
```

A-Shell Reference 

Page 2139 

```
xcall AUI, AUI_MENU, MNUOP_CHK, id’optmnu, "", 0, 0, "","", mstatus, dlgid, id’radio1
```

```
If (mstatus and MBST_CHECKED) ? "Radio 1 is selected"
```

CHANGING ITEM STATE:  The states of checked and radio menu items change automatically when clicked.  You may also change the state under application control, using MNUOP_STA.  For example, to select the "Radio 2" item in the menu shown above (which will automatically deselect the "Radio 1" item): 

```
xcall AUI, AUI_MENU, MNUOP_STA, id’optmnu, "Radio 2", MBST_ENABLE+MBST_CHECKED, 0, "","", &
```

```
mstatus, dlgid, id’radio2
```

A-Shell Reference 

Page 2140 

## **DELETING MENUS** 

When deleting a built-in menu, you can now set the _menuid_ parameter to "" and put either the string representation of the internal menu id # in the _mnutxt_ parameter, or the numeric value in the _itemid_ parameter (in which case set _mnutxt_ =""). The latter method apparently seems more natural to some users, whose efforts were previously failing. 

AG_MENU supports simplified deletion of menu items using either of the following formats: 

```
TAB(-10,AG_MENU);"3,,";str(IDM_PRINTS);chr(127);
```

```
TAB(-10,AG_MENU);"3,";MENUID$;",";MNUTXT$;chr(127);
```

The first example works for internal (built-in) menu items, where you must specify the str() of the IDM_xxx value for the menu (from ashell.def). 

The second example works for custom menu items, where you specify the text of the parent menu and the text of the item to delete. 

These formats are mainly useful with AGCMD,LIT, since they don't apply to AUI_MENU. They are faster than any other method for deleting individual items one at a time, since there is no return status. 

A-Shell Reference 

Page 2141 

## **ADDING/DELETING INTERNAL MENU ITEMS** 

In addition to menu items that send keyboard sequences (MBF_KBD), execute commands (MBF_CMDLIN) or launch object handlers (MBF_SHLEXC), typically via Virtual Key Symbolic Names, A-Shell and ATE come with a set of built-in or internal menus (e.g. File > Load Setting) that simply send their ID's to A-Shell, which has its own internal logic to deal with them. It would be pointless to add new menu items of this type, since A-Shell wouldn't recognize them. But, you can use the internal ID as a convenient and robust way to reference the built-in menus for purposes such as deleting, disabling, and/or later re-adding them. 

The internal menu IDs are defined via IDM_xxx symbols in ashell.def, for which see the following section Internal Menu Identifiers. 

## **Example 1: Deleting an internal menu** 

The most straightforward way to delete a built-in (but not top level) menu by its internal ID is by setting both the _menuid_ and _mnutxt_ parameters to "", the Mtype parameter to MBF_MENUID, and putting the internal menu ID in the Itemid parameter. (The _mstate_ , _cmd_ and _func_ parameters are irrelevant when deleting, and the _dlgid_ parameter isn't relevant for built-in menus.) For example, to delete the Edit > Copy menu: 

```
menuid$ = ""
```

```
mnutxt$ = ""
```

```
mtype = MBF_MENUID
```

```
xcall AUI, AUI_MENU, MNUOP_DEL, menuid$, mnutxt$, mstate, mtype, cmd$, func$, mstatus, 0, IDM_COPY
```

## **Example 2: Alternate syntax for deleting an internal menu** 

And alternate syntax sets the _Menuid_ parameter to "*", the _Mnutxt_ parameter to the string representation of the internal ID, and the _Mtype_ parameter to MBF_MENUID. For example, to delete the File > Save menu: 

```
menuid$ = "*"
```

```
mnutxt$ = str(IDM_SAVE)
```

```
mtype = MBF_MENUID
```

A-Shell Reference 

Page 2142 

```
xcall AUI, AUI_MENU, MNUOP_DEL, menuid$, mnutxt$, mstate, mtype, cmd$, func$, mstatus
```

This example deletes File > Exit, and adds a "New Exit" option to the Settings menu which performs the same function as the original File > Exit: 

```
mnu'exit'id$ = str(IDM_EXIT)    ! internal ID of File > Exit
```

```
xcall AUI, AUI_MENU, MNUOP_DEL, 1, mnu'exit'id$, 0, 0, "", "", mstatus
xcall AUI, AUI_MENU, MNUOP_ADD, 3, "New Exit", MBST_ENABLE, MBF_MENUID, mnu'exit'id$, "", mstatus
```

Note that the _Menuid_ parameters 1 and 3 reference the top level File and Settings menu by position. 

## **- Example 3: Moving / renaming a built in menu item** 

This example deletes File > Exit, and adds a "New Exit" option to the Settings menu which performs the same function as the original File > Exit: 

```
mnu'exit'id$ = str(IDM_EXIT)    ! internal ID of File > Exit
```

```
xcall AUI, AUI_MENU, MNUOP_DEL, 1, mnu'exit'id$, 0, 0, "", "", mstatus
```

```
xcall AUI, AUI_MENU, MNUOP_ADD, 3, "New Exit", MBST_ENABLE, MBF_MENUID, mnu'exit'id$, "", mstatus
```

Note that the _Menuid_ parameters 1 and 3 reference the top level File and Settings menu by position. 

## **Example 4: Deleting a Top Level Menu Item** 

Top level menu items (e.g. File, Edit, Settings, Help), unfortunately have no internal IDs, so they can only be deleted by position (first position = 0). The rest of the parameters have no particular significance here. For example, to delete the Settings menu (position 2): 

```
menuid$ = ""        ! must be "" or 0 to indicate top level
```

A-Shell Reference 

Page 2143 

```
mnutxt$ = "2"       ! position of Settings menu (2 = 3rd item)
xcall AUI, AUI_MENU, MNUOP_DEL, menuid$, mnutxt$, 0, 0, "", "", mstatus
```

Note that after deleting any menu item, the items following it are shifted up in position. So in this case, if we executed the above program sequence again, we would delete whatever menu was originally following the Settings menu (i.e. Help). Also note that deleting any menu item automatically deletes any and all sub-items beneath it. So the above sequence would delete (and clean up) all of the sub, sub-sub, etc. items beneath the Settings menu. 

A-Shell Reference 

Page 2144 

## **INTERNAL MENU IDENTIFIERS** 

|**Symbol**|**Value **|**Description**|
|---|---|---|
|IDM_ABOUT|101|Help..About|
|IDM_LOAD|107|File..Load Settings|
|IDM_SAVE|108|File..Save Settings|
|IDM_SAVEAS|109|File..Save Settings As|
|IDM_DEFAULTS|112|File..Default Settings|
|IDM_EXIT|111|File..Exit [216]|
|IDM_PRINTS|110|File..Print Screen [216][226]|
|IDM_AUTOMOUSE|124|Edit..AutoMouse [211]|
|IDM_COPY|115|Edit..Copy [211]|
|IDM_PASTE|116|Edit..Paste|
|IDM_SCHEDULE|106|Settings..Scheduling|



A-Shell Reference 

Page 2145 

|**Symbol**|**Value **|**Description**|
|---|---|---|
|IDM_BEVELING|122|Settings..Beveling|
|IDM_COLORS|113|Settings..Colors|
|IDM_FONTSYS|123|Settings..Font..System|
|IDM_FONTGUI|132|Settings..Font..GUI|
|IDM_FONTGRID|144|Settings..Font..Grid [211]|
|IDM_MISC|130|Settings..Misc Settings|
|IDM_DLGSIZING|134|Settings..Dialog Sizing|
|IDM_PVPREF|142|Settings..Preview Preferences [211]|
|IDM_KBDLOCK|117|Settings..Keyboard Lock|



A-Shell Reference 

Page 2146 

## **AUI_IMAGE** 

_Updated May 2016; see History_ 

## **xcall AUI, AUI_IMAGE, opcode, handle, status {,parameters...}** 

(Windows only) AUI_IMAGE allows you manage and manipulate images: scan, capture from screen, read from disk, display, convert, etc. Formats supported are BMP, PCX, JPG, TIF, PNG and one-page TIF files using JPG compression. The imaging operations require the use of external graphics library modules vic32.dll and victw32.dll, which are included with the A-Shell installation package and reside in the \bin folder. 

## **Parameters** 

Unlike most subroutines, the parameters for AUI_IMAGE vary with the opcode. Here are the parameters that apply to all opcodes: 

## _opcode_ (Num)  [in] 

|**Symbol**|**Value **|**Function**|
|---|---|---|
|IMGOP_LOAD|1|Load<br>image file from disk|
|IMGOP_CLOSE|2|Close<br>image|
|IMGOP_DISPLAY|3|Display<br> image|
|IMGOP_LOADDISP|4|Open and Display<br>image|
|IMGOP_INFO|5|Retrieve Information<br>about an image|



A-Shell Reference 

Page 2147 

|**Symbol**|**Value **|**Function**|
|---|---|---|
|IMGOP_HIDE|6|Remove from Display|
|IMGOP_ACQUIRE|7|Scan and save image (TWAINAcquire<br>)|
|IMGOP_SELECTSRC|8|Select Data Source|
|IMGOP_TWERR|9|Get TWAIN Error<br>code|
|IMGOP_CAPTURE|10|Capture Screen|
|IMGOP_SAVEAS|11|Convert<br>image|
|IMGOP_PAGEINFO|12|Count Pages<br>in multi-page TIF file|



## _handle_ (Num)  [in/out] 

The Load operation returns this value to identify the image in subsequent calls.  It must be passed to the other operations. 

## _status_ (signed integer)  [out] 

is returned from every call, with 0 indicating success. It should be mapped as a numeric type accepting positive or negative integers, such as F or I.. Possible values of status are given in the following Status Codes table. 

All of the other parameters are documented with they opcodes where they are used. Click on the links in the table above for specific opcodes and functions. 

A-Shell Reference 

Page 2148 

## **History** 

- 2018 August, A Shell 6.5.1644:  TIF files using JPG compression are now supported provided they are single page. 

- 2016 May A Shell 6.3.1512: Source code reorganization: symbols related to AUI_IMAGE have now been separated out of ashell.def into ashinc:image.def and augmented. Programs using them should now `++include ASHINC:ashell.def` and `+ +include:image.def.` 

AUI_IMAGE scanning enhancement: the IMGSF_HIDEUI option in the _scanflags_ parameter now works in single-page scanning mode. Previously single page scans (pages=1) always displayed the scanner's user interface regardless of the _scanflags_ . 

A-Shell Reference 

Page 2149 

## **LOAD** 

_Updated September 2013_ 

## **xcall AUI, AUI_IMAGE, IMGOP_LOAD, handle, status, filename {,pageno}** 

_filename_ is the name of the image file (in either AMOS or native Windows format). Its extension should correspond to the image type. 

_handle_ will be set to an integer value which identifies this image in memory and which must be passed to other calls to indicate which image the call refers to. 

Opening the image does not display it. It merely loads it into memory. Although good programming practice would suggest that you close up any open images at the end of your program, as with open files, A-Shell will automatically close them for you at the end of a program. 

We have the technology to figure out the image type by looking at the image file itself, but did not see much point in exercising it due to the overhead and the questionable benefit of having images with non-standard extensions. If you see this differently, please contact us to discuss the need. 

AUI_IMAGE supports loading up to 31 images at a time. Beyond that, you will need to close some before loading more. Note however that AUI_CONTROL also supports loading images into either buttons or static controls (see Image Control), and it has no limitation on the number of images that can be loaded at one time. 

## **History** 

- 2013 September, A Shell 6.1.1362:  Added _pageno_ to specify the page number of a multi-page TIF to display. The first page is considered 1. 0 is also treated as 1. Note that in order for this feature to be used with ATE, both server and client must be on A- Shell 6.1.1362.0 or later. Also note that since each page could potentially have a different configuration, in order to retrieve information on the page (with IMGOP_INFO), first load the page using IMGOP_LOAD. 

A-Shell Reference 

Page 2150 

## **CLOSE (IMGOP_CLOSE)** 

## **xcall AUI, AUI_IMAGE, IMGOP_CLOSE, handle, status** 

IMGOP_CLOSE removes the image from the screen and frees up the memory associated with it. 

A-Shell Reference 

Page 2151 

## **DISPLAY** 

## **xcall AUI, AUI_IMAGE, IMGOP_DISPLAY, handle, status, strow, stcol, erow, ecol, flags** 

IMGOP_DISPLAY displays the image (identified by _handle_ ) in the position specified by the starting row/column and ending 

row/column parameters. The image will be automatically scaled to fit in the allotted space, although by default the aspect ratio is preserved. So, for example, if the actual image is square, and you specify coordinates that mark out an elongated rectangle, not all of the space will be used for the image. 

_flags_ allows you to specify certain display options, such as whether to stretch the image to fit exactly in the space provided or to preserve its aspect ratio. See Open and Display for _flags_ definitions. 

The first two values apply only to printing. If IMGF_STRETCH  is specified, the aspect ratio is not preserved and the image is stretched as needed to completely fill the specified display rectangle. IMGF_SCALEQ forces us to use linear bitwise interpolation (as opposed to simple bit replication) during scaling, which theoretically will achieve a higher quality, less "blocky" image when enlarging beyond the original image size. 

The image display will overwrite any screen text that it overlaps, and is not affected by other screen operations such as clearing the screen or saving/restoring the screen. The only way to remove it from the screen is with _opcode_ 2 or _opcode_ 6. 

## **Images in Dialogs** 

If a modal dialog is active when the image is displayed, it will be displayed within, and relative to the dialog. If the coordinates given exceed the size of the dialog, the image will be trimmed to the borders of the dialog. This is one good way to display the kinds of horizontal and vertical banner images which are often used in "wizard" dialogs. 

A-Shell Reference 

Page 2152 

## **OPEN AND DISPLAY** 

_Updated September 2013_ 

## **xcall AUI, AUI_IMAGE, IMGOP_LOADDISP, handle, status, srow, scol, erow, ecol, flags, filename** 

## **{,pageno}** 

IMGOP_LOADDISP combines _opcodes 1_ (Load) and 3 (Display) to save you a step. Note that like _opcode 1_ , it leaves the image in memory, so you can later redisplay it using just _opcode 3_ . 

|**Symbol**|**Value **|**Description**|
|---|---|---|
|IMGF_HALFTONE|&h00<br>01|Use halftone print method.|
|IMGF_SCATTER|&h00<br>02|Use scatter print method.|
|IMGF_STRETCH|&h00<br>04|Stretch image to fit bounding rectangle. Otherwise retain aspect<br>ratio, meaning the image will likely be smaller than the rectangle in<br>one of the two dimensions.|
|IMGF_SCALEQ|&h00<br>08|Interpolate—i.e., use hq scaling.|
|IMGF_FORCEXFE<br>R|&h00<br>10|(ATE) Force image filespec to be treated as relative to the host and<br>transfer it to the client. Applies to IMGOP_LOAD and<br>IMGOP_LOADDISP. SeeTransfer of Server-Side Images<br>.|



- Hex Decimal Values 

A-Shell Reference 

Page 2153 

## **History** 

- 2013 September, A Shell 6.1.1362:  Added _pageno_ to specify the page number of a multi-page TIF to display. The first page is considered 1. 0 is also treated as 1. Note that in order for this feature to be used with ATE, both server and client must be on A- Shell 6.1.1362.0 or later. 

A-Shell Reference 

Page 2154 

## **- TRANSFER OF SERVER SIDE IMAGES** 

_Updated February 2020; see History_ 

One advantage of AUI_IMAGE over the otherwise nearly-identical IMAGE is that it has the ability to transfer the specified image from the host/server to the client, a necessary pre-requisite for displaying it on the client. Prior to A-Shell 5.1.1222, this only worked under Unix hosts, and was triggered whenever the image filespec contained a forward slash (indicating a Unix rather than Windows filespec), or the IMGF_FORCEXFER flag was specified. As of 5.1.1222, the transfer logic is also supported under Windows servers, using an ATE proprietary protocol to get around the usual lack of FTP support on Windows servers. 

In addition, the server checks to see if the image is already cached on the client either in the specified directory or one of the client's cache directories or the %miame%\icons directory, eliminating redundant transfers and the corresponding need for a manual pre-transfer of all the images likely to be needed. 

## **History** 

- 2020 February, A Shell 6.5.1676: When either XTEXT or AUI_IMAGE needs to transfer a file between the server and client via {S}FTP, they now use FTP2 rather than the older—and now deprecated—FTPDLX routine. Among other advantages of FTP2 is that it doesn't require registering a DLL on he Windows side. 

A-Shell Reference 

Page 2155 

## **RETRIEVE INFORMATION** 

## **xcall AUI, AUI_IMAGE, IMGOP_INFO, handle, status, imginfo {,filespec}** 

```
MAP1 IMGINFO              ! Image info packet
```

```
MAP2 IMG'OWIDTH,F     ! Original image width (pixels)
```

```
MAP2 IMG'OLENGTH,F    ! Original image length (pixels)
```

```
MAP2 IMG'DWIDTH,F     ! Display width (pixels)
MAP2 IMG'DLENGTH,F    ! Display length (pixels)
MAP2 IMG'BPP,F        ! Bits per pixel
MAP2 IMG'NA,F         ! not used
```

```
MAP2 IMG'TYPE,B,2     ! type: 1=tif,2=bmp,3=jpg,4=pcx,5=tga,6=gif,7=png
MAP2 IMG'BW'BLKPCT,F  ! % black pixels (B&W TIF only)
```

IMGOP_INFO retrieves some information about a previously opened image (by specifying the image _handle_ ), or from the disk file _filespec_ . The information is reasonably self-explanatory. Note that the operation can also be used merely to verify if a particular _handle_ value is valid. 

We may be adding fields to this structure in the future to accommodate additional pieces of information that developers discover a need for. The routine will however always be smart enough to look at the size of the packet you pass so as to not overrun the packet if new fields are added but not yet mapped in existing programs. 

## **History** 

- 2016 April, A Shell 6.3.1512:  The IMGOP_INFO opcode now returns the percent black for B&W TIF images. The calculation eliminates some noise (individual floating bits) and also ignores an outer margin equal to 1/40th of the width and/or length, and may be useful as a way of detecting blank (or perhaps too-light or too-dark) pages during scanning. 

A-Shell Reference 

Page 2156 

## **REMOVE FROM DISPLAY** 

## **xcall AUI, AUI_IMAGE, IMGOP_HIDE, handle, status** 

IMGOP_HIDE is similar to Close except that it leaves the image (still identified by _handle_ ) in memory so that it can be displayed again later without having to open it. This might be deemed more efficient in some applications than fully closing and reopening the image when switching between various screen displays. 

A-Shell Reference 

Page 2157 

## **ACQUIRE** 

_Updated May 2016; see History_ 

## **xcall AUI, AUI_IMAGE, IMGOP_ACQUIRE, handle, status, filespec, attribs {,appname, pages, scanflags, pagesize}** 

IMGOP_ACQUIRE invokes a TWAIN "Acquire" to retrieve an image from the default TWAIN input device (aka "Data Source"). In the most common case, which involves scanners, this is equivalent to "scan-and-save-image". Manufacturers of image input devices such as scanners typically provide a TWAIN driver and user interface which allows the user to access the functionality of the device. This way, the application does not need to know any details about the device (such as what kinds of controls and options it has). It just knows that once the Acquire operation is started, it will return with a file (if successful) or an error code (if not). 

- IMGOP_ACQUIRE provides support for scanning multiple pages; see the following topic, Multi Page Scanning, for more information. 

## **Parameters** 

_handle_ (Num)  [in] 

is not used here, is included only for conformity with the other opcodes.NumString 

_status_ (Num)  [out] 

returns 0 for success, else an error; see Status Codes. 

## _filespec_ 

is the specification of the file (AMOS or native format) to store the image in. The extension you specify will determine the image format and must be one of the file types listed in the _comp_ following table (e.g. test.jpg or dsk9:test.bmp[100,20]). 

## _attribs_ [in] 

defines various attributes for the scan, mapped as shown below. 

```
map1 attribs,b,4            ! compress, pixel type, resolution attributes
```

```
map1 attribsx,@attribs      ! overlay to break out fields
```

A-Shell Reference 

Page 2158 

```
   map2 comp,b,1            ! compression options; see below)
   map2 pixtype,b,1         ! pixel type: (see below)
   map2 resx,b,1            ! x resolution (in multiples of 25 DPI)
   map2 resy,b,1            ! y resolution (in multiples of 25 DIP)
```

## _comp_ [in] 

is a compression-related factor determined by the image type: 

|**Type**|**Explanation**|**Explanation**|**Explanation**|
|---|---|---|---|
|JPG|Values range from 1 to 100, with 100 being maximum size and quality—<br>i.e., minimum compression. 75 is the default and is generally considered<br>the point below which you start to perceive the loss of quality.|||
|TIF|**Symbol**|**Valu**<br>**e**|**Meaning**|
||TIFCF_NONE|0|No compression|
||TIFCF_PACKB<br>ITS|2|Pack Bits|
||TIFCF_GROU<br>P3|3|Group 3|



A-Shell Reference 

Page 2159 

|**Type**|**Explanation**|**Explanation**|**Explanation**|**Explanation**|
|---|---|---|---|---|
||TIFCF_GROU<br>P4|4|Group 4||
||TIFCF_CCITT<br>3|5|CCITT Group 3||
|BMP,PC<br>X|Ignored, not used||||
|PNG|**Symbol**|**Value**||**Meaning**|
||PNGF_ALL|0||Use best filter for each row (best compression)|
||PNGF_NONE|2||No filter (fastest)|
||PNGF_SUB|4||Difference filter with adjacent pixel|
||PNGF_UP|6||Difference filter with previous row|
||PNGF_AVG|8||Average filter|
||PNGF_PAETH|10||Paeth filter|



A-Shell Reference 

Page 2160 

|**Type**|**Explanation**|
|---|---|
||To save as an interlaced file, addPNGF_INTERLACE(+1) to any of the above.|



## _pixtype_ [in] 

The _pixtype_ options are shown in the following table. The first three of these are standard for most scanners, the others are somewhat exotic and may not be supported. 

|**Value**|**Definition**|
|---|---|
|1|Black and white (bi-level)|
|2|Grayscale (8 bit)|
|3|RGG (24 bit)|
|4|Palette|
|5|CMY|
|6|CMYK|



A-Shell Reference 

Page 2161 

|**Value**|**Definition**|
|---|---|
|7|YUV|
|8|YUVK|
|9|CIEXYZ|



_resx, resy_ [in] 

these fields are scaled to multiples of 25 DPI (i.e. 12=300 DPI), in order to fit a reasonable range of possible resolutions in 8 bits. 

For each of the _pixtype_ , _resx_ , and _resy_ fields, 0 is interpreted as no change to the existing or default settings. So existing programs that pass only the old _comp_ value will continue to work as before. 

Note that for many scanners, setting the pixel type and resolution options may not have an effect unless the IMGSF_HIDEUI flag is set in the _scanflags_ parameter. That is, displaying the scanner's user interface may override the application settings with the scanner's own previously saved settings. 

## _appname_ (String)  [in] 

is an optional string containing the name of your application, which, depending on the particular TWAIN driver, may be displayed in the title bar of the device’s user interface window. 

## _pages_ (Num)  [in/out] 

specifies the desired (or maximum) number of pages to scan. On return, it will contain the actual number scanned. 

A-Shell Reference 

Page 2162 

## _scanflags_ (Num)  [in] 

## specifies flags (defined in ashell.def) affecting the scanning operation: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|IMGSF_HIDEUI|&h000<br>1|Hide the scanner's user interface dialog, forcing the user to scan based on<br>the settings previously established.|
|IMGSF_ADFOUT|&h000<br>2|Quit when the Automatic Document Feeder (ADF) is out of paper (even if<br>less than the number of pages requested)|
|IMGSF_CONTIN<br>UE|&h000<br>4|Keep scanning until the requested # of pages is received, or the operator<br>terminates the operation, or an unrecoverable error. This may be the<br>same as the default operation, although in cases where there is no ADF, it<br>may be necessary in order to force the operation to continue for multiple<br>pages, since otherwise the scanner may return an ambiguous status,<br>making it unclear to the application whether the operator decided not to<br>continue, or the scanner just didn't now how to do multiple scans in one<br>call.|



## _pagesize_ (Num)  [in] 

sets pagesize. Options are defined in the ASHINC:ashell.def file, the most common options being: `TWSS_A4LETTER = 1, TWSS_USLETTER = 3, TWSS_USLEGAL  = 4` 

## **Comments** 

Note that the acquisition (scanning) of the image data is independent of the saving of the image file, so it is up to you to specify an image format (via the file extension) that is compatible with the type of scan. (Or conversely, for the scanning operator to 

A-Shell Reference 

Page 2163 

select options compatible with the file format.) For example, PCX only supports 1 and 8 bit data, so a 24-bit scan will result in an error while attempting to save the file. 

See the program IMAGE.BP in EXLIB:[908,32] for an example of using the _pages_ and _scanflags_ parameters. 

## **History** 

- 2016 April, A Shell 6.3.1512:  Add ability to set the page size via the _pagesize_ parameter. 

- 2016 April, A Shell 6.3.1510: Old _comp_ parameter _redefined_ as attribs. Note that existing/older programs which simply use the _comp_ parameter remain upward compatible with the _attribs_ interpretation; the layout above guarantees that the _comp_ value is interpreted the same either way, and the other fields would just be considered zero, meaning use the current defaults. 

- 2016 April, A Shell 6.3.1510: the IMGSF_HIDEUI option in the _scanflags_ parameter now works in single-page scanning mode. Previously single page scans (pages=1) always displayed the scanner's user interface regardless of the _scanflags_ . 

- 2012 June, A Shell 6.2.1306:  Add support for multi-page scanning via the _pages_ and _scanflags_ parameters. 

A-Shell Reference 

Page 2164 

## **- MULTI PAGE SCANNING** 

The individual pages of the scan will be saved using the filespec, but with the page # appended. So if you set filespec = "scan.tif", the resulting files would be "scan-1.tif", "scan-2.tif", etc. 

Typical multi-page scanning scenarios: 

• Documents with fixed number of pages (say, 5). Set PAGES=5, and IMGSF_CONTINUE flag. Depending on the nature of the scanner and whether the IMGSF_HIDEUI flags is set, the user may see a dialog containing SCAN/CLOSE/CANCEL buttons. Or maybe the scanner just returns after each scan (in which case the subroutine will internally keep calling it until it gets the 5 pages or an explicit CANCEL or other error is returned). Assuming all goes well, the subroutine returns STATUS=0 and PAGES=5 to the caller. If it runs into an error on page 3 and can't continue, it would return PAGES=2 (2 pages scanned) and STATUS=<some error code>. 

• Documents with variable number of pages. Set PAGES to a suitably high maximum value, perhaps 999999. If you are using the feeder to determine the end of the document (i.e. the operator will load exactly one document at a time), set IMGSF_ADFOUT. Else rely on the user to terminate the scan job after the desired number of pages. (Although there is some question whether it will always be possible to distinguish between a true "cancel", which should return STATUS=15, and "done" which ideally would return STATUS=0 to the application, but necessarily will have to return some other status to the internal interface to get it to stop scanning.) The application would presumably look at STATUS to make sure that the scan operation terminated normally, and then at PAGES to see how many pages were scanned. 

A-Shell Reference 

Page 2165 

## **SELECT DATA SOURCE** 

## **xcall AUI, AUI_IMAGE, IMGOP_SELECTSRC, handle, status {,sourcename}** 

IMGOP_SELECTSRC allows you to specify which of the available TWAIN data sources (input devices) is to be used for subsequent "Acquire" operations. If _sourcename_ is specified and non-blank, it will attempt to select the corresponding data source from among the available options. Otherwise it will pop up a dialog box allowing the user to select from among the available data sources. 

This operation (with no _sourcename_ ) should be exactly equivalent to the "Select Source" menu option that appears on the File menu of most programs that support TWAIN. 

A-Shell Reference 

Page 2166 

## **GET TWAIN ERROR** 

## **xcall AUI, AUI_IMAGE, IMGOP_TWERR, handle, status** 

IMGOP_TWERR only applies when the _status_ returned from another _opcode_ is 11 (TWAIN error). In that case, you can use _opcode_ 9 to retrieve a more specific error code, among the following: 

|**Value**|**Meaning**|
|---|---|
|1|Failure due to unknown causes|
|2|Not enough memory to perform<br>operation|
|3|No data source|
|4|Source already in use|
|5|Source/Manager error already reported|
|6|Unknown capability requested|
|7|Undefined error|
|8|Undefined error|
|9|Bad protocol|



A-Shell Reference 

Page 2167 

|**Value**|**Meaning**|
|---|---|
|||
|10|Parameter out of range|
|11|Message received out of sequence|
|12|Unknown destination source app|
|13|Could not create parent window|
|14|TWAIN Source Manager not found|



A-Shell Reference 

Page 2168 

## **CAPTURE SCREEN** 

## **xcall AUI, AUI_IMAGE, IMGOP_CAPTURE, handle, status, fspec, comp, winid** 

IMGOP_CAPTURE captures the screen or a window to a file. The concept is similar to that for IMGOP_ACQUIRE, except that the source of the image is the screen/monitor rather than a scanner. 

The parameter sequence and interpretation is also nearly identical to IMGOP_CAPTURE. The main exception is the last parameter (which in IMGOP_CAPTURE specifies the title to put on the scan dialog). Here it identifies the screen option to capture: 

## **Parameters** 

## _winid_ (String)  [in] 

indicates the image source: 

|**Symbol**|**Valu**<br>**e**|**Meaning**|
|---|---|---|
|IMGCWF_CURWI<br>N|-2|current A-Shell window or modal dialog (if<br>applicable)|
|IMGCWF_SCREE<br>N|-1|entire screen (primary monitor only)|
|IMGCWF_MAIN|0|main A-Shell window|
||0##<br>#|arbitrary window or control handle ###|



A-Shell Reference 

Page 2169 

|**Symbol**|**Valu**<br>**e**|**Meaning**|
|---|---|---|
||###|id of the AUI control to capture|
||name|name of the AUI control to capture|



Note that options -2 and 0 capture the target window/dialog and anything above it. 

## _comp_ [in] 

## In addition to the values shown in Acquire, _comp_ in this context (screen capture) supports these additional flags: 

|**Flag**|**Value**|**Meaning**|
|---|---|---|
|IMGCF_CLIENT|&h0008000<br>0|Capture just the client area of the target window. Else<br>include window border, title bar, menu, etc.|
|IMGCF_GRAY|&h0010000<br>0|Convert captured image to grayscale|
|**All of the following imply grayscale**|||
|IMGCF_BI_SCATTE<br>R|&h0020000<br>0|Convert to bi-level using scatter method|



A-Shell Reference 

Page 2170 

|**Flag**|**Value**|**Meaning**|
|---|---|---|
|IMGCF_BI_DITHER|&h0040000<br>0|Convert to bi-level using dither method|
|IMGCF_BI_THRESH|&h0080000<br>0|Convert to bi-level using threshold method|
|IMGCF_NEGATE|&h0100000<br>0|Negative image (useful with black window bg)|
|IMGCF_INKSAVER|&h0200000<br>0|Save ink by converting most common color to white*|



*The "ink saver" option attempts to address the common complaint about graphic screen images using up too much printer ink or toner. It analyzes the image to identify the color responsible for the most ink, then converts that color to white (requiring no ink). Any pixels that were originally white are changed to a light-gray so as to not completely disappear into the background. 

## **History** 

## - 2011 May, A Shell 5.1.1215: function added to A-Shell 

A-Shell Reference 

Page 2171 

## **CONVERT** 

## **xcall AUI, AUI_IMAGE,IMGOP_SAVEAS, handle, status, fspec, comp** 

IMGOP_SAVEAS takes a previously loaded image—specified by _handle_ —and saves it to the specified _fspec_ , converting the format in accordance with the extension in the _fspec_ and the _comp_ options. 

For example, you could use this opcode to load a 24 bit color BMP and save it as an 8 bit grayscale PNG with the "Ink Saver" transformation. In fact, the print screen utility (APRNTSCRN.SBX) now uses this technique to process changes in the image attributes, which is faster than taking a new screen picture. 

See Status Codes for the possible returned status values, and IMGOP_ACQUIRE and IMGOP_CAPTURE for definitions of the _comp_ options applicable to the supported image extensions/formats (JPG, TIF, BMP, PCX, PNG). Also see the sample program IMAGE in EXLIB:[908,32] for a complete example. 

## **History** 

- 2011 May, A Shell 5.1.1215: Function added to A-Shell 

A-Shell Reference 

Page 2172 

## **COUNT PAGES** 

_Added September 2013_ 

IMGOP_PAGEINFO returns the number of pages in a multi-page TIF file. 

## **xcall AUI, AUI_IMAGE, IMGOP_PAGEINFO, handle, status, filename, pages** 

## **Parameters** 

_handle_ 

Ignored. It is here only for uniformity with other opcodes 

_status_ (F,6)  [out] 

returns status; 0 for success 

_filename_ (String)  [in] 

file to examine, as for opcode 1 

_pages_ (Num)  [out] 

returns the number of pages in the file. 0 indicates that the number is unknown—or more likely, the file does not support multiple pages 

Note that in order for this feature to be used with ATE, both server and client must be on A-Shell 6.1.1362.0 or later. 

## **History** 

- 2013 September, A Shell 6.1.1362:  function added to A-Shell 

A-Shell Reference 

Page 2173 

## **STATUS CODES** 

The variable _status_ is returned from each xcall IMAGE operation (except for _opcode_ 9), with 0 indicating success. Common error codes are: 

|**Value **|**Meaning**|
|---|---|
|25|ADF out of paper|
|24|Unsupported platform|
|23|Bad window id|
|22|Unable to load icon|
|21|Cannot center|
|20|Unable to add/remove image to imagelist|
|19|Bad imagelist handle|
|18|Unable to write disk (full?)|
|17|Bits per pixel either unsupported or incompatible with<br>image type. For example, JPG requires 8 bpp.|



A-Shell Reference 

Page 2174 

|**Value **|**Meaning**|
|---|---|
|16|TWAIN function is busy|
|15|User cancelled scan|
|14|Could not open TWAIN Data Source|
|13|Could not open TWAIN Source Manager|
|12|Could not create TWAIN parent window|
|11|TWAIN error (See OPCODE 9)|
|10|Cannot load or linkvic32.dll(the imaging library<br>module)|
|9|Miscellaneous subroutine parameter error|
|8|Error during attempt to scale image|
|7|Bad image handle|
|6|Bad OPCODE|



A-Shell Reference 

Page 2175 

|**Value **|**Meaning**|
|---|---|
|5|Unable to allocated memory needed|
|4|Exceeded maximum number of open images (31)|
|3|Unknown image type/extension|
|2|Image file not found|
|1|Too few parameters passed to subroutine|
|0|OK|



## The remaining errors are returned from within the vic32.dll library 

|**Value **|**Meaning**|
|---|---|
|–1|Range error|
|–2|Digitizer board not detected|
|–3|Disk full|



A-Shell Reference 

Page 2176 

|**Value **|**Meaning**|
|---|---|
|–4|Filename not found|
|–5|Variable out of range|
|–6|Unreadable TIFF format|
|–7|8 TIFF bits per sample not supported|
|–9|Unreadable compression scheme|
|–10|Cannot create file|
|–11|Unknown file format|
|–12|Compressed DIB not supported|
|–14|Insufficient memory for function|
|–16|Unreadable PCX format|
|–17|Unreadable GIF format|



A-Shell Reference 

Page 2177 

|**Value **|**Meaning**|
|---|---|
|–18|Print error|
|–25|Unreadable TGA format|
|–26|Bits per pixel value not supported|
|–27|Unreadable BMP format|
|–34|Function timed out|
|–40|Could not lock memory|
|–41|Print function already executing|
|–42|Invalid image buffer address|
|–43|Unreadable JPEG format|
|–44|Image is too complex for operation|
|–53|LZW compression/decompress not enabled|



A-Shell Reference 

Page 2178 

|**Value **|**Meaning**|
|---|---|
|–68|Handle not valid|
|–69|TIFF file is in Motorola byte order|



## The following errors apply only to PNG images. 

|-100|Unknown critical chunk|
|---|---|
|-101|Not enough IDATs for image|
|-102|Invalid IHDR chunk|
|-103|Invalid bit depth in IHDR|
|-104|Invalid color type in IHDR|
|-105|Invalid color type/bit depth combo|
|-106|Invalid interlace method in IHDR|
|-107|Invalid compression method in IHDR|



A-Shell Reference 

Page 2179 

|-108|Invalid filter method in IHDR|
|---|---|
|-109|Invalid image size in IHDR|
|-110|Bad PNG signature|
|-111|Bad CRC value|
|-112|Extra data at end of file|
|-113|Unexpected End Of File|
|-114|Memory error|
|-115|Decompression error|
|-116|Compression error|
|-117|Out of disk space|



A-Shell Reference 

Page 2180 

## **AUI_WINDOW** 

## **xcall AUI, AUI_WINDOW, opflag {,lft,top,rgt,btm {,rows,cols {,tsts,bsts {,cid,hg,vg {,monitors** 

## **{,winsts}}}}}}** 

The AUI_WINDOW class is used for querying and changing the parameters of the window or monitor(s), such as its size, position, display state, number of rows and columns, etc. 

## This function has both a subroutine and a print tab implementation. 

## _opflag_ (Num)  [in] 

specifies the window state desired, or an option to query the current state, per the following table. 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SW_QRYCTLPIXCLI|-4|Same as SW_QRYCTLPIX (-3), except that it returns the control's<br>client rectangle in the lft,top,rgt and btm parameters, instead of the<br>control's window rectangle relative to the desktop. The client<br>rectangle always starts at 0,0, so that the rgt and btm parameters<br>give the width and height of the "usable" area (not counting borders,<br>menus, caption) of the control.|
|SW_QRYCTLPIX or SW_QRYPIX|-3|Same as -1 (SW_QRYCTLUNV) but returns the coordinates of the<br>target window or control in pixels rather than Universal units.|
|SW_QRYMONPIX or SW_QRYMON|-2|Query (multiple) monitor information. See_cid_. Returns rectangle (in<br>pixel coordinates) in_lft, top, rgt, btm._|



A-Shell Reference 

Page 2181 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SW_QRYCTLUNV or SW_QUERY|-1|Query the current settings and update all of the passed parameters<br>accordingly, return values in Universal units. See_cid_.|
|SW_HIDE|0|Hide window (i.e. make it invisible)|
|SW_SHOWNORMAL|1|Show window in normal format (neither minimized nor maximized)|
|SW_SHOWMINIMIZED|2|Activate window and show it minimized (displayed on the task bar)|
|SW_SHOWMAXIMIZED|3|Activate window and show it maximized|
|SW_SHOWNOACTIVATE|4|Show window in its most recent position but do not activate it|
|SW_SHOW|5|Activate and show window in its current size and position|
|SW_MINIMIZE|6|Minimize window and activate the next window in the task list|
|SW_MINNOACTIVE|7|Displays the window as a minimized window. This value is similar to<br>SW_SHOWMINIMIZED, except the window is not activated|
|SW_SHOWNA|8|Display window in its current size and position, but do not activate it|
|SW_RESTORE|9|Restore a minimized or maximized window to its original position|



A-Shell Reference 

Page 2182 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||||
|SW_WINDEFAULT|10|Display the window in the default state as defined in the shortcut or<br>startup info associated with the application|
|SW_ASHDEFAULT|65|Causes the window to initially be reset based on the current settings<br>file (as edited on the Settings menu and saved with the File..Save<br>menu). Omit all other parameters, or set them to 0 (except -1 for<br>_tsts_and_bsts_).|



## _lft, top, rgt, btm_ (Num)  [in/out] 

specify or retrieve the coordinates of the Window or monitor. Window coordinates ( _cid_ > 0) are in standardized units that range from 0,0 for the upper left corner of the screen to 10000,10000 for the bottom right. You may leave these 0 to retain the current window coordinates (if you just want to change the _rows_ / _cols_ or status lines.) Monitor coordinates ( _opflag_ = -2, _cid_ < 0) are in pixels (and may be negative for secondary monitors). 

When _opflag_ = -1 and _cid_ < 0 (to retrieve desktop resolution), these parameters taken on new meaning. _lft_ and _top_ return the dialog (altpos) grid size in pixels, while _rgt_ and _btm_ return the primary monitor size in dialog (altpos) grid units. (This provides an idea of the maximum size dialog that will fit on the screen.) 

_rows ,cols_ (Num)  [in/out] 

A-Shell Reference 

Page 2183 

|**cid**|**opfla**<br>**g**|**Target object, information returned (for queries)**|
|---|---|---|
|0|< 0|Return the main window grid in rows and columns (e.g. 24 x 80)|
|0|>= 0|Set the main window grid in rows and columns. Equivalent of tab(-5,rows) if rows > 0 and tab(-6,cols) if<br>cols > 0|
|0|>0|Return the size of the target control in millirows and millcolumns.|
|<0|-1|Return the dialog size overhead (title bar, borders, margins) in universal coordinates. Note that as a<br>general rule, the vertical overhead is equivalent to one logical row (one vertical dialog unit) and the<br>horizontal overhead is negligible.|
|<0|-3|Return the dialog size overhead (title bar, borders, margins) in pixels.|



## _tsts, bsts_ (Num)  [in / out] 

specify or retrieve the visible / invisible state of the top and bottom status lines (1=visible, 0=invisible). You may leave these -1 (or omit them) to retain the current status line state. 

## _cid_ (String or Num) [in] 

Identifies the window, control, or monitor that the operation is to be performed on, per the following table. Default is 0, i.e. the main window. See _Comments_ . 

A-Shell Reference 

Page 2184 

|**cid**|**opflag**|**Target object, information returned (for queries)**|
|---|---|---|
|>0 (or name)|0-9|Perform the display operation specified by opflag (e.g. show, hide, etc.) on the specified<br>control or window. No information returned. Operations on non-window controls may be<br>limited to SW_HIDE and SW_SHOW.|
|>0 (or name)|-1 or -3|_cid_identifies the control to be queried by its control number or name._lft_,_top_,_rgt_,_btm_<br>return the coordinates of the control, in universal coordinates (if_opflag_= -1), or pixels (if<br>_opflag_= -3)._rows_and_cols_return the logical size of the control in millirows and columns.|
|0|-1 or<br>-3|Main window._lft_,_top_,_rgt_,_btm_return the coordinates of the control, in universal coordinates<br>(if_opflag_= -1), or pixels (if_opflag_= -3)._rows_and_cols_return the logical size of the control<br>in millirows and columns._tsts_,_bsts_indicate the status line presence.|
|-1|-1|Primary monitor._lft_and_top_return dialog (altpos) grid size._rgt_and_btm_return monitor<br>size in dialog units._hg_and_vg_return monitor resolution in pixels.|
|-1|-2|Primary monitor._lft, top, rgt, btm_return pixel coordinates of monitor.|
|-2|-1|Primary monitor. Same as if_cid_= -1 except subtracts area of the task bar from the<br>returned parameters.|
|-2|-2|Primary monitor work area._lft, top, rgt, btm_return pixel coordinates of monitor less task<br>bar.|
|-3|-2|Second monitor._lft, top, rgt, btm_return pixel coordinates of monitor (which may be<br>negative if second monitor is to left of primary monitor).|



A-Shell Reference 

Page 2185 

|**cid**|**opflag**|**Target object, information returned (for queries)**|
|---|---|---|
|-4|-2|Second monitor work area._lft, top, rgt, btm_return pixel coordinates of monitor less task<br>bar.|
|-5|-2|Third monitor._lft, top, rgt, btm_return pixel coordinates of monitor. If there are three<br>monitors, the assumed configuration is with the second monitor on the left, the third on the<br>right.|
|-6|-2|Third monitor work area._lft, top, rgt, btm_return pixel coordinates of monitor less task<br>bar.|
|-99|-2|Total virtual screen._lft_,_top_,_rgt_,_btm_return pixel coordinates of the bounding rectangle for<br>the combination of all the monitors. Note that in the case of multiple monitors, depending<br>on their arrangement and configuration, there may be spaces within this rectangle which do<br>not actually appear on any monitor.|



## _hg, vg_ (Num)  [out] 

These parameters, horizontal and vertical grid units, are applicable only when _opflag_ = -1 (i.e. for query mode). When _cid_ = -1, these return the screen resolution in pixels. Otherwise, they return the grid size, in universal units (0-10000) of the specified window or control. You can compare these grid values to the values returned in the _lft, top, rgt, btm_ coordinates to determine sizes and positions in terms of row/column units. 

## _monitors_ (Num)  [out] 

When _opflag_ < 0, returns the number of monitors currently enabled. (You can then use opflag = -2 to retrieve information about individual monitors.) 

A-Shell Reference 

Page 2186 

## _winsts_ (Num)  [out] 

## If specified with one of the query opflags, _winsts_ will return one of: 

|**Symbol**|**Valu**<br>**e**|**Description**|
|---|---|---|
|SW_HIDE|0|Window is hidden|
|SW_SHOWNORMAL|1|Window is neither minimized nor maximized|
|SW_SHOWMINIMIZED|2|Window is minimized|
|SW_SHOWMAXIMIZED|3|Window is maximized|



Example: 

```
! retrieve status of main window
```

```
xcall AUI, AUI_WINDOW, SW_QUERY, 0,0,0,0, 0,0, 0,0, 0, 0,0,0, winsts
```

```
switch winsts
```

```
    case SW_HIDE
    ...
```

## **Examples** 

See the sample program AUIWIN [908,28] 

A-Shell Reference 

Page 2187 

## **Comments** 

When it comes to querying an individual control, the functionality of AUI_WINDOW overlaps that of AUI_CONTROL (with opcode CTLOP_INFO). In choosing between them, note that CTLOP_INFO returns coordinate information in logical millirows and columns, and relative to the parent of the control or window. These values will not be affected by moving the window or dialog around on the screen, or even resizing it. AUI_WINDOW, on the other hand, returns raw coordinate information, typically in "universal coordinates", relative to the desktop. 

If using AUI_WINDOW to hide or display a control other than the main window, set _cid_ to the name of numeric ID of the control, and set all the intervening parameters to 0, except _tsts_ and _bsts_ which should be set to -1. This functionality overlaps with that of AUI_CONTROL using _opcode_ CTLOP_CHG. 

A-Shell Reference 

Page 2188 

## **AUI_HTMLHELP** 

## **xcall AUI, AUI_HTMLHELP, opcode, status, hfile {,htopic{, row, col}}** 

The HTMLHELP class provides means of displaying context-sensitive help using Windows CHM/HTML help system. By establishing links between topics in your help file and operations in your program, you can call the appropriate topic when the user invokes help. As currently implemented, the specified CHM file opens and displays the referenced topic. 

## **Parameters** 

## _opcode_ (Num) 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|HHOP_DFLT|0|Set default application help file. This allows help topics to be specified toINFLDwithout<br>having to specify the help file each time.|
|HHOP_DSPID|1|Display topic based on HFILE (or default), and a numeric topic ID in HTOPIC. (You will have to<br>consult the creator of your CHM files to get a list of the numeric topic ID numbers.) If HTOPIC<br>is 0, the help file is launched in its default state.|
|HHOP_DSPSTR|2|Same as 1 except HTOPIC should be a string which specifies the internal HTM name for the<br>desired topic. These internal names are typically of the form "/topicname.htm", e.g.<br>"/comio.htm". The leading slash is typically necessary. You might be able to determine these<br>names by using a binary DUMP utility on the CHM file (such asDUMP.LIT). As with_opcode_1,<br>if HTOPIC is "", the help file is launched in its default state.|
|HHOP_POPUP|3|Display a pop-up message. The text of the message (up to 2048 characters) should be<br>specified in HTOPIC, and HFILE should be "". If ROW and COL are specified and non-zero,<br>then the top center of the pop-up box will be positioned at that point. Otherwise, the pop-up|



A-Shell Reference 

Page 2189 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||box will be positioned just below the current cursor location.|



## _status_ 

If you want a return status, specify an F,6 variable, in which case, >=0 indicates success, and <0 indicates failure (including -15 for ATE timeout). The most likely failures would be that the CHM system is not supported (due to running on Unix without ATE or perhaps an old version of Windows), or the help file/topic could not be located. If you do not care about the return status, specify this parameter as "". (This eliminates the need for the ATE client to return anything, which is a minor optimization.) 

_hfile_ (String) 

File filespec of CHM file. May be in AMOS or native format and may contain environment variables using the %ENV% syntax. Note that you may put your help files in the same directory as the A-Shell help files, in which case you can reference them by: 

```
HFILE = "%MIAME%\doc\filename.chm"
```

If the environment variable %MIAME% is not explicitly defined, it will be interpreted as pointing to the directory where miame.ini is located. 

_htopic_ (must be String for _opcode_ 2 & 3, may be Num for _opcode_ 1) 

Specifies the topic name (<topic>.htm) ( _opcode_ 2) or ID ( _opcode_ 1) or the actual text to display ( _opcode_ 3). Text may contain embedded CRLF characters for line breaks. 

## _row, col_ (Num) 

These apply only to _opcode_ 3, and only if you want to position the help window somewhere other than just below the cursor location. (For large messages, you might want to position it at something like ROW=2,COL=40.) 

This function works in A-Shell/Windows and ATE. It may also be called via MX_HTMLHELP (replacing "HTMLHELP" with 137). 

A-Shell Reference 

Page 2190 

## **B64ENC** 

_Updated October 2017_ 

## **xcall B64ENC, infile, och, status {,flag}** 

## **xcall B64ENC, indata, outdata, status, flag** 

B64ENC provides Base 64 (aka MIME) encoding and decoding. The first format encodes a file, writing the encoded output to another file, while the second format may be used for encoding and decoding of memory buffers. 

## **Parameters** 

_infile_ (String)  [in] 

Specification of file to encode in AMOS or native format 

_och_ (Num) [in] 

Channel of a file, previously opened for output, to which the encoded version of the input file will be written. The file remains open on return. 

_status_ (Signed Num)  [out] 

On return, will be set to the number of bytes written, or <0 for errors 

|**Value **|**Description**|
|---|---|
|>=0|Number of bytes written|
|-1|_infile_not found|
|-2|unable to open_infile_|



A-Shell Reference 

Page 2191 

|**Value **|**Description**|
|---|---|
|-3|_och_not valid (not open for OUTPUT)|
|-4|file error during input of file|
|-5|error during output|
|-6|_outdata_too small to hold encrypted output|



_indata_ (X or String)  [in] 

Variable containing data to encode or decode 

_outdata_ (X or String)  [out] 

Variable containing encoded or decoded version of _indata_ .  Since encoded data is 4/3 larger than raw data, the determination of whether the operation is encode or decode is based on the relative sizes of the _indata_ and _outdata_ parameters. If the physical variable _outdata_ is larger than _indata_ , then the operation will be to encode; otherwise it will be to decode. If using a dynamic string (S,0), you will need to initialize it so that it's effective size is greater than or less than the size of the indata string, depending on whether you are encoding or decoding. See the BASIC string function FILL$() for a convenient way to do this. 

## _flag_ (Num)  [in] 

If not specified, or set to 0, the format is assumed to be that given in the first syntax line above (encode a file).  Otherwise, to encode a memory buffer, _flag_ must be set to the number of bytes in _indata_ to encode.  (Since raw data may contain binary values, including 0, we can not use the normal string length method of determining the logical size of the input data.)  To decode data, _flag_ should be set to 1. 

## **Comments** 

A-Shell Reference 

Page 2192 

Base 64 encoded data uses only 64 distinct bytes (all printable) for representation, which is often convenient for including binary data within formats that are otherwise string-oriented (such as email). Because only six bits are used in each byte of the encoded representation, the encoded version of the data is 4/3 larger than the raw data. The raw data does not have to be a multiple of three. 

When using the first forma, to encode to an output file, the base64 data is split into lines of 72 characters. The decoding routine, however, expects the base64 data in the _indata_ parameter to be a single linear string with no line breaks. 

See the module fnb64.sbi in SOSLIB:[907,10] for a collection of convenience function wrappers for B64ENC. 

Also, for a more symmetrical implementation of base64 encoding/decoding, including other encoding formats such as hex, see CRYPTO. 

A-Shell Reference 

Page 2193 

## **BASORT** 

_Updated September 2025, see History_ 

Random file syntax: 

**xcall BASORT, ch, reccnt, recsiz, k1siz, k1pos, k1ord {,k2siz, k2pos, k2ord, k3siz, k3pos, k3ord, k1typ, k2typ, k3typ, k4siz, k4pos, k4ord, k5siz, k5pos, k5ord, k6siz, k6pos, k6ord, k4typ, k5typ, k6typ}** 

Sequential file syntax: 

**xcall BASORT, chin, chout, recsiz, k1siz, k1pos, k1ord {,k2siz, k2pos, k2ord, k3siz, k3pos, k3ord,** 

## **k1typ, k2typ, k3typ}** 

Note that in the syntax shown above, spaces and line breaks have no meaning—i.e., they do not and should not exist in the actual program. They are used here strictly as visual aides to illustrate the structure of the commands. 

xs BASORT sorts files, both random (aka contiguous) and sequential (aka  stream). For sorting arrays in memory, see SORTIT . 

A-Shell Reference 

Page 2194 

## All BASORT parameters are [in] and Num. 

All parameters after _k1ord_ are optional and if not specified, default to zero. Keys with 0 size or position are ignored. Keys with no explicit type default to string (0). 

|**Param**|**Description**|
|---|---|
|ch|File channel (used only with random files).|
|chin|Input file channel (used only with sequential files)|
|chout|Output file channel (used only with sequential files)|
|reccnt|Number of records in the file.|
|recsiz|Record length. For sequential files, this should be equal to or greater than the longest line in the file.<br>Maximum size is 6K.|
|k?siz|Size of the sort key, in bytes. May use.SIZEOF()<br>to rely on compiler to specify correct size.|
|k?pos|First character position occupied by the key. May use.OFFSET()<br> macro to have the compiler calculate the<br>correct offset.|
|k?ord|Sort order of the key, where 0=ascending, 1=descending.|
|k?typ|Data type of the key: 0=String, 1=Floating Point (random files only), 2=Binary (random files only), 3=Integer<br>(random only), 4=Natural Sort<br>,5=case-insensitive natural sort. See History note for A-Shell 5.1.1135 below|



A-Shell Reference 

Page 2195 

|**Param**|**Description**|
|---|---|
||for more details on types 3-5.|



A-Shell's implementation of BASORT is fully compatible with the original, optimized to make the best use of memory available. The sorting process is based around the quicksort algorithm, but up to three different types of sort may be performed depending on the amount of free memory. In the default case, the free memory is taken from the A-Shell partition. However, under systems with large amounts of efficient virtual memory available (e.g. Unix and Windows), you may specify the system parameter SBR=MALLOCSORT to cause A-Shell to dynamically allocate, if possible, a chunk of memory large enough to sort the entire file in one quicksort operation. See SBRSP topic for more details on the SBR options. 

In the case of the sequential file sort, there is no option for key types because the keys must be string type. Also, since the record lengths can be variable, you should specify a _recsiz_ as large or larger than the largest line in the file, up to a maximum of 4096. The file to be sorted must be open for input on _chin_ , and the program must supply the channel ( _chout_ ) of an output file into which you want the file sorted. If you want to sort the file on itself, you may specify _chout_ as the same value as _chin,_ in which case it only needs to be open once for input. If you want to re-read the sorted output file, you will need to close it and reopen it for input. 

Here is a description of the three sort algorithms: 

|**Type**|**Description**|
|---|---|
|Small|The entire file is loaded, quicksorted and then saved to disk. This will occur if there is sufficient memory to<br>load the entire file. It is extremely fast.|
|Medium|The keys are extracted from the file, and then quicksorted. A new file is then created by reading the records<br>from the old file in the order of the quicksorted keys. This will occur if there is sufficient memory to load a tag|



A-Shell Reference 

Page 2196 

|**Type**|**Description**|
|---|---|
||file consisting of the sort keys and record numbers. It is reasonably fast.|
|Large|The file is quicksorted in chunks into two separate files. A disk-based poly-phase merge sort is then used to<br>repeatedly merge these until a single sequence of sorted records results. This type of sort occurs in all other<br>situations. It is quite slow.|



The type of sort being used may be determined by specifying: 

```
TRACE=AMSORT
```

in the system configuration file or with the command: 

```
SET TRACE AMSORT
```

from the dot prompt. 

Among other uses, the tracing display may be useful for analyzing the performance of a LARGE model sort, since the individual phases are shown. 

Records with the same sort key are guaranteed not to be re-ordered in the resulting file. This also applies to direct memory sorting of files in MEM:. 

The normal limit on memory allocation with the MALLOCSORT option is 8MB, but you can change this with the MALLOCLIMIT 

system parameter; see MALLOCLIMIT. Bumping this up, to say, 32MB, on a typical modern desktop PC can make a huge difference when sorting files larger than 8MB but smaller than the limit you specify. 

The absolute limit for BASORT file size is 2GB. 

A-Shell Reference 

Page 2197 

Troubleshooting tip: if you're having problems with large sorts failing, the first recommendation is to activate and configure the MALLOCSORT and MALLOCLIMIT options so that the sort can be performed using the Medium, or preferably, the Small algorithm, which is not only the fastest but the simplest and thus the least likely to run into complications. 

**Warning** about using signed integer sort keys (B5, I1, I2 and I4) in files with a control record: traditionally the technique for preventing the control record from getting sorted out of place was to temporarily set it to all nulls, prior to sorting. But this is not adequate for signed integer sort keys, since nulls = 0, which is not at the bottom but in the middle of the range of signed values. The lowest possible signed integer value is -2^N where N is the # of bits in the field (e.g. -128, -32768, etc.) Similarly, for descending sort, the maximum value is 2^N-1. 

## **History** 

- 2025 September, A Shell 7.0.1778:  Record size (recsiz) increased from 4K to 6K. 

A-Shell Reference 

Page 2198 

## **BITOPS** 

_Reviewed and revised April 2024_ 

## **xcall BITOPS, opcode, chfld, pos, result, result2** 

BITOPS was developed to facilitate the use of large bit fields (bitmaps). These are quite useful when you want to keep a single binary flag for each of many items. The bit field can be held in memory in a variable of type X, or in a random file. 

## **Parameters** 

_opcode_ (Num)  [in] 

specifies the operation using the following values: 

|**Value **|**Meaning**|
|---|---|
|1|Clear bit #_<pos>_; if_<pos>_= -1 or is omitted, clear all bits in bitmap|
|2|Set bit #_<pos>_; if_<pos>_= -1 or is omitted, set all bits in bitmap|
|3|Counts all bits in bitmap; return number of 0s in_result_, number of 1s in_result2_|
|4|Set_result_to bit number of first zero bit on or after given_pos_. If no more zero bits,<br>return –1. At same time, set_result2_to bit number of first one bit on or after_pos_.|



## _chfld_ (BLOB or Unsigned Int)  [in] 

is either the bit field (if type X) of any size (first bit is considered bit #0); if any type other than X, _chfld_ is interpreted as an open random file channel (containing the bit field). 

A-Shell Reference 

Page 2199 

_pos_ (Num)  [in] 

specifies the bit number we are operating on or starting from; see _opcode_ table above. 

_result, result2_ (Num)  [out] 

are used to return the results; see _opcode_ table above. 

A-Shell Reference 

Page 2200 

## **BLOCKS** 

_Reviewed and revised April 2024_ 

## **xcall BLOCKS, device, blks, cblks {,tblks} {,unitscale}** 

BLOCKS allows a program to check how much disk space is free on the specified device and, optionally, the total space on the device. 

## **Parameters** 

_device_ (String)  [in] 

must be specified _without_ the trailing colon (e.g. DSK0 or EXT1) and must be a device defined in miame.ini. 

_blcks, cblks_ (Signed Int)  [out] 

returns the number of free blocks (512 bytes per block) on the device. If the device cannot be accessed, the block count will be returned as –1. 

_tblks_ (F,6)  [out] 

returns the total number of blocks (both free and used) on the device. 

_unitscale_ (Num)  [in] 

specifies a scale factor for the returned "block" units: 

|**Value**|**Size of "block"**|
|---|---|
|0 or not specified|512 bytes|
|1|1 KB|



A-Shell Reference 

Page 2201 

|**Value**|**Size of "block"**|
|---|---|
|11|1 MB|
|21|1 GB|



Note that the values for _unitscale_ are actually powers of 2 to be used relative to the number of 512-byte blocks. 

## **Comments** 

There are a few idiosyncrasies to note about BLOCKS: 

• Under A-Shell, there is no particular significance to contiguous blocks, since there is no particular significance to them under Windows or Unix. This is why it is always equal to the number of free blocks. You do not need contiguous blocks to allocate random files like you did under some older systems. 

- 512-byte blocks have no particular significance to the host operating system. Under Windows and Unix, the minimum 

- allocation unit is related to something other than physical disk blocks (i.e. clusters or inodes) and for that matter, the physical disk block size may or may not be 512. 

• Since A-Shell does not impose any kind of partitioning on the devices, it is really the free space on the logical host disk that is being measured. For example, `DSK0` may be mapped to `/vm/miame/dsk0` and `DSK1` to `/vm/miame/dsk1` , but both of those are part of the same Unix file system. So they will both show the same amount of free space. Do not get fooled into thinking that that much free space is separately available on both devices, since it is really only one device from the host operating system's point of view. 

Despite these quirks, it is still a useful approximation to the amount of free space available. 

## **History** 

- 2014 May, A Shell 6.1.1386: Add _unitscale_ 

A-Shell Reference 

Page 2202 

## **BLOFSH** 

_Added to A-Shell, August 2016_ 

## **xcall BLOFSH, opcode(=1), impure, key** 

## **xcall BLOFSH, opcode(=2), impure, cleartext, ciphertext** 

## **xcall BLOFSH, opcode(=3), impure, ciphertext, cleartext** 

BLOFSH implements the Blowfish encryption algorithm. It is used to encrypt or decrypt data in memory using a variable length key of 32 to 448 bits. 

Blowfish is a symmetric-key block cipher, designed in 1993 by Bruce Schneier and made available to the world for royalty-free use. See the Blowfish entry at Wikipedia for more information. 

## _opcode_ (Num)  [in] 

1 to load the key, 2 to encrypt, 3 to decrypt 

_impure_ (BLOB, 4168)  [in/out] 

A block of 4168 bytes which must be provided to the subroutine for its use as a work area. Do not modify it between calls. 

## _key_ (BLOB)  [in] 

A variable containing your encryption key. The mapped size of _key_ determines the length of the encryption key, which can be from 4 to 56 bytes—i.e. 32 to 448 bits. Note being a symmetric cipher, the same key is used for encryption and decryption. Obviously you should generate an unpredictable key and store it securely. 

## _cleartext_ (BLOB)  [in/out] 

An area containing or overlaying the clear data. For _opcode_ 2 (encrypt), this is the source; for _opcode_ 3 (decrypt), it is the destination. The size in bytes must be divisible by 4, and must match the _ciphertext_ size. You can use an overlay or an assignment to up-size your actual clear text field. For example, to encrypt a string 29 bytes long, you might map it as follows: 

A-Shell Reference 

Page 2203 

```
map1 cleartext$,s,29
map1 cleartext,x,32,@cleartext$
```

## _ciphertext_ (BLOB)  [in/out] 

An area containing or overlaying the encrypted data. Restrictions and comments given for cleartext apply here as well. 

## **Example** 

```
MAP1 X,I,2
```

```
MAP1 BF'IMPURE,X,4168    ! internal work area
MAP1 BF'KEY              ! (4 to 56 bytes, divisible by 4)
    MAP2 BF'KEY(4),B,4   ! 16 bytes (128 bits)
```

```
MAP1 SECRETS
```

```
    MAP2 NAME,S,36
    MAP2 CODE,F,6
```

```
MAP1 CLEARTEXT,X,48,@SECRETS   ! must be divisible by 8
MAP1 CIPHERTEXT,X,48           ! must be same size as CLEARTEXT
```

A-Shell Reference 

Page 2204 

```
X = SRND2(0,0,&hFFFFFFFF)  ! randomize, set 32 bit range
for X = 1 to 4            ! generate 4 32-bit random values for key
    BF'KEY(X) = RND2()
```

```
next X
open #1, "BLOTST.KEY", output    ! save the key
? #1, BF'KEY;
close #1
xcall BLOFSH, 1, BF'IMPURE, BF'KEY      !  init cipher from key
```

```
NAME = "James Bond"
CODE = 0.007
```

```
xcall BLOFSH, 2, BF'IMPURE, CLEARTEXT, CIPHERTEXT   ! encrypt
```

```
open #2, "BLOTST.DAT", OUTPUT
? #2, CIPHERTEXT;               ! write encrypted data to file
close #2
```

```
! later, to decrypt...
```

A-Shell Reference 

Page 2205 

```
open #1, "BLOTST.KEY", input         ! retrieve the saved key
input raw #1, BF'KEY
close #1
```

```
xcall BLOFSH, 1, BF'IMPURE, BF'KEY   !  re-init cipher from key
```

```
open #2, "BLOTST.DAT", input
input raw #2, CIPHERTEXT             ! read encrypted data
close #2
xcall BLOFSH, 3, BF'IMPURE, CIPHERTEXT, CLEARTEXT   ! decrypt
```

```
? "NAME = ";NAME;", CODE = ";CODE
```

```
end
```

When encrypting string fields, you can copy to/from the original (S format) field and the _cleartext_ / _ciphertext_ (X format) fields. But when encrypting numeric fields or structures, you must use the overlay method shown above. In all cases, you must save the entire _ciphertext_ variable, not just the number of bytes in the actual data. In the example above, the actual data is only 43 bytes but the encrypted data is 48 bytes long, i.e rounded up to the next multiple of 8 bytes. 

A-Shell Reference 

Page 2206 

To generate truly unpredictable keys, see Random Number Generators. To avoid saving the key, you may be able to use some fixed function based on inputs unique to the situation—file #, customer #, ppn, etc.—to produce the seed from which you then can generate and later regenerate a pseudo-random sequence. 

If you are exporting your application which encrypts or contains encrypted data, you may want to check your country's regulations. The US has loosened its requirements but there are still situations where Blowfish encryption with keys longer than 56 bits may be restricted. 

## **See Also** 

- CRYPTO 

- MX_PWCRYPT 

A-Shell Reference 

Page 2207 

## **CGIUTL** 

_Updated September 2014; see History_ 

## **xcall CGIUTL, opcode {,param1, param2 ...}** 

CGIUTL contains several utility functions which are very handy when writing CGI (traditional or FastCGI) programs. The calling format and parameters beyond _opcode_ depend on the value of _opcode_ , so we will consider each case separately, with the value - of _opcode_ inserted into the syntax examples below. _Opcode_ itself can be any numeric format. See A Shell as a CGI Engine for more details on using CGIUTL. 

|**Opcode**|**Valu**<br>**e**|**Function**|
|---|---|---|
|CGIOP_STATUS|0|CGI Status|
|CGIOP_STDIN|1|Retrieve stdin|
|CGIOP_GETPAR|2|Retrieve Single Parameter|
|CGIOP_MRGOUT|3|Copy Disk File to stdout|
|CGIOP_STDOUT|4|Write String to stdout|
|CGIOP_GETENV|5|Retrieve envvar into envdef|
|CGIOP_MRGFIL|6|Generate Custom File from Template|



A-Shell Reference 

Page 2208 

|**Opcode**|**Valu**<br>**e**|**Function**|
|---|---|---|
|CGIOP_GETPARX|7|Retrieve Multiple Parameters|
|CGIOP_UNESCAPE|9|Convert HTML Escapes|
|CGIOP_GETREQ|10|Support FastCGI|
|CGIOP_GETPARARY|12|Retrieve Params into Ordered Map|
|**Definition file: ashell.def**|||



|**Opcode**|**Valu**<br>**e**|**Function**|
|---|---|---|
|CGIOP_GETPARX|7|Retrieve Multiple Parameters|
|CGIOP_UNESCAPE|9|Convert HTML Escapes|
|CGIOP_GETREQ|10|Support FastCGI|
|CGIOP_GETPARARY|12|Retrieve Params into Ordered Map|
|**Definition file: ashell.def**|||



## **History** 

- 2018 February, A Shell 6.5.1628: Remove limit on number of subroutine parameters. 

2014 September, A-Shell 6.1.1394:  Add opcode CGIOP_GETPARARY. 

2014 September, A-Shell 6.1.1390:  Add support for FastCGI and opcodes CGIOP_UNESCAPE and CGIOP_GETREQ. 

A-Shell Reference 

Page 2209 

## **CGI STATUS** 

_Updated November 2025_ 

## **xcall CGIUTL, CGIOP_STATUS, status** 

_Opcode_ 0, CGIOP_STATUS, simply checks if A-Shell was launched with the –cgi or -cgifast switches. This can be useful when writing programs that work differently depending on whether they are running inactively or under control of a web server. 

## **Parameters** 

## _status_ (Num)  [out] 

|**Symbol**|**Value**|**Session launched...**|
|---|---|---|
||0|in normal mode—i.e., not -cgi or -cgifast.|
|CGIF_NORMAL|1|by web server in -cgi mode.|
|CGIF_FASTCGI|2|by web server in -cgifast (aka FastCGI or fcgid) mode.|
||-2|by web server in -cgifast but FastCGI/fcgid not supported by web server.|



A-Shell Reference 

Page 2210 

## **RETRIEVE STDIN** 

## **xcall CGIUTL, CGIOP_STDIN, string** 

_Opcode_ 1, CGIOP_STDIN retrieves the entire stdin into the _string_ parameter. The web server sends all of the form and parameter information from the request to the CGI program via the stdin channel for both the GET and POST methods. This method isn't typically necessary if you just want to retrieve standard parameters, since CGIOP_GETPAR is able to access the stdin channel directly. But it is essential for retrieving the body of a request, such as a SOAP request, or any request formatted as an XML or JSON document. 

## **Parameters** 

_string_ (String or unformatted)  [in] 

Returns the contents of stdin, up to the size of string (if fixed). If dynamic (S,0 or X,0) string will be expanded as needed to contain the entire stdin. 

_status_ (Signed Num)  [out] 

A-Shell Reference 

Page 2211 

## **RETRIEVE SINGLE PARAMETER** 

_Updated November 2025_ 

## **xcall CGIUTL, CGIOP_GETPAR, parmname, parmval, status {, string}** 

_Opcode_ 2, CGIOP_GETPAR, retrieves the web form parameter by name. Typically this requires that the program was launched in CGI mode (with the -cgi or -fastcgi switch) using the POST or GET method in the HTML form action statement, in which case the parameters are passed in via the stdin channel. (Technically, the GET method passes the parameters via the QUERY_STRING environment variable, but A-Shell will copy that into its stdin buffer so that both methods act the same within CGIUTL.) Alternatively, the application can provide a source string in place of stdin; see Comments below. 

## **Parameters** 

_parmname_ (String)  [in] 

name of the parameter to retrieve 

_parmval_ (String)  [out] 

value of the retrieved parameter 

_status_ (Signed Num)  [out] 

0 for OK, -1 if the parameter is not found, –2 if not in CGI mode. 

_string_ (String)  [in] 

If _string_ is specified it is used in place of stdin. It must be formatted in the same way that stdin would have been formatted by the CGI interface, i.e.: 

```
name1=value1&name2=value2&...nameN=valueN"
```

## **Comments** 

"+" characters in the source string are interpreted as spaces, and anything of the form %xx (where xx are two hex digits) is translated to the equivalent ASCII character.) 

A-Shell Reference 

Page 2212 

If you use the form action GET instead of POST, you can also query the variables by retrieving the definition of the environment variable QUERY_STRING (see MX_GETENV) into the _string_ parameter. 

When _string_ is specified, you do not actually have to be in CGI mode, and thus the operation could be useful for non-CGI purposes. 

This operation only works for standard parameters passed in the URL (GET method) or embedded in a form (POST method).  For POST requests containing a document body (e.g. XML, JSON, etc.) you'll have to use other methods to parse the request. 

A-Shell Reference 

Page 2213 

## **COPY DISK FILE TO STDOUT** 

_Updated November 2025_ 

## **xcall CGIUTL, CGIOP_MRGOUT, file, status {varsub1, varsub2 ..., varsubN}** 

_Opcode_ 3, CGIOP_MRGOUT, copies a disk file (typically a web page template) to stdout, thus completing the CGI operation. (The web server launches the CGI application, passes it input via stdin, then waits for the output to come back via stdout.)  To simplify the process of generating a custom web page, you may specify up to 256 variable substitutions, allowing you to use use a common template which is thereby customized. 

## **Parameters** 

_file_ (String)  [in] 

DevPPN or native file specification for input file. In the case of ambiguity, AMOS-style will be assumed; you can force it to assume native-style by prepending a "./" to the name (e.g. "./NativeFile.html")/  There is no particular limit to the size of the input file, but each line must be less than 32K (prior to any variable substitutions). 

## _varsubN_ (String)  [in] 

One or more variable substitution definitions of the form `<name>=<value>` (e.g. `$CLIENTID=12345` ). The maximum number of - substitution pairs is limited only by the A Shell limit on the number of XCALL parameters. 

You can overcome the limit by combining multiple substitution pairs in a single varsub parameter by separating them with a plus sign (+), for example " `$CLIENTID=12345+$NAME=Bits R US` ". To include the literal character '=' or '+' in a substitution, precede it with a backslash, e.g. `$FORMULA=1\+1\=2` . 

The variable substitution names are case sensitive, but do not have to be terminated or delimited in any special way. To avoid inadvertent matches, you might want to prefix and/or suffix them with some special character, like $. 

## _status_ (Signed Num)  [out] 

Will be set to 0 to indicate that a page was successfully generated, although it may still fail to meet the necessary syntactic requirements for a valid webpage. –1 indicates that file could not be opened. 

## **Comments** 

A-Shell Reference 

Page 2214 

This operation can be difficult to debug, since if the resulting page is not valid, the web server will not display any of it and it will not be available for inspection. A first debugging step would be to attempt to launch the file in the browser directly, which should work (displaying the variable names instead of the replacement values) provided that variables are not used for critical elements of the HTML page structure. A second debugging step would be to add `TRACE=XCALL` , or otherwise arrange for the command `SET TRACE XCALL ON` to be executed before the program runs. This will not only log the subroutine parameters (for all subroutines) to the ashlog.log file, but will also create a file cgiutl.log containing a copy of the merged file that was output to stdout. 

A common mistake in creating a template web page is to forget to include the "content-type" header line, which it not required in static web pages but is required in pages generated through CGI. As a minimum, the template and/or resulting page should contain the following elements (note the mandatory blank line following the "content-type" header: 

```
content-type: text/html
```

```
<HTML>
```

```
<HEAD>
```

```
<TITLE>This is the page title</TITLE>
```

```
</HEAD>
```

```
<BODY>
```

```
bla bla bla
```

```
bla bla bla
```

```
</BODY>
```

```
</HTML>
```

## **See Also** 

- See this post on the A-Shell Forum if you are trying to use a template file containing an embedded PHP block. 

A-Shell Reference 

Page 2215 

## **WRITE STRING TO STDOUT** 

_Updated November 2025_ 

## **xcall CGIUTL, CGIOP_STDOUT, string, status** 

_Opcode_ 4, CGIOP_STDOUT writes _string_ to stdout. 

## **Parameters** 

_string_ (String or unformatted) [out] 

The text to be output to the browser. A CRLF is appended to the string, analogous to a PRINT statement. For binary output, such as a data file download to the browser, the string parameter must be type X, in which case no CRLF is appended. 

_status_ (Signed Num)  [out] 

On success, returns the number of bytes output. Negative values represent system error codes. 

## **Comments** 

Use this in place of PRINT statements to output individual characters or lines to the new web page. In -cgi or -cgifast mode, the output of PRINT statements is sent to the stderr stream rather than stdout. For more information, see the Common Gateway Interface discussion. 

A-Shell Reference 

Page 2216 

## **RETRIEVE ENVVAR INTO ENVDEF** 

## **xcall CGIUTL, CGIOP_GETENV, envvar, envdef, status** 

_Opcode_ 5, CGIOP_GETENV, retrieves the contents of the environment variable _envvar_ into the string variable _envdef_ . 

## **Parameters** 

_envvar_ (String)  [in] 

name of the environment variable to query, e.g. "CONTENT_LENGTH" 

_envdef_ (String)  [out] 

value of the specified environment variable, or null if _envvar_ not defined 

_status_ (Num)  [out] 

_status_ will be set to 0 for OK, or 1 if the variable had to be truncated to fit in _envdef_ . 

A-Shell Reference 

Page 2217 

## **GENERATE CUSTOM FILE FROM TEMPLATE** 

## **xcall CGIUTL, CGIOP_MRGFIL, file, status, outch {,varsub1, varsub2 ... {,varsubN}** 

_Opcode_ 6, CGIOP_MRGFIL, is identical to opcode 3 (CGIOP_MRGOUT), which see for further parameter details, except that instead of outputting to stdout, it outputs to an arbitrary open file channel, thus making it useful for all kinds of purposes besides CGI. It was combined here rather than as a separate subroutine because it shares nearly all of the same logic as CGIOP_MRGOUT. 

## **Parameters** 

_file_ (String)  [in] 

AMOS or native file specification for input file. 

_status_ (Signed Num)  [out] 

Will be set to 0 to indicate that a page was successfully generated (although it may still fail to meet the necessary syntactic requirements for a valid webpage). –1 indicates that file could not be opened. 

_outch_ (Num) ,  [in] 

File channel; must be open for output. 

_varsubN_ (String)  [in] 

One or more variable substitution definitions of the form <name>=<value> (e.g. $CLIENTID=12345). 

A-Shell Reference 

Page 2218 

## **RETRIEVE MULTIPLE PARAMETERS** 

_Updated November 2025_ 

## **xcall CGIUTL, CGIOP_GETPARX, status, skipcount, parmname1, parmvalue1, ... parmnameN, parmvalueN {,string}** 

_Opcode_ 7, CGIOP_GETPARX, provides an alternative to CGIOP_GETPAR (2) for retrieving parameter values. Instead of retrieving one value at a time by parameter name, it retrieves several sets of parameter name/value pairs based on parameter number: 

## **Parameters** 

## _status_ (Signed Num)  [out] 

returns status: 

|**Value**|**Session launched...**|
|---|---|
|-1|Specified starting parameter number (skipcount+1) doesn't exist.|
|-2|Not cgi mode and no string parameter passed.|
|-3|Ssyntax error in parameter data. Last_parmname_arg will contain the relevant part of the<br>string.|
|>=0|The number of parameter name/value pairs available to process (after the skipcount). If this is<br>larger than the number of sets of_parmname/parvalue_pairs passed, it indicates to the<br>application that it can make another call (using skipcount) to get additional parameters.|



_skipcount_ (Num)  [in] 

A-Shell Reference 

Page 2219 

should be set to the number of name/value pairs to skip. Set to 0 to start with the first parameter. 

_parmname_ (String)  [out] 

returns parameter name 

## _parmvalue_ (String)  [out] 

returns parameter value. You can specify up to 48 pairs of these (to stay within the 100 subroutine parameter limit). You use the returned status to determine how many of the pairs contain valid information. CGIUTL will also set the first ununsed parmname to "" so you could also process the pairs until the first empty parmname. 

## _string_ (String)  [in]  optional 

may be used to pass a string to use as input, instead of the stdin string normally passed to A-Shell in CGI mode. Note that CGIUTL recognizes the existence of the string argument by there being an even number of arguments > 5. So make sure your parmname/parmvalue arguments are paired or the last one will be confused with an input string. See CGIOP_GETPAR  for information on the format of the string input. 

A-Shell Reference 

Page 2220 

## **- UNESCAPE URI ENCODED STRING** 

_Updated November 2025_ 

## **xcall CGIUTL, CGIOP_UNESCAPE, in, out, status** 

_Opcode 9_ , CGIOP_UNESCAPE, is a utility function—not limited to CGI programs—used to convert URI-encoded (or percent-encoded) strings to the ASCII equivalent. This type of encoding is primarily used for URLs and URIs (e.g. web addresses) and consists of replacing certain special characters (primarily "!#$&'()*+,/:;=?@[] ") with %xx where xx is the hex value of the original ASCII byte code. Although those are typically the only characters encoded this way in URI's, the function converts all %xx sequences to the equivalent raw ASCII characters. In addition, it will convert any "+" appearing after an initial "?" to a space (since query parameters appended to URLs start with "?" and usually replace any spaces with "+". 

## **Parameters** 

_in_ (String)  [in] 

URI-encoded string to unescape 

_out_ (String)  [out] 

receives the output , dynamic string ok 

_status_ (Num)  [out] 

returns a status code (0 for ok) 

## **See Also** 

- fnescape.bsi in SOSLIB:[907,10] 

A-Shell Reference 

Page 2221 

## **SUPPORT FASTCGI** 

_Updated November 2025_ 

## **xcall CGIUTL, CGIOP_GETREQ, status** 

_Opcode_ 10, CGIOP_GETREQ, is used to upport FastCGI, although it also works in normal CGI mode and is critical to enabling support for either mode in the same program. 

## **Parameters** 

_status_ (Num signed) 

returns 0 if a request is available to process, or -1 if not, in which case the application should terminate. 

## **Comments** 

For FastCGI mode requests after the first one for the instance of the application server, this call will sleep until a request is available or the web server tells us to exit, or an error occurs. 

When used in normal CGI mode, the first call will return 0 (just as it does for FastCGI mode), but the second call will return -1, since normal CGI mode only supports one request per application server instance. 

Note that in FastCGI mode, subsequent calls after the first one will block while waiting for a new request. The wait will be terminated only by one of the following events: 

- Arrival of a new request. 

- The web server deciding to terminate the application, based on minimum/maximum/timeout parameters in the server's 

- FastCGI or fcgid configuration. 

- A SIGINT or SIGTERM or SIGKILL signal sent by another Linux process. 

- Termination by the Windows Task Manager. 

Typically, none of those events are trappable, so the process will disappear but the job may remain in the job table as a zombie until it is replaced by a newly launched job. 

A-Shell Reference 

Page 2222 

See FastCGI for an example and further details. 

A-Shell Reference 

Page 2223 

## **RETRIEVE PARAMS INTO ORDERED MAP** 

_Updated February 2015_ 

## **xcall CGIUTL, CGIOP_GETPARARY, status, $ary() {,string}** 

_Opcode_ 12, CGIOP_GETPARARY, retrieves the entire set of name=value pairs into an ordered map (aka associative array) 

## **Parameters** 

_status_ (Num)  [out] 

Returns the number of name=value pairs loaded. 0 indicates either that no name=value pairs were passed into the CGI request. 

_$ary()_ (Ordered map)  [out] 

An associative array to be loaded with the name=value pairs. It should be declared as follows: 

## `dimx $ary, ordmap(varstr;varstr)` 

As with other parameters, you can name the array as you like, but you must specify the empty parentheses as in the example. This is special code to the subroutine to treat the parameter as an entire array, rather than as just one element. Also note that any existing contents of the array will not be automatically cleared, although any conflicting name=value pairs will be replaced. If reusing the array for multiple requests, you should probably use  .CLEAR to clear it. 

## _string_ (String)  [in] 

If specified, the string parameter should contain the list of name=value pairs making up the request; see CGIOP_STDIN. Otherwise the request is taken directly from the stdin passed to the program by the web server. 

## **Comments** 

The form of the request, whether in _string_ or in stdin, should be: 

```
name1=value1&name2=value2&...&nameN=valueN
```

## **Examples** 

A-Shell Reference 

Page 2224 

## For example, if assuming _string_ = "fromCurrency=US&toCurrency=Euro", the following code... 

```
dimx $req, ordmap(varstr;varstr)
```

```
xcall CGIUTL, CGIOP_GETPARARY, status, $req(), stdin$
```

```
print "fromCurrency = "; $req("fromCurrency")
```

## will print: 

```
fromCurrency = US
```

```
toCurrency = Euro
```

## Or you can use a FOREACH loop to retrieve all of the name=value pairs without knowing in advance what to expect, i.e. 

```
foreach $$i in $req()
```

```
    switch .key($$i)
```

```
        case "toCurrency"
```

```
            tocurr$ = $$i
```

```
            exit
```

```
        case "fromCurrency"
```

```
            fromcurr$ = $$i
```

```
            exit
```

```
        ...
```

```
    endswitch
```

A-Shell Reference 

Page 2225 

```
next $$i
```

A-Shell Reference 

Page 2226 

## **CISAM** 

_Added March 2013_ 

## **xcall CISAM, opcode, ch, idx, recno {,status}** 

CISAM is an internal interface to the ISAMPLUS file system, generally only used by system-level utilities and thus not previously documented. In A-Shell 6.1.1140 of March 2013, the routine was "made public" because new functions expose a capability that is not yet available in regular BASIC/ISAMPLUS syntax. The limitation with the old ISAM'PUSH and ISAM'POP was that it is singlelevel, i.e. supports only one level of ISAM'PUSH for any given channel at a time. The subroutine functions documented here allow you to "push" an arbitrary number of file positions/states and "pop" them in an arbitrary order. 

Opcode 33 is equivalent to ISAM'PUSH #CH, except that it returns to you the current IDX and RECNO. 

Opcode 34 is equivalent to ISAM'GOTO #CH, IDX, RECNO (which does not yet exist). This is similar to ISAM'POP, except repositions the internal state and position according to the specified IDX and RECNO, rather than the previously pushed one. 

Note that the IDX numbering starts from 1 here, contrary to the IDX numbering in Basic, which starts at zero. 

Both functions return 0 in STATUS for success, else error. 

A-Shell Reference 

Page 2227 

## **COMIO** 

## **xcall COMIO, opcode, channel, buffer, status, count {,msg, timeout}** 

COMIO is included with A-Shell/Windows to allow simple I/O on Windows serial ports, since you cannot open up a Windows serial port as a file, like you can on other platforms. COMIO supports ports beyond COM9, and logs read/write errors to ashlog.log. Also: 

- Refer to the sample program COMIO in EXLIB:[908,54]. 

- For more sophisticated applications involving serial communications, Autolog from Soft Machines is recommended. 

## _opcode_ (Num)  [in] 

specifies the operation according to these options: 

|**Valu**<br>**e**|**Meaning**|
|---|---|
|1|Open port specified in the_buffer_parameter, return channel in_channel_|
|2|Close port specified by_channel_|
|4|Check if any characters available to read; return count in_count_|
|8|Input a maximum of_count_characters; see the_count_table below for special cases|
|16|Write exactly_count_characters (or up to null if_count_=0)|



A-Shell Reference 

Page 2228 

## _channel_ (Num)  [out] 

specifies the channel number associated with the port. This value is returned from the open operation, and must be passed to the subroutine for all other operations. 

## _buffer_ [in/out] 

is usually a string variable to pass the data to be sent or received (for read/write operations). For the open operation, it is used to pass control information about the port settings, and must be mapped as follows: 

```
MAP1 BUFFER
```

```
MAP2 BYTESIZE,B,1     ! 7=7 bits, 0 or 8 = 8 bits
MAP2 PARITY,B,1       ! 0=none, 1=odd, 2=even, 3=mark, 4=space
MAP2 STOPBITS,B,1     ! 0=1, 1=1.5, 2=2
MAP2 FLOWCTL,B,1      ! Add: 1=DTR/DSR, 2=RTS/CTS, 4=XON/XOFF
MAP2 MISC,B,2         ! Unused
MAP2 PORT,S,20        ! e.g. "COM1" (no colon)
```

## _status_ (Num)  [out] 

returns a status code or bit field indicating the level of success of failure of the operation: 

|**Value**|**Meaning**|
|---|---|
|0|Success|
|-1|Parameter error|



A-Shell Reference 

Page 2229 

|**Value**|**Meaning**|
|---|---|
|||
|-2|No more memory handles available|
|-3|Memory allocation failure|
|-4|Unable to create write event|
|-5|Unable to create read event|
|-6|Invalid channel passed in CH argument|
|-7|Unable to open connection to port|
|-8|CTRL+Creceived while waiting for input|
|-9|Unable to set comm parameters; see History below.|
|>0|Bit field containing one or more port status error flags from the following table:|



A-Shell Reference 

Page 2230 

|**Value**|**Port Status Error Flags**|
|---|---|
|&h0001|Input buffer overflow. (Either no room in input buffer, or char received after EOF)|
|&h0002|Buffer overrun (next character is lost)|
|&h0004|Parity error|
|&h0008|Framing Error|
|&h0010|Break detected|
|&h0100|Output buffer full|
|&h0200|Time out (parallel device)|
|&h0400|I/O error|
|&h0800|Device not selected (parallel device)|
|&h1000|Parallel device is out of paper|
|&h8000|Requested mode not supported|



- Hex Decimal Values 

A-Shell Reference 

Page 2231 

## _count_ (Num)  [in/out] 

usage depends on the operation, as given in the table. Also see History, below. 

|**Operatio**<br>**n**|**Value **|**Usage of COUNT parameter**|
|---|---|---|
|Open|1|Must be set to the desired baud rate.|
|Close|2|Ignored|
|Check|4|Returns number of characters available to be read.|
|Read|8|Must be set to either the number of characters you wish to read, or a special code (<=0) indicating the<br>character you want to terminate the read on. The read routine will continue reading (and waiting if necessary)<br>until the requested number of characters, or the requested terminating character, is received (up to the time<br>limit specified by a timeout parameter > 0). To input up to a specific terminating character whose ASCII value<br>is N, set count to -N. (For example, set count = -3 to input up to a byte chr(3).) 0 and -1 are historical<br>exceptions to this formula. 0 inputs up to a terminating LF, while -1 inputs up to a terminating CR. (The<br>terminating character, and in the case of LF, the immediately preceding CR, will be stripped from the buffer.)<br>On return, count will be set to the number of bytes received, including any terminating character(s).|
|Write|16|Must be set to the number of characters to write (from the BUFFER parameter). You may set it to 0 to output<br>up to the first null byte in the BUFFER string. On return, it will contain the number of characters actually<br>output.|



_msg_ (String)  [out] 

A-Shell Reference 

Page 2232 

returns the text of the Windows error message if an error occurs. The text will be truncated to fit, but for best results map _msg_ to eighty-plus characters. If no error, then _msg_ will be "". The error message begins with the actual Windows error code, making it easier to identify with precision. 

## _timeout_ (Num)  [in] 

timeout value (in seconds), applies only to check (4), read (8) and write (16) operations. This is particularly useful when reading with the option to read until CR or LF, since if the data ends without sending a CR or LF, you could otherwise be stuck waiting forever. If timeout occurs, _msg_ will be set to " **TIME** " (or possibly " **(#) TIME** " where # is an internal error code). The _status_ and _count_ parameters may or may not indicate an error, so when using the _timeout_ option, you should always check _msg_ to see if it contains the substring " **TIME** ". 

A-Shell Reference 

Page 2233 

## **COMMON** 

_Reviewed and revised April 2024_ 

## **xcall COMMON, send, msgnam, var** 

## **xcall COMMON, recv, msgnam, var** 

COMMON is a widely used (and widely modified) routine for sending a block of data from one program to another. 

## **Parameters** 

```
map1 send,b,1,0
```

```
map1 recv
```

```
map2 f'rcv,b,1,1
```

```
map2 rcvflg,b,1,0
```

_send_ (Bitmap 1)  [in] 

must be mapped as shown above. As the names imply, _send_ is used for sending a packet and _recv_ for receiving one. 

_recv_ (Structure)  [in] 

must be mapped as shown above. As the names imply, _send_ is used for sending a packet and _recv_ for receiving one. 

_msgnam_ (String, up to 6 characters)  [in] 

specifies the name of the packet. This is how packets are identified if more than one is being stored at the same time. 

_var_ (BLOB) 

supplies the data to send or returns the received data. Do not use a dynamic variable (X,0) variable. 

_rcvflg_ (Bitmap 1)  [out] 

A-Shell Reference 

Page 2234 

Returns on failure to read packet, else non-zero. 

## **Comments** 

Under AMOS, normal usage requires that you load COMMON into user memory, since it stores the data within itself. COMMON does not exist as a separate module under A-Shell; however, the command line `.LOAD BAS:COMMON` will have the same effect as under AMOS, in that all COMMON packets will be cleared. 

The default packet set-up is 6 packets of 150 bytes. This may be changed by adding, for example, the following line to miame.ini: 

```
SBR=MSGNUM:4,MSGSIZ:1024
```

This would decrease the number of packets to 4, with a size of 1024 bytes each. More information is given in the documentation for miame.ini. 

As with the original version of COMMON, a read operation is destructive. That is, the packet is cleared upon reading it. Thus, if you want to read the packet and then pass it on to another program, you have to rewrite it after reading. Some people use a modified version of COMMON which has a non-destructive read. To support this variation, add `SBR=COMMONNDR` to your MIAME configuration file (the NDR stands for _Non Destructive Read_ ). 

## **See Also** 

- DSKCOM (disk based version of COMMON) 

- PEEK ,POKE (simplified wrappers) 

- XOKEY 

- XUSER 

A-Shell Reference 

Page 2235 

## **CONDEV** 

_Reviewed and revised, July 2020_ 

## **xcall CONDEV, dev {,dns'flag}** 

CONDEV returns an identifier for the client workstation or console/terminal device. It is useful in situations where you want to identify the physical workstation, rather than the user or session. 

The identifier can take one of several forms, depending on the operating system and other factors. Under Windows, it will return the computer name (e.g. "SALESPC"). Under Unix, it will first check to see if the environment variable REMOTEHOST is defined, and if so, it returns its definition. (Many shells will define the environment variable REMOTEHOST to contain the IP address of the workstation). Otherwise, if it can determine the IP address of the client workstation, it will return that in ###.###.###.### format. Otherwise, it will return the terminal device (pseudo or real tty) name, e.g. "ttya02" or "pts/0". 

## **Parameters** 

_dev_ (String)  [out] 

receives the identifier (described above) 

_dns'flag_ (Num)  [in] 

If specified and non-zero, an attempt will be made to convert the IP address to the equivalent host name. This can sometimes introduce a delay if there is no local DNS server. 

## **Comments** 

See GETUSN, which is similar. 

If you are using the ZTERM terminal emulator (and possibly others) you can retrieve the client’s IP address using a ZTERM Escape Sequences. In the case of ATE, you can also use MX_GETIP. 

A-Shell Reference 

Page 2236 

## **CRC16** 

_Reviewed and revised April 2024_ 

## **xcall CRC16, block, crc, size** 

CRC16 calculates a 16 bit CRC (aka CRC-16) for the specified block of data. 

## **Parameters** 

_block_ (BLOB)  [in] 

is an unformatted variable of arbitrary size. 

_crc_ (Num)  [out] 

will return the CRC-16 value. 

_size_ (Num)  [in] 

specifies the number of bytes within _block_ to consider. 

A-Shell Reference 

Page 2237 

## **CRYPTO** 

_Reviewed and revised April 2024_ 

## **xcall CRYPTO, opcode, status, src, decoding, dst, encoding, cflags {, cipher, key, keybits, cmode, padding {, cbsrc {, iv {, aad, authtag}}}}** 

CRYPTO provides a collection of cryptographic-related functions. 

## _opcode_ (Num)  [in] 

One of the following: 

|**Symbol**|**Opcode**|**Description**|
|---|---|---|
|CRYPTOP_ENCRYPT|1|Encrypt the src parameter into the dst parameter|
|CRYPTOP_DECRYPT|2|Descript the src parameter into the dst parameter|
|CRYPTOP_GENKEY|3|Generate a random symmetric key|
|CRYPTOP_ENCODE|4|Encode (or decode) src parameter into dst parameter|
|CRYPTOP_GENPUBKEY|6|Generate aPublic/Private Key<br> file pair; see for details.|
|CRYPTOP_HMAC|7|Allows CRYPTO to createHMACs<br>; see for details.|



A-Shell Reference 

Page 2238 

|**Symbol**|**Opcode**|**Description**|
|---|---|---|
|**Definition File:**crypto.def|||



## _status_ (Signed Num)   [out] 

Returns the result status of the operation: >= 0 for success (number of bytes output to dst), <0 for errors (see CRYPTERR_xxx in CRYPTO.DEF) 

## _src_ (String or BLOB)  [in] 

Supplies the input data for the operation. May be either a filespec (AMOS or native), a string, or an arbitrary length of binary data. In the case of an X variable containing binary data, the number of bytes must be specified in the _cbsrc_ parameter. Otherwise the length can be determined from the file size or the string length. Note that in the case of an encoded src string— e.g. hex or base64, the string must be null terminated. See _cflags_ . 

## _decoding_ (String)  [in] 

Specifies a type of character decoding to perform on the _src_ prior to any further processing, from the table below: 

|**Encoding/**<br>**Decoding**|**Description**|
|---|---|
|“raw” (or “”)|None|
|“hex”|Hexadecimal format (each byte of data represented by two hex characters)|
|“base64”|MIME/base64 (each three bytes of data represented by four bytes from the|



A-Shell Reference 

Page 2239 

|**Encoding/**<br>**Decoding**|**Description**|
|---|---|
||64-byte MIME character set); typical format for storing encrypted text|
|"url"|url format (non-printable characters represented using %xx notation|



## _dst_ (String or BLOB)  [in/out] 

The output of the operation.  May be a filespec in AMOS or native format (replacing an existing file or creating a new one), or a string (S) or unformatted (X) variable. If a dynamic variable is used (S,0 or X,0) it must be pre-sized to at least the required size. See _cflags_ . 

## _encoding_ (String)  [in] 

Specifies a type of character encoding to perform on the dst after the main cryptographic operation, from the same table of encoding choices listed above for the _decoding_ parameter. 

## _cflags_ (Num)  [in] 

Specifies zero or more options from the following: 

|**Symbol**|**value**|**Description**|
|---|---|---|
|CRYPF_NONE|&h0000|placeholder for no flags (i.e. all defaults)|
|CRYPF_SRCFILE|&h0001|src is a filespec (rather than the variable containing the source<br>data)|



A-Shell Reference 

Page 2240 

|**Symbol**|**value**|**Description**|
|---|---|---|
|CRYPF_SRCTEXT|&h0002|src data (after decoding) contains text (as opposed to binary<br>data)|
|CRYPF_DSTFILE|&h0008|dst is a filespec (rather than a variable to receive the output)|
|CRYPF_DSTTEXT|&h0010|dst (prior to encoding) will be a text string (as opposed to binary<br>data)|
|CRYPF_KEYFILE|&h0020|key is a file, rather than the variable containing the key. Applies<br>to CRYPTO_CIPHER_RSA only|
|CRYPF_KEYHEX|&h0040|key is hex encoded (decode before using)|
|CRYPF_PUBKEY|&h0200|For RSA encryption/decryption, use the public key (otherwise the<br>private key)|
|CRYPF_BIGENDIAN|&h0400|(Applies to type cipher CRYPTO_CIPHER_RSA only.) Use big-<br>endian (openssl) byte order rather than the default little-endian<br>(Microsoft) order|
|CRYPF_IVHEX|&h0800|IV is hex-encoded, else binary.|
|CRYPTF_KEYBASE32|&h4000|Supports keys encoded in base32, needed to support 2FA / TOTP<br>(two factor authentication using time-based one-time passwords)|



A-Shell Reference 

Page 2241 

|**Symbol**|**value**|**Description**|
|---|---|---|
|||generated by smart phone authenticator apps.|
|**Definition File:**crypto.def|||



- Hex Decimal Values 

## _cipher_ (Num)  [in] 

## For encryption/decryption, cryptographic algorithm to use. 

|**Cipher**|**Value**|**Description**|
|---|---|---|
|CRYPTO_CIPHER_NA|0|none / not applicable|
|CRYPTO_CIPHER_RSA|1|RSA (public/private key)|
|CRYPTO_CIPHER_AES|2|Advanced Encryption Standard (aka Rjindael) symmetric block cipher|
|**Definition File:**crypto.def|||



_key_ (String or BLOB)  [in] 

A-Shell Reference 

Page 2242 

Key to use for encryption/decryption. For the RSA cipher, must be a file containing the public and/or private key. Supported file formats are: PEM, XML, JWK, DER (PCKCS1 or PKCS8). (See History Note for required library version.) If the file format requires a password, specify it in the _aad_ parameter. For the other ciphers, it may be the key itself, or the name of the file containing the key. As a convenience the key may be specified in hex-encoded format; see _cflags_ . Note that the key size must correspond with the _keybits_ parameter. 

## _keybits_ (Num)  [in] 

Number of bits in the encryption key. Not required for the RSA cipher, since it can be determined from the PEM file. For AES, the options are 128, 192, or 256 bits. This corresponds to 16, 24, or 32 bytes (or twice that if the _key_ is hex-encoded). 

_mode_ (Num)  [in] 

For AES cipher, the cipher mode: 

|**Cipher**|**Value**|**Description**|
|---|---|---|
|CRYPTO_MODE_ECB|1|Electronic CookBook|
|CRYPTO_MODE_CBC|2|Cipher Block Chaining (block)|
|CRYPTO_MODE_RFC4716|3||
|CRYPTO_MODE_CTR|4|Counter Mode (stream)|
|CRYPTO_MODE_CFB|5|Cipher Feedback (stream)|
|CRYPTO_MODE_OFB|6|Output Feedback (stream)|



A-Shell Reference 

Page 2243 

|**Cipher**|**Value**|**Description**|
|---|---|---|
|CRYPTO_MODE_GCM|7|Galois/Counter Mode (stream)|
|**Definition File:**crypto.def|||



## _padding_ (Num)  [in] 

For the AES cipher, the padding scheme to use: 

|**Cipher**|**Value**|**Description**|
|---|---|---|
|CRYPTO_PAD_NA|-1|Padding not applicable; use with stream cipher modes<br>CTR, CFB, OFG, GCM.|
|CRYPTO_PAD_PKCS5|0|Each padding byte equal to the number of padding bytes.<br>If message length an even multiple of the block size, an<br>extra block of padding is added.|
|CRYPTO_PAD_FIPS81|1|Last byte of padding indicates the number of bytes<br>(including itself). Remaining padding bytes are random.|
|CRYPTO_PAD_RAND|2|Padding bytes are random. Decrypter must know the<br>length of the message (i.e. the number of padding bytes)|
|CRYPTO_PAD_NULL|3|Padding bytes set to null. If message length is a multiple|



A-Shell Reference 

Page 2244 

|**Cipher**|**Value**|**Description**|
|---|---|---|
|||of the block size, no padding is used.|
|CRYPTO_PAD_SPACE|4|Padding bytes set to space. If message length is a multiple<br>of the block size, no padding is used.|
|CRYPTO_PAD_SPACE|5|Padding bytes set to space. If message length is a multiple<br>of the block size, no padding is used.|
|CRYPTO_PAD_SPACE|6|Padding bytes set to space. If message length is a multiple<br>of the block size, no padding is used.|
|CRYPTO_PAD_SPACE|74|Padding bytes set to space. If message length is a multiple<br>of the block size, no padding is used.|
|**Definition File:**crypto.def|||



Note that the stream cipher modes (CTR,CFB,OFB,GCM) do not require or use padding and thus ignore the padding parameter; the use of CRYPT_PAD_NA is recommended for clarity. Without padding, the encrypted text is the same size as the plain text, assuming the same encoding. The block cipher modes (ECB and CBC) do require one of the other padding options, all of which will increase the encrypted text size up to a multiple of the block size (i.e. a multiple of 16). 

## _cbsrc_ (Num)  [in] 

Number of data bytes in the _src_ parameter. Only required when the _src_ is not a file and contains binary data. (If not specified in this case, the raw parameter size will be used.) 

A-Shell Reference 

Page 2245 

## _iv_ (String or BLOB)  [in] 

Initialization vector for optional use with CRYPTOP_ENCRYPT/DECRYPT opcodes with the AES cipher (all cipher modes except ECB). For cipher modes other than GCM or ECB, it should match the cipher block size, i.e. 16 bytes for AES (128 bits, not to be confused with the key size). For GCM cipher mode, 96 bits or less is recommended for best efficiency and interoperability. In all cases, it should be unique for any given key, preferably randomly generated. For GCM, it is only necessary that each _iv_ not be used more than once. The same _iv_ used for the encryption must be supplied to the decryption. The _iv_ may be specified as raw bytes (preferably using an X format variable), or as a string of hex digits (in which case the CRYPF_IVHEX flag must be specified.) 

## _aad_ (String, null terminated)  [in] 

Additional authentication data, used in the following two cases: 

- For RSA encryption/decryption, if the file containing the public and/or private key is password protected, 

- supply the password here, either in plain text or using one of the password encryption modes supported by MX_PWCRYPT (using the default key and seed). 

- For the GCM cipher mode (see Comments), must be a string of hex digits. This is typically used to provide an 

- identifying label or other association for the encrypted text, with the intent of making sure that the decrypted text is not just valid, but valid for a particular context/use. A corresponding authentication tag is generated (by combining the aad with the message and hashing and encrypting it) and output to the _authtag_ parameter. The _aad_ does not have to be kept secret, but both it and the corresponding _authtag_ must be provided to the decryption routine in order to authenticate the result. The _aad_ parameter can be null, but a unique _authtag_ will still be generated and must be passed (along with the null _aad_ ) to the decryption). 

## _authtag_ (String, 33+ bytes)  [in/out] 

Required for AES-GCM encryption/decryption. During encryption, an authentication tag is generated from the combination of the _aad_ and the message text and output to this parameter in the form of a string of 32 hex digits. This computed value must then be passed along with the origional _aad_ to the decryption. 

## **Comments** 

Unused parameters, needed as placeholders for later parameters, should be set to "" if of type string or 0 if of type numeric . 

A-Shell Reference 

Page 2246 

AES is a symmetric block cipher, meaning that the same key is used for both encryption and decryption, and that the process works one block at a time. The block length for AES is 128 bits (16 bytes).  This is independent of the key length, which can be 128, 192, or 256 bits. Several different cipher modes are available, which divide into the block modes (ECB and CBC), which pad the text to a multiple of the block size, and stream modes (CTR, CFB, OFB, and GCM) which do not use padding and thus generate encrypted text the same size as the plain text. 

ECB mode is relatively weak, using the same key on every block, and thus is normally only used for very short messages for which a different random key is generated for each message.  The other modes are suitable for any size message. CBC increases the security by deriving a new key for each block from the output of the encryption of the previous block. An initialization vector (IV) is typically supplied for use with the first block. In most cases it is essential that the IV be unique for each message, especially if the same key is used for multiple messages. 

CTR, CFB, OFB and GCM are all variations of CBC, except that they are stream oriented (not requiring padding to a multiple of the block size). GCM also combines additional authentication data (AAD) with the message (to identify or label the message, i.e. supply metadata for it). An 128 bit authentication tag is generated for the combination of the AAD and the message, and is used along with the AAD to authenticate the decryption (i.e. make sure the decrypted data is not just internally valid, but valid in the context of the specified metadata). 

The RSA public/private cipher is asymmetric (different keys used for encryption and decryption). It is extremely useful in situations where a private party (holding the private key) is exchanging messages with the public (which can share the public key). However, it is limited to messages no longer than the key modulus, which is typically 1024 or 2048 bits (128 or 256 bytes), so it is typically used for messages that are naturally short, such as AES keys and message digests. 

## **See Also** 

- DIGEST 

- HTTP 

- MX_PWCRYPT 

- BLOFSH 

- CRYPTO.DEF in SOSLIB:[907,16] 

- FNTOTP.BSI in SOSLIB:[907,10] for an example of 2FA / TOTP authentication. 

A-Shell Reference 

Page 2247 

## **History** 

- 2022 October, A Shell 6.5.1721, ASHNET 1.4.186:  CRYPTO encryption/decryption using RSA public/private keys now supports additional file formats beyond PEM: XML, JWK, DER (PKCS1 or PKCS8, raw or base64 encoded). If a password is required, specify it in the aad (additional authentication data) parameter and set the prior unused params to "" or 0 according to their types. 

2018 May, A-Shell 6.5.1635:  Add opcode CRYPTOP_HMAC to create HMACs (Hash-based Message Authentication Codes). 

- 2016 December, A Shell 6.3.1539:  Major upgrade of routine. Added parameters _iv_ , _aad_ , _authtag_ ; added five cipher modes (cmode) to use with AES algorithm; added support for Unix; updated ASHINC:cipher.def. Note that CRYPTO as now documented above requires ASHNET 1.9.156. 

2014 May, A-Shell 6.1.1385: Added opcode 6,  CRYPTOP_GENPUBKEY. 

- 2013 July, A Shell 6.1.1355: Routine added to A-Shell. Note that it requires ASHNET 1.5.137 or higher. 

## **Subtopics** 

- Public/Private Key 

- HMACs 

- CRYPTO Examples 

A-Shell Reference 

Page 2248 

## **PUBLIC/PRIVATE KEY** 

CRYPTO's opcode CRYPTOP_GENPUBKEY is used to generate a public/private key file pair. Its syntax differs slightly from the other opcodes: 

## **xcall CRYPTO, CRYPTOP_GENPUBKEY, status, pubkeyfile, decoding, privkeyfile, encoding, cflags, cipher, passphrase, keybits, cmode** 

## **Parameters** 

## _status_ 

Returns the result status of the operation: >= 0 for success (number of bytes output to dst), <0 for errors. See CRYPTERR_xxx in CRYPTO.DEF in SOSLIB:[907,16]. 

_pubkeyfile_ and _privkeyfile_ (in place of the _src_ and _dst_ parameters for other opcodes) 

must be set to the filespecs for the generated public and private key files. 

## _decoding_ and en _coding_ 

should be ""; there are no options for this opcode. 

## _cflags_ 

should be set to CRYPF_NONE, since output is always to file 

## _cipher_ 

should be set to either CRYPTO_CIPHER_RSA or CRYPTO_CIPHER_DSA 

_passphrase_ (in place of the _key_ parameter for other opcodes) 

must be set to the passphrase to encrypt the private key file or "" for none. 

## _keybits_ 

must be a multiple of 64, between 384 and 4096. 

A-Shell Reference 

Page 2249 

_cmode_ 

determines the format of the public key file: 

- CRYPTO_MODE_OPENSSH (0) OpenSSH format 

- CRYPTO_MODE_RFC4716 (3) RFC 4716 format 

## **Comments** 

For Unix login authentication, the most typical options would be: 

```
cipher = CRYPTO_CIPHER_RSA
```

```
keybits = 2048
```

```
cmode = CRYPTO_MODE_OPENSSH
```

A-Shell Reference 

Page 2250 

## **HMACS** 

_Added May 2018_ 

Opcode CRYPTOP_HMAC allows CRYPTO to create HMACs (Hash-based Message Authentication Codes), commonly used for 

signing web service requests. They combine a hash/digest algorithm (e.g. SHA256) with a cryptographic key (typically preshared between sender and receiver) to both verify data integrity of a message and authenticate the sender. 

## **xcall CRYPTO, CRYPTOP_HMAC, status, src, decoding, dst, encoding, cflags, cipher, key {, keybits, cmode, padding, cbsrc}** 

## **Parameters** 

## _src_ and _decoding_ 

specify the source message and decoding, as with other opcodes. 

## _dst and encoding_ 

specify the destination for the output of the function. Typically it is encoded using base64 or hex so as to make it easily insertable into a web document. The destination length is independent of the source length and instead is determined by the hash function—e.g. SHA256 results in 32 bytes raw, 43 for base64, 64 for hex. 

## _cflags_ 

used as for the other opcodes 

## _cipher_ 

should be set to CRYPTO_CIPHER_NA (0) 

## _key_ 

as for the CRYPTOP_ENCODE operation 

## _keybits_ 

may be set to 0 if the key is encoded in a text format; otherwise it should specify the number of bytes in a binary-format key. 

A-Shell Reference 

Page 2251 

## _mode_ 

## should be set to one of the following to specify the hash function to use (default CRYPTO_MODE_SHA1): 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|CRYPTO_MODE_SHA1|20|HMAC-SHA1|
|CRYPTO_MODE_SHA256|21|HMAC-SHA256|
|CRYPTO_MODE_SHA384|22|HMAC-SHA384|
|CRYPTO_MODE_SHA512|23|HMAC-SHA512|
|CRYPTO_MODE_MD2|24|HMAC-MD2|
|CRYPTO_MODE_RIPEMB128|26|HMAC-RIPEMB128|
|CRYPTO_MODE_RIPEMB160|27|HMAC-RIPEMB160|
|CRYPTO_MODE_RIPEMB256|28|HMAC-RIPEMB256|
|CRYPTO_MODE_RIPEMB320|29|HMAC-RIPEMB320|
|CRYPTO_MODE_SHA3_224|30|HMAC-SHA3-224|
|CRYPTO_MODE_SHA3_256|31|HMAC-SHA3-256|



A-Shell Reference 

Page 2252 

|**Symbol**|**Value**|**Description**|
|---|---|---|
||||
|CRYPTO_MODE_SHA3_384|32|HMAC-SHA3-384|
|CRYPTO_MODE_SHA3_512|33|HMAC-SHA3-512|
|**Definition File:**crypto.def|||



## _cbsrc_ 

## the same as for other opcodes. 

## **Example** 

```
++include ashinc:crypto.def
```

```
map1 text$,s,0,"The quick brown fox jumps over the lazy dog"
```

```
map1 key$,s,64,"key"
```

```
map1 hmac$,s,132
map1 status,i,4
```

- `! generate HMAC-SHA256 for text$ using key$` 

A-Shell Reference 

Page 2253 

```
xcall CRYPTO, CRYPTOP_HMAC, status, text$, "", hmac$, "hex", &
CRYPF_NONE, CRYPTO_CIPHER_NA, key$, 0, CRYPTO_MODE_SHA256
```

```
? "hex encoded hmac-sha256: ";hmac$
```

## **History** 

- 2020 July, A Shell 6.5.1688: The updated ASHNET 1.1.173 supports SHA3 hash algorithms in the HMAC operation via new mode parameter symbols 30 through 33. 

A-Shell Reference 

Page 2254 

## **CRYPTO EXAMPLES** 

Here we generate two 128 bit keys, returning the first one in a hex string format, and writing the other in raw binary format to a file. Note in both cases we are using the _dst_ parameter (and not the _key_ parameter) for the returned key. The _src_ , _decoding_ , _cipher_ , and _key_ parameters aren't used. Also note that although hex format for binary keys is convenient for string handling and printing purposes, handling it directly in an X variable would be the most compact (and would also eliminate the possibility of it being accidentally exposed in a subroutine trace). 

```
++include ashinc:crypto.def
```

```
map1 keybits,b,2,128        ! 128 bit key length
map1 hexkey$,s,32           ! 128 bits = 16 bytes (32 hex chars)
map1 status,f               ! return status
```

```
! return hex key directly in hexkey$ (dst) param:
```

```
xcall CRYPTO, CRYPTOP_GENKEY, status, "", "", hexkey$, "hex", &
CRYPF_NONE, CRYPTO_CIPHER_NA,"", keybits
if status = 32 then         ! (expecting 32 hex characters)
    print "key (in hex format):";hexkey$
```

```
else
```

```
    print "Error: ";status
```

```
endif
```

A-Shell Reference 

Page 2255 

```
! now generate another, writing it in binary format to file
```

```
xcall CRYPTO, CRYPTOP_GENKEY, status, "", "", "testkey.bin", "", &
```

```
CRYPF_DSTFILE, CRYPTO_CIPHER_NA, "", keybits
```

```
if status = 16 then         ! (expecting 16 bytes)
```

```
    print "key written to testkey.bin"
```

```
else
```

```
    print "Error: ";status
```

```
endif
```

Note: CRYPTOP_GENKEY provides the same functionality as the openssl rand utility. In fact, the second example (above) is directly equivalent to: 

```
openssl rand 16 > test.key
```

Here we generate a new random key (in raw binary format) and use it to encrypt a string, which is then encoded in base64. (This is a typical approach to encrypting sensitive fields within an XML web service request.) Error checking has been removed to simplify the example. 

```
++include ashinc:crypto.def
```

```
map1 keybits,b,2,128          ! 128 bit key
map1 symkey,x,16              ! raw symmetric key (128 bits = 16 bytes)
map1 src$,s,50                ! plain text string to encrypt
```

A-Shell Reference 

Page 2256 

```
map1 enc$,s,90                ! encrypted/encoded output
map1 dec$,s,50                ! decrypted string (to test decryption)
map1 status,f                 ! return status
```

```
! generate key into key var
xcall CRYPTO, CRYPTOP_GENKEY, status, "", "", symkey, "", &
CRYPF_NONE, CRYPTO_CIPHER_NA,"", keybits
```

```
! now use it to encrypt the src$
```

```
src$ = "This is a secret"
```

```
xcall CRYPTO, CRYPTOP_ENCRYPT, status, src$, "", enc$, "base64", &
```

```
CRYPF_SRCTEXT, CRYPTO_CIPHER_AES,symkey, keybits, CRYPTO_MODE_ECB, CRYPTO_PAD_PKCS5
print "status=";status;" cipher text = ";enc$
```

```
! now decrypt it to see if we get the original back
```

```
! (we'll use out of the encryption as the input of the decryption)
xcall CRYPTO, CRYPTOP_DECRYPT, status, enc$, "base64", dec$, "", &
```

```
CRYPF_SRCTEXT, CRYPTO_CIPHER_AES, symkey, keybits, CRYPTO_MODE_ECB, CRYPTO_PAD_PKCS5
```

```
if dec$ = src$ then
```

```
    print "Success: decrypted string matches original!"
```

A-Shell Reference 

Page 2257 

```
else
```

```
    print "Error: decrypted string doesn't match original!"
```

```
endif
```

Note that the _dst_ parameter here must be large enough to hold the encrypted/encoded message. For block ciphers like AES, the raw encrypted message length will be rounded up to the next multiple of the block (key) size, so for a 50 byte source, the encrypted version could be 64 bytes long. The base64 encoding will increase it further by a ratio of 4/3 (rounded up to next multiple of 4), so we would need 88 bytes to be safe. You can use a dynamic string output variable, but you must pre-initialize it to at least the minimum required size (if in doubt, err on the high side!). 

This is similar to Example 2 except that we'll use files for the source and destination, and a hex string variable for the key. This will be equivalent to the following openssl command strin1g: 

```
"openssl enc -aes-128-ecb -in msg.dat -out msg.enc -a -e -nosalt -K " + hexkey$
```

```
++include ashinc:crypto.def
```

```
map1 keybits,b,2,128          ! 128 bit key
map1 hexkey$,s,32             ! hex encoded key
```

```
map1 status,f                 ! return status
```

```
map1 src$,s,50                ! source filespec
map1 dst$,s,50                ! dest filespec
map1 decoding$,s,10           ! source file decoding
map1 encoding$,s,10           ! dest file encoding
```

A-Shell Reference 

Page 2258 

```
map1 cflags,b,4
```

## `! generate 128 bit key in hex format` 

```
xcall CRYPTO, CRYPTOP_GENKEY, status, "", "", hexkey$, "hex", CRYPF_NONE, CRYPTO_CIPHER_NA,"", keybits
```

- `src$      = "msg.dat"` 

```
decoding$ = ""                    ! no decoding of source (treat as raw)
dst$      = "msg.enc"
```

```
encoding$ = "base64"              ! encode the dest after encryption
```

```
cflags = CRYPF_KEYHEX             ! key is in hex format
```

```
cflags = cflags or CRYPF_SRCFILE  ! source is a file
```

```
cflags = cflags or CRYPF_DSTFILE  ! destination is a file
```

- `? "encrypting ";src$;" into ";dst$;" ..."` 

```
xcall CRYPTO, CRYPTOP_ENCRYPT, status, src$, decoding$, dst$, encoding$, &
```

```
    cflags, CRYPTO_CIPHER_AES, hexkey$, keybits, CRYPTO_MODE_ECB, CRYPTO_PAD_PKCS5
```

```
if status >= 0 then
```

```
    print status;" bytes output to ";dst$
```

```
else
```

A-Shell Reference 

Page 2259 

```
    print "error: ";status
    end
```

```
endif
```

```
! now decrypt it into msg.dec (which should match the original msg.dat)
```

```
src$      = "msg.enc"             ! source for decryption is the encrypted file
decoding$ = "base64"              ! pre-decode encrypted file before decryption
dst$      = "msg.dec"             ! decrypted file
encoding$ = ""                    ! no post-decryption encoding
```

```
? "decrypting ";src$;" into ";dst$; " ..."
```

```
xcall CRYPTO, CRYPTOP_DECRYPT, status, src$, decoding$, dst$, encoding$, &
```

```
    cflags, CRYPTO_CIPHER_AES, hexkey$, keybits, CRYPTO_MODE_ECB, CRYPTO_PAD_PKCS5
```

```
if status >= 0 then
```

```
    print "Decrypted file (";dst$;") should now match original"
```

```
else
    print "error: ";status
```

```
endif
```

A-Shell Reference 

Page 2260 

Note that in this case, it isn't necessary to specify whether the files contain text or binary data. (Treating it as binary is always safe.) Also note that for the decryption, the decoding option must match the encoding for the encryption. (We base64-encoded the encrypted file; so we need to first base64-decode it before decrypting.) 

Here we RSA-encrypt the 16 byte raw symmetric key (generated in Example 2), using a public key stored in the file testpub.pem. This is similar to the openssl rsautl command sequence: 

```
echo $KEY | openssl rsautl -encrypt -inkey tetpub.pem -pubin | openssl enc -base64
```

Note that the source for this operation may itself be a key (e.g. the symmetric key used to encrypt something else that we want to transmit secretly to the remote side), but from the perspective of the RSA encryption operation, it's just an arbitrary message to encrypt. This technique would apply to RSA public/private key encryption of any message, provided it is no longer than the RSA modulus (typically either 1024 or 2048 bits, i.e. 128/256 bytes). 

```
++include ashinc:crypto.def
```

```
map1 symkey,x,16              ! raw 128 bit symmetric key (generated in Example 2)
map1 symkey2,x,16             ! (to test decryption)
map1 status,f                 ! return status
map1 dst$,s,346               ! dest string
map1 keyfile$,s,30            ! PEM file (public or private key)
map1 cflags,b,4
```

```
cflags = CRYPF_KEYFILE            ! key is a file (cryptopub.pem)
```

```
cflags = cflags or CRYPF_PUBKEY   ! use the public key
```

A-Shell Reference 

Page 2261 

```
keyfile$ = "testpub.pem"          ! public key file
if lookup(keyfile$)= 0 then
    print keyfile$;" not found!  See doc notes to create"
    end
endif
```

```
xcall CRYPTO, CRYPTOP_ENCRYPT, status, symkey, "", dst$, "base64", &
    cflags, CRYPTO_CIPHER_RSA, keyfile$
if status >= 0
    print "Encryption success: ";status;" encrypted/encoded bytes output"
else
    print "Encryption error: status=";status
    end
endif
```

```
! now decrypt it into rawkey2 (which should match the original msg.dat)
```

```
! (this would normally be done by the remote counterpart)
```

```
cflags = cflags and not CRYPF_PUBKEY   ! clear PUB flag (we're using private key here)
keyfile$ = "test.pem"                  ! private key file
```

A-Shell Reference 

Page 2262 

```
xcall CRYPTO, CRYPTOP_DECRYPT, status, dst$, "base64", symkey2, "", &
    cflags, CRYPTO_CIPHER_RSA, keyfile$
if status >= 0 and symkey = symkey2 then
```

```
    print "Decryption success: decrypted symkey matches the original"
```

```
else
```

```
    print "Decryption error: status=";status
```

```
endif
```

## Notes: 

- The size of the encrypted output for RSA encryption is always the same as the RSA modulus (1024 or 2048 bits), adjusted for 

- the encoding. In this case, since base64 encoding expands the message by 4/3, we need at least 256 * 4/3 bytes (rounded up to next multiple of 4) or 344 bytes to hold the output. We mapped dst$ as 346 here to allow for a trailing null and even size. 

- The keybits parameter is not used with the RSA cipher 

- You can generate the test.pem (private key) and testpub.pem (public key) files for this example using openssl as follows: 

```
openssl genrsa -out test.pem 2048
```

```
openssl rsa -in test.pem -pubout > testpub.pem
```

## Here we encode 16 bytes of binary data as a 32 byte hex string: 

```
++include ashinc:crypto.def
```

```
map1 xdata
```

A-Shell Reference 

Page 2263 

```
    map2 xdata'bytes(16),b,1
map1 hexdata$,s,32            ! hex encoded key (from example 1)
map1 status,f                 ! return status
map1 x,f
```

```
for x = 1 to 16               ! generate 16 binary bytes
    xdata'bytes(x) = x
```

```
next x
```

```
! encode it in hex
```

```
xcall CRYPTO, CRYPTOP_ENCODE, status, xdata, "", hexdata$, "hex", CRYPF_NONE
```

```
? "hex encoded bytes: ";hexdata$
```

A-Shell Reference 

Page 2264 

## **DATES** 

_Reviewed and revised April 2024_ 

## **xcall DATES, opcode, result, <params...>** 

DATES performs several different date utility functions and has several calling formats, as shown below. 

## _opcode_ (Num)  [in] 

## specifies operation to perform: 

|**Symbol**|**Value**|**Operation**|**Syntax**|
|---|---|---|---|
|DTOP_CVTFMT|1|Convert one format (_date1_) to another<br>(_date2_)|xcall DATES, 1, result, date1, date2|
|DTOP_DATEAFTER|2|Compute date (_date2_) which is a specified<br>number of days (_days_) after_date1_|xcall DATES, 2, result, date1, date2, days|
|DTOP_DAYSAFTER|3|Compute number of days_date1_is after<br>_date2_|xcall DATES, 3, result, date1, date2, days|
|DTOP_YWD|4|Compute_date2_based on year, week, day of<br>week in X,6 or X,5 format of_date1_|xcall DATES, 4, result, date1, date2|
|DTOP_YWMD|5|Compute_date2_based on year, month,<br>week and day of week in X,6 format of|xcall DATES, 5, result, date1, date2|



A-Shell Reference 

Page 2265 

|**Symbol**|**Value**|**Operation**|**Syntax**|
|---|---|---|---|
|||_date1_||
|DTOP_EOM|6|Compute_date2_as last day of month in<br>_date1_|xcall DATES, 6, result, date1, date2|
|DTOP_ODTIM|7|Output formatted date (similar toODTIM<br>)|xcall DATES, 7, result, testdate, time, flags,<br>outbuf'or'chan|
|DTOP_IDTIM|8|Input formatted date (similar toIDTIM<br>)|xcall DATES, 8, result, inputstr, flags,<br>outdate, outtime|
|DTOP_RANGE|9|Return_out'of'range_(F) <>0 if_testdate_is<br>not between_lodate_and_hidate_(inclusive)|xcall DATES, 9, result, testdate, lodate,<br>hidate, out'of'range|



## **Definition file: ashell.def** 

## _result_ (Num)  [out] 

returns a code indicating if the operation was successful or what kind of error occurred: 

|**Value**|**Meaning**|
|---|---|
|0|OK|



A-Shell Reference 

Page 2266 

|**Value**|**Meaning**|
|---|---|
|1|Function number out of range (1-9)|
|2|Error in conversion of input date|
|3|Invalid format for date|
|4|Improper number/type of parameters|
|5|Invalid format for_days_|
|6|Error locating file channel (_opcode_7)|



## _days_ (Signed Num)  [out] 

for DTOP_DAYSAFTER, returns number of days _date2_ is after _date1_ 

## _out'of'range_ (Num)  [out] 

for DTOP_RANGE, returns zero if _testdate_ is within range defined by _lodate_ and _hidate_ (inclusive); else non-zero. 

## _date1, date2, testdate, lodate, hidate_ 

used for input and output, depending on the operation, with the format based on the way they are mapped: 

```
MAP1 ADATE,S,8          ! MM/DD/YY or DD/MM/YY; see note below
```

```
MAP1 BDATE,S,10         ! MM/DD/CCYY or DD/MM/CCYY; see note below
```

A-Shell Reference 

Page 2267 

```
MAP1 XDATE              ! Separated format (3 to 7 bytes)
```

```
    MAP2 MONTH,B,1
```

```
    MAP2 DOW,B,1         ! 1=Monday...7=Sunday (optional)
```

```
    MAP2 YWEEK,B,1       ! Week of year (1-52)     (optional)
```

```
    MAP2 MWEEK,B,1       ! Week of month (1-5)     (optional)
```

```
    MAP2 MDAYS,B,1       ! Days in month (1-31)    (optional)
```

```
MAP1 IDATE,B,4          ! Internal true Julian
```

```
MAP1 BDATE,B,3          ! Std AMOS date (same as 3 byte XDATE
```

```
MAP1 CDATE,B,2          ! Century Julian (days since 1/1/1900)
```

```
MAP1 JDATE,B,2          ! Yearly Julian (days since start of yr)
```

```
MAP1 FDATE,F,6          ! Special case (0=today on input)
```

## _inputstr_ (String)  [in] 

should be set to the date and/or time to be converted, with the time following the date (with a space separator) if both date and time are included. (Also see _flags_ parameter, which indicates if date and/or time are present.) The date, if present, should be in `MM-DD-{CC}YY` or `DD-MM-{CC}YY` format, depending on your language definition file specification for date order. The separator character, however, need not be a dash or even match the language definition file; it can be any non-numeric character. The time format is `HH:MM{:SS} {AM/PM}` . Legal examples would be: 

```
12/30/24 13:01
```

```
01-01-2024 10:15:33 PM
```

A-Shell Reference 

Page 2268 

```
23:01:10
```

```
05.03.1915
```

If only two digits are specified for the year, it is assumed to be in the twentieth century (19xx) unless the SBR=CCYY is included in miame.ini, in which case it will determine the YY cutoff below which we assume 20xx instead of 19xx. 

## _outdate_ (Structure)  [out] 

will return the date in system separated format, or zero if the date is not included in the input string. Note that to access the individual fields while still being able to test the overall value for 0, it should be mapped as an overlay per the following: 

```
MAP1 Sepdate
```

```
   MAP2 Mon,B,1              ! Month 1-12
   MAP2 Day,B,1              ! Day 1-31
   MAP2 Yr,B,1               ! Year-1900
   MAP2 Dow,B,1              ! Day of week (0=Mon, 6=Sun)
MAP1   Bdate,B,4,@Sepdate    ! B,4 version of Sepdate, as used by
                             !  the DATE system function
MAP1   Idate,F,6             ! F,6 version as needed by IDTIM
```

```
xcall IDTIM, StringFmt, Idate, Itime, Flags, Status
```

```
Bdate = Idate
```

```
Print "Separated date: ";Mon;Day;Yr;Dow
Bdate = DATE                 ! Get today's date (for comparison)
Print "Today's separated date: ";Mon;Day;Yr;Dow
```

A-Shell Reference 

Page 2269 

## _outtime_ (Bitmap 4)  [out] 

will return the internal format time (i.e. seconds since midnight) or zero if the time is not present. 

## _flags_ (Num) 

should be set to 0 to process both the date and time; 1 if the string is expected to contain only the time, and 2 if it is expected to contain only the date. 

## **Notes** 

- DATES considers a 4 byte binary input date to be in internal Julian format, rather than in the standard AMOS system date 

- format (which is actually a separated date format). A common mistake is to pass DATES a date in B4 format which was returned from the system DATE function or IDTIM, leading to massive confusion, especially when using the range testing operation (9). 

- The system parameter setting SBR=CCYY:## is used to determine the century cutoff on input dates in MM/DD/YY format. For 

- more details, see the SBR command. 

- The order of the parts of an eight or ten character string date is based on the LANG'DATE'FORMAT field in the current 

- language definition file, which is month first for the US, day first for most of the rest of the world. 

## **Counting Weeks** 

DATES counts the days of each week from Monday=1 to Sunday=7. (That may be a little strange, since most calendars show Sunday as the first day of the week instead of the last. But DATES is a port of some existing AMOS routine, so it was A-Shell's task to preserve the existing behavior, not to justify it.) 

The weeks are counted like rows in a calendar, again taking into account that our calendar weeks start with Monday and end with Sunday. So for 2011, the first week had only 2 days: Saturday and Sunday. Jan 3 was the start of the 2nd week. 

If you want to convert to a more standard calendar arrangement, where each week starts with Sunday and ends with Saturday, then just add +1 to Mon-Sat and for Sunday, set it back to 1 and add +1 to the week. 

On the other hand, if you want to say that each week of the year, including the first one, has seven days, then the week is simply the "yearly Julian" (DATES option 6) divided by seven, truncating the fractional remainder and then addding one (so the 

A-Shell Reference 

Page 2270 

first week is one rather than zero). Under that scheme, Mar 15 is the 74th day; 74/7 = 10.57; truncate to 10 and then add 1 to get the 11th week (which it is). 

## **History** 

- July 2017, A Shell 6.4.1551: Bug fix: Opcode 3 (DTOP_DAYSAFTER) was failing to handle the negative case properly, returning a large positive number instead of a negative number if date1 was before date2. Problem was introduced around 6.3.1516. Same fix as 6.5.1610. 

- 2017 February, A Shell 6.4.1543: Bug fix: DATES was outputting mm/dd/yy when it should have been mm/dd/ccyy—i.e. when the output string length >= 10. 

A-Shell Reference 

Page 2271 

## **DIGEST** 

_Reviewed and revised April 2024_ 

## **xcall DIGEST, digtype, srcdata, bytes, digest, status** 

DIGEST returns various cryptographic digests of strings or files. 

## **Parameters** 

## _digtype_ (Num)  [in] 

indicates the type of digest desired: 

|**Valu**<br>**e**|**Type**|**Digest Length**<br>**in Bits**|
|---|---|---|
|3|MD5|128|
|4|SHA 1|160|
|5|SHA 256|256|



Note that the _digtype_ values start at 3 rather than 1 to avoid possible conflict/confusion with the very similar HASH. See comments below. 

## _srcdata_ (String or BLOB)  [in] 

data to get the digest of. If _bytes_ =-1, then this is interpreted as the filespec (AMOS or native) containing the data. _bytes_ (Num)  [in] 

A-Shell Reference 

Page 2272 

number of bytes to process. If _srcdata_ is type S, _bytes_ may be set to 0 to mean the logical string length. If -1, _srcdata_ is interpreted as the name of the file to process. 

## _digest_ (String or BLOB)  [out] 

returned digest. If X, the digest is returned in raw binary form. If S, it is returned in hex representation. Minimum sizes depend on the _digtype_ : 

|**Value**|**Type**|
|---|---|
|MD5|X,16 or S,32|
|SHA-1|X,20 or S,40|
|SHA-256|X,32 or S,64|



Note: for applications requiring the digest encoded in base64, you can use CRYPTOXS to perform the conversion. 

## _status_ (Signed Num)  [out] 

returns status indicator: 

|**Value**|**Meaning**|
|---|---|
|>=0|# of bytes processed; should match_bytes_|



A-Shell Reference 

Page 2273 

|**Value**|**Meaning**|
|---|---|
|-1|bad data type for_srcdata_|
|-2|bad_digtype_|
|-3|bad_digest_type or size|
|-4|file not found|



## **Comments** 

DIGEST and HASHXS are very similar and may eventually be merged, although at present only DIGEST supports the file option. HASH is more oriented towards maximum performance with relatively small keys, as might be useful in a hash table alternative to a traditional index. DIGEST is more oriented towards security applications and large keys (or files) where computational performance and compactness are less important than minimizing the possibility of different keys having the same digest. 

## **See Also** 

- CRYPTOXS for HMAC (key encrypted) versions of the SHA and MD[XS] ~~,~~ as well as hex/base64 conversions. 

- DIGEST in EXLIB:[908,55] for example of usage. 

- MX_HASHFILEXS to get file hash total 

- HASHXS 

## **History** 

A-Shell Reference 

Page 2274 

- 2013 May, A Shell 6.1.1353: Routine added to A-Shell 

A-Shell Reference 

Page 2275 

## **DSKCOM** 

## **xcall DSKCOM, opcode, msgnam, var** 

DSKCOM is identical to COMMON except that it is disk-based, allowing sharing of information between different jobs. Also, the package name ( _msgnam_ ) may be up to twelve characters instead of the standard six. This allows you plenty of space to prepend the jobname if you want to identify which packets go with which jobs. 

The file is opr:common.sys, and will be automatically created on first access if it does not exist. You can erase it to forcefully reset any existing packets. 

The number and size of packets is determined in the same way as for COMMON, i.e. via the SBR=MSGNUM:#,MSGSIZ:# system parameters. The default is six packets of 150 bytes. 

You may use `ALIAS=COMMON:DSKCOM` if you want to convert your existing COMMON to disk based. 

A-Shell Reference 

Page 2276 

## **DSKPPN** 

_Reviewed and revised April 2024_ 

## **xcall DSKPPN, disk, ppn** 

or 

## **xcall DSKPPN, a$, ppn2** 

DSKPPN retrieves either the disk and PPN, or just the PPN. In the second format, it mimics an old custom subroutine called GETLOG. In that case, use `ALIAS=GETLOG:DSKPPN` . 

## **Parameters** 

All parameters are [out]. 

|**Paramete**<br>**r**|**Type**|**Comment**|
|---|---|---|
|disk|S,6|e.g. "DSK01"|
|ppn|S,7|e.g. "7,13"|
|ppn2|S,10|e.g. "[7,13]"|
|a$|S,1|dummy parameter|



A-Shell Reference 

Page 2277 

## **DSTOI** 

_Reviewed and revised April 2024_ 

## **xcall DSTOI, xdate** 

DSTOI converts a separated date (which is the format returned by the DATE system function in BASIC) into a Julian date which starts with 1/1/1900. You can use ODTIM or DATES to convert the Julian date back to various separated and printable formats. 

## **Parameters** 

_xdate_ (Structure)  [in/out] 

A separated date for the input data, overlaid with a B,4 variable for the output (Julian) date, mapped as follows: 

```
MAP1 xdate
```

```
   MAP2 mon,B,1        ! Month 1-12
   MAP2 day,B,1        ! Day 1-31
   MAP2 yr,B,1         ! Year-1900
   MAP2 dow,B,1        ! Day of week (0=Mon, 6=Sun)
MAP1 jdate,B,4,@xdate  ! # days since 1/1/1900
```

## **Example** 

```
xdate = DATE           ! load Xdate with separated date
xcall DSTOI, xdate     ! convert Xdate from separated to Julian
print "Julian date is: ";jdate
```

A-Shell Reference 

Page 2278 

## **DYNLIB** 

_Updated October 2021; see History_ 

To load/unload an external library: 

## **xcall DYNLIB, dlctl {,lib, convention, stackspace}** 

To call a function in the external library: 

## **xcall DYNLIB, dlctl, funcsig {,parms...}** 

(Windows and Linux only) DYNLIB provides a mechanism for A-ShellBASIC programs to dynamically access routines in external libraries written in C (or compiled to a C compatible object format), without the need for any special compile-time linking or modifications to A-Shell to support the external library. The fundamental difficulty here is the fact that third-party libraries may have many different calling conventions, and there is almost no limit to the variety of return types and parameter lists for the functions involved. DYNLIB deals with this variability by supporting a wide variety of the most common library calling 

conventions, and a flexible scheme for specifying function signatures so that the function arguments can be properly passed and converted. 

## _dlctl (ST_DYNLIBCTL)_ [in/out] 

This is a structure containing various control parameters used and/or updated for every call. It is defined in ashinc:dynlib.def as: 

```
defstruct ST_DYNLIBCTL
```

```
    map2 handle,DLHANDLE   ! handle to the external module
```

```
    map2 opcode,b,4        ! see DCOP_xxx
```

```
    map2 flags,b,4         ! flags (see DLF_xxx)
```

```
    map2 status,i,4        ! see (DYNLIBE_xxx)
```

```
    map2 syserr,i,4        ! system error set by called fun, e.g. GetLastError() for Windows; else errno
```

A-Shell Reference 

Page 2279 

```
    map2 lastfunc$,s,64    ! function signature of last called function
```

```
endstruct
```

## Opcodes from ashinc:dynlib.def are: 

|**Value**|**Symbol**|
|---|---|
|0|DCOP_LOAD|
|1|DCOP_UNLOAD|
|2|DCOP_CALL|
|4|DCOP_DEREF|
|5|DCOP_GETREF|



## _lib_ (String)  [in] 

Used only for the load routine (opcode DCOP_LOAD), _lib_ specifies the name of the external library. For Windows, this is just the DLL name (no path or extension needed, provided the DLL is in the standard search path, or in the A-Shell bin directory). For Linux, it will be a name like "libxl.so.1" which references a shared library in the system library path (typically /usr/lib). By convention, typically file in the /usr/lib directory is actually a symbolic link to the actual library file. 

_convention_ (Num)  [in] 

A-Shell Reference 

Page 2280 

Used only for the load routine to specify the calling convention for the external library. See the DLCC_xxx codes defined in ashinc:dynlib.def for the possibilities. Note that the most common options are DLCC_C_X86_WIN32_STD for Windows DLLs, and DLCC_C_X86_CDECL for Linux. 

## _stackspace_ (Num)  [in] 

Used only for the load routine to specify the amount of stack space to reserve for the library. 4 to 8K is typically plenty. 

## _funcsig_ (String)  [in] 

This string is used in conjunction with a call to a library function (opcode DCOP_CALL) to declare the function name, return type, and expected parameter list. The format is: 

## _funcname(pppp....)r_ 

## where: 

- _funcname_ is the name of the function to call in the external library 

- each p is a one letter code indicating the type of parameter from the table below 

- r indicates the return type of the function, from the table below 

|**Code**|**Description**||**Code**|**Description**|
|---|---|---|---|---|
|a|char * (convert ANSI to UTF8)||L|64 bit unsigned integer (x,8)|
|A|const char* (convert ANSI to<br>UTF8)||p|(lower case "p") void*; see_Output_<br>_Parameters_below|
|B|_Bool, bool (i,2) or i,4?||P|(upper case "P") similar to "p" but receives<br>the size of a ">" argument. See_Output_<br>_Parameters_below.|



A-Shell Reference 

Page 2281 

|**Code**|**Description**||**Code**|**Description**|
|---|---|---|---|---|
|c|char (s,1)||s|short (i,2)|
|C|unsigned char (s,1)||S|unsigned short (b,2)|
|d|double (f8)||u|char * (from UTF8 string). See_Output_<br>_Parameters_below.|
|f|float (f4)||U|const wchar * (from UTF8 string)|
|h|32 or 64 bit handle (x,8)||v|(lower case "v") void. See_Output_<br>_Parameters_below.|
||||V|(Upper case "V")const void *; like Z but is<br>converted to NULL if the corresponding<br>parameter value is "". See_Output_<br>_Parameters_below.|
|i|int (i,4)||w|wchar_t * (s)|
|I|unsigned int (b,4)||W|const wchar_t * (s)|
|j|long (i,4)||z|char * (s,0)|
|J|unsigned long (b,4)||Z|const char * (s,0)|



A-Shell Reference 

Page 2282 

|**Code**|**Description**||**Code**|**Description**|
|---|---|---|---|---|
|l|64 bit signed integer (x,8)||>|identifies an indirect output string<br>parameter. SeeDYNLIB Indirect Output.|



## **Examples** 

|**C Function Prototype**|**funcsig**|
|---|---|
|void f1();|”f1()v”|
|int f2(int, int);|”f2(ii)i”|
|long long f3(void*);|”f3(p)L”|
|void f3(int**);|”f3(p)v”|
|double f4(int, bool, char, double, const char*);|”f4(iBcdZ)d”|



Following the function signature, the remaining parameters are the arguments being passed, followed by the parameter to receive the return value of the function. 

## **Output Parameters** 

Parameters to be output or updated by the called routine should be defined using one of the **p** , **P** , **u** , **v** , **w** , or **>** codes. Codes **u** and **w** will convert ASCII / Latin1 strings used in the application to UTF8 or UNICODE-16 characters used by the called library routine, and vice versa if the parameter is updated by the routine. Code **v** is used for routines that do not return any value. See Indirect Output Parameters, for more details on the **P** and **>** codes. 

A-Shell Reference 

Page 2283 

## **Comments** 

See LIBXL.BSI in EXLIB:[908,68] for examples. 

Because this is a bit tricky, if you have an external library you would like to interface with, you may want to consult with MicroSabio to help you evaluate it and get it started. 

## **History** 

- 2021 October, A Shell 6.5.1708: Fully implemented types "l" and "L," added type "h." These were required to support using DYNLIB to call 64 bit library routines. The "h" (handle) option in particular is needed to allow BASIC programs to interface with libraries that rely on handles (like AXL) and which may be either 32 or 64 bit. 

- 2019 September, A Shell 6.5.1667:  Added type "P" which acts similarly to "p" but receives the size of a ">" argument. Useful for functions that return a pointer to a buffer in one argument and the size the buffer in another. The AXL function Fn'LibXL'GetPicture uses this technique. 

- 2017 November, A Shell 6.5.1621:  Added parameter types ">" and "P", plus opcode DCOP_DEREF. 

- 2017 November, A Shell 6.5.1619:  DYNLIB now supports up to four dynamic libraries simultaneously; previously it could only handle one at a time. 

- 2017 January, A Shell 6.3.1542:  automatic conversion from ANSI to/from UTF8 now supported via the "A" (read only) and "a" (read/write) codes. This is used in the Linux version of the LIBXL API to handle accented and other special Latin1 characters. 

- 2015 November, A Shell 6.3.1500:  Routine added to A-Shell. Initially for internal use only in conjunction with LibXL, later to be documented and made available to programmers. Documentation posted January 2017. 

## **Subtopics** 

- DYNLIB Indirect Output 

A-Shell Reference 

Page 2284 

## **DYNLIB INDIRECT OUTPUT** 

Although ASB doesn't normally allow direct handling of pointers, sometimes it is necessary in order to interface with external library routines written in lower-level languages such as C. A case in point occurs when the external routine passes back a pointer to an output string, rather than the contents of the string directly. DYNLIB offers two special parameter codes (capital **P** and **>** ) plus a special _opcode_ (DCOP_DEREF) to help manage these situations. 

In this first example, we want to use DYNLIB to call the following C function which returns a string. But rather than returning it directly, it returns a pointer to the string in the output parameter _pstring_ : 

```
void getstring(char **pstring);
```

To capture the string data (rather than its pointer), use the parameter code > as follows: 

```
map1 buffer,s,0            ! (dynamic ok, or size sufficient for output)
```

```
dlctl.opcode = DCOP_CALL
```

```
xcall DYNLIB, dlctl, "getstring(>)v", buffer
```

The " **>** " parameter code causes DYNLIB to copy the actual output string to the buffer parameter rather than copying its address. 

The DCOP_DEREF opcode provides an alternate way to handle pointers passed back by the external library routine. Rather than converting the pointer directly to its value as in the example above using the > parameter code, we instead allow the routine to just pass us back raw pointers (parameter code lower case p), and then use a separate operation (opcode DCOP_DEREF) to copy the strings referenced by the returned pointers into string variables. 

To illustrate using the same getstring() function as before, change the parameter type from **>** to code **p** (lower case), allowing us to retrieve the address of the string rather than it's contents... 

```
map1 buffer,s,0
```

```
map2 address,b,4    ! 32 bit!! (see note below)
```

```
dlctl.opcode = DCOP_CALL
```

A-Shell Reference 

Page 2285 

```
xcall DYNLIB, dlctl, "getstring(p)v", address   ! get ptr into address
```

Since we can't access the string via its address directly in ASB, we then use the DCOP_DEREF opcode to copy the referenced string into a string variable... 

dlctl.opcode = DCOP_DEREF 

xcall DYNLIB, dlctl, address, buffer  ! copy string pointed to by address into buffer 

Note that the variable you supply to receive the address must match the pointer size for the current execution environment. The example above uses B,4 for a 32 bit environment.  For 64 bit, use X,8. 

This two-step method is obviously more complicated than the one-step conversion using code **>** ,  but is the only way to deal with cases where the external routine returns a structure containing string pointers within it.  In such cases, you have to use the generic lower case **p** to receive the raw structure into a properly mapped ASB structure and then convert the string pointer(s) using individual DCOP_DEREF calls. 

**Warning** : referencing pointers is inherently dangerous—one reason why they are normally out of reach in higher level languages like ASB. Extreme caution must be exercised to make sure that the signature and received parameters match the external library requirements; any discrepancy will likely cause a segmentation fault. 

## **History** 

- 2017 November, A Shell 6.5.1621:  Added parameter type ">" and opcode DCOP_DEREF. 

A-Shell Reference 

Page 2286 

## **ECHO** 

_Reviewed and revised April 2024_ 

## **xcall ECHO {,channel}** 

## **xcall NOECHO {,channel}** 

ECHO is used to turn terminal echo on. It may also be used to return a serial port under UNIX to its normal settings. NOECHO is used to disable terminal echo. 

## **Parameters** 

_channel_ (Unsigned Int)  [in] 

Optional file channel associated with a serial point under UNIX. A value of zero, or omitted, refers to the terminal. 

Calling ECHO with no arguments is equivalent to executing the ECHO statement. 

## **Comments** 

NOECHO is usually used in conjunction with GET or some other subroutine for terminal input, such as INFLD, in order to (a) allow character input, and (b) disable echo. NOECHO does not affect the true state of the terminal, but merely changes the internal operation of A-Shell itself. So, for example, if HOSTEX is used to execute a host command, that command will function in the same way whether or not the NOECHO subroutine had been used. 

Under Unix, a serial port may be opened for input, and then NOECHO called with that channel specified, for example: 

```
open #1,"/dev/tty1",input
```

```
xcall NOECHO,1
```

In this case, the true _host_ mode of the port will be changed. Echo will be disabled, cooked mode processing will be disabled and so on, enabling all characters to be received unaltered from the port with the GET routine. This is particularly useful for communicating with external equipment such as modems, time record devices and so on. 

A-Shell Reference 

Page 2287 

If a port’s mode is changed in this way, then it should be reset with NOECHO before closing the channel. Failure to do this will leave the port in its altered state even when A-Shell is exited. 

## **Also See** 

- GETXS for more details on inputting from a serial port 

- ECHOSC 

A-Shell Reference 

Page 2288 

## **EFS** 

_Rewritten July 2016_ 

EFS (Encrypted File System) is an A-Shell add-on that provides various encryption-related functions. It is only available on certain Linux 32 bit platforms. Contact MicroSabio for further details. 

The EFS command syntax is dependent on the _opcode_ parameter. The various forms are: 

```
xcall EFS, 0, status
```

```
xcall EFS, 1, status, key {,append}
```

```
xcall EFS, 2, status, fspec, isencrypted
```

```
xcall EFS, 3, status, ispec {,ospec}
```

```
xcall EFS, 4, status, ispec {,ospec}
```

```
xcall EFS, 5, status, key
xcall EFS, 6, buildno
```

```
xcall EFS, 7, enable'logging
xcall EFS, 14 , flags
xcall EFS, 15, flags
```

EFS supports AES encryption of files at the I/O layer below that used by A-Shell/BASIC programs. There are various ways to specify which files are to be encrypted, such as in miame.ini by category or extension, and explicitly by a subroutine. But once encrypted, provided the decryption key has been registered, normal A-Shell/BASIC file I/O operations will automatically decrypt and re-encrypt the data on the fly as needed. Although A-Shell provides various cryptographic routines which operate on strings or individual files, if you have a lot of files to encrypt, EFS provides a more encompassing, more secure, and easier-to-implement solution. 

A-Shell Reference 

Page 2289 

## _opcode_ (Num)  [in] 

## Operation to perform, per following table 

|**Valu**<br>**e**|**Function**|
|---|---|
|0|Check if EFS is supported|
|1|Set key|
|2|Check if file is encrypted|
|3|Encrypt file|
|4|Decrypt file|
|5|Check key|
|6|Check efslib build|
|7|Enable/disable logging|
|14|Set A-Shell/EFS flags|



A-Shell Reference 

Page 2290 

|**Valu**<br>**e**|**Function**|
|---|---|
|15|Get A-Shell/EFS flags|



## _status_ (Signed Num)  [out] 

Status return code, per following table 

|**Valu**<br>**e**|**Meaning**|
|---|---|
|0|Available, licensed, okay|
|-1|Available, not licensed|
|-2|Not available|
|-3|Opcode not supported|
|-4|Parameter error|
|>0|Errno|



A-Shell Reference 

Page 2291 

_key_ (x,32)  [in] 

specifies encryption key, mapped as: 

```
MAP1 KEY,X,32
```

```
    MAP2 KEY$,S,32,@KEY
```

By specifying the unformatted key parameter, it will not show up in the trace log even if `TRACE=XCALL` is set. Furthermore, if your key is less than 32 bytes long, the remaining key bytes will be supplied from a default internal ashell key. By taking advantage of this feature, even if your part of the key was exposed and a copy of the file stolen, the culprit would still need a licensed copy of A-Shell to decrypt it. 

_append_ (Num  [in] 

if specified and non-zero, specified key is appended to the default internal A-Shell key 

_fspec_ (String)  [in] 

filespec in native or A-Shell notation 

_ispec_ (String)  [in] 

input filespec in native or A-Shell notation 

_ospec_ (String)  [in] 

output filespec in native or A-Shell notation 

_isencrypted_ (Num)  [out] 

returns non-zero if file encrypted, else zero 

_buildno_ (Num)  [out] 

returns the EFS build # (version #), which will be an integer in the range of 1-9999 

_flags_ (Num)  [in/out] 

A-Shell Reference 

Page 2292 

EFS system option flags. See History note for A-Shell 6.1.1379. 

_enable'logging_ (Num)   [in] 

Specify 0 to disable logging, 1 to enable it 

When the EFS license option in enabled, A-Shell will automatically detect when a random, ISAM, ISAM-A or sequential file has been encrypted and thus there is no need to specifically identify to A-Shell which files are encrypted, except when you create a new file. In that case, for RANDOM files created with ALLOCATE, use `XCALL ASFLAG,AF_CRYPTE` prior to the allocate to set the encryption flag. As with other ASFLAG values, the setting only lasts until the end of the current program. For ISAM-A, you can use the ISMUTL /E switch, which requires ISMUTL.LIT 1.3(128) or higher. For old ISAM, you can first use ISMBLD, then use `XCALL EFS,3,STS,ISPEC` to encrypt the DAT and/or IDX file(s). 

For encrypting sequential output files, you can either set the system parameters OPTIONS=EFS_OUT_AMOS or EFS_OUT_HOST, or the corresponding GOP2_EFS_OUT_xxx flags via MX_SETOPTIONS. 

You can also request that particular file extensions be automatically encrypted when created via the EFSEXT option in miame.ini. 

DIR.LIT will display an "E" next to any encrypted files. 

Because EFS is so powerful, and because the stakes are high, developers considering EFS  are urged to carefully review the capabilities and configuration options before implementation. You don't want to go to a lot of trouble to lock all the windows but leave the front door open, and you don't want to lock yourself out of the house! We cannot help you recover a lost encryption key!!! 

- EFSEXT in maime.ini 

- OPTIONS in maime.ini 

- MX_GETOPTIONS, MX_SETOPTIONS 

- TRACE=EFS TRACE in miame.ini 

A-Shell Reference 

Page 2293 

- MX_GETTRACE, MX_SETTRACE 

## **History** 

- 2014 March, A Shell 6.1.1379:  When A-Shell enters the interactive dot prompt state, it now (by default) clears the encryption key. This way, if a program should unexpectedly abort and drop to the dot prompt, it will not leave the user with access to encrypted files. You can override this behavior by using one or both of the new opcodes 14 or 15. Currently the only defined flag is: 

```
AEFS_CLEAR_KEY_ON_EXIT   &h0001        Clear EFS key on exit to dot prompt
```

The AEFS_CLR_KEY_ON_EXIT flag is set by default. To disable the option (returning to the prior behavior), use `{ XCALL EFS, 14, 0 }` to clear the flag. 

A-Shell Reference 

Page 2294 

## **EMAILP** 

## **command = sbx:EMAILP {,flags, subject, intro}** 

(Windows only) EMAILP.SBX is a print filter subroutine intended only for use in a COMMAND statement within a printer ini file. It launches your local email client and embeds the specified printfile into the body of the message, allowing the user to then address and complete the sending process. 

Note that since the way this subroutine can be called is from within a printer ini file, the parameters must be specified as literals. (There are no "variables" within printer ini files.) Remember to enclose strings in quotes if they contain embedded commas. 

## **Parameters** 

## _flags_ 

may optionally be specified as the sum of one or more of the following values: 

|**Value **|**Meaning**|
|---|---|
|1|Receipt requested|
|2|Send file as attachment instead of embedded within message. (Not yet<br>implemented; consult source code EMAILP.BAS for update notes.)|
|4|Use HTML coding to set fixed pitch (when embedding)|



## _subject_ (String) 

a literal string containing the desired subject of the email message. 

_intro_ (String) 

A-Shell Reference 

Page 2295 

contains the text that will be inserted at the top of the message. 

A-Shell Reference 

Page 2296 

## **EMAILX** 

## **xcall EMAILX, opflags, cfgfile, to, header, body, status {,from, attachments, signature, errmsg, socket, server, host, username, password}** 

EMAILX.SBX is a subroutine that allows an application to communicate with an SMTP server to send email. It supports the following general features: 

- Plain text or HTML formatted message content 

- Up to 10 attachments 

- Basic and OAUTH2 authentication (use the subroutine OAUTH2 to obtain the access token) 

- SSL/TLS 

- STARTTLS 

- No restriction on headers 

See the following sections for more information. 

Note that EMAILX is not included in the normal A-Shell distribution package but is an extra-cost option; details in EMAILX Adminisetera. 

## **Subtopics** 

- EMAILX Parameters 

- EMAILX Config File 

- EMAILX Header Specifications 

- EMAILX Scenarios 

- EMAILX Troubleshooting 

A-Shell Reference 

Page 2297 

- EMAILX Revision History 

- EMAILX Adminisetera 

A-Shell Reference 

Page 2298 

## **EMAILX PARAMETERS** 

|**Parameter**|**I/O**|**Description**|
|---|---|---|
|Opflags|in|Operation flags|
|Cfgfile|in|Name of configuration file|
|To|in|Address of recipient(s)|
|Header|in|Header fields|
|Body|in|Text of message|
|Status|out|Return code|
|From|in|Email address of sender|
|Attachments|in|Attachments|
|signature|in|DevPPN or native filespec to be appended to bottom of message body. Like_body_,_signature_can<br>also contain the actual text rather than a filename. See note below.|
|errmsg|out|If present, will receive a (possibly) useful text string if STATUS # 0 (elaborating on the error<br>condition.).|



A-Shell Reference 

Page 2299 

|**Parameter**|**I/O**|**Description**|
|---|---|---|
|socket|in/out|Ignored on input unless you use_opflags_to avoid opening and closing the SMTP session for each<br>message; in which case it receives the socket # of the session on the open call and must be<br>passed to all the subsequent calls. Note that you must manually close the socket if you use the<br>EMF_LEAVEOPENoption.|
|server|in|Name or IP address of the SMTP server. (append :<port> if not using port 25). See note below.|
|host|in|Name to identify your domain to the SMTP server in the initial protocol exchange with the SMTP<br>server. See note below.|
|username|in|Overrides the_username_field in the configuration file to specify the user name needed to<br>authenticate with the SMTP server. If_username_and_password_are both specified (and not blank)<br>and no AUTH mode was specified, AUTH = AUTO is used automatically.|
|password|in|Overrides the_password_field in the configuration file to specify the password needed to<br>authenticate with the SMTP server. If_username_and_password_are both specified (and not blank)<br>and no AUTH mode was specified, AUTH = AUTO is used automatically. Note that the password<br>may be specified in encrypted form (provided it was encrypted withMX_PWCRYPT). In the case of<br>AUTH = XOAUTH2, the password should be the access token.|



Note that if values for _signature_ , _server_ and _host_ are not specified explicitly, the values for those parameters will be taken from the configuration file. If no _host_ is provided, we use nothing, which may lead to your mail being rejected, or possibly sent with a warning that it comes from an unidentified source. 

A-Shell Reference 

Page 2300 

## **OPFLAGS** 

_opflags_ (Num)  specifies various operation flags, using the sum of one or more of the following: 

|**Symbol**|**Valu**<br>**e**|**Type**|**Description**|
|---|---|---|---|
|EMF_NORMAL|0|B,2|normal operation|
|EMF_LEAVEOPEN|1|B,2|don't close session|
|EMF_ALREADYOPEN|2|B,2|don't open; (already open)|
|EMF_OPENONLY|4|B,2|open only; ignore all but SERVER & HOST|
|EMF_CLOSEONLY|8|B,2|close only|
|EMF_HDRCAT|16|B,2|concatenate HEADER+BODY (no CRLF)|
|EMF_HTMLBODY|32|B,2|BODY contains <HTML>|
|EMF_MIMEBODY|64||BODY is a self-contained MIME part|
|EMF_TLS|1024||Use SSL/TLS for SMTP connection|



A-Shell Reference 

Page 2301 

|**Symbol**|**Valu**<br>**e**|**Type**|**Description**|
|---|---|---|---|
|EMF_STARTTLS|2048||Use STARTTLS (start with unencrypted connection, then<br>elevate to TLS with the STARTTLS SMTP command)|
|**Definition file:**emailx.def||||



Note that in most cases you can get by with EMF_NORMAL. The next four flags (EMF_LEAVEOPEN, EMF_ALREADYOPEN, EMF_OPENONLY, and EMF_CLOSEONLY) are only of interest if you are sending a lot of emails in a batch and want to eliminate the overhead of having to open and close the connection with the SMTP server for each message. EMF_HDRCAT is only used when you want to include email header items in both the _header_ and _body_ parameters. And EMF_HTMLBODY is only recommended when you have used your own HTML formatting within the body of your message. 

A-Shell Reference 

Page 2302 

## **CFGFILE** 

_cfgfile_ (String, may be null)  specifies the filename (DevPPN or native) of a configuration file containing additional parameters of the type that are thought likely to vary by installation but otherwise remain fixed for that installation; see EMAILX Config File for details. Note that all of the parameters after _status_ are optional on the subroutine, but only to the extent that the corresponding parameter is defined in the configuration file. 

A-Shell Reference 

Page 2303 

## **TO** 

_to_ (String)  specifies the email address(es) of recipient(s), each using standard unadorned email address format such as `tom@microsabio.com` . If you are specifying multiple addresses, separate them with chr(13) characters. Up to 100 addresses allowed. 

Note that if you plan to use the CC: or BCC: header items to send copies of the message to other people, those people must be listed here in the _to_ parameter. This parameter is strictly used by the SMTP server for routing and does not (usually) show in the recipient’s message header. 

A-Shell Reference 

Page 2304 

## **HEADER** 

_header_ (String)  specifies zero or more header fields, separated by CRLF (i.e. chr(13)+chr(10)) and each conforming to the formatting rules in the appropriate RFC’s such as RFC 822 and RFC 1521. EMAILX does not check your header items for validity. Note that you may decide to skip this parameter and put all of your header items in the body of the message; see _body_ . Or you can put some here and some in the _body_ parameter, provided you then specify the EMF_HDRCAT flag in _opflags_ . Here are some sample header lines: 

```
To      : "George Washington" <gw@cherrytree.com>
```

```
From    : "Paul Revere" <prevere@patriots.net>
```

```
Subject : The Redcoats are Coming
```

```
Reply-To: <admin@federalists.org>
```

```
cc      : <tj@montebello.net>
```

Although headers are technically part of the body of the message as far as the SMTP server is concerned, there is a core set of headers that SMTP servers, and especially email readers understand, plus an extended set that most understand, plus a specification for how to define your own headers. See the section on EMAILX Header Specifications for more details. 

Internet email (and most other) standards are documented in a series of "RFC’s" (Request For Comments) which fortunately are very accessible via the Internet; just search for "RFC 822." 

A-Shell Reference 

Page 2305 

## **BODY** 

_body_ (String)  specifies the body of the message, either directly by including the entire body in the variable (with each line terminated by a CRLF), or indirectly (by giving the name of a file which contains the body of the message.) If you are specifying a filename (either DevPPN or native) rather than the body itself, this parameter must contain a string less than 128 characters long with no carriage returns. Otherwise, the parameter will be treated as the literal body of the message. Note that if the _header_ parameter was not blank, and the EMF_HDRCAT flag was not specified, then a blank line will be automatically inserted into the message to separate the header from the body. (This is part of the standard mail format rules, but is so likely to be overlooked by Basic programmers that we do it automatically here.) 

If you include HTML formatting within the body of the message, you should specify the EMF_BODYHTML flag in the _opflags_ parameter. Most modern email readers are smart enough to figure it out for themselves, but some older ones may fail to recognize HTML formatting without a "Content-Type: text/html" header, which EMAILX will add for you if you specify the flag. 

A-Shell Reference 

Page 2306 

## **STATUS** 

_status_ (F,6)  provides the return code. 0=success, else error. Negative numbers represent system or network errors such as unable to connect, no route to host, etc. The string associated with the error will be returned in _errmsg_ or output to the specified file. Positive numbers greater than 100 are the actual codes returned by the SMTP server with the remainder of the message returned in _errmsg_ . Positive numbers between 71 and 99 are application or miscellaneous errors. The more common _status_ values are defined in EMAILX.DEF (++include in your application) as shown below: 

|**Symbol**|**Value **|**Type **|**Description**|
|---|---|---|---|
|EMS_OK|0|B,1|Ok|
|EMS_TOOFEW|71|B,1|Too few parameters|
|EMS_TIMEOUT|72|B,1|Timed out|
|EMS_NOTO|73|B,1|No_to_address|
|EMS_NOBODY|74|B,1|No_body_text|
|EMS_BADRESP|75|B,1|Bad SMTP response|
|EMS_NOSOCKET|76|B,1|No socket open|
|EMS_NOCFG|77|B,1|Specified CFG file not present|
|EMS_BADCFG|78|B,1|Syntax error within CFGFILE|



A-Shell Reference 

Page 2307 

|**Symbol**|**Value **|**Type **|**Description**|
|---|---|---|---|
|||||
|EMS_BADSIG|79|B,1|Bad signature file|
|EMS_BADATT|80|B,1|Bad (empty or missing) attachment|
|EMS_B64ERR|81|B,1|Base64 encoding error|
|**Definition file:**emailx.def||||



Values 1-70 would indicate ASB error conditions. Consult sys:errmsg.usa or use DERR to get the text message associated with the error number. 

Error 80 (EMS_BADATT) indicates that the specified attached is missing or empty, not that its contents are somehow bad. A likely cause—other than the obvious bad filespec—is that you're creating the file immediately prior to emailing it as an attachment, and you either failed to close it, or the creation mechanism uses an external process (e.g. PDFX) that may be taking longer than expected. One debugging technique for verifying that the filespec is at least correct is to activate the FOPENS and XDEBUG TRACE flags prior to running your program, and then check the ashlog file. 

Negative values represent system network errors. To get the error message associated with a negative value of STATUS, use `XCALL TCPX, TCPOP_ERRMSG, STATUS, MESSAGE$, TCPFLAGS` (where TCPFLAGS must contain TCPXFLG_TLS if either of the EMF_TLS or EMF_STARTTLS bits are set in _opflags_ ). Also see the ERRMSG parameter, which may contain a useful message, typically the last command sent to the server or last response from it. 

Values in the range of 200-599 are SMTP reply codes. (The SMTP protocol consists of a series of command/requests, each of which receives a response beginning with one of these reply codes. When the code indicates a failure, EMAILX will abort and 

A-Shell Reference 

Page 2308 

return that code in the _status_ parameter.) You can get a more complete picture of the conversation between EMAILX and the SMTP server by examining the log file (see the LOGFILE and LOGLVL parameters in the configuration file). For a complete understanding of the theory and interpretation of the SMTP protocol, including the reply codes, consult the relevant RFCs, particularly RFC 5321. The log file may also show additional enhanced "status codes", typically presented in the form of x.x.x, which may provide more information about the nature of the problem. A simple web search for "SMTP reply codes" or "SMTP status codes" will help you locate a variety of websites with simplified lists of the codes (the RFC is thorough and academic, but not conducive to a quick look-up), as well as forum/support/blogs discussing typical SMTP problems. Because these issues are generally specific to the particular SMTP server or network, EMAILX can do little more than report the information returned from the SMTP server, and this documentation can do little more than provide this general advice before sending you off to the web for more troubleshooting. 

A-Shell Reference 

Page 2309 

## **FROM** 

_from_ (String, optional)  specifies the email address of the sender. This is optional because it is likely to be the same for the entire application and thus can be specified in the configuration file via the `RTNADDR` parameter. If specified here, it will override the configuration file. Note that this is the address that will receive messages from the SMTP server itself about problems delivering the mail. 

## **History** 

- 2024 February, A Shell 6.5.1755, EMAILX.SBX(147) and (148): The RTNADDR directive and _from_ parameters can now include descriptive names, such as `Big Brother <bigbro@us.gov>` instead of just `bigbro@us.gov` . Also, a descriptive name included in the _from_ parameter or RTNADDR configuration file directive will now appear in the header seen by the recipient, if no explicit "From:" clause is included in the _header_ parameter. Previously, if not specified explicitly, the recipient would see only the unadorned version of the _from_ address, e.g. name@domain. 

A-Shell Reference 

Page 2310 

## **ATTACHMENTS** 

_attachments_ is a formatted parameter which may specify any number of attachments: 

```
MAP1 ATTACHMENTS
```

```
   MAP2 ATT’COUNT,B,2               ! # of attachments
```

```
   MAP2 ATTX(n)                     ! n >= value of ATT’COUNT
      MAP3 ATT’FILE,S,128           ! attachment filespec
      MAP3 ATT’CONTENT’TYPE,S,127   ! content’type string
      MAP3 ATT’ENCODING,B,1         ! See CTE’xx in EMAILX.DEF
```

If you are not using attachments, you can specify the _attachments_ parameter as a null string (mapped or literal) for simplicity. 

The size of the `ATTX()` array (n as shown above) is up to you, but must be at least as large as `ATT’COUNT` , which in turn must equal the number of items in the array (i.e. attachments) which are to be used. The maximum is currently 10 (i.e. up to 10 attachments allowed.) 

The `ATT’FILE()` items must contain the name of the file to be attached in either DevPPN or native format. 

`ATT’CONTENT’TYPE()` is optional; if non-blank, it should be a legal MIME Content-Type header, for example: 

```
Content-Type: application/octet-stream; name="xyz.doc"
```

You may omit the "Content-Type:" preface to the string, since if not present, it will automatically be added. You can also omit the name= field, in which case the name will be set to the actual name of the attachment (stripped of its directory.) If the entire string is blank, EMAILX will build one using "application/octet-stream" as the type. 

`ATT’ENCODING()` indicates the MIME Content-Transfer-Encoding to be used. The default (0) is base64, which should work for all attachments because it delivers an exact copy of the attached file. The only downside is that the encoding increases the size of the mail message by about 34%. 

A-Shell Reference 

Page 2311 

## Note that EMAILX will automatically perform the Base64 encoding for you; you just supply the name of the file. 

The encoding types are defined as: 

|**Symbol**|**Value **|**Type **|**Description**|
|---|---|---|---|
|CTE'BASE64|0|B,1|Base64 (default)|
|CTE'7BIT|1|B,1|7 bit unencoded text|
|CTE'8BIT|2|B,1|8 bit unencoded text|
|CTE'BINARY|3|B,1|Binary unencoded data|
|CTE'QUOTED|4|B,1|Quoted Printable encoding|
|CTE_ATT'ON'G<br>W|128||Attachment_fspec_is on gateway<br>machine|
|**Definition file:**emailx.def||||



`CTE’7BIT` , `CTE’8BIT` , and `CTE’BINARY` are all similar in that they indicate that no encoding has been done to the attachment. Of these, the first two should only be used with text consisting of reasonably short delimited lines. `CTE’BINARY` indicates that the data is truly raw, possibly not fitting into the line length requirements of SMTP. Both `CTE’8BIT` and `CTE’BINARY` require that all of the MTA’s (Mail Transfer Agents) can handle 8 bit data, which is not necessarily guaranteed. (This is why `CTE’BASE64` is preferred, since it encodes anything using a 7 bit character set.) 

A-Shell Reference 

Page 2312 

Also note that most mail readers will display 7bit text/plain attachments as if they were simply part of the message body rather than clearly separating them as attachments. 

`CTE’QUOTED` indicates that the attachment is already in "quoted printable" format. This is a format that consists mostly of plain text, with an escape mechanism use to encode special characters. The advantage of this over Base64 is primarily that it is still somewhat readable even if the mail reader doesn’t understand the encoding. (Base64, on the other hand, is not human-readable at all.) However, by now, virtually all mail readers support Base 64, so we have not bothered to implement quoted printable encoding, other than to allow you to do your own encoding and then indicate that it has been done. 

It is worth repeating that if you want to use quoted printable (CTE’QUOTED) encoding, you must do it yourself. EMAILX will only supply the proper header for you. 

Refer to RFC 1521 for more details on attachments and MIME headers. 

A-Shell Reference 

Page 2313 

## **EMAILX CONFIG FILE** 

_Updated January 2024; see History_ 

The EMAILX configuration file provides a means of setting default parameters and other options in one place rather than having to set them redundantly across many programs in an application, department or site. The file is normally called emailx.cfg, although there is no default name or search path; you must specify it explicitly in the _cfgfile_ parameter. It consists of directives in the form: 

## **<item> = <value>  ; <optional comment>** 

Items which correspond directly to actual EMAILX parameters, such as PASSWORD, will be overridden by a non-blank value passed in the corresponding parameter in the xcall statement. Other items, such as LOGLVL, control extensions not otherwise configurable via the parameter list. 

Note that while the format is generally typical of other configuration files, it doesn't completely conform to the INI standard required by INIX.SBX, due to the lack of [sections] and the looser use of spaces and comments. 

Note also that the config file items are case INsensitive. 

|**Item**|**Value / Description**|
|---|---|
|ADDATTACHMENT|This specifies the filespec of file to be attached in DevPPN or native format. It is equivalent to the<br>attachments parameter except it uses defaults for the ATT'CONTENT'TYPE and ATT'ENCODING<br>attributes.|
|ADDBCC|Any number of ADDBCC directives may be specified, each with a single unadorned email address, for<br>example "ADDBCC=eavesdropper@bigbrother.com."|
|AUTH|SMTP Authentication.|



A-Shell Reference 

Page 2314 

|**Item**|**Value / Description**|
|---|---|
|CONNLOCK|The only option is 1 (CONNLOCK=1), which uses a system lock to limit usage to only one SMTP<br>session—i.e. to prevent multiple users from making simultaneous connections to the SMTP server.<br>Typically unnecessary.|
|DELAY|This specifies the number of seconds to delay prior to connecting to the SMTP server. This only makes<br>sense in situations where the application is calling EMAILX multiple times rapidly, potentially<br>overwhelming the server or crossing some kind of usage/rate threshold.|
|DOMAIN|DOMAIN is a strictly optional directive which specifies the domain to be added to any unqualified<br>address, thus allowing you to abbreviate the addresses, say, for your local company by dropping the<br>@ and everything after it. For example, if<br>`DOMAIN=microsabio.com`, then if you specify the address<br>`"admin"`in the_to_or_from_fields, it will automatically be expanded to<br>`"admin@microsabio.com"`.|
|HOST|HOST fulfills the same purpose here as it does in the subroutine parameter list, and is used only if<br>HOST is blank or not specified in the subroutine. This is typically your domain name, and is used to<br>identify your computer or domain to the SMTP server when making the initial connection.<br>Theoretically, the SMTP server may decide to accept or reject you based on whether it recognizes or<br>can resolve this domain name.|
|LOGFILE|Log file name|
|LOGLVL|Log level|
|PASSWORD|Password.|
|REDIRECT|REDIRECT provides an easy way to temporarily redirect ALL outgoing mail to a specified address for|



A-Shell Reference 

Page 2315 

|**Item**|**Value / Description**|
|---|---|
||testing purposes. Note that the original To, CC, and BCC addresses will remain in the header, but will<br>all be changed to the redirect address for actual routing purposes. For example:<br>`REDIRECT =`<br>`me@mydomain.com`|
|REPLYTO|This is an important directive often confused with the return address. This is where mail will be sent if<br>the reader clicks the "Reply" button in their email client. It may or may not be the same as the<br>address of the person (or cyber-entity) that actually sent the message. If specified, it inserts a line in<br>the message header reading<br>`"Reply-To: "`followed by the specified address.|
|RTNADDR|Default return address; used only if the_from_parameter is empty. May be unadorned, i.e.<br>name@domain, or adorned with a descriptive prefix, e.g.`Mr. Magoo <magoo@cartoons. tv>`. See<br>History below. Also see REPLYTO above.|
|SECUREHELLO|Enable/Disable secure EHLO message.|
|SECURE|Type of secure connection.|
|SERVER|SMTP server name|
|SIGNATURE|Signature file|
|USERNAME|USERNAME fulfills the same purpose here as it does in the subroutine parameter list, and is used only<br>if the AUTH directive is specified, and the username is blank or not specified in the subroutine.|
|WAIT|Maximum wait for SMTP response|



A-Shell Reference 

Page 2316 

|**Item**|**Value / Description**|
|---|---|
|||
|WAIT2|Similar to WAIT, but units are milliseconds (default=200) rather than seconds, and applies only to<br>packets received after the first response to the HELO/EHLO command. Normally, once the first packet<br>of a response to a command is received, any additional packets are received without delay. But in the<br>case of HELO/EHLO, the server typically responds with an extended list of supported options,<br>sometimes with small delays between them.|



## **Sample** 

```
;EMAILX.SBX configuration file
```

```
WAIT      = 10                      ; max wait (secs) for SMTP response
SERVER    = localhost               ; SMTP server
SECURE    = STARTTLS                ; use STARTTLS protocol
AUTH      = *                       ; SMTP auth mode (LOGIN or PLAIN)
USERNAME  = yo@micasa.com           ; SMTP login username
PASSWORD  = secret                  ; SMTP login password
HOST      = microsabio.com          ; HELO (sending domain)
DOMAIN    = microsabio.com          ; default domain to add to unqualified addrs
RTNADDR   = ashell@microsabio.com   ; return address (default FROM address)
```

A-Shell Reference 

Page 2317 

```
REPLYTO   = replyto@microsabio.com  ; default Reply-To address
```

```
SIGNATURE = EMAILX.SIG              ; signature file (text, DevPPN or native spec)
LOGFILE   = EMAILX.LOG              ; log file name (DevPPN or native)
LOGLVL    = 3                       ;
```

## **History** 

- 2024 February, A Shell 6.5.1755, EMAILX.SBX(147) and (148): The RTNADDR directive and _from_ parameters can now include descriptive names, such as `Big Brother <bigbro@us.gov>` instead of just `bigbro@us.gov` . Also, a descriptive name included in the _from_ parameter or RTNADDR configuration file directive will now appear in the header seen by the recipient, if no explicit "From:" clause is included in the _header_ parameter. Previously, if not specified explicitly, the recipient would see only the unadorned version of the _from_ address, e.g. name@domain. 

- 2023 June, A Shell 6.5.1732, EMAILX.SBX(144):  Support multiple ADDBCC directives. 

- 2018 December, A Shell 6.5.1651, EMAILX.SBX(139):  Add parameters ADDBCC and REDIRECT. 

A-Shell Reference 

Page 2318 

## **WAIT** 

WAIT specifies the maximum number of seconds we will wait for a response from the SMTP server before aborting and returning `STATUS` = `EMS’TIMEOUT` . If not specified, default is 30 seconds. Note that if you are using a dial-on-demand connection to your SMTP server, 30 seconds may not be long enough. On the other hand, if your SMTP server is on the local LAN, it is probably unnecessarily long—although the only harm there is that the user may get tired of waiting for the timeout, particularly during initial testing when the connection parameters may need tweaking. 

Note: Users have reported that Gmail can take as long as 240 seconds to respond sometimes. 

A-Shell Reference 

Page 2319 

## **SERVER** 

SERVER fulfills the same purpose here as the _server_ parameter in the XCALL parameter list is used only if SERVER is blank or not specified. Since a given installation will probably always use the same server, it may be much more convenient to put the information here in the configuration file than having to embed it in the application. Note that although the traditional default port for SMTP servers remains 25, most modern SMTP servers use other ports such as 465 (typically for implicit SSL connections) or 587 (typically for STARTTLS). To avoid confusion, append the port number to the server DNS name or IP address. For example: 

```
SERVER = localhost:10025    ; local SMTP server on port 10025
SERVER = 1.2.3.4:9925       ; SMTP server at 1.2.3.4 port 9925
SERVER = mail.myisp.net     ; SMTP server at ISP
```

A-Shell Reference 

Page 2320 

## **SECURE** 

SECURE may optionally be used to specify the type of secure connection to establish with the SMTP server. The options are **TLS** (establish an SSL/TLS encrypted connection immediately, typically at port 465), **STARTTLS** (start with an unencrypted connection and then upgrade to TLS using the STARTTLS SMTP command), or **NONE** (unencrypted connection). If SECURE is not specified, the option defaults to NONE. Note that changing the SECURE option typically requires changing the port (see _server_ above). 

## **See Also** 

- SECUREHELLO 

- EMAILX Adminicetera (for related requirements) 

A-Shell Reference 

Page 2321 

## **AUTH** 

The AUTH directive is used to specify the type of SMTP authentication. As of edit 142, EMAILX supports the following authentication methods: 

- None: typically used with local relay servers; just omit the AUTH directive 

- PLAIN: plain text username/password 

- LOGIN: encrypted username/password exchange 

- AUTO: EMAILX will select LOGIN if available, else fall back to PLAIN 

- XOAUTH2: application must specify the access token as the password 

Note that SMTP servers will normally list their supported AUTH options in response to the EHLO message, e.g. 

- `EHLO microsabio.com` 

- `< 250-smtp.abc.xyz.com Hello` 

```
250-PIPELINING
```

```
250-ENHANCEDSTATUSCODES
```

```
250-AUTH LOGIN
```

```
etc.
```

You can see this in the Log file for Loglvl 4 or higher. 

In the above case, the server is announcing that it supports just the AUTH LOGIN variation. Some servers, however, will not indicate which AUTH methods it supports until after a secure channel is negotiated, followed by a re-sending of the EHLO command. So the first list might omit the AUTH line, or show it with no options. Then, after the second EHLO, it will report another another list of supported options, similar to the above, but perhaps with variations or additions, corresponding to secure mode. 

A-Shell Reference 

Page 2322 

## **See Also** 

- SECUREHELLO 

- XOAUTH2 Authentication 

## **History** 

- 2018 June, A Shell 6.5.1637, EMAILX edit 138, ASHNET 163:  Add XOAUTH2 support. 

A-Shell Reference 

Page 2323 

## **PASSWORD** 

PASSWORD fulfills the same purpose here as it does in the subroutine parameter list, and is used only if the AUTH configurlation file directive is specified, and the _password_ parameter on the XCALL statement is blank or not specified. As of EMAILX 5.1(129), you may supply the password text in encrypted form (using MX_PWCRYPT to encrypt it). When the encrypted password contains control characters which are not conveniently represented in a text editor, you may also supply the password as a comma delimited series of decimal values representing the ASCII characters. 

## **Examples** 

```
PASSWORD = secret123
```

```
PASSWORD = 2, 33, 124, 1, 98, 13, 127, 52, 44
```

```
PASSWORD = C4VnnLkfd0RyrS7Mo9kpo7bJLnzC1F678/KJ99wB1q2wOKW87Nhivb36Qi4y5sYmX+ppD
```

The first example shows a plain text password being stored in the configuration file; this is a bad idea. The second illustrates specifying the password characters using their ASCII decimal values; in this case it is a MX_PWCRYPT mode 2 encrypted password. The third is a MX_PWCRYPT mode 3 encrypted password EMAILX will automatically recognize and decrypt passwords encrypted by MX_PWCRYPT, using the SMTP USERNAME as the seed and a null key. 

Note that although the password value can also be an XOAUTH2 access token, it wouldn't make sense to store that in the EMAILX configuration file, since it is subject to frequent updating. 

A-Shell Reference 

Page 2324 

## **SIGNATURE** 

SIGNATURE is equivalent to the subroutine parameter of the same name, and is used only if the subroutine parameter is blank or not present. The theory behind putting it here is that you may wish to include the same "signature" text on every message, yet every installation will surely have their own (typically listing important contact information for the company), so why bother having to reference it explicitly on every email. Note that there is nothing magical about the "signature" – it is just text (possibly "styled text") which could just as easily be included with the _body_ parameter or not at all. 

A-Shell Reference 

Page 2325 

## **LOGFILE** 

LOGFILE is an optional string specifying the name of a log file to which EMAILX will output (possibly) useful tracing and/or debugging information. The amount, or degree of detail, is determined by the next parameter ( _loglvl_ ). Beware that if you send a lot of mail, and especially if you opt for a high degree of detail, this file can rapidly grow quite large. The expectation is that installations might temporarily use it for debugging problems with the SMTP server (for which it is extremely useful) and otherwise turn the feature off or set it to errors only. As with all of the other parameters which specify filenames, you can use DevPPN or native syntax here. 

A-Shell Reference 

Page 2326 

## **LOGLVL** 

LOGLVL specifies the degree of detail to be written to the log file per the following table. It is ignored if LOGFILE is blank or not present, and it defaults to 1 (Errors only) if LOGLVL is not specified. The options are perhaps not completely self-explanatory, but the best way to understand them is just to experiment with a few sample messages and different settings. Typically you would just leave this set to 1 and check it periodically for error messages. Note that in the debug modes (4 and 5) the log file provides a rather graphic tutorial on how the SMTP protocol works, since it documents both the commands sent to the server and the responses received. 

|**Value **|**Result**|
|---|---|
|0|Off|
|1|Errors only|
|2|Info summary (to, from, number of bytes)|
|3|Full message (to, from header, body)|
|4|Partial debug (most commands and responses)|
|5|Full debug (everything)|



## **History** 

- 2023 June, A Shell 6.5.1732, EMAILX.SBX(145):  Add the Subject line (if present in the header) to the LOGLVL 4 output. 

A-Shell Reference 

Page 2327 

## **SECUREHELLO** 

The **STARTTLS** protocol suggests that the EHLO (aka "Hello") message be re-sent after the secure channel has been negotiated, in which case the server should completely ignore anything it learned in the first (unencrypted) EHLO message. However, most servers do not actually require it, and prior to 5.1(124), EMAILX did not send it. Starting with 5.1(124), EMAILX automatically re-sends the EHLO via the secure channel, unless the SECUREHELLO option is specified in the config file as **0** , **N** , or **F** (i.e. zero, no, or false). That would be necessary only if the server was unable to handle the re-send EHLO. 

A-Shell Reference 

Page 2328 

## **EMAILX HEADER SPECIFICATIONS** 

The specification for header fields is spelled out (in excruciating detail) in RFC 822, to which any search engine can take you. However, if you are not interested in that level of detail, here is a mercifully (but not very) brief overview. 

The first thing to note is that from the standpoint of the STMP protocol, headers are actually part of the body or "data" of the message, and thus is it quite possible that an SMTP server would accept virtually anything, including nothing, in the way of headers at the start of your message. However, that is not to say that SMTP servers do not typically parse and possibly interpret your headers and add their own, nor that email readers do not depend on certain minimum standards for message headers. 

Format wise, the main syntactic requirement is that the header section of the message consist of one or more lines with header keywords (e.g. To, From, Date, etc) followed by optional whitespace, followed by a colon, followed by more optional whitespace, followed by some kind of text, which may have further syntactic requirements depending on the header keyword. 

For example, the **To:** field must contain validly formatted email addresses. If the data following the colon is too long to fit on one line, you may continue it by inserting a CRLF followed by at least one whitespace character followed by the continuation of your field. The whitespace at the start of the continuation line is essential to mark it as a continuation of the prior header field and not a new header field. 

Header keywords (e.g. To, From, Subject, etc.) are not case sensitive. However, in order to slightly reduce the confusion between similarly named header keywords (e.g. To, From) and EMAILX parameters (e.g. TO, FROM) we will from here on reference the former using upper and lower case, followed by a colon (.e.g. To:) and the latter using upper case (e.g. TO). We highlight both in bold to make them stand out as keywords from the surrounding text.) 

The end of the headers and the start of the body of the message is marked by a blank line (two CRLF’s in a row.) This may explain the need for the EMF_HDRCAT flag in _opflags_ ; it helps EMAILX decide if it should insert a blank line between your _header_ parameter and your _body_ parameter. 

As a bare minimum, every message should have Date:, To:, and From: header fields. The normal—and universally recognized— header fields are shown in the following table. 

It is also possible to have User Defined Header Fields, which see for more information. 

A-Shell Reference 

Page 2329 

|**Header**|**Description**|
|---|---|
|Date|The SMTP server will automatically insert the**Date:**header field for you, so there is no need to manually<br>include one.|
|To||
|From||
|Subject|A free format line describing the message. This is so common that most email readers have a space<br>dedicated to it.|
|cc|A list of names this message is being copied to. To reiterate a critical point in the discussion above about<br>the difference between the**To:**header and the_to_parameter, the**cc:**header field is just for aesthetics. If<br>you want to actually_send_the message to the people listed, you must include them in the_to_parameter.|
|Bcc|A list of people this message is being blindly copied to. The comment above for the**cc:**field applies here as<br>well, except that in practice, virtually all SMTP servers and/or email readers will interpret this field and hide<br>the information from some or all of the recipients of the message.|
|Reply-To|Address to send replies to. Virtually all email readers will interpret this field and use it if you select the<br>"reply" option within the email program.|
|Sender|Address of the person sending the message, as distinct from the composer of the message. For example, a<br>secretary’s email address.|
|Comment|A free-format comment which is not technically part of the message body. For example, you might use this|



A-Shell Reference 

Page 2330 

|**Header**|**Description**|
|---|---|
||to include some explanatory remarks when a message is being forwarded, or when the message is being<br>sent by someone other than the actual originator of the message. It might be considered analogous to a<br>post-it note stuck to a typewritten letter.|
|In-Reply-To|An indication of what (and/or who) this message is in reply to.|
|Message-ID|A unique identifier for the message. If you don't specify one, EMAILX (as of edit 149) will automatically add<br>one using the format CCYYMMDDssss.#####@<host> where_sssss_is the number of milliseconds since<br>midnight,_#####_is a random number, and_<host>_is the host parameter specified in the parameter list<br>or configuration file.|



A-Shell Reference 

Page 2331 

## **TO** 

The **To:** header field should not be confused with the _to_ parameter. The former is used mainly by the email reader application to format the message, whereas the latter is a critical parameter given directly to the SMTP server prior to the message. The SMTP server only wants an unadorned address for routing purposes, whereas the email reader may appreciate a fancier one, possibly including a text name in addition to the actual address. The actual _to_ parameter is typically not visible to the reader at all, whereas the **To:** header field is possibly the first thing he or she sees. An important ramification of this dichotomy between the _to_ parameter and the **To:** header field is that if you want to send your message to multiple people, you must specify them all in the _to_ parameter, but you do not have to (and may not want to) do so in the **To:** header field. (You might want to use the **cc:** or **bcc:** header fields instead, or not at all.). To see an example of this, just look at the headers generated by any mass-mailed message (or junk mail message.) Typically, the actual **To:** header line will have nothing to do with you, and your email address will not appear anywhere in the header at all. 

Taking the example of traditional postal mail for comparison, the _to_ parameter is analogous to the address on the outside of the envelope, whereas the **To:** header field is analogous to the heading or salutation at the top of the letter inside the envelope. Similarly, if you want to copy your letter to multiple people, you have the option of including a **cc:** header in your letter, but the only way the message will actually be delivered multiple recipients is if you use multiple envelopes (i.e. multiple _to_ addresses.) 

A-Shell Reference 

Page 2332 

## **FROM** 

The **From:** header field differs from the _from_ parameter in nearly the same way as the **To:** header differs from the _to_ parameter. The _from_ parameter is a separate command to the SMTP server, and is used to identify the sender to the SMTP server, not necessarily to the recipient of the message. Typically, however, they are the same, with the possible addition of an informal text version of the sender’s name in the **From:** header, such as `Big Brother <bigbro@us.gov>` instead of just `bigbro@us.gov` . SMTP servers will often insist that the _from_ parameter specify a valid address, since it needs this if it has to return the message because it was undeliverable. They may or may not put restrictions on the **From:** header, but apparently this is not too common or we would not be deluged with junk-email with no usable **From:** address. Note that since your **From:** header is likely to be the same for all messages, you may want to put it in the configuration file and not bother with it in each message. 

A-Shell Reference 

Page 2333 

## **USER DEFINED HEADER FIELDS** 

If you want to define your own header fields, the specification requires that you start them with "X-" to avoid any possible confusion with previously defined or other header fields that may be recognized and interpreted by the SMTP server or mail reader. The most common example of this is the field **X-Mailer:** which most email clients now add to identify the name of the software or server used to generate the message. For example, here are two commonly seen **X-Mailer:** headers: 

```
X-Mailer: Microsoft Outlook Express 5.00.2314.1300
```

```
X-Mailer: QUALCOMM Windows Eudora Version 5.0
```

EMAILX adds its own X-Mailer header indicating its version number. 

A-Shell Reference 

Page 2334 

## **EMAILX SCENARIOS** 

Even though EMAILX goes a long way towards simplifying the process of sending email from an application, the need for flexibility combined with the underlying complexity of the email format rules make for a lot of confusion. To help clear away some of that confusion, we discuss a few "scenarios" here in more detail. 

## **Subtopics** 

- XOAUTH2 Authentication 

- Simple Plain Text Messages 

- Simple HTML Text Messages 

- Messages with Attachments 

- Emailing Reports to Lists 

A-Shell Reference 

Page 2335 

## **XOAUTH2 AUTHENTICATION** 

XOAUTH2 is a Microsoft extension to the OAUTH2 protocol, and is an increasingly popular SMTP authentication method. To implement it in EMAILX, you must first use the subroutine OAUTH2 to obtain an "access token;" see note below. The access token is then passed to EMAILX in place of the password, which combines it with the user name for transmission to the SMTP server according to the XOAUTH2 protocol. 

## **Creating an Access Token** 

Typically this involves first creating an API account with the provider of the SMTP server, such as Google or Azure, and then executing the three-legged procedure in which you send your client tokens to the API which sends back a custom URL which the app then uses a browser to redirect the end user to log in and request access. Once accomplished, the access token will last for a certain amount of time, and can be refreshed without further user interaction for a much Typically this involves first creating an API account with the provider of the SMTP server, such as Google or Azure, and then executing the three-legged procedure in which you send your client tokens to the API which sends back a custom URL which the app then uses a browser to redirect the end user to log in and request access. Once accomplished, the access token will last for a certain amount of time, and can be refreshed without further user interaction for a much longer amount of time. 

A-Shell Reference 

Page 2336 

## **SIMPLE PLAIN TEXT MESSAGES** 

This case does not require much elaboration. Just put your message either entirely in the _body_ parameter, either as a text string with CRLF between each line or as a file, or put the header items in the _header_ parameter and the rest of the message in the _body_ parameter. The _signature_ is optional, and if present is treated logically just like a continuation of the message body. No special flags are needed in _opflags_ . Here is an extremely simple example which does not even use on a configuration file: 

```
MAP1 EMAIL’PARAMS
```

```
   MAP2 EM’TO,S,200
   MAP2 EM’FROM,S,50
   MAP2 EM’HEADER,S,1000
   MAP2 EM’BODY,S,2000
   MAP2 EM’SERVER,S,20,"mail.king.net"
   MAP2 EM’HOST,S,20,"looseheads.net"
   MAP2 EM’ERRMSG,S,100
   MAP2 CRLF$,S,2
   MAP2 EM’STATUS,F
```

```
EM’TO = "louisxvi@versailles.gov" + chr(13) + "robespierre@reignofterror.org"
EM’FROM = "marie@foodnet.org"
CRLF$ = chr(13) + chr(10)
EM’HEADER = "To: Louis" + CRLF$ + "From: Marie" + CRLF$ &
   + "Subject: cake recipes"
EM’BODY = "Dear Louis," + CRLF$ &
```

A-Shell Reference 

Page 2337 

```
   + "What is this ‘cake’ I keep hearing so much about?" &
```

```
   + CRLF$ + "Je t’aime, Marie"
```

```
XCALL EMAILX,0,"",EM’TO,EM’HEADER,EM’BODY,EM’STATUS,EM’FROM,"","",EM’ERRMSG,SOCKET,SERVER,HOST
```

```
IF EM’STATUS # 0 then print "Error #";EM’STATUS;" – ";EM’ERRMSG
```

A-Shell Reference 

Page 2338 

## **SIMPLE HTML TEXT MESSAGES** 

This case is identical to the plain text case above, except that you can include HTML markup commands in your text to give it "style". Most modern email readers understand HTML commands, even if you don’t bother to indicate in the header that you are using them. (But to be correct, you should set the EMF_HTMLBODY flag in _opflags_ .) If the email reader does not understand HTML, then the reader will see your markup commands as if they were part of the text. But fortunately due to the nature of HTML commands, the text is still likely to be "readable", although the extent may depend on how complicated you make your HTML. 

Here is a slightly more complicated example using a configuration file and a file for the body of the message: 

```
EMAILX.CFG ------------------------------------------------
```

```
;EMAILX.SBX configuration file
```

```
WAIT      = 10                       ; 10 sec wait for server
SERVER    = localhost                ; SMTP server on local host
HOST      = sabionet.com             ; our domain id
DOMAIN    = microsabio.com           ; default domain for addresses
RTNADDR   = email@microsbio.com      ; default ‘FROM’ addr
REPLYTO   = replyto@microsabio.com   ; reply-to addr
LOGFILE   = EMAILX.LOG               ; name of log file
LOGLVL    = 2                        ; info summary
```

```
BODY1.TXT -------------------------------------------------
```

```
<HTML>
```

```
<HEAD><TITLE>This is the title</TITLE></HEAD>
```

```
<BODY>
```

```
<H1>This is Header #1</H1>
```

A-Shell Reference 

Page 2339 

```
<H2>This is Header #2</H2>
<P>This is paragraph #1.
As you can see the formatting is based
```

```
on
```

```
the
```

```
P and /P notations and not on the
actual line breaks</P>
<P>This is paragraph #2</P>
</BODY></HTML>
```

```
EMHTML.BAS ------------------------------------------------
```

```
MAP1 EMAIL’PARAMS
```

```
   MAP2 EM’OPFLAGS,B,2
   MAP2 EM’TO,S,200
   MAP2 EM’CFGFILE,S,20,"EMAILX.CFG"
   MAP2 EM’FROM,S,50
   MAP2 EM’HEADER,S,1000
   MAP2 EM’BODY,S,30
   MAP2 EM’ERRMSG,S,100
   MAP2 CRLF$,S,2
   MAP2 EM’STATUS,F
```

A-Shell Reference 

Page 2340 

```
++INCLUDE EMAILX.DEF      ! contains needed symbols
```

```
EM’OPFLAGS = EMF_BODYHTML
```

```
EM’TO = "test@microsabio.com"
```

```
CRLF$ = chr(13) + chr(10)
```

```
EM’HEADER = "To: HTML Test Department" + CRLF$ + "From: Field Research" + CRLF$ + "Subject: Testing HTML
formatted message"
```

```
EM’BODY = "BODY1.TXT"
```

```
XCALL EMAILX,EM’OPFLAGS,EM’CFGFILE,EM’TO,EM’HEADER,EM’BODY, EM’STATUS,EM’FROM,"","",EM’ERRMSG
```

```
IF EM’STATUS # 0 then print "Error #";EM’STATUS;" – ";EM’ERRMSG
```

A-Shell Reference 

Page 2341 

## **MESSAGES WITH ATTACHMENTS** 

Attachments require the construction of MIME headers and usually the encoding of the attachment using "base64". Most people do not want to know anything about how that is accomplished, and would prefer to imagine that it is as simple as just listing the names of the attached files in the header of the message (an illusion happily fostered by most email client applications.) Fortunately, EMAILX is willing to go along with this charade, allowing you to specify nothing other the names of the files you want to attach. 

Most email clients make assumptions about the types of file attachments based either on the extension of the filename, or possibly by scanning the file to see if consists of anything other than text. Rather than get mired in such hocus-pocus, EMAILX adopts a simpler approach. If you don’t tell it otherwise, it automatically treats each attachment as being of type 

"application/octet-stream" which is the most general type. If you want to be more specific, you can specify one of the content types defined in the email standard (see RFC 1521 and 1522), such as: 

```
application/postscript
```

```
image/jpeg+
```

```
image/gif
```

```
audio/basic
```

```
video/mpeg
```

The following example uses the same configuration file (emailx.cfg) as in the previous example, and is otherwise very similar except for the inclusion of two attachments and the addition of a signature block: 

```
EMSIG.TXT ----------------------------------------------------------
```

```
************************************************************
```

```
*************** EMAIL Field Research and Testing ***********
```

```
************************************************************
```

```
EMATT.BAS ----------------------------------------------------------
```

A-Shell Reference 

Page 2342 

```
MAP1 EMAIL’PARAMS
   MAP2 EM’OPFLAGS,B,2
   MAP2 EM’TO,S,200
   MAP2 EM’CFGFILE,S,20,"EMAILX.CFG"
   MAP2 EM’FROM,S,50
   MAP2 EM’HEADER,S,1000
   MAP2 EM’BODY,S,1000
   MAP2 EM’ERRMSG,S,100
   MAP2 CRLF$,S,2
   MAP2 EM’STATUS,F
```

```
MAP1 EM’ATTACHMENTS
   MAP2 ATT’COUNT,B,2
   MAP2 ATTX(10)
      MAP3 ATT’FILE,S,128
      MAP3 ATT’CONTENT’TYPE,S,127
      MAP3 ATT’ENCODING,B,1
```

```
++INCLUDE EMAILX.DEF
```

A-Shell Reference 

Page 2343 

```
EM’OPFLAGS = EMF_NORMAL
```

```
EM’TO = "test@microsabio.com"
```

```
CRLF$ = chr(13) + chr(10)
```

```
EM’HEADER = "To: Attachment Test Department" + CRLF$ &
```

```
+ "From: Field Research" + CRLF$ + "Subject: Testing Attachments"
```

```
EM’BODY = "There are two attachments to this message:" + CRLF$ + " EMAILX.SBX (binary) and miame.ini (text)"
+ CRLF$
```

```
ATT’COUNT = 2
```

```
ATT’FILE(1) = "BAS:EMAILX.SBX"
ATT’CONTENT’TYPE(1) = ""         ! (let it default)
ATT’ENCODING(1) = CTE’BASE64      ! (base64 encoding)
ATT’FILE(2) = "/vm/miame/miame.ini"
```

```
ATT’CONTENT’TYPE(2) = "text/plain"
ATT’ENCODING(2) = CTE’7BIT      ! 7 bit text, no encoding
```

```
XCALL EMAILX,EM’OPFLAGS,EM’CFGFILE,EM’TO,EM’HEADER,EM’BODY,
EM’STATUS,EM’FROM,EM’ATTACHMENTS,"EMSIG.TXT",EM’ERRMSG
```

```
IF EM’STATUS # 0 then print "Error #";EM’STATUS;" – ";EM’ERRMSG
```

Note that there was no particularly good reason to not use base64 encoding (CTE’BASE64) for the second attachment as well, other than to save a few bytes. In fact, one possible problem with text/plain encoding is that the line terminators will be converted to CRLF, even if they were originally just LF. Base64 encoding eliminates this possibility. 

A-Shell Reference 

Page 2344 

A-Shell Reference 

Page 2345 

## **EMAILING REPORTS TO LISTS** 

_Added May 2017_ 

When emailing capability is introduced into an existing environment, a common user request is to add an email option to several existing report programs, with the possibility of a common or different distribution lists for each report. To accomplish this with minimal programming effort, you may find the utility package EMXREP in EXLIB: [909,30] helpful. The package consists of a standalone program, EMXREP.BP, for maintaining a cross-reference grid of email addresses and reports, plus an include file, emxrep.bsi, containing a high level function, _Fn'EMX'Send'Rep()_ , that reduces the task down to a single function call. 

The EMXREP maintenance program appears as follows: 

The idea is to add all of the email addresses to the first column (using the "Add Addr") button as needed, and add columns for each of the reports you want to email (using the Add Report button). Then to include a particular email address in the distribution list for a particular report, just check the corresponding box in the grid. Each row indicates all of the reports to be emailed to that address, and each column represents the distribution list for that report. You can sort and rearrange the columns to make it easier to handle as the number of addresses and reports gets large. 

The report names can be arbitrary, but typically using the name of the program that generates the report is the simplest approach. 

To send the report to the distribution list, just insert the following call into the program after the report file is closed (typically just before or after spooling it), e.g. 

```
++include emailx:emxrep.bsi
```

```
open #ch, REPORT$, output
```

```
<create report>
```

```
close #ch
```

A-Shell Reference 

Page 2346 

```
EMX'STATUS = Fn'EMX'Send'Rep(repfile$=REPORT$, &
```

`from$=` "admin@yourdomain.com" `, &` 

```
             subject$="Sample Report")
```

Note that the Fn'EMX'Send'Rep() function uses named parameters, so you must compil with the /P (or /PX) switch, and there are several additional optional parameters which you can specify to modify the default behavior. In the default case, it simply wraps the report in a fixed pitch HTML envelope and strips any control characters found at the start of text lines. This simple approach works well for short plain text reports, eliminating the need for attachments, viewers, etc. In GUI environments, it displays a progress/abort dialog during the sending process, and a completion dialog with the success or failure information. The success dialog uses the enhanced MSGBOX time-out capability introduced in A-Shell version 6.4 which does not require user intervention, whereas the failure dialog waits for an acknowledgment. 

See the EMXREP.BSI source code for further details about the other parameters and options, or to use the standard routine as the basis for your own customized version. 

A-Shell Reference 

Page 2347 

## **EMAILX TROUBLESHOOTING** 

Resources available to you for troubleshooting EMAILX problems include the log file, the SMTP response codes, and the A-Shell forum. See below for details. 

## **Log file** 

The first go-to troubleshooting tool is the log file. Before spending much time on anything else, we highly recommend editing your CFG file to add LOGFILE and LOGLVL entries and then examining the log after the failure. Here is an example for a GMAIL session with LOGLVL=4 ... 

```
26-Mar-18 10:49:04 [EMAIL5M-joaquin-2] > Opening socket smtp.gmail.com (port 587) Flags=2097153...
```

```
26-Mar-18 10:49:04 [EMAIL5M-joaquin-2]   [Socket=1]
```

```
26-Mar-18 10:49:04 [EMAIL5M-joaquin-2] < 220 smtp.gmail.com ESMTP o4sm4316117oia.44 - gsmtp
```

```
26-Mar-18 10:49:04 [EMAIL5M-joaquin-2] > EHLO microsabio.com
```

```
26-Mar-18 10:49:04 [EMAIL5M-joaquin-2] < 250-smtp.gmail.com at your service, [174.77.78.50]
```

```
250-SIZE 35882577
```

```
250-8BITMIME
```

```
250-STARTTLS
```

```
250-ENHANCEDSTATUSCODES
```

```
250-PIPELINING
```

```
250-CHUNKING
```

```
250 SMTPUTF8
```

```
26-Mar-18 10:49:05 [EMAIL5M-joaquin-2] > STARTTLS
```

```
26-Mar-18 10:49:05 [EMAIL5M-joaquin-2] < 220 2.0.0 Ready to start TLS
26-Mar-18 10:49:05 [EMAIL5M-joaquin-2] > EHLO microsabio.com
```

A-Shell Reference 

Page 2348 

```
26-Mar-18 10:49:05 [EMAIL5M-joaquin-2] < 250-smtp.gmail.com at your service, [174.77.78.50]
250-SIZE 35882577
```

## `250-8BITMIME` 

```
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
```

```
250-ENHANCEDSTATUSCODES
```

```
250-PIPELINING
```

## `250-CHUNKING` 

```
250 SMTPUTF826-Mar-18 10:49:06 [EMAIL5M-joaquin-2] > AUTH PLAIN
AGpvYXF1aW4ubWNncmVnb3JAZ21haWwuY29tAE5kc3NvLTk3c2Vh
```

```
26-Mar-18 10:49:06 [EMAIL5M-joaquin-2] < 235 2.7.0 Accepted
```

- `26-Mar-18 10:49:06 [EMAIL5M-joaquin-2] > MAIL FROM:` <return@microsabio.com> 

- `26-Mar-18 10:49:06 [EMAIL5M-joaquin-2] < 250 2.1.0 OK o4sm4316117oia.44 - gsmtp` 

- `26-Mar-18 10:49:06 [EMAIL5M-joaquin-2] > RCPT TO:` <jack@microsabio.com> 

```
26-Mar-18 10:49:06 [EMAIL5M-joaquin-2] < 250 2.1.5 OK o4sm4316117oia.44 - gsmtp
```

- `26-Mar-18 10:49:06 [EMAIL5M-joaquin-2] > DATA` 

```
26-Mar-18 10:49:07 [EMAIL5M-joaquin-2] < 354  Go ahead o4sm4316117oia.44 - gsmtp
```

`26-Mar-18 10:49:07 [EMAIL5M-joaquin-2] > To:` test@microsabio.com `...` 

```
26-Mar-18 10:49:07 [EMAIL5M-joaquin-2] > This is a nice little test message....
```

```
26-Mar-18 10:49:07 [EMAIL5M-joaquin-2] > M...
```

```
26-Mar-18 10:49:09 [EMAIL5M-joaquin-2] < 250 2.0.0 OK 1522079347 o4sm4316117oia.44 - gsmtp
26-Mar-18 10:49:09 [EMAIL5M-joaquin-2] > QUIT
```

A-Shell Reference 

Page 2349 

```
26-Mar-18 10:49:09 [EMAIL5M-joaquin-2] < 221 2.0.0 closing connection o4sm4316117oia.44 - gsmtp
```

```
26-Mar-18 10:49:09 [EMAIL5M-joaquin-2] > Closing socket #1...
```

```
26-Mar-18 10:49:09 [EMAIL5M-joaquin-2] > Connection lock cleared.
```

Each line starts with a timestamp showing the date, time, program-user-job#, then either ">" for outgoing commands or "<" for incoming responses, followed by the command or response text, or a description thereof. Lines with no directory indicator are just reporting internal status (like the socket # on the second line), or are reporting a breakdown in the protocol (such as a timeout). Lines with no timestamp are generally continuations of a multi-line response. Most SMTP responses start with a threedigit numeric code indicating the status (as part of the SMTP protocol - see the table below), and are followed by some nonstandard explanatory text. Some messages may contain the word "Status" followed by a number, often negative, indicating a local library error code, as in the following examples... 

```
> Checking for data... [Status=-10057 (A request to send or receive data was disallowed because ...)]
```

```
> Opening socket mail.optonline.net (port 25) Flags=1... [Status=-10060 (A connection attempt failed
because ...)]
```

```
*** (Status -10049) ***
```

Usually the error code is followed by a description, but if not, you can usually look them up on the Internet. In the case of Windows, search the Internet for "Windows System Errors"; for Linux, try "Linux errno values". 

## **Table of SMTP Response Codes** 

The following table lists the most common response codes. Note that since the SMTP standard is constantly evolving, new codes are added periodically. These are typically easy to look up on the Internet. 

A-Shell Reference 

Page 2350 

|**Code **|**Description**|
|---|---|
|200|(nonstandard success response, see rfc876)|
|211|System status, or system help reply|
|214|Help message|
|220|<domain> Service ready|
|221|<domain> Service closing transmission channel|
|250|Requested mail action okay, completed|
|251|User not local; will forward to <forward-path>|
|252|Cannot VRFY user, but will accept message and attempt<br>delivery|
|354|Start mail input; end with <CRLF>.<CRLF>|
|421|<domain> Service not available, closing transmission<br>channel|
|450|Requested mail action not taken: mailbox unavailable|



A-Shell Reference 

Page 2351 

|**Code **|**Description**|
|---|---|
|||
|451|Requested action aborted: local error in processing|
|452|Requested action not taken: insufficient system storage|
|500|Syntax error, command unrecognized|
|501|Syntax error in parameters or arguments|
|502|Command not implemented|
|503|Bad sequence of commands|
|504|Command parameter not implemented|
|521|<domain> does not accept mail (see rfc1846)|
|530|Access denied|
|534|Authorization failure|



A-Shell Reference 

Page 2352 

|**Code **|**Description**|
|---|---|
|550|Requested action not taken: mailbox unavailable|
|551|User not local; please try <forward-path>|
|552|Requested mail action aborted: exceeded storage<br>allocation|
|554|Requested action not taken: mailbox name not allowed|
|554|Transaction failed|



## **Forum** 

- If the log file doesn't reveal the solution, next, try searching the A Shell Forum for "EMAILX". There should be several threads covering actual problems reported by users. 

## **- GMAIL specific problems** 

GMAIL may be the most popular outgoing SMTP service, but it's also one of the most persnickety to use. you will find some - useful tips relating specifically to GMAIL by searching the A Shell Forum for "EMAILX GMAIL". 

A-Shell Reference 

Page 2353 

## **EMAILX REVISION HISTORY** 

|**Edit**|**Date**|**Description**|
|---|---|---|
|151|Jan 2026|Add DELAY to CFGFILE directives|
|150|July 2025|Replace Message ID with Message-ID|
|149|July 2025|Add MessageID header|
|148|Feb 2024|Automatically plug the adorned FROM address into the header if no From: clause specified|
|147|Jan 2024|Allow descriptive name prefix in RTNADDR parameter.|
|146|Dec 2023|Support ADDATTACHMENT directive in config file; internal tracing fixes.|
|145|June 2023|Add subject line to the LOGLVL 4 log.|
|144|June 2023|Allow any number of ADDBCC directives in the config file (up from 1).|
|143|Apr 2023|Improved check for and reporting of SMTP connection failures.|
|142|Nov 2022|Remove limits on length of password (was 1024) and list of recipient addresses (was 25000).|
|141|Oct 2022|Attachment names were getting truncated at 50 characters.|



A-Shell Reference 

Page 2354 

|**Edit**|**Date**|**Description**|
|---|---|---|
|140|April 2019|Fix bug in logic testing for minimum parameters.|
|139|Dec 2018|Support REDIRECT=addr and ADDBCC=addr in config file to redirect or BCC all emails to specified<br>address; minor cleanup.|
|138|July 2018|Support XOAUTH2 authentication (GMAIL).|
|137|July 2018|Fix problem with sending a string body twice, introduced in 135/136; deal with accidental trailing<br>chr(13) on EM'TO.|
|136|July 2018|Fix a problem with authentication failure introduced in edit 135.|
|135|July 2018|Remove problem with truncation of lines or strings at 2000 bytes. Eliminate use of temp file<br>SMTP.TMP.|
|134|May 2018|Fix glitch introduced in 129 which effectively disabled the signature parameter.|
|133|May 2017|Strip trailing TABs and any other control characters from HOST name. In some cases these were not<br>being stripped when extracting the HOST from the CFG file, and some SMTP servers, particular<br>Office 365, were then complaining about an invalid domain.|
|132|May 2017|Adjust error trapping so that on<br>^C, routine just passes the<br>^C flag to the caller. This allows callers<br>which offer a<br>^C cancel button, such asemxrep.bsi:Fn'EMX'Send'Rep(), to gracefully recover.|



A-Shell Reference 

Page 2355 

|**Edit**|**Date**|**Description**|
|---|---|---|
|131|Mar 2016|Increase hostname limit from 32 to 80 characters|
|130|Dec 2014|Adjust MIME attachment headers problem. Existing header format wasn't working with certain SMTP<br>servers.|
|129|Dec 2014|Fix glitch failing to detect auth method due to slight format variations between servers. Fix<br>redundant EHLO with using TLS/SSL (but not STARTTLS) mode (most servers ignore the redundant<br>EHLO but some were aborting on it.)|
|128|May 2014|Support auto-decryption of mode 3 passwords introduced in 6.1.1385. When generating the<br>password, use the SMTP user name as the seed.|
|127|Oct 2013|Add EMF_NOAUTOHDR to disable unnecessary headers; useful for SMS messages.|
|126|June 2013|Return message for EMS_BADCFG error in ERRMSG param.|
|125|June 2013|Add CONNLOCK=1 option to CFG file to lock connection. Also add enhancements to log file.|
|124|July 2012|Upgrade STARTTLS protocol to deal with some servers; disable with SECUREHELLO=0.|
|123|Apr 2010|Silence some spurious screen output during appending operations.|
|122||Add the PASSWORD decryption option.|



A-Shell Reference 

Page 2356 

|**Edit**|**Date**|**Description**|
|---|---|---|
|121||Add SECURE configuration option for SSL/TLS and STARTTLS connections.|



A-Shell Reference 

Page 2357 

## **EMAILX ADMINISETERA** 

## **Requirements** 

The requirements for using EMAILX are: 

- The minimum supported version of A-Shell is 6.4. 

- You must have an SMTP server which is within "routing distance." That is, EMAILX needs to be able to open a socket 

- connection to your SMTP server. The SMTP server may be on the same machine as A-Shell, or on the local network, or at your ISP connected via a full-time connection. Wherever it is, it must accept mail from you. Note that most SMTP servers have filters to protect against unauthorized users. 

- EMAILX supports several methods of SMTP authentication. See AUTH for more details. 

- For secure connections (see SECURE), EMAILX requires the LIBASHTLS library to be installed along with the A-Shell 

- executable. LIBASHTLS in turn requires the GNUTLS package. This is typically pre-installed or available via yum for Linux. For Windows, it is available as a set of DLLs; contact MicroSabio for assistance. LIBASHTLS is not currently available for AIX. 

## **Licensing** 

EMAILX is not included in the general release of A-Shell. It is, instead, an add-on option which is purchased and licensed separately. For additional information on pricing, licensing and purchasing, contact MicroSabio or see the price list at microsabio.com. 

Like all external subroutines (SBXes), EMAILX is written in BASIC. Source code is included with the license. 

A-Shell Reference 

Page 2358 

## **ERRMSG** 

_Reviewed and revised April 2024_ 

## **(1) xcall ERRMSG {,errarg}** 

## **(2) xcall ERRMSG, msg, errnum** 

## **Parameters** 

_errarg_ (Structure)  [in] 

A structure mapped as shown below specifying your application-defined error code and message 

```
MAP1 ERRARG
```

```
   MAP2 err'id,S,6      ! (this field is ignored)
   MAP2 err'cde,B,2     ! app-defined error #
   MAP2 err'msg,S,50    ! app-defined error message
```

_msg_ (String)  [out] 

Receives the standard language-dependent error message corresponding to the ASB error code in _errnum_ . Messages are defined in SYS:ERRMSG.xxx where xxx is the extension defined in the current Language Definition File. 

_errnum_ (Unsigned Int)  [in] 

ASB error code. You can retrieve this via the ERR(0) function. 

ERRMSG is a handy way to handle ASB error trap reporting. Add the subroutine to your ASB error trap, and it can display a standardized message at the bottom of the screen (listing information about the error) and log the error to file, and/or retrieve the text associated with the current error. The routine must be set up as an alias to DERR in miame.ini as follows: 

```
ALIAS=ERRMSG:DERR
```

A-Shell Reference 

Page 2359 

DERR is a Debug plc routine which is similar to ERRMSG. It is not documented here since we prefer that you use ERRMSG. If you are already using DERR, feel free to continue, but note that it expects four arguments, rather than the 0-2 that ERRMSG expects. 

If 0 or 1 argument is passed and an ASB error has occurred, then ERRMSG ignores the _errarg_ argument (if passed) and displays a three line message at the bottom of the screen relating to the ASB error, which looks something like this: 

- `ERROR MESSAGE * TSKAAA    Illegal record number` 

```
Error 31 in Line 360 of MYPROG Last File: 5 (ERRMSG.TMP)
```

```
Press ESC to Abort
```

You may also call the ERRMSG directly (i.e. absent any ASB error) to report application-defined errors. In that case, you must include the _errarg_ parameter, assigning your own values to the fields. For example, consider the following code: 

- `125   err'cde = 142` 

- `130   err'msg = "Something bad has happened!"` 

- `135   xcall ERRMSG,ERRARG` 

## This would display the following message (where "MYPROG" is the current program name): 

- `ERROR MESSAGE * TSKAAA    Something bad has happened!` 

```
Error 142 in Line 135 of MYPROG
```

```
Press RETURN to Continue or Retry
```

In either of the above cases, the subroutine will also log a similar message to the text file bas:baserr.log. 

If two arguments are passed (as in the second sample format above) then it simply retrieves the ASB error message associated with the specified error number. This can be useful for creating your own error message display within an error trap, since when 

A-Shell Reference 

Page 2360 

error trapping is enabled, BASIC no longer displays the error message. (It only supplies you with the error number, last line number, and last channel number, via the ERR(0), ERR(1), and ERR(2) functions.) 

ERRMSG (i.e., DERR) uses a Windows-style message box if GUI support is available. 

## **See Also** 

- ERRMSG$() function 

A-Shell Reference 

Page 2361 

## **EVTWIN** 

_Reviewed and revised April 2024_ 

## **xcall EVTWIN, opcode, {,arg1, ...}** 

The subroutine EVTWIN displays messages to the system message window. It is primarily used internally to implement the TRACE and DEBUG statements, which are translated into EVTWIN statements by the compiler, but can be called directly like any other subroutine. 

## **Parameters** 

## _opcode_ (Bitmap 16)  [in] 

Action to perform, coded per the following table.  Specify one of the first three options (Open, Print, Close) and zero or more of the last two. 

|**Value**|**Meaning**|
|---|---|
|&h0001|Open|
|&h0002|Print|
|&h0003|Close|
|&h0100|Debug (versus trace)|
|&h0200|Pause (wait for double-click)|



_arg1, ..._ (String or Num)  [in] 

zero or more arguments whose values will be displayed in a single output line 

## **Comments** 

If you don't like the way the TRACE.PRINT statements look, you can replace the internal EVTWIN with your own EVTWIN.SBX. 

A-Shell Reference 

Page 2362 

## **See Also** 

- TRACE statements 

- Event Tracing 

A-Shell Reference 

Page 2363 

## **EZSPL** 

Following this introduction are sections on EZSPL Old Format, EZSPL New Format, and EZSPL Processing. 

EZSPL is a very useful utility, which is fully compatible with and may be used in place of the SPOOL subroutine. In A-Shell, in fact, SPOOL is implemented as an alias to EZSPL. EZSPL provides three main functions: 

- It incorporates a **screen preview facility** , enabling the user to browse through the document either before or instead of 

- sending it to a printer. This feature has been fully implemented under A-Shell. In fact, the A-Shell version of the viewer (known as EZ-TYPE or, under its latest incarnation, EZ-VUE) supports many enhancements over the original version. 

• It optionally provides a **front-end printer selection** , enabling the user to select the printer and various print options (such as banner, header, etc.). Many of the switches are specific to the AMOS environment, and so there is a fair amount of divergence here between the AMOS and A-Shell versions, but the concepts are similar and the differences can be handled in the configuration files, external to the application source code. 

- It optionally provides **transparent character translation** through what it terms _port filters_ . These enable programs written 

- to generate escape sequences for specific printers to have their codes transparently modified to the sequences required for other printers as the documents are output. 

Port filters are not implemented under A-Shell, but the equivalent functionality is available using either the COMMAND=SBX:<routine name> option in the printer initialization file, or traditional Unix filters in the Unix environment. 

In addition to the above features, EZSPL, like SPOOL, performs the mundane task of sending the specified file to the specified print queue. Two calling formats are available, each described in the following topics, followed by t*he a brief discussion of the EZ-SPOOL configuration file processing. 

SPOOL is handled by using the ALIAS[SP] facility in the A-Shell configuration file to redirect it to EZSPL, which supports a superset of the normal SPOOL capabilities. 

## **History** 

- 2013 October, A Shell 6.1.1373: SPOOL (or EZSPL) refinement: Under Unix, spooling a print file that is still open does not generate any error or warning, but the spooled output may be truncated if the last block written hadn't been flushed to disk. To avoid this intolerable result that can nonetheless go without notice for an indefinite period, A-Shell now detects if the print file is still open, and if so, flushes its buffer to disk so the spooled output will be complete. It also logs a warning message to the 

A-Shell Reference 

Page 2364 

ashlog.log file. It does not, however, close the print file, since that might lead to an I/O-to-unopened error if the file was closed later. And although that might be a good thing, forcing the underlying bug to be fixed, it's seldom appreciated when a new error occurs in a "working" program after installing an A-Shell update. Note that the issue didn't affect Windows because in that environment, attempting to spool an open file would generate an error. 

## **Subtopics** 

- SPOOL (EZSPL Old Format) 

- EZSPL New Format 

- EZSPL Processing 

A-Shell Reference 

Page 2365 

## **SPOOL (EZSPL OLD FORMAT)** 

_Reviewed and revised April 2024_ 

## **xcall SPOOL, file {,printer, switches, copies, form, lpp, width, prefix, suffix, overlay, totpages}** 

## **Parameters** 

All of the parameters are [in]. 

_file_ (String) 

is the specification of the file to print, and is the only required parameter. 

## _printer_ (String) 

is the name of the printer to send the file to. If not specified, the default defined by the PRINTER parameter in miame.ini will be used. In most cases, the _printer_ name should correspond to a printer initialization file with a matching name, either sys:<printer>.ini or ashcfg:<printer>.pqi. The exceptions to this rule are as follows. 

Under Windows, you may specify the pseudo printer name "PROMPT", which is interpreted as a printer whose initialization file contains the following: 

```
DEVICE = PROMPT:
```

```
PASSTHROUGH = OFF
```

```
PITCH = AUTO
```

If the name you specify is longer than 6 characters (which was the maximum for AMOS printer names and remains the maximum for A-Shell printers which have corresponding initialization files), then it is interpreted like the PROMPT example above, except with the DEVICE set to the name you specify. (This "implied printer" technique can be taken to its logical extreme by specifying a \\machine\sharename name for the printer, in which case there does not even need to be a local printer driver definition.) 

A-Shell Reference 

Page 2366 

Under Unix, if you specify a printer name which has no corresponding initialization file, then it is treated as if the initialization file were simply: 

## `DEVICE = <printer>` 

## Refer to Printer Configuration for more information about printer initialization files. 

## _switches_ (Num) 

may be any combination of the following: 

|**Symbol**|**Value**|**Equivalent PRINT.LIT switch**|
|---|---|---|
|SPSW_BANNER|&h00000001|BANNER (applies only to Unix, if at all)|
|SPSW_NOBANNER|&h00000002|NOBANNER|
|SPSW_DELETE|&h00000004|DELETE|
|SPSW_NODELETE|&h00000008|NODELETE|
|SPSW_HEADER|&h00000010|HEADER; ignored by A-Shell, see note 5 below|
|SPSW_NOHEADER|&h00000020|NOHEADER; ignored by A-Shell, see note 5 below|
|SPSW_FF|&h00000040|FF (formfeed after printing)|



A-Shell Reference 

Page 2367 

|**Symbol**|**Value**|**Equivalent PRINT.LIT switch**|
|---|---|---|
|SPSW_NOFF|&h00000080|NOFF|
|SPSW_WAIT|&h00000100|WAIT; applies only to PDFX, see note 4 below|
|SPSW_INFORM|&h00000400|INFORM; ignored by A-Shell, see note 5 below|
|SPSW_KILL|&h00000800|KILL; ignored by A-Shell, see note 5 below|
|SPSW_PASSTHROUGH|&h00002000|PASSTHROUGH (Windows only)|
|SPSW_NOPASSTHROUGH|&h00004000|NOPASSTHROUGH (Windows only|
|SPSW_LANDSCAPE|&h00008000|LANDSCAPE (Windows only); see Note 2 below|
|SPSW_PORTRAIT|&h00010000|NOLANDSCAPE (Windows only); see Note 2 below|
|SPSW_PREVIEW|&h00080000|Force Preview on; see Note 3 below|
|SPSW_NOPREVIEW|&h00100000|Force Preview off; see Note 3 below|
|SPSW_APEX|&h00400000|Force APEX Preview on; see Note 3 below|



A-Shell Reference 

Page 2368 

|**Symbol**|**Value**|**Equivalent PRINT.LIT switch**|
|---|---|---|
|SPSW_NOSAVESTATE|&h02000000|Don't save APEX state on exit|
|**Definition file: ashell.def**|||



- Hex Decimal Values 

## Notes on Switches 

- 1 Any switches specified this way will override the corresponding switches in the printer’s initialization file. 

2 The LANDSCAPE and NOLANDSCAPE switches are equivalent to the printer init commands ORIENTATION=LANDSCAPE and ORIENTATION=PORTRAIT, respectively. 

3 In the standard Windows GUI environment, the Force Preview On switch (&h00080000) will use the GUI-mode APEX previewer rather than the EZVUE text-mode version. But in the case of a telnet connection to a server, the default is to preview the file using EZVUE on the server side, unless the Force APEX Preview switch is set. Set both switches to automatically use APEX whenever applicable, and to fall back to EZVUE otherwise. 

4 The WAIT switch (see History) applies only to PDFX version 5 or higher. When set, the subroutine will wait until the PDFX driver has written the PDF file to disk before returning to the application. This is useful when you need to do something with the PDF file immediately after creating it. Note since it is not always possible to predict the final PDF filespec, particularly if the user is allowed access to the Save As dialog, the application may want to use MX_LASTPRTFIL to retrieve the filespec after return from SPOOL. 

5 The switches referring to this note apply only to pre-A-Shell versions of EZSPL. In A-Shell they have no use or meaning and should be ignored. 

_copies_ (Num) 

is the number of copies to print (default 1). 

A-Shell Reference 

Page 2369 

## _form_ (String) 

is the form name. Note that names are not generally used in the Windows or Unix world and are thus ignored by A-Shell. To get the equivalent effect, you would probably define multiple logical printers associated with a single physical printer. 

_lpp_ (Num) 

is the number of lines per page (ignored). 

_width_ (Num) 

is the number of columns per page (ignored). 

## _prefix_ (String) 

specifies the name of a file to be prepended to the front of the printfile before sending it to the printer. This is useful for sending printer initialization codes or routing instructions. 

## _suffix_ (String) 

specifies the name of a file to be appended to the end of the printfile. 

## _overlay_ (String) 

specifies the name of an overlay file. This has the same affect as setting OVERLAY= in the printer ini file, but any overlay specified in the subroutine statement will override an overlay in the printer ini file. 

## _totpages_ (Num) 

This parameter, which works only in the Windows GDI printing environment, specifies the number of pages in the printout. If specified, any occurrence of "%#" in the printfile will be replaced with the total number of pages. For example, a string in the printfile of the form "Page 1 of %#" would be converted to "Page 1 of 100", assuming that the total pages had been set to 100. Obviously you could have done this directly in your application, but it is often difficult to know in advance how many pages you are going to generate, whereas it is easy to count them as you generate them and then pass the total to SPOOL/EZSPL.name of a file to be appended to the end of the printfile. 

## **History** 

A-Shell Reference 

Page 2370 

## - 2018 February, A Shell 6.5.1630: Add switch SPSW_NOSAVESTATE. 

- 2016 April, A Shell 6.3.1509: Re-define WAIT function to be PDFX-specific, add MX_LASTPRTFIL to A-Shell also. 

A-Shell Reference 

Page 2371 

## **EZSPL NEW FORMAT** 

_Reviewed and revised April 2024_ 

## **xcall EZSPL (or SPOOL), file, table** 

## **Parameters:** 

_file_ (String)  [in] 

File specification for the file to print 

## _table_ (Structure) [in] 

Multiple options arranged per the following. Items marked with an asterisk are ignored by all A-Shell platforms. `MAP1 TABLE` 

```
MAP2 PRINTER,S,64             ! spooler name (was 6 under AMOS)
```

```
MAP2 CPU,F,6                  !*CPU id
```

```
MAP2 SWITCHES,F,6             ! option switches
```

```
MAP2 COPIES,F,6               ! copies to spool
MAP2 BANNER,S,50              !*banner
```

```
MAP2 LPP,F,6                  !*lines per page
MAP2 WIDTH,F,6                !*columns per page
MAP2 FORMS,S,6                ! printer form
MAP2 PRI,F,6                  !*priority
MAP2 ADATE,B,4                !*spool after date
MAP2 ATIME,B,4                !*spool after time
MAP2 RESTART,F,6              !*restart
```

Page 2372 

## A-Shell Reference 

```
MAP2 START,F,6                !*start page
MAP2 FINISH,F,6               !*finish page
MAP2 LIMIT,F,6                !*limit form feeds
MAP2 OPTIONS,F,6              ! (EZ-SPOOL) options
MAP2 SEQNO,F,6                !*(EZ-SPOOL) sequence #
MAP2 COUNT,F,6                !*(EZ-SPOOL) # blocks queued
MAP2 ITCERR,F,6               !*(EZ-SPOOL) ITC error
MAP2 NONITC,F,6               !*(EZ-SPOOL) spooler
MAP2 FILERR,F,6               !*(EZ-SPOOL) file error code
MAP2 EXTOPT,F,6               ! (EZ-SPOOL) extended options
MAP2 PREFIX,S,28              ! (A-Shell) prefix file
MAP2 SUFFIX,S,28              ! (A-Shell) suffix file
MAP2 HOSTROWS,F,6             ! (A-Shell) number of rows reserved for host in EZTYP
MAP2 EZCOLORS                 ! User-defined color scheme
   MAP3 EZFG'TXT,B,1          ! text colors
   MAP3 EZBG'TXT,B,1          !
   MAP3 EZFG'BDR,B,1          ! border colors
   MAP3 EZBG'BDR,B,1          !
   MAP3 EZFG'CMD,B,1          !
   MAP3 EZBG'CMD,B,1          ! command colors
   MAP3 EZFG'STS,B,1          !
```

A-Shell Reference 

Page 2373 

```
   MAP3 EZBG'STS,B,1          ! status colors
   MAP3 EZFG'HLP,B,1          !
   MAP3 EZBG'HLP,B,1          ! help colors
   MAP3 EZFG'HLT,B,1          !
   MAP3 EZBG'HLT,B,1          ! highlight colors
   MAP3 EZFG'MNU,B,1          !
   MAP3 EZBG'MNU,B,1          ! menu colors
   MAP3 EZFG'BRF,B,1          !
   MAP3 EZBG'BRF,B,1          ! brief colors
MAP2 OVERLAY,S,28             ! overlay file
MAP2 TOTPAGES,F,6             ! total pages
```

The fields marked (EZ-SPOOL) were not part of the original AMOS specification and were added by EZ-SPOOL (as developed for AMOS). The fields marked (A-Shell) are A-Shell extensions that were not part of either the original AMOS or EZ-SPOOL specifications. All of the fields for both types of extensions are optional under A-Shell. 

The PRINTER field was 6 bytes under AMOS but expanded to 64 in the A-Shell implementation to allow for the possibility of using Unix and especially Windows printer names. If you use the 64 byte version of the PRINTER field, then you MUST specify all of the other fields—even the ones which we just got through saying were optional. A-Shell can only determine which version of PRINTER you used by considering the total size of the TABLE parameter. 

The EZCOLORS fields, if specified, will override the normal default color scheme used by EZ-SPOOL. The only exceptions to this are that they will be ignored if they are ALL ZERO, and that that can be overridden themselves by the EZCLR section of the INI.CLR file. For information on the color configuration file format, see Color Configuration and MX_INICLR. 

A-Shell Reference 

Page 2374 

The OPTIONS parameter above may be set to any combination of the values in the following table. Values that are ignored by A- Shell have been omitted (which is why there are gaps). 

|**Value**|**Meaning**|
|---|---|
|&h00000001|PRINTER selection menu on|
|&h00000002|PRINTER selection menu off|
|&h00000004|OPTION menu on (questions at bottom of PRINTER menu)|
|&h00000008|OPTION menu off|
|&h00000010|TYPE (preview) allowed (by selecting printer X)|
|&h00000020|TYPE (preview) not allowed|
|&h00020000|ASKPRT on (Prompt to confirm user wants to print the file)|
|&h00040000|ASKPRT off|
|&h02000000|BRIEF on (single line printer selection prompt)|
|&h80000000|Preview file only (same asxcall EZTYP)|



A-Shell Reference 

Page 2375 

## - Hex Decimal Values 

The EXTOPT parameter above may be set to any combination of the values in the following table. These may also be set via the EXTOPT=### parameter in the EZSPL configuration file. Values that are ignored by A-Shell have been omitted (which is why there are gaps). 

|**Value**|**Meaning**|
|---|---|
|&h0004|Disable screen save/restore|
|&h0020|Allow exit from EZVUE withLEFT-ARROW|
|&h0040|Allow exit from EZVUE withTAB|
|&h0080|Allow exit from EZVUE withF1-F16|
|&h0100|Do not ask questions on PRINT from within EZVUE|
|&h0200|HittingHOMEwhen already at the top of the file in EZVUE acts like the PRINT command.|



- Hex Decimal Values 

## **Notes** 

The PRINTER, SWITCHES, COPIES, FORMS, LPP, WIDTH, PREFIX, SUFFIX, OVERLAY, and TOTPAGES fields are interpreted in the same way as the individual parameters of the same names in XCALL SPOOL. 

A-Shell Reference 

Page 2376 

## **EZSPL PROCESSING** 

The A-Shell version of EZ-SPOOL is quite similar to the AMOS version, but with some limitations and some extensions. Perhaps most importantly for those not interested in these features, they remain silent and hidden unless you go out of your way to activate them. Such people may safely skip this section. For the rest of you, we will give a very brief overview of EZ-SPOOL configuration, concentrating mainly on the areas of difference between the AMOS and A-Shell versions. Those wanting to know more about EZ-SPOOL should contact MicroSabio for a copy of the EZ-SPOOL User’s Guide. 

## **Subtopics** 

- EZSPL Config Files 

- EZSPL Commands 

A-Shell Reference 

Page 2377 

## **EZSPL CONFIG FILES** 

The first thing EZSPL (SPOOL) does upon being called is look for configuration files. The A-Shell version of the configuration file search path is much more abbreviated than the AMOS version, consisting only of the following: 

```
EZ:<printfilename>.SFL
```

```
EZ:<programname>.SPG
```

```
EZ:<printername>.SPR
```

```
EZ:<termname>.SPL
```

```
MEM:SYSTEM.SPL
```

```
SYSTEM.SPL[p,pn]
```

```
SYSTEM.SPL[p,0]
```

- `EZ:SYSTEM.SPL` 

If none of these are found, then printing proceeds as if EZ-SPOOL did not exist. Otherwise, it opens the first file it finds and process the parameters contained within. The parameters supported under A-Shell are: 

```
ASKPRT=<boolean>
```

```
AUTOWIDTH=<boolean>
```

```
BRIEF=<boolean>
```

```
DEFAULT=<default printer name>
```

```
EXTOPT=<sum of extended options flags>
```

```
MENU=<boolean>
```

```
OPTIONS=<boolean>
```

```
PRINTER=<forced printer name>
```

A-Shell Reference 

Page 2378 

```
PRTSPL=spooler1,description                (up to 64 PRTSPL statements)
```

```
SWITCHES=<sum of spooler switch flags>
```

```
TYPE=<boolean>
```

```
WAIT=<# seconds>
```

Each of these statements must be in all upper case, with no spaces, except within a description field. (e.g. " `MENU = ON` " and " `menu = On` " are invalid). Boolean options are " `ON` ", " `OFF` ", " `YES` ", " `NO` ", " `TRUE` " and " `FALSE` ". 

The lines of the configuration file are scanned from the top. For most parameters, if more than one instance of the parameter is processed, the last instance overrides earlier instances. The main except is the DEFAULT option, which only has an effect if no printer has been set (and no previous DEFAULT option processed). PRTSPL parameters are additive. The file may be broken into sections pertaining to individual users by prefixing the section with a line formatted as [ _username_ ]. Lines between one [ _username_ ] header and another are skipped unless the current username matches the name in the header. Two special [username] values may be used: a section with the header [always] is always processed, while a section with the header [default] is only processed if no previous username-specific section has yet been processed. ([always] and [default] don't count as username-specific sections.) 

User name is determined by the native operating system logon procedure, and can be seen in the SYSTAT display or retrieved with GETUSN. It is not case sensitive in this context. 

## u **EZSPL Sample Config File** 

```
MENU=OFF
```

```
TYPE=OFF
```

```
ASKPRT=OFF
```

```
PRTSPL=PDFX,PDF Printer
```

A-Shell Reference 

Page 2379 

```
[jack]
```

```
MENU=ON
```

```
TYPE=ON
```

```
ASKPRT=ON
```

```
DEFAULT=JET2
PRTSPL=JET2,Jack's Jet Printer
```

```
[always]
PRTSPL=JET1,Common Jet Printer
PRTSPL=DRAFT,Oki draft
```

```
[default]
DEFAULT=JET1
```

In the above case, the first four lines are always processed. They could have been preceded with another [always] header, or combined with the other [always] section. The five lines under [jack] are only processed if the user is jack, in which case the boolean options would override the previously set ones, the DEFAULT printer would only apply if no printer had been previously specified (by the application or in miame.ini), and the PRTSPL line defining the JET2 printer would be added to the previous set of printers (currently containing only PDFX). The [always] section always gets processed. The [default] section would only be processed for users other than jack. 

The capability of adding sections for individual users allows a great deal of flexibility for large systems. 

A-Shell Reference 

Page 2380 

## **See Also** 

- EZSPL Config File 

A-Shell Reference 

Page 2381 

## **EZSPL COMMANDS** 

Following is a brief rundown on the EZ-SPOOL configuration file commands. These are also supported under EZ-SPOOL for AMOS. 

|**Command**|**Argument**|**Description (default)**|
|---|---|---|
|ASKPRT|Boolean|Provides an option to not go through with the spooling operation. If MENU=ON, the<br>operation is aborted by entering choice Z. If MENU=OFF, the user is prompted on line 24<br>of the terminal whether to print. (OFF)|
|AUTOWIDTH|Boolean|OFF affects the initial display width of the preview utility (see Type) Normally (when on) it<br>scans the first several dozen lines of the file to be previewed, and if any are longer than 80<br>columns, it switches automatically to 132 columns.   (ON)|
|BRIEF|Boolean|ON activates a single-line menu (on line 24) asking for the name of the printer only. The<br>user can TAB through the available choices. If OPTIONS=ON (or omitted) it will also<br>prompt for the number of copies.  (OFF)|
|DEFAULT|printer name|Defines the default spooler name to be used if no spooler name is passed in the XCALL<br>SPOOL. This overrides the default established by the PRINTER statement in miame.ini.|
|EXTOPT|Numeric|Enable various options.|
|LEFT MARGIN|Numeric|Leaves the specified number of columns untouched by EZVUE. This may be useful if you<br>want to retain a sense of context with the underlying screen (or perhaps the underlying<br>screen has some useful information you want to be able to see while looking at a report).|
|MENU|Boolean|ON causes a printer selection menu to appear. The choices on the menu consist of the|



A-Shell Reference 

Page 2382 

|**Command**|**Argument**|**Description (default)**|
|---|---|---|
|||printers defined in the PRTSPL statements. (OFF)|
|OPTIONS|Boolean|OFF eliminates the question about number of copies from the BRIEF menu. (ON)|
|PRINTER|Printer name|PRINTER (in the EZ-SPOOL configuration file, as opposed to miame.ini) is like DEFAULT<br>but overrides the spooler choice specified in the subroutine. (The confusion with miame.ini<br>PRINTER property is regrettable, but this terminology matches EZ-SPOOL under AMOS.)|
|PRTSPL|Spooler name,<br>desc|These statements (e.g. PRTSPL=JET,LaserJet) establish choices that appear on the printer<br>selection menu. If MENU=OFF, these statements have no effect. You may define up to 64<br>printer choices this way.|
|ROWS|# of rows|Establishes the initial number of display rows, when set to a legal value within the range of<br>24-50, subject to the capabilities of the terminal. The default setting is equal to the screen<br>height at the timeEZTYPis called. Note that the operator can also toggle between 24 and<br>42 row mode from theEZTYPcommand prompt with the "T" command or with the<br>Shift+UpArrow or Shift+DownArrow keys.|
|SWITCHES|{+/-}#####|Allows you to add, remove, or replace the switches passed in the XCALL EZSPL, XCALL<br>SPOOL, or even XCALL EZTYP.|
|TOPMARGIN|Numeric|Leaves the specified number of rows untouched by EZVUE. (Same idea as LEFTMARGIN.)|
|TYPE|Boolean|ON provides an option to preview the file on the screen. If MENU=ON, this becomes choice<br>X. Otherwise, the user is prompted on line 24 whether to preview the file.|



A-Shell Reference 

Page 2383 

|**Command**|**Argument**|**Description (default)**|
|---|---|---|
|WAIT|# of seconds|Specifies the number of seconds that various EZ-SPOOL screen prompts will wait for an<br>answer before using the default value. "0" produces an unlimited wait. The default value<br>(no WAIT specified) is 300 seconds.|



A-Shell Reference 

Page 2384 

## **EXTOPT** 

Argument is a sum of zero or more of the following flags values: 

|**Flag**|**Description**|
|---|---|
|&h0004|Disable screen save/restore|
|&h0020|Allow exit from EZVUE withLEFT-ARROW|
|&h0040|Allow exit from EZVUE withTAB|
|&h0080|Allow exit from EZVUE withF1-F16|
|&h0100|Don’t ask questions on PRINT command from within file viewer. This is mainly useful in<br>conjunction with the SBR=EZPRTX option inmiame.ini, which causes EZVUE to XCALL EZPRTX<br>instead of XCALL SPOOL when printing from the viewer. Since you can customize EZPRTX.SBX,<br>you may not want EZVUE to ask about starting and ending pages, or even about the printer<br>choices.|
|&h0200|Hitting theHOMEkey before any other cursor motion keys while in the file viewer will act like the<br>print command. This is a bit obscure, but apparently there are some people who feel it is just the<br>ticket.|



A-Shell Reference 

Page 2385 

## **SWITCHES** 

The EZSPL configuration file command: 

## **SWITCHES = {+/-}#####** 

allows you to add, remove, or replace the SWITCHES passed in the XCALL EZSPL, XCALL SPOOL, or even XCALL EZTYP. 

For example, SWITCHES = +&h80000 would force EZSPL (including EZTYP) to act as if the &h80000 (GUI PREVIEW) switch had been set by the caller, and thus would launch the GUI Preview utility instead of the text preview. 

The main value of this switch is that it allows you to force EZTYP to use the APEX preview utility, provided you are running under A-Shell/Windows. 

## **See Also** 

- EZSPL Config File 

A-Shell Reference 

Page 2386 

## **EZTYP** 

_Reviewed and revised April 2024_ 

## **xcall EZTYP, fspec {,topmgn, leftmgn, exitcode}** 

EZTYP provides a simple way to call the text/print file viewer within the EZ-SPOOL subsystem. Note that it is possible to print individual pages or page ranges (including the entire file) within EZTYP, so it could in some circumstances be used in place of EZSPL. See EZTYP.LIT for more information on the capabilities of the print file viewer. 

Note that EZTYP behavior may be affected by the WAIT (timeout) and AUTOWIDTH parameters in the EZSPL configuration files, as well as the EZCLR entry in the INI.CLR file. Refer to EZSPL Config Files and Color Customization for more information. 

## **Parameters** 

_fspec_ (String)  [in] 

file (native or DevPPN format) to display 

_topmgn, leftmgn_ (Unsigned Int)  [in] 

allows you to preserve the specified number of rows and columns at the left and top of the screen to be untouched by the EZTYP display. If you are not using these parameters, set them to 0. 

_exitcode_ (Signed Int)  [in] 

optionally returns the exitcode (INFLD-compatible) which caused the preview session to exit. _Exitcode_ should be a floating point since many of the return values are negative. The typical _exitcode_ would be 1 (ESCAPE). 

A-Shell Reference 

Page 2387 

## **F2HOST** 

## **xcall F2HOST, alphaflt, hostflt** 

F2HOST converts a six byte BASIC-format floating point value to the equivalent IEEE four byte (single precision) or eight byte (double precision) floating point format. Although this is done internally by A-Shell all the time, since it uses the IEEE format for internal calculations, the subroutine may be handy when exporting data to outside sources. 

## **Parameters** 

_alphaflt_ (F,6) 

will return the converted value. 

## _hostflt_ 

should be mapped as X,4 or X,8 depending on the size of the IEEE floating point value to be converted. 

## **Comments** 

See HOST2F for the reverse conversion. Note that when exporting data, it is usually more practical to output in string CSV format; see WRITECD for an easy way to do this. 

A-Shell Reference 

Page 2388 

## **FIFO** 

## **xcall FIFO, opcode, ch, buffer, flags, status** 

FIFO (Unix only) provides a general-purpose technique for communicating with other processes, including those outside of A- Shell and possibly even on other machines (connected via a network) using named pipes. Named pipes (sometimes called FIFOs because that is the way they act) are supported under most implementations of Unix and are similar to sockets, except that they are disk based and therefore somewhat removed from the details of networking. 

## `MAP1 OPCODE, F` 

- `! opcode (any numeric type)` 

- `! 0 = create FIFO` 

- `! 1 = open FIFO` 

- `! 2 = close FIFO` 

- `! 3 = read FIFO` 

- `! 4 = write FIFO` 

## `MAP1 CH ,F` 

- `! channel returned from open; passed to other` 

- `! opcodes (any numeric type)` 

## `MAP1 BUFFER, S` 

- `! data used in various ways depending on` 

- `! opcode. May be type X or S as appropriate` 

A-Shell Reference 

Page 2389 

```
MAP1 FLAGS, F
```

- `! misc. flags, based on OPCODE (any numeric type)` 

- `! opcode 0:  permission bits (modified by umask)` 

- `! opcode 1:  open flags (0=read, 1=write, +4 for 'NDELAY'` 

- `!       +100 for 'NONBLOCK' (see explanation below)` 

- `! opcode 2:  ignored` 

- `! opcode 3:  maximum number of bytes to read (if 0, use map size of BUFFER)` 

- `! opcode 4:  maximum number of bytes to write (if 0, use map size of BUFFER;` 

- `!if –1, use length of BUFFER up to first null)` 

```
MAP1 STATUS, F
```

- `! result code (any numeric type)` 

- `! opcode 0:  0=OK, else –errno (see notes below on errno)` 

- `! opcode 1:  >0=file number, else –errno` 

- `! opcode 2:  none` 

- `! opcode 3:  number of bytes read; else –errno` 

- `! opcode 4:  number of bytes written; else –errno` 

**NDELAY** and **NONBLOCK** are mode options controlling how the routine attempts to read or write to a FIFO when the other end is not ready. The exact behavior may differ from one Unix to another, so some experimentation may be required. In general, 

A-Shell Reference 

Page 2390 

without either flag, read and write operations will suspend the caller until the operation can be completed. With **NDELAY** set, the operation will generally succeed and return immediately. That is, data written is buffered if the other end is not ready to read it, and read operations will just return NULL if no data is available. With **NONBLOCK** set, the routine will return immediately but will fail with an error code if the operation cannot be complete immediately. 

Under SCO OpenServer (and possibly others) **NONBLOCK** is probably not practical for the writing end of a pipe, and in all cases it is not practical for both ends to use **NONBLOCK.** 

**Error Codes:** Aside from the standard Unix **errno** values, two special STATUS values are possible:-999 indicates that you passed a bad _opcode_ , and –998 is returned when in **NONBLOCK** mode and the operation could not be carried out immediately. 

A-Shell Reference 

Page 2391 

## **FILNAM** 

## **xcall FILNAM, ch, filename** 

FILNAM returns _filename_ when only the file channel is known. This is frequently useful in conjunction with error trapping, where the trapping routine identifies the file only by channel. 

## **Parameters** 

_ch_ (Num)  [in] 

the channel that the file is open on 

## _filename_ (String)  [out] 

will return the filename (as specified in the open statement) corresponding to the specified file channel. If no file is open on that channel, _filename_ returns a null string. 

A-Shell Reference 

Page 2392 

## **FLOCK** 

_Updated March 2016; see History_ 

## **xcall FLOCK, action, mode, status, file, rec** 

FLOCK provides a scheme for implementing shared and exclusive file and record locks, with an option to wait or return an in-use code. The A-Shell version is fully upward compatible with the AMOS version, and in addition goes beyond the various 64K limits in the AMOS version to support file channels and record number values up to 2 billion. 

## _action_ (Num)   ([in] 

## Numeric code indicating the action to perform: 

|**Value **|**Description**|
|---|---|
|0|Request permission to open file (see File)|
|1|InformFLOCKthat file has been closed|
|2|Program terminating – requests all locks on all files for this user to be released|
|3|Request permission to read record (see File, Rec)|
|4|Request permission to read/write all records of File|
|5|Release Rec (previously locked with Action 3)|



A-Shell Reference 

Page 2393 

|**Value **|**Description**|
|---|---|
|6|Release File (previously locked with Action 4)|



## _mode_ (Num)  [in] 

Flags for exclusive and wait options: 

|**Value **|**Description**|
|---|---|
|0|Non exclusive lock, wait until request can be granted|
|2|Exclusive lock, wait until request can be granted|
|4|Non exclusive lock, no wait (return immediately with Status = 1 if request cannot be granted)|
|6|Exclusive lock, no wait (return immediately with Status = 1 if request cannot be granted)|



_status_ (F,6) 

Return code (for actions indicated in parentheses): 

A-Shell Reference 

Page 2394 

|**Value **|**Description**|
|---|---|
|0|Success|
|1|Resource unavailable (0,3,4)|
|2|Open request already granted (0)|
|3|Permission to open must first be granted (1,3-6)|
|4|Duplicate request for some record in file (3,4)|
|5|Permission to use record must first be granted (5,6)|
|100|Unimplemented action|
|101|File channel not open for random processing (3-6)|
|102|File channel already open for ISAM (0)|
|103|Less than 15 queue blocks available (0,3,4)|
|104|Illegal record (3-6)|



A-Shell Reference 

Page 2395 

_file_ (Num _)_ 

Numeric value indicating the file channel 

_rec_ (Num) 

Numeric value indicating the record number 

FLOCK uses the queue block system to store the locks. You can specify the number of available queue blocks, and the location of the queue file (on disk or in memory) using the QUEUE= property in miame.ini. Note that since the memory option (available under Unix/Linux only) is much faster, it is highly recommended if you are using FLOCK or XLOCK. 

QUTL can be used to display the locks in use and to manually clear locks left by an aborted job. It also displays locks that are pending (i.e. that a job is waiting on), which can be very useful in determining why a job appears to be hung. (An application can, and probably should, warn the user directly when it is stuck waiting on a lock, by using the no-wait mode flags 4 and 6.) 

A-Shell’s implementation of FLOCK has an additional feature in that after waiting for more than 10 seconds for a lock, it will write out a "pending" lock record to the queue. This has no effect except that it can be displayed in the QUTL utility (which can also be executed under program control to create a list file) and thus allows for possibility of reporting to the user who has the lock that he or she is waiting for. 

The system parameter setting TRACE=LOCKS causes information about the conflicting lock that you are waiting for to be displayed on the bottom status line of the terminal. 

## **History** 

- 2016 March, A Shell 6.2.1425:  FLOCK bug fix/refinement: The memory allocation for the FLOCK cache now registers the name "FLKCACHE" in the log, which is useful when debugging memory handle use with the MALLOC TRACE. Also, close a memory leak whereby the cache was needlessly reallocated if FLOCK called within an SBX. 

A-Shell Reference 

Page 2396 

## **FNDUSR** 

_Added February 2017_ 

## **xcall FNDUSR, user'name, status, user'map** 

FNDUSR.SBX emulates the AMOS subroutine of the same name, acting as a companion to MUSER.LIT and LOGON.LIT to retrieve information about the current (or another) user from the database. 

## **xcall FNDUSR, user'name, status, user'map** 

## **Parameters** 

_user'name_ (String)  [in/out] 

is the name to look for. If blank, the current user is retrieved. 

_status_ (F,6)  [out] 

returns 0=success, else unable to locate user 

_user'map_ (Structure)  [out] 

returns attributes of found user: 

```
MAP1 USER'MAP
```

```
MAP2 USER'NAME,S,20
```

```
MAP2 USER'FLAGS,F,6
```

```
MAP2 USER'ROOT'PPN,S,10
```

```
MAP2 USER'ROOT'DEVICE,S,10
```

```
MAP2 USER'MAIL'PPN,S,10
```

```
MAP2 USER'MAIL'DEVICE,S,10
```

A-Shell Reference 

Page 2397 

```
MAP2 USER'MAIL'CPU,S,10
```

```
MAP2 USER'PRIV,F,6
```

```
MAP2 USER'CLASS,F,6
```

```
MAP2 USER'EXP,F,6
```

```
MAP2 USER'CPU'TIME,F,6
```

```
MAP2 USER'CONNECT'TIME,F,6
```

```
MAP2 USER'KRAM,F,6
```

```
MAP2 USER'DISK'READS,F,6
```

```
MAP2 USER'DISK'WRITES,S,6
```

```
MAP2 USER'PAGES'PRINTED,F,6
```

```
MAP2 USER'DEFAULT'PROTECTION,F,6
```

```
MAP2 USER'DEFAULT'PRIORITY,F,6
```

```
MAP2 USER'DEFAULT'LANGUAGE,F,6
```

```
MAP2 USER'DEFAULT'PROMPT,S,20
```

## The above structure is also defined as DEFSTRUCT ST_USER_MAP in ASHINC:USER.DEF. 

## **History** 

- 2017 February, A Shell 6.4.1543: FNDUSR.SBX version 1.0(101) added to A-Shell 

A-Shell Reference 

Page 2398 

## **FTPDLX** 

_Updated January 2024;_ 

## **With A-Shell 7.0.1754, FTPDLX is officially deleted.** All calls to FTPDLX are re-directed to FTP2, which see for details. 

**Deprecated** . Replaced by FTP2, which works under both Windows and Linux and should always be used for new/current programs. FTPDLX continues to work for historical compatibility, but should not be used in any new program elements. 

## **xcall FTPDLX, host, user, password, localpath, hostfile, hostdir, opcode, status {, port, emsg, privkey, passphrase}** 

(Windows only) FTPDLX sends and sends and receives files via FTP or SFTP protocol. 

## _host_ (String)  [in] 

Specifies the name or IP address of the host computer you want to send files to or receive files from. 

_user_ (String)  [in] 

Specifies the user login name for the remote host. For anonymous FTP, use "anonymous" 

_password_ (String)  [in] 

Specifies the login password. For anonymous FTP, use your email address (e.g. myname@mydoman.com) 

## _localpath_ (String)  [in] 

Full pathspec (PC format) for the local file (whether sending or receiving.) If no directory specified, the current login directory will be used. Note: you may want to use MIAMEX, MX_FSPEC to translate an AMOS directory specification to a PC version. See _Comments_ below for wildcarding. 

_hostfile_ (String)  [in] 

A-Shell Reference 

Page 2399 

May be the full pathspec of the remote file, or just the filename and extension. In the former case, leave HOSTDIR blank, otherwise specify the directory in HOSTDIR. HOSTFILE is case sensitive. See _Comments_ below for wildcarding. 

## _hostdir_ (String)  [in] 

If not blank, it is prepended to the _hostfile_ field to form the full pathspec of the remote file. _hostdir_ is case sensitive. 

## _opcode_ (Num)  [in] 

Note that while most of the codes apply to both FTPDLX and FTP2, some apply—as indicated—only to one or the other. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XFTPF_GET|&h00000000|Transfer from server to client PC.|
|XFTPF_PUT|&h00000001|Transfer from client PC to server.|
|XFTPF_ASCII|&h00000002|ASCII transfer mode. Note that some FTP servers will ignore the ASCII option as<br>a security precaution.|
|XFTPF_NOERRMSG|&h00000010|Disable the error message dialog box display that will otherwise appear in the<br>case of errors. In either case, the error code is also returned in the STATUS<br>parameter.|
|XFTPF_PASSIVE|&h00000020|Passive transfer mode. This is often needed to get past firewall restrictions.|
|XFTPF_NOBANNER|&h00000040|Suppress the transfer banner.|
|XFTPF_DEBUG|&h00000080|Activates debug mode, which writes out a very detailed log file toc:\debug.log.|



A-Shell Reference 

Page 2400 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||This is mainly of use when trying to solve low-level protocol problems. FTPDLX<br>only_._|
|XFTPF_SFTP|&h00000100|Use SFTP protocol instead of FTP. This requires a SSH2 service on the server<br>side, typically at port 22.|
|XFTPF_RMVEXT|&h00000200|Rename host file after transfer, removing the last extension. This may be useful<br>to prevent the file from being accessed by the remote system until the transfer<br>is complete. Since it removes the last extension, you probably want to set the<br>host file to have two extensions, such asmyfle.dat.up. After the transfer is<br>complete, the file would be renamed tomyfle.dat.|
|XFTPF_VERSION2|&h00001000|RequestFTP2. FTPSYNC mode only.|
|XFTPF_KEEPOPEN|&h00002000|Keep connection open. FTP2only_._|
|XFTPF_REUSE|&h00004000|Reuse previous connection if available. FTP2only_._|
|XFTPF_CLOSE|&h00008000|Close connection, no transfer.FTP2only_.._|
|XFTPF_DEL|&h00010000|Remote delete.FTP2only_._|



**Definition file: ashell.def** 

A-Shell Reference 

Page 2401 

_status_ (F,6)  [out] 

*Return status. 0=success. Negative numbers are internal errors in FTPDLXcall which you can see from the source code and which are listed in the table below. -1 indicates a user abort. Numbers 1000 and up are EZFTP.OCX errors. 

_port_ (Num)  [in] 

Specifies the control port to connect to the FTP server on. Default is 21 for FTP and 22 for SFTP. 

_emsg_ (String)  [out] 

May return a message on error. 

_privkey_ (String)  [in]) 

contains the filespec of private key file in OpenSSH format. If specified and non-blank, FTPDLX will use public/private key authentication rather than standard password authentication. 

_passphrase_ (String)  [in] 

is the passphrase for the private key. May be omitted if the private key is not passphrase-protected. 

- Nothing is displayed during the transfer, unless an error occurs and _opcode_ +16 is not specified . 

- You can rename FTPDLX to another name, provided that you change the ALIAS[SP] statement accordingly. Change only the part 

- to the left of the colon. 

- The source file specification (in _localpath_ or _hostfile_ , depending on the directory of the transfer) may contain the "*" wildcard. 

- For example, /vm/miame/dsk0/007006/*.dat, or /vm/miame/dsk0/007006/ab*, or even c:\vm\miame\dsk0\007006\cyxz*.d* 

- FTPDLX is actually an internal front-end to an external COM routine, and is dependent on the following entry in miame.ini: 

```
ALIAS=FTPDLX:FtpDLXcall.FTP
```

A-Shell Reference 

Page 2402 

It relies on two dlls: FTPDLXcall2.dll and wodFtpDLX.dll, both of which are normally stored in the %miame%\bin directory, and both of which must be registered using regsvr32.exe. The alias, dlls, and registration are handled automatically by a typical installation, but might require a manual assist if the installation was set up manually using COPY commands rather than the installer. 

## **Environmental Notes** 

FTPDLX is based on a commercial COM FTP control called wodFTPDLX by WeOnlyDo Controls, the runtime license for which is included with A-Shell. 

FTPDLX relies on two DLLs, wodFTPDLX and FTPDLXcall, being in the bin directory (where ashw32.exe is loaded from), and it requires the following miame.ini setting: 

```
ALIAS=FTPDLX:FTPDLXcall.FTP
```

FTPDLX is used internally by ATE to implement the AG_FTP and ZTERM file transfer escape sequence. See also: 

- ZTXFER.LIT and ATSYNC.LIT. 

- ATEAPX.SBX 

- 2015 April, A Shell 6.1.1406:  Added FTP/SFTP remote delete. 

2014 May, A-Shell 6.1.1385: Add parameters _privkey_ and _passphrase_ . 

- 2014 February, A Shell 6.1.1379: Rewrote _opcode_ table to add new options for FPT2 and to improve clarity. 

## **Negative Error Codes Returned in status** 

A-Shell Reference 

Page 2403 

|**Valu**<br>**e**|**Description**|
|---|---|
|-1|too few params|
|-2|can't malloc (or out of malloc hdls)|
|-3|no such Opcode|
|-4|misc param error|
|-5|can't dynamically link library|
|-6|license failure|
|-7|error during adding file (upload)|
|-8|error during SyncRequest|
|-9|error processing file for post|
|-10|unable to allocate string buf|
|-11|error during put|



A-Shell Reference 

Page 2404 

|**Valu**<br>**e**|**Description**|
|---|---|
|-12|error during download|
|-13|unable to log in to server (FTP OR SSH)|
|-14|unable to log to directory on server (FTP)|
|-15|failure to connect (ssh)|
|-17|open session  failure (ssh)|
|-18|pty (termtype?) failure (ssh)|
|-19|shell startup failure (ssh)|
|-20|error receiving data (ssh)|
|-21|error sending data (ssh)|
|-22|connection lost (ssh)|
|-23|no channel (ssh)|



A-Shell Reference 

Page 2405 

|**Valu**<br>**e**|**Description**|
|---|---|
|-24|received eof (ssh)|
|-25|cert problem|
|-26|get failed (no access?)|
|-27|bad cipher type|
|-28|invalid key len|
|-29|bad cipher mode|
|-30|bad padding value|
|-31|bad file (or file error)|
|-32|catch-all CRYPT errors|
|-33|bad encoding|
|-34|bad public key (or error extracting it)|



A-Shell Reference 

Page 2406 

|**Valu**<br>**e**|**Description**|
|---|---|
|-35|bad private key (or error extracting it)|
|-36|failure to open remote file|
|-37|attempt to call function already executing|
|-38|error uploading (possibly local file doesn't exist?)|
|-39|error close remote|
|-99|unsupported platform (Windows only)|



A-Shell Reference 

Page 2407 

## **FTP DEBUGGING** 

Note: these debugging tips do not apply when the FTP2 protocol is being used (i.e. XFTPF_VERSION flag set in FTPDLX.SBX, /2 switch in ZTXFER.LIT, /V2 switch in ATSYNC.LIT, etc.). See XCALL FTP2 for more details. 

Aside from the error codes listed in this section, the FTPDLX also writes a human readable log file, ftpdlx.log in the current directory, which may identify discrepancies between what you thought you were asking it to do and what it was actually trying to do. In addition, if the environment variable ASHFTPDEBUG is defined, a more detailed, lower-level log will written to %temp% \ftpdebug.log. 

The two DLLs mentioned early must be recorded in the Windows Registry, and this process will normally be taken care of automatically by the A-Shell installation program. However, if FTPDLX doesn't work even if the DLLs and the ALIAS[SP] statement are in place, you may need to manually register to the two DLLs: 

```
Start..Run..REGSVR32 <bin-path>\WODFTPDLX.DLL
```

```
Start..Run..REGSVR32 <bin-path>\FTPDLXCALL.DLL
```

## **FTPDLX Error Codes** 

The following error codes may be returned from the FTPDLX control based on logic within the subroutine itself. 

|**Value**|**Description**|
|---|---|
|-1|User abort|
|-2|Error retrieving subroutine parameters|
|-3|Error setting remote address|
|-4|Error setting username|



A-Shell Reference 

Page 2408 

|**Value**|**Description**|
|---|---|
|||
|-5|Error setting password|
|-6|Error setting port (may suggest you have the 1.0 version of EZFTP.OCX)|
|-7|Error setting remote directory and file|
|-8|Error displaying progress dialog|
|-9|Error during connect|
|-10|Error setting binary/ASCII transfer mode|
|-11|Error in get or put operation|
|-12|Error setting local file|



**wodFTPDLX.DLL Error Codes** 

A-Shell Reference 

Page 2409 

|**Value**|**Description**|
|---|---|
|30001|Cannot connect at this time. Use Disconnect first.|
|30002|Cannot execute, not yet connected.|
|30003|Component busy.|
|30004|Cannot change Hostname at this time. Use Disconnect first.|
|30005|Cannot change Port at this time. Use Disconnect first.|
|30006|Cannot change Protocol at this time. Use Disconnect first.|
|30007|Please set login, and password/certificate first.|
|30009|Invalid local file name or path.|
|30010|Could not resolve given Hostname.|
|30011|Invalid data received from remote server. Protocol error.|
|30012|Protocol version mismatch error.|



A-Shell Reference 

Page 2410 

|**Value**|**Description**|
|---|---|
|30013|Server signature does not match. Aborted by user.|
|30014|Bad server public DH value.|
|30015|Server signature does not match.|
|30016|Invalid username or password reported by server.|
|30017|Could not obtain pty on remote server.|
|30018|Server does not support password authentication.|
|30019|Server rejected due to bad fingerprint/certificate information.|
|30020|Failed to open channel on the server.|
|30021|LocalPath should specify a file, and such file does not exist.|
|30022|Error occurred trying to open local file.|
|30023|Error occurred trying to read from local file.|



A-Shell Reference 

Page 2411 

|**Value**|**Description**|
|---|---|
|30024|Error occurred trying to write to local file.|
|30025|Server replied with invalid response ID.|
|30026|Failed to load key or certificate. Password invalid?|
|30027|Cannot use Append method when Resume property is set to True.|
|30028|Please set Hostname property.|
|30029|Component was busy while disconnected by the server.|
|30030|Given path on the server is a directory.|
|30031|Server returned an error:|
|30032|Failed to create temporary file.|
|30033|Server returned invalid response to FXP_ATTRS.|
|30034|Server cannot write to a given path.|



A-Shell Reference 

Page 2412 

|**Value**|**Description**|
|---|---|
|30035|Data connection has timed out.|
|30037|Not enabled in SFTP protocol.|
|30038|Selected proxy type cannot be used with selected protocol.|
|30039|Selected proxy type requires passive mode connection.|
|30040|Proxy server has closed the connection.|
|30041|Proxy server rejected supplied login credentials.|
|30042|Crypto algorithm could not be negotiated.|
|30043|Buffer size out of range 1kb-1mb.|
|30044|Only valid in SSL secured protocols.|
|39999|License key missing. You can not use this component in design<br>environment.|



**FTP Protocol return codes** 

A-Shell Reference 

Page 2413 

|**Value**|**Description**|
|---|---|
|40110|Restart marker reply.|
|40120|Service ready in few minutes.|
|40125|Data connection already open; transfer starting.|
|40150|File status okay; about to open data connection.|
|40200|Command okay.|
|40202|Command not implemented, superfluous at this site.|
|40211|System status, or system help reply.|
|40212|Directory status.|
|40213|File status.|
|40214|Help message.|
|40215|System type.|



A-Shell Reference 

Page 2414 

|**Value**|**Description**|
|---|---|
|40220|Service ready for new user.|
|40221|Service closing control connection.|
|40225|Data connection open; no transfer in progress.|
|40226|Closing data connection.|
|40227|Entering Passive Mode.|
|40230|User logged in, proceed.|
|40250|Requested file action okay, completed.|
|40257|Path created.|
|40331|User name okay, need password.|
|40332|Need account for login.|
|40350|Requested file action pending further information.|



A-Shell Reference 

Page 2415 

|**Value**|**Description**|
|---|---|
|40421|Service not available, closing control connection.|
|40425|Can't open data connection.|
|40426|Connection closed; transfer aborted.|
|40450|Requested file action not taken. File unavailable (e.g., file busy).|
|40451|Requested action aborted: local error in processing.|
|40452|Requested action not taken. Insufficient storage space in system.|
|40500|Syntax error, command unrecognized.|
|40501|Syntax error in parameters or arguments.|
|40502|Command not implemented.|
|40503|Bad sequence of commands.|
|40504|Command not implemented for that parameter.|



A-Shell Reference 

Page 2416 

|**Value**|**Description**|
|---|---|
|40530|Not logged in.|
|40532|Need account for storing files.|
|40550|Requested action not taken. File unavailable (e.g., file not found, no<br>access).|
|40551|Action aborted: broken pipe.|
|40552|Requested file action aborted. Exceeded storage allocation (for current<br>directory or dataset).|
|40553|Requested action not taken. File name not allowed.|



## **Certificate Errors** 

|**Value**|**Description**|
|---|---|
|50000|Certificate ok|
|50002|Certificate error: Unable to get issuer certificate.|



A-Shell Reference 

Page 2417 

|**Value**|**Description**|
|---|---|
|50003|Certificate error: Unable to get CRL (Certificate revocation list).|
|50004|Certificate error: Unable to decrypt certificate signature.|
|50005|Certificate error: Unable to decrypt CRL (Certificate revocation list)<br>signature.|
|50006|Certificate error: Unable to decode issuer public key.|
|50007|Certificate error: Certificate signature failure.|
|50008|Certificate error: CRL (Certificate revocation list). signature failure.|
|50009|Certificate error: Certificate not yet valid;|
|50010|Certificate error: Certificate has expired.|
|50011|Certificate error: CRL not yet valid.|
|50012|Certificate error: CRL has expired.|
|50013|Certificate error: Certificate does not have 'before' field.|



A-Shell Reference 

Page 2418 

|**Value**|**Description**|
|---|---|
|50014|Certificate error: Certificate does not have 'after' field.|
|50015|Certificate error: CRL does not have 'last update' field.|
|50016|Certificate error: CRL error in 'next update' field.|
|50017|Certificate error: Out of memory while reading certificate.|
|50018|Certificate error: Depth zero self signed certificate.|
|50019|Certificate error: Self signed certificate in chain.|
|50020|Certificate error: Unable to get issuer certificate locally.|
|50021|Certificate error: Unable to verify the first certificate.|
|50022|Certificate error: Certificate chain too long.|
|50023|Certificate error: Certificate revoked.|
|50024|Certificate error: Invalid Certificate Authority.|



A-Shell Reference 

Page 2419 

|**Value**|**Description**|
|---|---|
|50025|Certificate error: Path length exceeded.|
|50026|Certificate error: Invalid certificate purpose.|
|50027|Certificate error: Certificate not trusted.|
|50028|Certificate error: Certificate rejected.|
|50029|Certificate error: Subject issuer mismatch.|
|50030|Certificate error: Authority and subject key identifier mismatch.|
|50031|Certificate error: Authority and issuer serial number mismatch.|
|50032|Certificate error: Key usage does not include certificate signing.|
|50050|Certificate error: Application verification failure.|



**Winsock Errors** 

A-Shell Reference 

Page 2420 

|**Value**|**Description**|
|---|---|
|10004|Interrupted function call. A blocking operation was interrupted by a call to WSACancelBlockingCall.|
|10009|Generic error for invalid format, bad format.|
|10013|Permission denied. An attempt was made to access a socket in a way forbidden by its access permissions. An example is using<br>a broadcast address for "sendto" without broadcast permission being set using setsockopt (SO_BROADCAST).|
|10014|Bad address. The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error<br>occurs if an program passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an<br>argument which is a struct sockaddr is smaller than sizeof(struct sockaddr).|
|10022|Invalid argument. Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In<br>some instances, it also refers to the current state of the socket - for instance, calling accept on a socket that is not listening.|
|10024|Too many open files. Too many open sockets. Each implementation may have a maximum number of socket handles available,<br>either globally, per process or per thread.|
|10025|The IP address provided is not valid or the host specified by the IP does not exist.|
|10038|Socket operation on a non-socket. An operation was attempted on something that is not a socket. Either the socket handle<br>parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.|
|10048|Address already in use. Only one usage of each socket address (protocol/IP address/port) is normally permitted. This error<br>occurs if a program attempts to bind a socket to an IP address/port that has already been used for an existing socket, or a<br>socket that wasn't closed properly, or one that is still in the process of closing. For server programs that need to bind multiple|



A-Shell Reference 

Page 2421 

|**Value**|**Description**|
|---|---|
||sockets to the same port number, consider using setsockopt(SO_REUSEADDR). Client programs usually need not call bind at all<br>- connect will choose an unused port automatically.|
|10049|Cannot assign requested address. The requested address is not valid in its context. Normally results from an attempt to bind to<br>an address that is not valid for the local machine, or connect/sendto an address or port that is not valid for a remote machine<br>(e.g. port 0).|
|10050|Network is down. A socket operation encountered a dead network. This could indicate a serious failure of the network system<br>(the protocol stack that the WinSock DLL runs over), the network interface, or the local network itself.|
|10051|Network is unreachable. A socket operation was attempted to an unreachable network. This usually means the local software<br>knows no route to reach the remote host.|
|10052|Network dropped connection on reset. The host you were connected to crashed and rebooted. May also be returned by<br>setsockopt if an attempt is made to set SO_KEEPALIVE on a connection that has already failed.|
|10053|Software caused connection abort. An established connection was aborted by the software in your host machine, possibly due<br>to a data transmission timeout or protocol error.|
|10054|Connection reset by peer. An existing connection was forcibly closed by the remote host. This normally results if the peer<br>program on the remote host is suddenly stopped, the host is rebooted, or the remote host used a "hard close" (see setsockopt<br>for more information on the SO_LINGER option on the remote socket.)|
|10057|Socket is not connected. A request to send or receive data was disallowed because the socket is not connected and (when<br>sending on a datagram socket using sendto) no address was supplied. Any other type of operation might also return this error -|



A-Shell Reference 

Page 2422 

|**Value**|**Description**|
|---|---|
||for example, setsockopt setting SO_KEEPALIVE if the connection has been reset.|
|10058|Cannot send after socket shutdown. A request to send or receive data was disallowed because the socket had already been shut<br>down in that direction with a previous shutdown call. By calling shutdown a partial close of a socket is requested, which is a<br>signal that sending or receiving or both has been discontinued.|
|10060|Connection timed out. A connection attempt failed because the connected party did not properly respond after a period of time,<br>or established connection failed because connected host has failed to respond.|
|10061|Connection refused. No connection could be made because the target machine actively refused it. This usually results from<br>trying to connect to a service that is inactive on the foreign host - i.e. one with no server program running.|
|10063|Specified host name is too long.|
|10064|Host is down. A socket operation failed because the destination host was down. A socket operation encountered a dead host.<br>Networking activity on the local host has not been initiated. These conditions are more likely to be indicated by the error<br>WSAETIMEDOUT.|
|10065|No route to host. A socket operation was attempted to an unreachable host. See WSAENETUNREACH|
|10091|Network subsystem is unavailable. This error is returned by WSAStartup if the Windows Sockets implementation cannot<br>function at this time because the underlying system it uses to provide network services is currently unavailable.|
|10093|Successful WSAStartup not yet performed. Either the program has not called WSAStartup or WSAStartup failed. The program<br>may be accessing a socket which the current active task does not own (i.e. trying to share a socket between tasks), or|



A-Shell Reference 

Page 2423 

|**Value**|**Description**|
|---|---|
||WSACleanup has been called too many times.|
|10094|Graceful shutdown in progress. Returned by recv, WSARecv to indicate the remote party has initiated a graceful shutdown<br>sequence.|
|11001|Host not found. No such host is known. The name is not an official hostname or alias, or it cannot be found in the database(s)<br>being queried. This error may also be returned for protocol and service queries, and means the specified name could not be<br>found in the relevant database.|
|11002|Authoritative host not found. This is usually a temporary error during hostname resolution and means that the local server did<br>not receive a response from an authoritative server. A retry at some time later may be successful.|



A-Shell Reference 

Page 2424 

## **FTP2** 

_Updated January 2024; see History_ 

## **xcall FTP2, host, user, password, localpath, hostfile, hostdir, opcode, status, port, {,emsg, privkey,** 

## **passphrase }** 

FTP2 provides the client side of FTP and SFTP file transfers. Similar to, and mostly upward compatible with the now deprecated FTPDLX (see "Migrating..." below), FTP2 offers additional features and support for the latest security patches and protocol updates. 

## _host_ (String)  [in] 

Specifies the name or IP address of the host computer you want to send files to or receive files from. 

_user_ (String)  [in] 

Specifies the user login name for the remote host. For anonymous FTP, use "anonymous" 

## _password_ (String)  [in] 

Specifies the login password. For anonymous FTP, use your email address (e.g. myname@mydoman.com). Ignored when the _privkey_ argument is specified. 

## _localpath_ (String)  [in] 

Native file specification for the local file, whether sending or receiving. If not fully qualified, it will be treated as relative to the current local login directory. For non-wildcard GET operations, it must include the target filename and extension. See Comments below for wildcarding, and MX_FSPEC or the function Fn'FQFS$() in SOSLIB:[907,10] for converting DevPPN specs to native equivalents. 

## _hostfile_ (String)  [in] 

May be the full pathspec of the remote file, or just the filename and extension. In the former case, leave _hostdir_ blank, otherwise specify the directory in _hostdir_ . _hostfile_ is case sensitive. See _Comments_ below for wildcarding and deletions. 

A-Shell Reference 

Page 2425 

## _hostdir_ (String)  [in] 

If not blank, it is prepended to the _hostfile_ field to form the full pathspec of the remote file. _hostdir_ is case sensitive. 

## _opcode_ (Num)  [in] 

Note that while most of the codes apply to both FTPDLX and FTP2, some apply—as indicated—only to one or the other. Table of Opcodes 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XFTPF_GET|&h00000000|Transfer from server to client PC.|
|XFTPF_PUT|&h00000001|Transfer from client PC to server.|
|XFTPF_ASCII|&h00000002|ASCII transfer mode. Note that some FTP servers will ignore the ASCII option as a security<br>precaution.|
|XFTPF_NOERRMSG|&h00000010|Suppress error dialogs.|
|XFTPF_PASSIVE|&h00000020|Passive transfer mode. This is often needed to get past firewall restrictions.|
|XFTPF_NOBANNER|&h00000040|Suppress the transfer banner.|
|XFTPF_SFTP|&h00000100|Use SFTP protocol instead of FTP. This requires a SSH2 service on the server side, typically at port<br>22.|
|XFTPF_VERSION2|&h00001000|RequestFTP2. Automatically set.|



A-Shell Reference 

Page 2426 

|**Symbol**|**Value**|**Description**|
|---|---|---|
||||
|XFTPF_KEEPOPEN|&h00002000|Keep connection open.|
|XFTPF_REUSE|&h00004000|Reuse previous connection if available.|
|XFTPF_CLOSE|&h00008000|Close connection, no transfer.|
|XFTPF_RMVEXT|&h00000200|Rename host file after transfer, removing the last extension. This may be useful to prevent the file<br>from being accessed by the remote system until the transfer is complete. Since it removes the last<br>extension, you probably want to set the host file to have two extensions, such asmyfle.dat.up.<br>After the transfer is complete, the file would be renamed tomyfle.dat.|
|XFTPF_DEL|&h00100000|Remote delete.|
|XFTPF_RECURSE|&h00200000|Recurse subdirectories, with wildcards.|
|XFTPF_DIR|&h00400000|Output directory listing of remote directory into_localpath_.|
|XFTPF_RENAME|&h00800000|rename a remote file or directory|
|**The following are mutually exclusive (SFTP only); M=missing, N=newer, S=size.**|||



A-Shell Reference 

Page 2427 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XFTPF_SYNC_ALL|&h00000000|All matching files.|
|XFTPF_SYNC_M|&h01000000|All files that don't exist in destination.|
|XFTPF_SYNC_MN|&h02000000|All files that don't exist in destination, or are newer in source.|
|XFTPF_SYNC_N|&h03000000|Only files that exist in both places but are newer in source.|
|XFTPF_SYNC_MS|&h04000000|All files that don't exist in destination or are different size.|
|XFTPF_SYNC_MNS|&h05000000|All files that don't exist in destination or are different size or newer.|
|XFTPF_SYNC_DELM|&h0F000000|With XFTPF_DEL, only remote files not existing locally.|
|||**This data was extracted from the d**<br>**efinition file ashell.def**|



## _status_ (F,6)  [out] 

Return status. Greater than zero indicates success. In some cases, primarily wildcard operations with SFTP protocol, _status_ will return the number of files actually transferred or deleted. Negative values indicate errors as shown in the ASHNET Status Codes. 

## _port_ (Num)  [in] 

Specifies the control port to use when connecting to the remote FTP/SFTP server. The most typical ports are 21 for FTP and 22 for SFTP, but servers are free to change them for various security and firewall-related reasons. In any case the parameter must be explicitly set. 

A-Shell Reference 

Page 2428 

_emsg_ (String)  [out] 

Will contain a debug trace in the case of an error. Since this can be lengthy, you should provide a string of at least 1500 bytes (or S,0) to contain it all. In the case of wildcard transfers or deletions using the SFTP protocol, on success it will contain a list of the files actually transferred or deleted. 

## _privkey_ (String)  [in]) 

contains the filespec of private key file in OpenSSH format. If specified and non-blank, FTPDLX will use public/private key authentication rather than standard password authentication. 

## _passphrase_ (String)  [in] 

is the passphrase for the private key. May be omitted if the private key is not passphrase-protected. 

## **Comments** 

The source file specification—in _localpath_ or _hostfile_ , depending on the direction of the transfer—may contain the "*" wildcard. For example, /vm/miame/dsk0/007006/*.dat, or /vm/miame/dsk0/007006/ab*, or even c:\vm\miame\dsk0\007006\cyxz*.d*. 

When receiving files using a wildcard _hostfile_ specification, _localpath_ should be set to the base directory to receive the files. Setting _localpath_ to "" will result in them being received into the local root directory, which will likely fail due to permissions. 

FTP2 is used in ZTXFER and ATSYNC if the /2 switch is specified. 

The XFTPF_SYNC _opcode_ options apply only to the SFTP protocol (XTFPF_SFTP), and only come into play when a wildcard is specified in the relevant source argument and the destination is just a directory. The wildcard source argument acts as the first level of filtering on files to be transferred, with further filtering determined by the XFTPF_SYNC_xxx options. 

Note that unlike most of the XFTPF_xxx flags, which are coded as unique bits and thus could theoretically be combined in any way, provided it makes functional sense, the XFTPF_SYNC_xxx options are all mutually exclusive—i.e., choose only one. Also note that XFTPF_SYNC_DELM only applies in conjunction with XFTPF_DEL. 

A-Shell Reference 

Page 2429 

When doing wildcard transfers or remote deletions, the status parameter returns on success the number of files transferred or deleted, rather than just zero. Also, the _emsg_ parameter in that case will contain a list of the files transferred or deleted, delimited by line breaks. See History notes below related to XFTPF_DEL. 

## **Debugging** 

In most cases, FTP2 will create a log file in the %TEMP%  (Windows) or /tmp (Linux) directories named ashnet.log which may contain useful details. The same detailed error log information will be returned in _emsg_ on any error. 

## **Migrating from FTPDLX** 

For the most part you can just change the name of the XCALL routine from FTPDLX to FTP2, but there are a few differences to watch out for: 

- For non-wildcard transfers, FTP2 requires a complete filespec in _localpath,_ including the filename and extension, whereas 

- FTPDLX accepts a directory and will copy the filename from the source. 

- FTP2 error messages are more like complete logs rather than the mere messages returned by FTPDLX. You may therefore 

- need to increase the size of _emsg_ and possibly adjust the way you display or otherwise handle them. 

- FTP2 ignores the debug flag (XFTPF_DEBUG or &h0080) and always writes error debugging information to the ashnet.log file 

- (see Debugging) and to the _emsg_ parameter. 

## **See Also** 

- FTPDLX (deprecated) 

- Program FTPTST in SOSLIB:[907,33] 

- AG_FTP; includes discussion of other file transfer alternatives 

## **History** 

- 2024 January, A Shell 7.0.1753:  The GET operation now manually replicates the file.ext from the _hostfile_ parameter if the _localpath_ parameter doesn't contain one, eliminating one obstacle to switching from FTPDLX to FTP2. In most cases, the file.ext 

A-Shell Reference 

Page 2430 

defaulting is handled by the FTP/SFTP service anyway, but there are scenarios, particularly with SFTP, where FTP2 was failing due to lack of an explicit file.ext in _localpath_ . 

FTP2TIMEOUT environment variable now affects SFTP as well as FTP connections. Also, XFTPF_RMVEXT support added. 

- 2021 December, A Shell 6.5.1709, ASHNET 1.14.177:  FTP2TIMEOUT environment variable now affects SFTP as well as FTP connections. Also, XFTPF_RMVEXT support added. 

- 2021 June, A Shell 6.5.1703, ASHNET 1.4.174:  XFTPF_DEL now supports a complete filespec in _hostfile._ Previously it required the directory and filename to be split into _hostdir_ and _hostfile_ . 

2019 June, A-Shell 6.5.1662:  Add opcodes XFTPF_DIR and XFTPF_RENAME. 

- 2017 February, A Shell 6.3.1544: FTP2 now exposed to Linux via libashnet.so.1.9.157. Wildcards are now supported in the SFTP protocol; previously they were only supported for the FTP protocol. New _opcode_ options added. 

- 2015 April, A Shell 6.1.1406:  Added FTP/SFTP remote delete. 

- 2015 March, A Shell 6.1.1405, ASHNET 1.7.147:   you can now override the default timeout for FTP2 (60 seconds) by defining the environment variable FTP2TIMEOUT as the desired timeout in seconds, e.g. `.SETENV FTP2TIMEOUT=10` . Note that this is implemented entirely in ASHNET. 

- 2014 February, A Shell 6.1.1379: Added routine to A-Shell. 

A-Shell Reference 

Page 2431 

## **XFTPF_DIR** 

_Added June 2019_ 

Opcode XFTPF_DIR (&h00400000) in conjunction with XFTPF_SFTP allows you to create a local directory listing of a remote directory. The subroutine parameter usage is similar to that for XFTPF_GET, with localpath specifying the filespec of the directory listing, which will be created in CSV format as follows: 

```
"file.ext",type,permissions,owner,group,size,"ctime","mtime"
```

## **Comments** 

The _hostfile_ and _hostdir_ parameters must specify the remote directory; filecards are optional. (*.* will be assumed if hostfile="".) 

The host directory is not included in the "file.ext" field in the CSV directory listing. 

The type field will be one of the following: regular,directory,symLink, special,unknown,socket,charDevice,blockDevice,fifo 

The owner and group fields will be empty if the server does not support SFTP v4+. 

The "ctime" (creation time) and "mtime" (last modification time) fields will be in RFC822 format, e.g. "Mon, 17 Jun 2019 17:40:32 -0700". See the Fn'Date'To'xxxx() functions in fndatetime.bsi SOSLIB:[907,10] for handy conversions from RFC822 (and many other) date formats. 

The implementation is entirely within the ASHNET library modules for Windows and Linux, and is not dependent on any particular A-Shell version. 

## **History** 

- 2019 June, A Shell 6.5.1662, ASHNET library update 1.13.166: Opcode added to A-Shell. 

A-Shell Reference 

Page 2432 

## **XFTPF_RENAME** 

_Added June 2019_ 

Opcode XFTPF_RENAME (&h00800000), in conjunction with XFTPF_SFTP allows you to rename a remote file or directory. Use the same parameter list as for the other opcodes, except: 

_localpath_ should specify the old file or directory name 

_hostfile_ should specify the new file or directory name 

_hostdir_ should be set to "" 

On return the status parameter will be set to 1 on success. 

## **History** 

- 2019 June, A Shell 6.5.1662, ASHNET library update 1.13.167: Opcode added to A-Shell. 

A-Shell Reference 

Page 2433 

## **GDIPRT** 

## **command = sbx:GDIPRT {,<option1>, <option2>, <option3>...}** 

(Unix/Linux only.) GDIPRT.SBX is a print filter subroutine intended only for use in a COMMAND statement within a printer ini file, which performs the function of transferring the file from the Unix/Linux server to the workstation, where it be will be resubmitted to an AshLite printer of the same name (as the printer originally requested on the server). The usual motivation would be to take advantage of Windows printing features that would otherwise be unavailable on a Unix or Linux server. 

The standard version of GDIPRT requires that the workstation have a network connection to the server, using the ZTERM terminal emulator, as it uses ZTERM escape sequences to perform an FTP file transfer. You could modify the source code to work for other terminal emulators or other file transfer methods. 

The procedure works as follows: 

- The file is submitted to the print on the server (say, to printer "prt1"). 

- The printer ini file (e.g. ashcfg:prt1.pqi or sys:prt1.ini) invokes the GDIPRT subroutine via the COMMAND statement as shown 

- above. 

- The GDIPRT subroutine first attempts to detect if the terminal emulator is ZTERM, it aborts with STATUS=-2. 

- It then opens the print file and scans it, looking for IMAGE and METAFILE statements. For any that are found, the 

- corresponding files are transferred to the PC’s temp directory (see <dir> option in the following table.) 

- The print file itself is then transferred to the PC. 

- AshLite is launched on the PC, passing it the command PRINT PRT1=<print file>. Note that the printer name, in this case 

- PRT1, will be the same as for the original print request. If the AshLite launch fails, it will return STATUS=-3. 

- Otherwise, we assume that the operation succeeded and return STATUS=0 (so that we do not try to print it on the server.) 

The _option_ parameters may be used to specify any of the following options (expressed as quoted, literal strings): 

A-Shell Reference 

Page 2434 

|**Value**|**Meaning**|
|---|---|
|"VERBOSE"|Causes a dialog box to appear during the transfer operation showing details of the various steps. Useful for<br>debugging, or just to have something to look at.|
|"DEBUG"|Causes AshLite to be launched with a visible window, and to not automatically exit on completion of the print<br>command (thus making it easier to see what may have gone wrong). If VERBOSE was also specified, then the<br>subroutine (on the server) will wait for an acknowledgment from the user before removing the display box.|
|"LOG"|Causes the subroutine to log details about the operation to the log fileopr:gdiprt.log|
|"<dir>"|Any string containing a backslash or colon, e.g.c:\temp, will cause the routine to use the specified directory<br>as the temporary working directory on the PC. Otherwise, if ZTERM build 143+ is detected, it will use the<br>%TEMP% environment variable, else it will usec:\temp.|



A-Shell Reference 

Page 2435 

## **GET** 

_Updated March 2024; see History_ 

## **xcall GET, buffer {,chan, bytes'req, bytes'rcvd, timeout, flags}** 

GET is useful for simple or sophisticated input of raw characters from the keyboard or a file. Under Unix/Linux, it may also be used for Inputting from a serial device. See COMIO for serial I/O under Windows. 

## _buffer_ (String, may be dynamic)  [out] 

receives the byte(s) input. Note that no trailing null byte is added by the subroutine, so you may want to pre-clear this variable before calling GET. In the simplest case of GET where no parameters beyond _buffer_ are specified, it will input a single character from the keyboard, waiting as long as necessary. 

## _chan_ (Num)  [in]  (optional) 

File channel number of a file that has been opened for input, and from which the character(s) are to be read. If not specified, or zero, input is from the keyboard. 

## _bytes’requested_ (Num)  [in]  (optional) 

Number of bytes to input. If not specified, default is 1. You can specify 0 in conjunction with the timeout feature if you just want to know if a character is available without actually inputting it. Two special values are supported: -1 requests a line of input terminating with LF (and ignoring CR); -2 requests a line of input terminating with CR (and ignoring LF). Note that for the special values -1 and -2, the terminating CR and/or LF will not be included in _buffer_ , but will be included in the count in _bytes'received_ . 

_bytes’ received_ (Num)  [out]  (optional) 

Returns the number of bytes that were actually input (and returned into the Buffer parameter). Normally this will be the same as _bytes’requested_ , except in the following circumstances: 

If _bytes’requested_ was 0, then _bytes’received_ will be 1 if there was one or more characters available to be input, or 0 to indicate no characters available. 

A-Shell Reference 

Page 2436 

If we hit the end of the input file, or the _timeout_ period expires before reading the number of requested bytes, then _bytes’received_ will be less than _bytes’requested_ . 

If an I/O error occurs, or if a _timeout_ period is specified and no characters are input because the file was already at the end-offile mark, _bytes’received_ will be set to -1. This distinguishes the case of end-of-file from timeout. 

When _bytes'requested_ is set to -1 or -2, _bytes'received_ will be set to the total number of bytes received, including the terminating character(s). However, the terminating characters (CR and/or LF) are not returned in _buffer_ . 

_timeout_ (Num)  [in]  (optional) 

Number of milliseconds to wait for input before aborting. If set to 0 or not specified, there is no timeout. Note that the actual elapsed time may be substantially longer that the specified period. This is both because of CPU time dedicated to other processes and because the total timeout period is actually divided into slices equal to the number of characters to be input, with each slice being used up only if no characters are available. 

For example, if you have a 5000 millisecond (5 second) _timeout_ and are requesting 5 characters, then you will actually be allotted 5 one-second timeout periods, and each period is only spent if no characters are input during that period. If exactly one character arrived every 0.75 seconds, then you would still have five unused seconds after four characters had be input, even though three seconds had actually elapsed. This scheme may seem a bit strange, but is actually a reasonable compromise between the two extreme approaches of treating the timeout period as an absolute maximum or of resetting it entirely after each character. 

**Note:** In order for the timeout to be reliable when inputting from a device such as a serial port, you must first disable buffering on the input channel (see MX_NOBUF). Failure to do so could result in apparently flaky behavior, since the timeout mechanism may not be aware of buffered characters, thus leading to false timeouts. 

## _flags_ (Num)  [in]  (optional) 

|**Value**|**Description**|
|---|---|
|&h01|Raw mode. See notes below.|
|&h02|Convert CRLF to CR.|



A-Shell Reference 

Page 2437 

Raw mode eliminates all input processing and filtering such as function key support, terminal driver input translations, and adds the ability to input null bytes. Otherwise, null bytes are stripped out of the input stream before your application gets a chance to see them. Note the following restrictions on the _flags_ parameter: 

- Under Unix, setting _flags_ =1 and _bytes'req_ =0 (in order to check if any characters are available without inputting anything) will 

- properly return _bytes'rcvd_ =1 if anything is available to input, but if the first byte available is a null, it will be lost. So it is best to just set _bytes'req_ to the number of bytes you want, and use timeout to avoid getting stuck in an input wait. 

- Under Windows, input processing occurs asynchronously as characters arrive, not as they are requested by the application. 

- So the _raw flag_ will only be useful if the `XCALL GET` occurs before the characters in question arrive. 

## **Comments** 

- When inputting from the keyboard, NOECHO will be set automatically and left that way on exit. 

- Function key translations are not processed by GET. Use GETX or ACCEPTXS if you need that feature. 

- GET may also be used to check if a character is available without waiting and without actually inputting the character, by 

- setting _bytes’requested_ and _timeout_ to zero. This is equivalent to GETKEY(-2). 

## **See Also** 

- ACCEPT, ACCEPNXS 

- GETXS  (keyboard or file input) 

- GETKEYXS 

- TINKEYXS 

## **History** 

2024 March, A-Shell 7.0.1757:  Add _flags_ value &h02. 

A-Shell Reference 

Page 2438 

## **INPUTTING FROM A SERIAL DEVICE** 

To input from a serial device under Unix or Linux, open it as an input file, e.g.: 

```
OPEN #9, "/dev/cua0", INPUT
```

Then pass the file channel to XCALL GET just like any other input file channel. Beware, however, that under Unix, such serial ports will be by default set to "line input" mode. Thus, while you may be asking for only two characters, you would not actually "see" them until a line terminator (usually LF) had been received. To avoid this annoyance and get the characters immediately as they are transmitted from the other end, you need to take the port out of "line input" mode. One way to accomplish this is to use HOSTEX with the Unix _stty_ command to turn off "icanon" mode, for example: 

```
xcall HOSTEX, "stty –icanon < /dev/cua0"
```

## **Comments** 

- Use the STTY command only after opening the file channel. Otherwise, the settings may be wiped out by the open operation. 

- Also, note that _stty_ and its arguments are case sensitive, usually all in lower case. 

- If inputting from a serial device under Unix/Linux, you may want to adjust port settings, such as flow control, baud rate, etc, 

- which can be done by executing an **stty** command (via HOSTEX) after opening the port and before using GET. Consult the Unix **stty** man page or other documentation for details on the available settings. 

- You may need to use `chmod 666` on the port device file to allow it to be read and its settings modified by a non-root user. 

A-Shell Reference 

Page 2439 

## **GETADR** 

## **xcall GETADR, var, varaddr {, varsize}** 

GETADR retrieves the memory address, and optionally the size, of the variable specified as the first parameter. This technique was used in the so called "Speed Optimized Interface" of INFLD under AMOS, and is preserved here just for backward compatibility. The so called interface is a misnomer under A-Shell, where it actually requires more overhead, and thus is not recommended for new programming. Getting the address and size of a variable might have some other exotic application, but we are not sure what. 

## **Parameters** 

_var_ [in] 

can be any arbitrary variable. 

## _varaddr_ [out] 

can be any numeric type. 

_varsize_ [out] 

if specified, must be a 2 byte binary. Note that if _var_ is an array element, the size and address will be for that element, not for the entire array. You can get the starting address of the array by specifying the first element, but the only way to get the total size of the array would be to map an unformatted variable on top of the array with the appropriate size specified in the MAP statement. 

## **Comments** 

Note that iIf the address parameter specified in argument 2 is an X,8 variable, then it is assumed to be formatted as a pair of B,4 variables as in the structure above. This will allow for a transition to 64 bit mode should it ever occur, without the application having to be aware of it. 

A-Shell Reference 

Page 2440 

## **GETBYT** 

## **xcall GETBYT, channel, buffer, bytes** 

GETBYT reads a specified number of bytes from an open input file. 

## **Parameters** 

_channel_ (Num)  [in] 

is the channel number of the file, which must be open for input. 

_buffer_ (BLOB)  [out] 

Receives the data. 

_bytes_ (Num)  [in] 

Specifies the number of bytes to read, which must be less than or equal to the size of _buffer_ . 

## **Comments** 

Use the EOF() function to test for end of file condition before each call to GETBYT. 

You can get a similar effect with INPUT RAW, except that it always reads a number of bytes equal to the size of the specified variable. 

Note that GETXS performs a similar operation but is somewhat more sophisticated. 

## **See Also** 

- PUTBYTXS 

A-Shell Reference 

Page 2441 

## **GETDEV** 

## **xcall GETDEV, devstr** 

## **xcall GETDEV, unit, dev** 

GETDEV retrieves the current device information in one of two formats, as shown above. 

## **Parameters** 

```
MAP1 Devstr,S,6      ! (e.g. "DSK1")
MAP1 Unit,B,2        ! (logical unit #)
MAP1 Dev,S,3         ! (e.g. "DSK")
```

A-Shell Reference 

Page 2442 

## **GETJOB** 

## **xcall GETJOB, jobnam {,progrm}** 

## **xcall GETJOB, jobnam {,ppn, jobnum}** 

GETJOB retrieves the jobname, plus optionally the program name or the PPN and job number. 

## **Parameters** 

_jobnam_ (String, 6) 

_program_ (String, 6) 

_ppn_ (B,2) 

_jobnum_ (B, any size 1-5) 

## **Comments** 

Note that _ppn_ can be mapped either as above or as: 

```
MAP1 PPN
```

```
   MAP2 P,B,1          ! project
```

```
   MAP2 PN,B,1         ! programmer number
```

or 

```
MAP1 PPN
```

A-Shell Reference 

Page 2443 

```
   MAP2 PROJ,S,3       ! for example, "001"
   MAP2 PROG,S,3       ! for example, "004"
```

The latter format is preferable, since A-Shell supports decimal PPNs up to 999,999. If you use the B,1 format, you will be limited to octal PPNs update to 377,377. 

A-Shell Reference 

Page 2444 

## **GETJTB** 

## **xcall GETJTB, job-table-variable** 

There are innumerable subroutines which have been written in order to return the current PPN, terminal name, job name, and so on. Although many of the more common subroutines are implemented in A-Shell, it is clearly not possible to cater to all possibilities. A-Shell therefore also contains this subroutine, GETJTB and its counterpart SETJTB to return into a structure, everything that is likely to be needed from the job control block, within an application. 

The structure of the _job-table-variable_ is: 

```
MAP1 JOB'TABLE             ! 130+ byte area
```

```
MAP2 JOBNAM,s,6         ! Job name
```

```
MAP2 JOBNO,f,6          ! Entry in job table
```

```
MAP2 JOBDEV,s,5         ! Current device
```

```
MAP2 JOB'FIL1,x,1
```

```
MAP2 PPN                ! Current PPN
```

```
    MAP3 P,b,1          ! Project number
```

```
    MAP3 PN,b,1         ! Programmer number
```

```
MAP2 JOBPRV,f,6         ! Job privilege word
```

```
MAP2 JOBPRG,s,6         ! Current program name
```

```
MAP2 USRNAM,s,20,""     ! Current user name
```

```
MAP2 TRMNAM,s,6         ! Terminal name
```

```
MAP2 DRVNAM,s,6         ! Terminal driver name
MAP2 TRMBAUD,f,6        ! Terminal baud rate
```

```
MAP2 JOBDFP,x,6         ! Default file protection
```

A-Shell Reference 

Page 2445 

```
MAP2 JOBLVL,f,6         ! Class of user (level)
MAP2 JOBEXP,f,6         ! Experience of user
MAP2 SYSDOS,s,14        ! Operating system name
MAP2 JOBATT,s,6         ! Parent job name
MAP2 SYSVER,s,4         ! Operating sys. version (to 9.9N)
MAP2 JOBSTS,f,6         ! Job status word
MAP2 PRJ'STR,s,3        ! Project no. string
MAP2 PRG'STR,s,3        ! Programmer no. string
MAP2 JOBTYP,f,6         ! Job type
```

## **Comments** 

By calling GETJTB once at the start of each program, all the information likely to be required is readily available, without the need to call a hotchpotch of routines later on. 

The operating system field, _sysdos_ , contains the name of the host operating system on which A-Shell is running, for example **Windows/32** or **AIX** . If A-Shell is running in demonstration mode, then an asterisk is appended to the name, e.g. **AIX*** . 

The user name field, _usrnam_ , returns the current logon user name. 

The _jobnam_ parameter will be returned with the trailing spaces removed, but the program name ( _jobprg_ ) will be padded with trailing spaces to a length of 6. 

The _p_ and _pn_ fields, being only one byte each, are only capable of handling up to 377,377 (octal). Since A-Shell supports decimal PPNs update to 999,999, you should use the _prj’str_ and _prg’str_ fields instead. 

A-Shell Reference 

Page 2446 

## **GETMAC** 

## **xcall GETMAC, addr {,maxcount, adapters(1)}** 

GETMAC returns the hardware MAC ("Media Access Control") address of the Ethernet controller. Depending on how the _addr_ parameter is mapped, it either returns it as a set of six decimal numbers in an array, or as a string of the format xx:xx:xx:xx:xx:xx (where each ‘xx’ is a hex octet). Under Windows, it can also return a list of all the available adapters. 

## **Parameters** 

_addr_ [out] 

The returned MAC address, mapped either as: 

```
MAP1 ADDR
```

```
   MAP2 ADDRB(6),B,1
```

## Or 

```
MAP1 ADDR,S,18
```

In the first case, the MAC address is returned as a sequence of 6 decimal values, one byte each. In the second, it is returned as a string in the format "xx:xx:xx:xx:xx:xx" (where each 'xx' is a hex octet). 

_maxcount_ (optional, Windows only)  [in] 

This optional parameter may be used under Windows, in conjunction with the following _adapters_ parameter, to retrieve a list of all the available Ethernet adapters on the local PC. The value of _maxcount_ must be the same or less than the mapped size of the _adapters_ array and serves to set a limit on the number of adapters about which information will be returned. 

_adapters_ (optional, Windows only)  [out] 

If specified, this array will return details about all of the available adapters, and must be mapped as follows: 

```
map1 adapters(#)              ! # must be >= value of maxcount
```

A-Shell Reference 

Page 2447 

```
   map2 adap'mac(8),b,1       ! MAC address (decimal bytes)
   map2 adap'mac$,s,24        ! MAC address (hex format)
   map2 adap'name$,s,128      ! Adapter name
   map2 adap'descr$,s,128     ! Adapter description
   map2 adap'ip$,s,16         ! IP address
```

## **Comments** 

The main purpose of this subroutine would probably be as a security mechanism to prevent unauthorized use of an application, since every Ethernet controller ever produced has a unique MAC address, and there is no practical way to duplicate them. However, before you get too excited about this as a replacement for SSD chips, be aware that there are a number of potential or real pitfalls with MAC addresses: 

• A computer may have multiple Ethernet cards. Under Unix variants, GETMAC only returns the first one. Under Windows, the _addr_ parameter will return the one which appears to be the one currently connecting the PC to the network, but this determination can be confused, and it can obviously change over time. For example, a laptop user might connect with a wired adapter sometimes, and with a wireless adapter other times. 

- In the PC environment, an adapter could be portable (such as a PCMCIA or USB adapter). 

- With virtualization software (like VMware or Parallels), you might have virtualized adapters, in effect allowing two machines to 

- have the same MAC address. (Such adapters would most likely have the word "Virtual" in their description, so if this is a concern, you might want to check the descriptions via the _adapters_ list and disallow licensing to such a Virtual adapter. 

- Adapters that are disabled will not show up in the list. (So, for example, if you attach your license to a particular adapter, and 

- later the user disables it in favor of another adapter, you might have to re-license it.) 

Most of the potential problems listed above apply only to PCs (since a Unix server is unlikely to suffer from such changes to the adapter hardware list). One strategy for dealing with the variability of adapters on a PC would be to scan the list of available adapters in order to choose one (or two) that appear to be permanent (i.e. not virtual, not USB, etc.) for licensing purposes. At runtime, as long as it (or one of them) is present in the current list, you could be reasonably sure that the software hadn't been moved from the licensed machine. 

A-Shell Reference 

Page 2448 

Note that the first two fields of the _adapters_ array are mapped to accommodate up to eight bytes of MAC address, which is a nod to some future possibility not currently applicable. 

See CONDEV and MX_GETIP (Get IP address) for information on getting the IP address. 

A-Shell Reference 

Page 2449 

## **GETPRG** 

_Updated August 2017_ 

## **xcall GETPRG, prgnam {,sbxnam, svr'prgnam, svr'prgver, prgdir, sbxdir}** 

GETPRG returns the name and associated attributes for the current program and SBX routine, with some ATE client/server options. 

## **Parameters** 

|**Paramet**<br>**er**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|prgnam|String|out|Returns program name; no extension, stripping of trailing spaces|
|sbxnam|String|in/<br>out|If specified, it also returns the name of the current routine (if called from<br>within a subroutine). Otherwise, set to "".|
|svr'prgna<br>m|String|out|Applies only to subroutines running in the ATE client context (e.g. launched via<br>AG_XFUNC); it returns the name of the program currently running on the<br>server. Otherwise it will return a null string.|
|svr'prgver|String|out|Also only applies to the ATE client context, returning the version of the<br>program currently running on the server. Example format: 1.2A(345)|
|prgdir|String|out|Returns the device:[p,pn] where the program (prgnam) was loaded from.<br>Example format:  DSK22:[123,456]. If the program was loaded directly from<br>memory, it will return a null string.|



A-Shell Reference 

Page 2450 

|**Paramet**<br>**er**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|sbxdir|String|out|Same as prgdir, but for the last called SBX.|



A-Shell Reference 

Page 2451 

## **GETUSN** 

_Updated July 2013_ 

## **xcall GETUSN, usrnam$ {, machine$, ate'user$, ate'machine$, compname$, wts'session}** 

GETUSN returns the current user login name along with, optionally, the other variables listed in the syntax line and the table below. See OPTIONS=EFFUSR and CONDEV for related information. 

## **Parameters** 

|**Parameter**|**Type**|**I/O**|**Notes**|
|---|---|---|---|
|usrnam$|String|in/<br>out|The current user login name. If the user name has been overridden (viaMX_SETUSRNAM<br>or automatically by an ATSD server when accepting an ATE connection), then_usrnam$_<br>will return the over-ridden name. To force it to return the original name (either the server<br>login name or effective user name), set_usrnam$_to "!" before callingGETUSN.|
|machine$|String|out|The console device name.|
|ate'usrnam$|String|out|The login name of the ATE client.|
|ate'machine$|String|out|The machine name of the ATE client.|
|compname$|String|out|The Windows computer name of the client machine. In many cases this will be the same<br>as the_machine$_parameter, except it will be just the computer name without any<br>suffixes. It is mainly useful in cases where you are using the -awts command line switch<br>(or OPTIONS=NTTS) where the_machine$_parameter may have little relation to the actual<br>client computer name.|



A-Shell Reference 

Page 2452 

|**Parameter**|**Type**|**I/O**|**Notes**|
|---|---|---|---|
|wts'session|Num|out|The Windows Terminal Services client session ID, if applicable. Zero indicates the client is<br>not running a WTS connection. Note, however, that internally WTS numbers client<br>sessions from zero, so if you are using the value to reference registry or other information<br>tied to the session #, subtract one first.|



A-Shell Reference 

Page 2453 

## **GETVER** 

## **xcall GETVER, verstring** 

GETVER returns the version of the currently running program module, either RUN or LIT or SBX. 

## **Parameters** 

_verstring_ [out]  (String) 

should be 13+ characters to handle the longest possible version string. 

## **Example** 

Given the following PROGRAM statement: 

```
PROGRAM MYTEST,1.0A(234)
```

GETVER would return: 

```
1.0A(234)
```

## **Comments** 

If the program is currently executing an SBX, then GETVER will return the version of the SBX rather than the version of the main program. 

A module with no PROGRAM statement will return version "0.0(0)" 

The version string returned by GETVER is the same as that displayed by DIR/V and also the same as the value of the dot variable .PGMVERSION. 

To retrieve the version of a program module other than the one currently executing (i.e. like DIR/V does), see the function Fn'ProgVer$(fspec) in SOSLIB:[907,11]. 

## **See Also** 

A-Shell Reference 

Page 2454 

- VERSYS.LIT, which returns the versions of source modules embedded within a compiled program module. 

- MX_GETVERXS, which returns the A-Shell version. 

- MX_OSVERXS which returns the operating system version information 

- Fn'MinAshVer() in SOSLIB:[907,10] provides an easy way to check that A-Shell and/or ATE are at least a specified version. 

- Fn'FileVer$() in SOSLIB:[907,10] retrieves the version of a program file on disk. 

A-Shell Reference 

Page 2455 

## **GETX** 

_Reviewed April 2024_ 

## **xcall GETX, char** 

GETX inputs a single character from the keyboard, with function key translation support. The function key translation table will be any PFK loaded into user memory, or the LIB:<tdvnam>.IFX file. The routine will automatically set NOECHO mode (equivalent to `XCALL NOECHO` ) and leave the terminal in that mode. It will not display the input character. It is exactly equivalent to `XCALL ACCEPN, Char, "IFX"` . 

## **Parameters** 

_char_ (F6, B1, or S1)  [out] 

If _char_ is passed as a floating point, it will be returned with the ASCII value of the input character. Otherwise, for B1 and S1 parameters, the raw input character is returned. 

## **See Also** 

- ACCEPT, ACCEPNXS 

- GETXS  (keyboard or file input) 

- GETKEYXS 

- TINKEYXS 

A-Shell Reference 

Page 2456 

## **GRECNV** 

## **xcall GRECNV, dblock** 

GRECNV takes an input date and converts it to a variety of other formats (String, Gregorian, separated) with optional range and validity checking. The type of conversion is specified by the PCONC field. 

```
MAP1 DBLOCK
```

```
   MAP2 PSTR,S,12    ! MM/DD/YY or MM/DD/CCYY
```

```
   MAP2 PYEAR,B,2    ! Year in Century
   MAP2 PMON,B,1     ! Month
   MAP2 PDAY,B,1     ! Day
   MAP2 PCENT,B,2    ! Century
   MAP2 PBASE,B,4    ! New – Zero for Gregorian date
   MAP2 PJDAT,B,5    ! Gregorian form of the date
   MAP2 PCONC,S,1    ! Conversion request code
```

```
                     ! "D" = Start with string (PSTR)
```

```
                     ! "G" = Start with Gregorian (PJDAT)
```

```
                     ! "M" = Start with separated
                     (PYEAR,PMON,PDAY,PCENT)
```

```
                     ! "T" = Start with today
   MAP2 PVALD,S,1    ! To-Gregorian validity checking
```

```
                     ! "N" = Do not do reverse conversion check
```

```
   MAP2 PFRMT,S,1    ! Date format code
```

A-Shell Reference 

Page 2457 

```
                     ! "C" = MM-DD-YYYY (Yr+Cent*100)
                     ! "S" = MM-DD-YY-CCCC (Sep Century)
   MAP2 PCMPC,S,1    ! Completion code
                     ! "S" = Success
                     ! "R" = Success but out of range
                     ! "U" = Failure
   MAP2 PDOW,B,1     ! Day of week (0=Monday)
   MAP2 POLD,B,5     ! Oldest date within range
   MAP2 PRNGE,S,1    ! Range check code
                     ! "B" = Date must be BC
                     ! "A" = Date must be AD
                     ! "R" = Date must be within old/new range
   MAP2 PNEW,B,5     ! Newest date within range
   MAP2 PFIL,B,5     ! Not used
```

GRECNV was originally written for AMOS by Bob Strunk of Software Systems Consulting in Cincinnati, Ohio, and may be still available if you are looking for a date conversion routine that is available on both AMOS and A-Shell. 

A-Shell Reference 

Page 2458 

## **GTLANG** 

## **xcall GTLANG, status, gtlang'map** 

GTLANG retrieves information from the currently selected language definition file, such as the names of the days of the week, affirmative and negative abbreviations, currency symbol, etc. Using these variables instead of hard coding such information can go a long way towards making your application adaptable to other languages. 

The A-Shell extended form of the ASHINC:GTLANG.MAP file is supported in order to return the upper collating sequence. The sample program GTLANG in EXLIB:[908,49] is provided to illustrate. 

## **Parameters** 

_status_ (F,6) returns 0 for success or –1 for failure. 

## _gtlang'map_ 

The following table shows the variable names. 

|**Variable name**|**Type**|**Description**|
|---|---|---|
|LANG'NAME1, LANG'NAME2|S,20|Standard and alternate names for the language.|
|LANG'EXTENSION|S,4|is the extension used for message files associated with this language. For<br>example, the extension for theenglsh.ldf(Language Definition File) is USA,<br>which is why you will find message files with names likeerrmsg.usa,<br>sbrmsg.usa,litmsg.usa, etc.|
|LANG'CURRENCY'SYM|S,4|Currency symbol for this language.|
|LANG'CURRENCY'POS|F,6|Will be set to 0 if the symbol should appear before the currency amount, or|



A-Shell Reference 

Page 2459 

|**Variable name**|**Type**|**Description**|
|---|---|---|
|||1 if after.|
|LANG'CURRENCY'SPC|F,6|Specifies the "currency spacing" (whatever that is).|
|LANG'CURRENCY'SIZE|F,6|Specifies the number of digits making up the "currency amount" (whatever<br>that means).|
|LANG'THOUSANDS|S,1|Character to be used to separate thousands (i.e. to insert between every<br>three digits). In the USA we use a comma, while in much of Europe they use<br>the period, with the comma being used for the decimal point.|
|LANG'DECIMAL|S,1|Character to be used for the decimal point.|
|LANG'DATE'FORMAT|F,6|Date format: 0=month-day-year, 1=day-month-year, 2=year-month-date.|
|LANG'TIME'FORMAT|F,6|Time format: 0=12 hour, 1=24 hour.|
|LANG'DATE'SEP|S,1|Character used to separate the day, month, and year parts of a date, e.g.<br>"/" for MM/DD/YY.|
|LANG'TIME'SEP|S,1|Character used to separate the hours, minutes, and seconds in time<br>(typically ":").|
|LANG'DATA'SEP|S,1|Character used to separate elements of data.|



A-Shell Reference 

Page 2460 

|**Variable name**|**Type**|**Description**|
|---|---|---|
||||
|LANG'PPN'LEFT,<br>LANG'PPN'RIGHT|S,1|Characters used to enclose PPN, (e.g. [7,6]).|
|LANG'CHARSET|F,6|Character set number to be used. This is probably only relevant under<br>AMOS.|
|LANG'YES'WORD,<br>LANG'NO'WORD|S,6|Complete name of the affirmative word ("yes", "sí", "ouí", etc.) or negative<br>word ("no", "non", "nyet", etc.).|
|LANG'YES'CHAR,<br>LANG'NO'CHAR|S,1|Standard one-character abbreviation for yes'word and no'word.|
|LANG'WORD'CHARS|S,30|Contains all of the characters that can be considered part of a word in this<br>language. (For English, this is just A-Z and a-z, but other languages may<br>allow for accented or other special characters.)|
|LANG'ULC|S,30|May specify up to 15 pairs of upper and lower case letters that are to be<br>considered equivalent. The idea here is to identify how to fold accented and<br>other special characters to upper and lower case. (Not necessary for the<br>standard ASCII A-Z.)|
|LANG'SPARE|S,30|Reserved for something.|



A-Shell Reference 

Page 2461 

|**Variable name**|**Type**|**Description**|
|---|---|---|
|LANG'USR|S,30|Reserved for user-defined extensions to the language definition.|
|LANG'COL|X,12<br>8|May be used to specify the first 128 bytes of the collating sequence for this<br>language. It should consist of all the characters 0-127 in ascending sort<br>order. If you are using an 8 bit character set, then the upper 128 bytes may<br>be placed in_Col2_provided that the_Extend1_and_Extend2_fields are set<br>appropriately.|
|LANG'JAN <through><br>LANG'DEC|S,20|Full names of the twelve months of the year: Jan, Feb, Mar, Apr, May, Jun,<br>Jul, Aug, Sep, Oct, Nov, Dec|
|LANG'MON <through><br>LANG'SUN|S,20|Full names of the seven days of the week: Mon, Tue, Wed, Thu, Fri, Sat, Sun|
|LANG'EXTEND1,<br>LANG'EXTEND2|B,1|Set to 1 to indicate that the corresponding collating sequence field (_Col_and<br>_Col2_respectively) is valid.|
|LANG'COL2|X,12<br>8|Collating sequence for the second 128 bytes (128-255) of the character set.|
|**Definition file:**gtlang.map|||



## **See Also** 

• Language system parameter 

A-Shell Reference 

Page 2462 

A-Shell Reference 

Page 2463 

## **HASH** 

## **xcall HASH, hashtype, key, cbkey, hash, status** 

HASH generates a hash code from a string of characters. 

_hashtype_ specifies the type of hash to generate. Currently there are only two possibilities: 1=ELF, 2=DJB.  ELF is one of the most commonly used hash algorithms in the Unix world, and is tweaked for 32 bit processors. DJB (named after its creator Dan J. Bernstein) is thought to be one of the most efficient hash algorithms and is thought to work work well on very short keys, but may be considered somewhat weaker than the ELF algorithm (i.e. more likely to generate the same hash from different keys) when it comes to avalanche and permutation. 

## **See Also** 

- DIGESTXS 

## **Parameters** 

|**Parameter **|**Type**|**I/O**|**Description**|
|---|---|---|---|
|hashtype|Num|in|1=ELF, 2=DJB. See above|
|key|String|in|the source data from which the hash will be calculated. It can be any length.|
|cbkey|Num|in|optionally specifies the number of bytes to be considered in key. If 0, key is processed up<br>to the first null byte or its physical length.|
|hash|String|out|the generated hash. If string (8+ bytes), then it will be returned as 8 hex digits. If b,4, it<br>will be returned as a 32 bit value.|



A-Shell Reference 

Page 2464 

|**Parameter **|**Type**|**I/O**|**Description**|**Description**|
|---|---|---|---|---|
|status|Signed Num|out|indicates success or failure:||
||||>=0|success|
||||-1|bad key type|
||||-2|bad hash type|
||||-3|bad has data type of size|



A-Shell Reference 

Page 2465 

## **HOST2F** 

## **xcall HOST2F, alphaflt, hostflt** 

HOST2F converts an IEEE 4 byte (single precision) or 8 byte (double precision) floating point to the equivalent BASIC 6 byte format. Although this is done internally by A-Shell all the time, since it uses the IEEE format for internal calculations, the subroutine may be handy when importing data from outside sources. 

## **Parameters** 

## _alphaflt_ 

should be mapped as F,6 and will return the converted value. 

## _hostflt_ 

should be mapped as X,4 or X,8 depending on the size of the IEEE floating point value to be converted. 

## **Comments** 

See F2HOST for the reverse conversion. Also note that when importing data, if you have any control over the formatting of the import file, it will probably be much easier to use string CSV format. See the INPUT CSV for an easy way to import CSV data. 

A-Shell Reference 

Page 2466 

## **HOSTEX** 

_Updated December 2024; see History_ 

## **xcall HOSTEX, cmd {,status, stdout}** 

HOSTEX allows you to execute a host operating system command from within your BASIC program. 

_cmd_ (String)  [in] 

- valid command line for the current host operating system, with an optional suffix; see Command Modifiers and Launching A Shell with HOSTEX. 

_status_ (Signed Num)  [out] 

is an optional return variable. If specified, it will return the exit value of the command, if any. (Zero generally means success; anything else would be considered an error, but the interpretation of the error is dependent on the command executed.) 

## _stdout_ (String)  [out] 

an optional parameter, used only with Unix, that may be specified to receive the stdout of the specified command. For example: 

```
MAP1 STDOUT$,S,2048
```

```
MAP1 STS,F
```

```
xcall HOSTEX,"uname -a",STS,STDOUT
```

This would capture the output of the "uname -a" command into the variable STDOUT. 

It also works with multi-line output, e.g.: 

```
xcall HOSTEX,"ls -l",STS,STDOUT
```

A-Shell Reference 

Page 2467 

In this case, the individual lines of output will be delimited within the variable (STDOUT) using the standard Unix line delimiter (ASCII 10). 

Note that this technique is really only reliable with "regular commands", especially shell commands. If you execute an arbitrary executable, there is no telling whether it will generate stdout in a fashion compatible with this scheme. 

Note also that dynamic (variable-length) strings are not supported for this parameter. Any output that exceeds the physical length of the parameter will be discarded. 

Under Unix, a new process is forked to execute the command as a child process to the current process, but by default the child process uses the same screen console as the parent. If you do not want the output of the child process to disturb the current screen, you can redirect its output to a file (as in the example above). You may also want to redirect the _stderr_ channel to a file as well, as in this example which searches for the string "abcd" in all the .prt files in the current directory, writing its output and any error messages to grep.lst: 

```
xcall HOSTEX, "grep abcd *.prt > grep.lst 2>&1"
```

If you want to get the output of the executed command on the current screen, then beware that A-Shell will not know what has been displayed there, and thus the cursor will be out of sync with the display. One way around this is to redirect the output to a file, then read the file back in and use PRINT statements to output it in the context of A-Shell. For example, PWD.LIT uses this technique to print the current working directory: 

```
xcall HOSTEX, "pwd > pwd.lst"
```

```
Open #1, "pwd.lst", input
```

```
Input line #1, PLINE
```

```
Print PLINE
```

```
Close #1
```

Another technique which might be appropriate for some kinds of interactive commands would be to save the current screen, clear it, execute the new command, then restore the original screen, for example: 

A-Shell Reference 

Page 2468 

```
PRINT TAB(-1,202); TAB(-1,0);      ! save screen & clear it
```

```
xcall HOSTEX, CMD$
```

```
PRINT TAB(-1,0);TAB(-1,203);       ! clear and then restore it
```

For commands that generate simple teletype-style text output, the easiest and cleanest method for capturing the output is to use the stdout parameter which, when specified, automatically captures the stdout output into the specified variable. You can append the 2>&1 redirection modifier to the command to also redirect the _stderr_ output there as well. 

Under A-Shell/Windows, HOSTEX executes both Windows and certain DOS-legacy (also known as "console mode") commands (for which an EXE exists). This will create a new Windows process which will run in its own window without disturbing the current window, other than perhaps to cover it up. 

Note that for later versions of Windows, you can use the CMD.EXE (command executor) to execute any console commands, for example: 

```
xcall HOSTEX, "cmd.exe /c pwd > pwd.lst"
```

Use _cmd /?_ from the Windows command prompt to see all of the switches and options available. See the discussion "Executing - " - Windows command prompt commands on the A Shell forum for related information. 

Note that in the ATSD environment, you cannot launch a child session on the server unless it runs only in background—i.e. you must use the "&" Command Modifier. Even then, processes that require a Windows GUI context may fail to execute since ATSD is purely a background session (the GUI is on the ATE client side). In the ATE environment, regardless of the server operating system, you may choose to execute a command on the client computer via one of the following techniques: 

- AG_WINEXEC 

- MX_SHELLEX 

- Call SBX as a Function 

## **See Also** 

A-Shell Reference 

Page 2469 

- HOST.LIT 

- XSHLEX.SBX 

## **History** 

- 2024 December, A Shell 7.0.1766:  the -z switches (for invisible mode) are no longer passed through from the parent to the child if the parent has a GUI dialog present. GUI programs may launch with the -z switch to eliminate any visual trace of the text mode window, but that doesn't mean that they are running in invisible mode. Note that this behavior was changed in 1764.1 to match the longstanding documentation, which will now be corrected. 

## **Subtopics** 

- Command Modifiers 

- Launching A-Shell with HOSTEX 

A-Shell Reference 

Page 2470 

## **COMMAND MODIFIERS** 

_Modified March 2017; see History_ 

By default, the current program is suspended while waiting for the command to finish executing. In other words, the command is executed like it was a subroutine. However, this can be modified by appending a modifier to the end of the _cmd_ string, from the following table: 

|**Modifie**<br>**r**|**Function**|
|---|---|
|<none>|Current process is suspended while waiting for the command to complete|
|&|Command executes in background (or in the case of Windows, minimized) and in parallel with current<br>job. (Current job not suspended.)|
|%|(Windows only) Command executes in a minimized window, but current job is suspended while<br>waiting for it to complete. This is most useful for minimizing the screen flash which would otherwise<br>accompany a command that executed very quickly.|
|$|(Windows only) Command executes in a normal window, but current job is not suspended.|
|#|(Windows only) Similar to "$", except that it allows the child process to inherit the handles opened by<br>the parent. This is mainly only of interest for passing a socket opened by the parent to the child, so<br>that the parent can close it and accept another on the same port.|
|^|(Windows only) Allows for a slight variation in the Windows behavior that you otherwise would get<br>without specifying any suffix character. In both cases, the parent session waits for the child to exit,<br>but in the case of the "^" suffix, it does not try to get the focus back when the child returns, and it|



A-Shell Reference 

Page 2471 

|**Modifie**<br>**r**|**Function**|
|---|---|
||doesn't notify any sibling A-Shell sessions when the user transmits keystrokes or mouse events while<br>waiting that are ignored by the child while the parent is waiting.<br>This addresses an exotic situation with child processes that have no user interface support but which<br>take long enough that it becomes likely for the user to either switch to another session in the<br>meantime, or to try mouse or keyboard actions in the suspended parent session which then interfered<br>with a  sibling A-Shell session.|



The command modifier, if present, should be separated from the end of the cmd string by a space. For example, to launch the Windows calculator without suspending the current job, you would use: 

```
xcall HOSTEX,"CALC.EXE $"
```

## **History** 

- - 2017 March, A Shell A Shell 6.3.1545: added ^ switch 

A-Shell Reference 

Page 2472 

## **- LAUNCHING A SHELL WITH HOSTEX** 

_Updated August 2020; see History_ 

```
xcall HOSTEX,"$ASHELL –e run myprog &"
```

Since A-Shell is itself a valid host operating system command (e.g. "ashell" or "ashw32.exe"), you can use HOSTEX to launch another instance of A-Shell. To make this easier, HOSTEX replaces the symbol "$ASHELL" with a portion of the command line used to launch the current instance of A-Shell; this eliminates the problem of keeping track of how A-Shell was launched, which differs among platforms and installations. Specifically, $ASHELL will expand into the full path of the A-Shell executable, plus the -i <miame.ini> switch, plus the -g <icon> switch if applicable. In addition, the following switches are replicated from the parent to the child: 

- -cgi; see History below 

- -o <settings file> 

- -nm 

- -m, -mx, provided no -m or -mx is specified in subroutine command line 

- -z, -zt, -zi, provided no -z, -zt, or -zi is specified in subroutine command line 

For example, this command would work under either Windows or Unix, launching another instance of A-Shell using the same executable and miame.ini as the current session. The new session would run in background (or minimized under Windows) and would automatically terminate when "myprog" ended: 

```
xcall HOSTEX,"$ASHELL –e run myprog &"
```

Note that the -e switch is needed to cause the child session of A-Shell to terminate when the command (in this case, "run myprog") finishes executing. Otherwise the child session will remain active at the dot prompt until it is explicitly terminated with the HOST command. 

## **Notes** 

Under both Unix and Windows, spawning another copy of A-Shell will not count as another node against the node license. The license banner will be omitted from the spawned copy, but only if both the extension and the path are omitted from the 

A-Shell Reference 

Page 2473 

command line, as in the examples. In other words, the directory c:\vm\miame\bin or /vm/miame/bin must be in the environment **PATH** . 

If you want to launch a child copy of A-Shell in order to run another BASIC program or LIT commands, the preferred way to do this is with XCALL ASHELL, which acts as a front end to HOSTEX. 

Under Windows, it is possible to execute DOS (or "console) commands with HOSTEX, but only if an EXE for the command actually exists. For example, there is no copy.exe (use XCOPY instead). (The console command EXE files are usually stored in the /windows/command subdirectory.) You may also want to check out the Windows START command which is useful for executing other console commands and BAT files. (Type START /? from the command prompt for help.) 

## **History** 

- 2020 July, A Shell 6.5.1688: The $ASHELL macro now includes the -cgi switch if applicable, which allows CGI programs to use HOSTEX to launch subprograms. Note that this also affects ASHELL in situations where it is forced to launch a new session. 

- 2006 May, A Shell 4.9.956: Add ability to replicate switches from parent to child. 

A-Shell Reference 

Page 2474 

## **HTMLP** 

## **command = sbx:HTMLP** 

(Windows only) HTMLP.SBX is a print filter subroutine intended only for use in a COMMAND statement within a printer ini file. It creates a temporary copy of the specified print file with an HTML prefix and suffix, and then launches your local browser to view it. 

Source, samples and related functions can be found in SOSLIB:[907,29]. 

A-Shell Reference 

Page 2475 

## **HTTP** 

_Updated October 2022; see History_ 

HTTP handles various kinds of HTTP requests. See the subtopics listed at the bottom of this page for in-depth comments. 

## **xcall HTTP, opcode, status, flags, url, request, response {,properties, certpw}** 

_opcode_ (Num)  [in] 

1 (XHTTPOP_REQ) = general HTTP request. _Opcode_ must be set to "1" in all cases. 

_status_ (Signed Num)  [out] 

0 = ok (for simple functions) 

>0 = response code returned from HTTP server. It generally means that operation succeeded in communicating with the server. Whether that represents an unqualified success will depend on the application and the body of the response. Note that these HTTP response codes are standardized; detailed descriptions can be found by searching the Internet for "HTTP Response Codes". 

<0 = Operational errors; see ashinc:HTTP.DEF 

_flags_ (Num)  [in] 

sum of options flags. These flags are listed in ashinc:HTTP.DEF. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XHTTPF_SSL|&h00000001|Use a secure protocol (SSL/TLS) per preference of server. See<br>XHTTPF_SSL_xxx below to coerce a particular variation. Note: must be<br>set explicitly (not automatic from "https:" in url).|
|XHTTPF_REQPOST|&h00000002|Send the request as an HTTP POST transaction. Default headers will be|



A-Shell Reference 

Page 2476 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||automatically generated according to the request document (see_request_<br>parameter). Add XHTTFP_DEBUG to see the generated headers in<br>debug.req, and seeCustomizing POST headers<br> for customizing them. See<br>History note of April 2025.|
|XHTTPF_REQUPLOAD|&h00000004|Variation of an HTTP POST transaction used exclusively for uploading files<br>containing data (not to be confused with file-based requests). Requires<br>XHTTPF_FILEREQ. SeeCustomizing REQUPLOAD Headers<br>.|
|XHTTPF_REQHEAD|&h00000008|Makes the request a HEAD request. See History note of April 2025.|
|XHTTPF_REQXML|&h00000010|**Deprecated**. Use XHTTPF_REQPOST + XHTTPF_HDRBODY instead; see<br>Customizing POST headers<br>. Old description: Makes the request a POST<br>using text/xml content.|
|XHTTPF_REQGET|&h00000020|Simple GET (text of HTML page). Also see XHTTPF_REQGETX below.|
|XHTTPF_REQPUT|&h00000040|Simple PUT.|
|XHTTPF_DOWNLOAD|&h00000080|Download a file.|
|XHTTPF_FILEREQ|&h00000100|Request arg is a filespec (or list of) not a buffer.|
|XHTTPF_FILERESP|&h00000200|Response arg is a filespec not a buffer.|



A-Shell Reference 

Page 2477 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XHTTPF_DEBUG|&h00000400|Outputs copy of the generated request todebug.req; transcript of the<br>transmission and internal calls todebug.log; appends connection<br>summary toashnet.log.|
|XHTTPF_HDRBODY|&h00000800|Parse file into headers (added individually) and body. SeeCustomizing<br>POST headers<br>.|
|XHTTPF_PARMBODY|&h00001000|Like HDRBODY but use AddParam instead of AddHeader|
|XHTTPF_SETFROMURL|&h00002000|Extract path and form info from URL for use in the request header.<br>Typically not used with XHTTPF_REQPOST, since it will strip any ?<suffix><br>from the resulting POST header.|
|XHTTPF_FORCEXFR|&h00004000|File parms are server-relative; transfer to PC|
|XHTTPF_REQGETRAW|&h00008000|Like XHTTPF_REQGET (&h0020) but works around a limitation of<br>XHTTPF_REQGET in which certain characters outside the range supported<br>by Latin1/ANSI (e.g. Russian or Chinese) would just be dropped from the<br>response. Can also be used to retrieve binary data containing embedded<br>nulls (such as a file), although you must then use XHTTPF_FILERESP<br>(&h0200) to write the response to a file. Added inASHNET<br>1.4.132.|
|XHTTPF_SSL_TLS1|&h00010000|XHTTPF_SSL modifier: request TLS 1.0 or higher.|
|XHTTPF_SSL_SSL2|&h00020000|XHTTPF_SSL modifier: request SSL 2.0.|



A-Shell Reference 

Page 2478 

|**Symbol**|**Value**|**Description**|
|---|---|---|
||||
|XHTTPF_SSL_SSL3|&h00040000|XHTTPF_SSL modifier: request SSL 3.0.|
|XHTTPF_SSL_PCT1|&h00080000|XHTTPF_SSL modifier: request PCT 1.0.|
|XHTTPF_GETSTSTXT|&h00100000|Retrieve HTTP status text from last operation.|
|XHTTPF_SSL_TLS11|&h01000000|XHTTPF_SSL modifier: request TLS 1.1 or higher.|
|XHTTPF_SSL_TLS12|&h02000000|XHTTPF_SSL modifier: request TLS 1.2 or higher.|
|XHTTPF_REQGETX|&h01000000|Implements a more advanced version of the "GET" operation. The main<br>visible difference is that the returned reponse will be more detailed in the<br>case of a successful connection but a failed transaction, due to some kind<br>of logic or validation issue on the server. Also supportsCustomizing GET<br>Headers<br>.|
|XHTTPF_NOTLS13|&h04000000|Specifically disables TLS 1.3 negotiation, making 1.2 the highest TLS level<br>supported. This is a workaround for some exotic problems introduced in<br>some server versions of TLS 1.3.|



**Definition file:** http.def 

A-Shell Reference 

Page 2479 

_url_ (String)   [in] 

Fully qualified URL, with optional path and/or {:port}. URL maximum length is 1024. For example: 

```
"http://www.microsabio.net/dist/51dev/temphold/junk.zip"
```

```
"https://www.paypal.com"
```

```
"http://someserver.com:10080/some/path" (see History notes below)
```

## _request_ (String)   [in] 

Contains content of the request, for operations that require it, such as uploading files, POST, etc. Depending on XHTTPF_FILEREQ flag, may be a string buffer or a filespec (native or A-Shell, but see subtopic ATE). For the XHTTPF_REQUPLOAD option, can be a list of filespecs with semi-colon delimiters and an optional prefix indicating the content-type of the file and the "name" attribute to associate with it; see Customizing REQUPLOAD Headers. Note that some options only work with file mode, while some may only work with string mode. 

_response_ (String)   [in/out]  (If S,0, must be pre-initialized to desired maximum length) 

Returns the body of the response, or in the case of XHTTPF_GETSTSTXT, the HTTP status text from the _prior_ XCALL HTTP operation. If XHTTPF_FILERESP is set, then the passed-in value of _response_ is interpreted as a filespec (native) and the actual response is written to that file. Otherwise the response is returned in the specified parameter. Beginning with A-Shell 6.4.1555, _response_ accepts AMOS-style filespecs; see History note. 

## _properties_ (String)  [in] 

An optional list of name=value clauses delimited by semicolons, e.g.: name1=value;name2=value2,value3;...;nameN=valueN. See the following topic HTTP Properties Parameter for a table of _properties_ . Note: to maintain backwards compatibility with old and now deprecated _certfile_ parameter and syntax: if there is no "=" (equals sign) character in the string, it will be intepreted as the old _certfile_ spec. 

_certpw_ (String)  [in] 

A-Shell Reference 

Page 2480 

Optional password for the PFX file. See History note of 2022 October. 

Simple file download: here we download a JPG file from our public server, using XHTTPF_DOWNLOAD. 

```
++include ashinc:http.def
```

```
map1 params
map2 flags,b,4
```

```
map2 url$,s,100,"http://www.microsabio.net/dist/other/images/EditorShot.jpg"
```

```
map2 response$,s,20,"download.jpg"
map2 status,f
```

```
flags = XHTTPF_DOWNLOAD or XHTTPF_FILERESP
```

```
xcall HTTP, XHTTPOP_REQ, status, flags, url$, "", response$
```

```
? "status: ";status;
if status = 0 or status = 200 then
```

```
    ? "ok"
```

```
else
```

```
    ? "error - ";response$;" may contain details (as text)"
```

```
endif
```

A-Shell Reference 

Page 2481 

- Prior to ASHNET 1.4.131, the normal return code for this operation was 0, and errors would return -12. In ASHNET 1.4.131 

- and later, it returns HTTP status codes (200 for ok, most everything else would be an error.) 

- In the case of an error, the response file may contain details (in text) rather than the downloaded file. 

- For ATE compatibility, use XCALL ATHTTP instead of XCALL HTTP. ATHTTP also works with local Windows as a pass-through 

- to HTTP. 

- The function Fn'HttpGet() in SOSLIB:[907,10] can also download files, although it uses multiple XCALL TCPX operations to do 

- so. The approach shown here is somewhat more efficient when running under Windows, but less efficient under ATE (due to the need to transfer files back and forth between the ATE client and the server). 

- If the URL is https: (secure), simply add the XHTTPF_SSL flag. 

## **See Also** 

- EXLIB:[908,25] for several other examples. 

- Google Cloud Access Token 

## **History** 

- 2025 April, A Shell 7.0.1771, ASHNET 1.4.202:  XHTTPF_REQPOST can now be combined with XHTTPF_REQHEAD to retrieve both the headers and the body of the response together (separated by a blank line).. 

## - 2025 January, A Shell 7.0.1767, ASHNET 1.4.200: Add flag XHTTPF_NOTLS13. 

- 2022 October, A Shell 6.5.1721, ASHNET 1.4.186:  The _certpw_ parameter now supports all three of the encryption modes supported by MX_PWCRYPT. Previously it only recognized modes 1 and 2. Note that for mode 3, it assumes the default seed and key. 

- 2019 April, A Shell 6.5.1660, ASHNET 1.12.165: 

A-Shell Reference 

Page 2482 

• When the XHTTPF_REQGET call fails, it now returns an abbreviated status message in the response parameter instead of the full library debug string. In cases where the call succeeds in connecting to the endpoint, but the endpoint service then rejects the request, the response will be an HTTP header—e.g. "415 Unauthorized." In the case of a complete failure to connect, the response will be empty or "0". The status parameter will give additional information, as will a subsequent call using XHTTPF_GETSTSTXT. 

• A new opcode flag, XHTTPF_REQGETX (&h01000000) has been defined to implement a more advanced version of the "GET" operation. Currently the main visible difference is that the returned reponse will be more detailed in the case of a successful connection but a failed transaction, due to some kind of logic or validation issue on the server. The ashinc:HTTP.DEF file contains the updated symbol definition. 

• You can now include custom headers—using XHTTPF_HDRBODY—with the string request versions of the XHTTPF_REQPOST and XHTTPF_REQGETX operations. Previously this was only possible with XHTTPF_FILEREQ, file based requests. Format the request string the same way you would the file, i.e. with CRLF between each custom header, then a blank line (terminate by CRLF), then, in the case of _REQPOST, the body of the request. GET operations have no request body. 

- 2019 April, A Shell 6.5.1659, ASHNET 1.12.164:  Refinement to HTTP to allow custom headers to be added to a GET request (XHTTPF_REQGET). Previously this was only possible with the POST request type (XHTTPF_REQPOST / XHTTPF_REQUPLOAD). To specify custom headers, set the XHTTPF_HDRBODY flag and put the new headers into the request$ parameter, using chr(13) to separate multiple headers, e.g.: 

```
flags = XHTTPF_REQGET or XHTTPF_HDRBODY
```

```
request$ = "Referer: http://www.microsabio.com"
```

```
request$ += chr(13) + "User-Agent: A-Shell/ashnet-1.2.164"
...
xcall HTTP, 1, status, flags, url$, request$, response$, properties$
```

Note that you must specify at least 7 parameters—i.e., at least thru the properties$ parameter—even if the properties$ parameter is blank. Otherwise a more limited version of the routine will be used, which doesn't support this enhancement. 

You can also put the custom headers into a file, as you would with XHTTPF_REQPOST + XHTTPF_FILEREQ + XHTTPF_HDRBODY. 

A-Shell Reference 

Page 2483 

With the GET request, anything following the first blank line would be ignored. 

Note that to examine/debug your headers, set the XHTTPF_DEBUG flag and then look at the debug.log file on return from the subroutine. 

- 2018 May, A Shell 6.5.1636, ASHNET 1.11.162:  Several changes: 

- Support secure protocols TLS 1.1 and TLS 1.2 in HTTP via the new flags XHTTPF_SSL_TLS11 and XHTTPF_SSL_TLS12. 

- Append Connection Failure Codes to the XHTTPF_GETSTSTXT return string, as well as the ashnet.log, to assist with 

- debugging failed connections. 

- Remove 100 character limit on header lines included at the top of the request using XHTTPF_HDRBODY. Maximum length is 

- now unlimited, which is useful when headers include lengthy signatures or digests. 

- 2017 November, A Shell 6.4.1555:  the _request_ and _response_ parameters now accept AMOS-style filespecs. Previously they were assumed to be in native format, and didn't work properly otherwise. 

- 2017 February, A Shell 6.3.1544: HTTP now exposed to Linux via libashnet.so.1.9.157. Also, filespecs passed in the request and response parameters are now folded to lower case. The documentation has always noted that they are to be native filespecs, but since case doesn't matter in the Windows world, folding them to lower avoids a common mistake when porting a working application from Windows to Linux. 

## **Subtopics** 

- HTTP Properties Parameter 

- ATE 

- Customizing POST headers 

- Customizing GET Headers 

A-Shell Reference 

Page 2484 

- Customizing REQUPLOAD Headers 

- SOAP Example 

- Debugging HTTP.SBR 

- Retrieving HTTP status text 

- Connection Failure Codes 

- Other HTTP Verbs 

A-Shell Reference 

Page 2485 

## **HTTP PROPERTIES PARAMETER** 

The current list of property names and values is shown below. Note that the property names are case sensitive, but the values are not. For boolean values, anything starting with "T" or "1" is considered TRUE; everything else is considered false. Note the default values for the case where the property is not specified. 

|**Name = Value**|**Default**|**Description**|
|---|---|---|
|Cert=<fspec>|none|Specify cert file spec|
|AllowHeaderFolding|True|Disables MIME header folding|
|BasicAuth|False|Allows HTTP basic authentication; see Comments.|
|RequiresSslCertVerify|False|If true, verify server's SSL cert; if expired or invalid, abort connection.|
|SslAllowedCiphers|<all>|Specify comma-delimited list of allowed SSL/TLS ciphers; see Comments.|
|AutoAddHostHeader|False|If true, the "Host" header will be added to the request header for XHTTPF_REQGET|
|MimicFireFox|False|If true, headers are added to XHTTPF_REQGET calls to mimic those used by FireFox|
|MimicIE|False|If true, headers are added XHTTPF_REQGET to mimic those used by Internet Explorer|
|ReadTimeout|75|Time in seconds to wait while reading the response from the server before timing out.|



A-Shell Reference 

Page 2486 

|**Name = Value**|**Default**|**Description**|
|---|---|---|
|ConnectTimeout|30|Time in seconds to wait for the connection to be established before timing out|



## **Comments** 

If more than one Name=Value pair is specified, separate them with semi-colons, without any excess leading or trailing spaces. For example: 

```
properties = "AllowHeaderFolding=False;MimicFireFox=True;ConnectTimeout=60"
```

BasicAuth: Basic Authentication is one of many types of HTTP authentication, but it is often considered a security risk because the name and password are transmitted in plain text. For an SSL/TSL connection, this may be ok, but in any case, the default is set to False just to err on the safe side. 

SslAllowedCiphers: To limit SSL/TLS connections to a more specific set of possible ciphers, specify one or more of the following (comma-delimited). You may also use the special value "best-practices" to request "current best practices". Currently this means the following, but may evolve over time: 

- Any RSA keys must be 1024 bits or more 

- All renegotiations must be secure 

- All ciphers using RC4, DES or 3DES are disallowed 

## **Available ciphers** 

Note that in the following table, all items on a line have the same "root" and only the "suffix" varies. 

|TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA3<br>84|TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA3<br>84|TLS_ECDHE_RSA_WITH_AES_256_CBC_SH<br>A||
|---|---|---|---|



A-Shell Reference 

Page 2487 

|ell Reference||Page 2487|
|---|---|---|
|TLS_DHE_RSA_WITH_AES_256_CBC_SHA256|TLS_DHE_RSA_WITH_AES_256_GCM_SHA384|TLS_DHE_RSA_WITH_AES_256_CBC_SHA|
|TLS_RSA_WITH_AES_256_CBC_SHA256|TLS_RSA_WITH_AES_256_GCM_SHA384|TLS_RSA_WITH_AES_256_CBC_SHA|
|TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA2<br>56|TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA2<br>56|TLS_ECDHE_RSA_WITH_AES_128_CBC_SH<br>A|
|TLS_DHE_RSA_WITH_AES_128_CBC_SHA256|TLS_DHE_RSA_WITH_AES_128_GCM_SHA256|TLS_DHE_RSA_WITH_AES_128_CBC_SHA|
|TLS_RSA_WITH_AES_128_CBC_SHA256|TLS_RSA_WITH_AES_128_GCM_SHA256|TLS_RSA_WITH_AES_128_CBC_SHA|
|TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA|TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA|TLS_RSA_WITH_3DES_EDE_CBC_SHA|
|TLS_ECDHE_RSA_WITH_RC4_128_SHA|TLS_RSA_WITH_RC4_128_SHA|TLS_RSA_WITH_RC4_128_MD5|
|TLS_DHE_RSA_WITH_DES_CBC_SHA|TLS_RSA_WITH_DES_CBC_SHA||



## **History** 

- 2016 November, October, A Shell 1535:  Replaced old parameter _certfile_ with new parameter _properties_ and much expanded its usage. 

A-Shell Reference 

Page 2488 

## **ATE** 

_Revised January 2022_ 

In the ATE environment, the HTTP subroutine can be invoked from either the server or the client. The main reason for invoking it from the client is that the server may not have access to the HTTP subroutine; it requires a separate library, libashnet.so, which is not available under AIX. Another possible reason might have to do with complex heterogeneous network topologies, where only the client can 'see' the target web server. 

To invoke HTTP from the client, use the wrapper routine ATHTTP.SBX. It uses essentially the same calling format, limited however to the file mode operations, but handles the communication and data transfers between the server and the ATE client. Note that filenames in the _request_ and _response_ parameters here will be converted, if necessary, to server-relative native format. Only one filename may be specified in the _request_ parameter, and if using the content-type prefix, ATHTTP.SBX 1.0(102) or higher is required. . See the source code ATHTTP.BP in SOSLIB:[907,33] for further details, and the sample program HTTP1.BP in EXLIB:[908,25] for an example of calling it. 

A-Shell Reference 

Page 2489 

## **CUSTOMIZING POST HEADERS** 

By itself, the XHTTPF_REQPOST flag will generate a standard set of headers to accompany the specified request, e.g.: 

```
POST /my/web/service HTTP/1.1
```

```
Host: mydomain.com
Content-Type: text/plain; charset="ansi"
Content-Length: 84
```

```
<body of request here>
```

But let's suppose you don't like the auto-generated Content-Type, and want to add your own Authorization line. You can do this by modifying your request file (we're assuming XHTTPF_FILEREQ) to add the desired headers at top, separated from your request body by a blank line, and then add the XHTTPF_HDRBODY flag. (Note: this is a slightly different situation than the previous example using XHTTPF_REQUPLOAD; in that case the Content-Type and name header for the individually uploaded files could be addressed via special syntax in the _request_ parameter. In this case we are changing the main header for the entire request.) For example: 

```
Content-Type: application/json; charset=utf-8
```

```
Authorization: Basic YWdlYmFwaTpCN2VyQDhhYw==
```

```
<body of request here>
```

Submitting the above file, using XHTTPF_REQPOST + XHTTPF_HDRBODY + XHTTPF_FILEREQ would result in the auto-generated Content-Type line being changed to the one specified in our request file, and the Authorization line we specified being added, as follows: `POST /my/web/service HTTP/1.1` 

```
Host: mydomain.com
```

A-Shell Reference 

Page 2490 

```
Content-Type: application/json; charset="utf-8"
```

```
Authorization: Basic YWdlYmFwaTpCN2VyQDhhYw==
```

```
Content-Length: 84
```

```
<body of request here>
```

A-Shell Reference 

Page 2491 

## **CUSTOMIZING GET HEADERS** 

As with other request methods, the XHTTPF_REQGETX flag will generate a standard set of headers to accompany the GET request. For example, the URL 

```
https://www.googleapis.com/drive/v3/files?key=AIzaS9UiXD_1LX,Dn04MzjWR8yQ-Z HTTP/1.1
```

## might auto expand into the following: 

```
GET /drive/v3/files?key=AIzaS9UiXD_1LX,Dn04MzjWR8yQ-Z HTTP/1.1
```

```
Host: www.googleapis.com
```

```
Content-Type: application/x-www-form-urlencoded
```

But in some cases you need to either change one of the automatic headers or add your own. For example, Google API requests typically require an Authorization header containing your access token, and may require an Accept header to indicate the acceptable response format, e.g. 

```
GET /drive/v3/files?key=AIzaS9UiXD_1LX,Dn04MzjWR8yQ-Z HTTP/1.1
```

```
Host: www.googleapis.com
```

```
Accept: application/json
```

```
Content-Type: application/x-www-form-urlencoded
```

```
Authorization: Bearer xcl89SDFweln1890sdfa90s12435...
```

To achieve the desired headers, you can use the same technique described in Customizing POST headers. However, since most GET requests don't require a request body, it is probably more convenient to drop the XHTTPF_FILEREQ and just supply the headers as a string, e.g. 

```
url$ = "https://www.googleapis.com/drive/v3/files?key=" + apikey$ + " HTTP/1.1"
```

A-Shell Reference 

Page 2492 

```
flags = XHTTPF_REQGETX + XHTTPF_HDRBODY + XHTTPF_FILERESP + XHTTPF_SSL
```

```
request$ = "Authorization: Bearer " + access'token$ &
```

```
    + chr(13) + chr(10) + "Accept: application/json"
```

```
xcall HTTP, XHTTPOP_REQ, status, flags, url$, request$, response$
```

Note that you still need the XHTTPF_HDRBODY flag, but no XHTTPF_REQFILE. Just concatenate your desired headers with chr(13)+chr(10) between them. 

A-Shell Reference 

Page 2493 

## **CUSTOMIZING REQUPLOAD HEADERS** 

_Revised January 2022_ 

When using the XHTTPF_REQUPLOAD flag to upload files, the generated request will contain a header for each file, specifying a content-type and name attribute. For example, if request = "myfile.qry", the generated header will look something like: 

```
Content-Disposition: form-data; name="file"; filename="myfile.qry"
```

```
Content-Type: application/octet-stream
```

You can modify the default Content-Type and Content-Disposition headers by prepending a control sequence prefix to the front of each filespec in the list specified in the _request_ parameter. The format of the prefix is: 

```
Content-Type=<type>|<name>=
```

where `<type>` may be any content-type string, known or unknown, and `<name>` is the value of the "name" attribute to be associated with the file. For example: 

```
request$ = "Content-Type=text/html|homepage=c:\temp\mypage.txt"
```

In the above case, the header generated and sent to the web server would look something like: 

```
Content-Disposition: form-data; name="homepage"; filename="mypage.txt"
```

```
Content-Type: text/html
```

To upload multiple files in a single request, just separate them in the _request_ parameter string with semicolons. Any filename which does not start with the "Content-Type" prefix will be given the default treatment, with the Content-Type being set according to the file extension, and the name attribute set to "file" (,"file2", etc.) 

A-Shell Reference 

Page 2494 

## **SOAP EXAMPLE** 

_Added June 2013_ 

SOAP requests may be formed by combining an XML-format document (based on the requirements for the web service as defined in the WSDL for the service) with a set of HTTP binding headers. The technique is essentially the same as described in Customizing POST headers, except that the Content-Type may be different and typically you will be adding a SOAPAction header. The following is a an example of a real web service (as of June 2013) provided by WebserviceX.NET which returns details about airports based on the airport code. The format of the XML request document is as follows: 

```
<?xml version="1.0" encoding="utf-8"?>
```

" - " `<soap:Envelope xmlns:xsi=` http://www.w3.org/2001/XMLSchema instance 

`xmlns:xsd=` "http://www.w3.org/2001/XMLSchema" `xmlns:soap=` "http://schemas.xmlsoap.org/soap/envelope/" `>` 

```
  <soap:Body>
```

`<getAirportInformationByAirportCode xmlns=` "http://www.webserviceX.NET" `>` 

```
       <airportCode>$AIRPORTCODE$</airportCode>
```

```
    </getAirportInformationByAirportCode>
```

```
  </soap:Body>
```

```
</soap:Envelope>
```

To generate an actual request, we copy the above into a file, replacing the $AIRPORTCODE$ with the actual code (see CGIUTL for one technique to simply such replacements). In order to specify the desired Content-Type and the SOAPAction header, we insert it at the top of our file, followed by a blank line and then the XML request: 

## `Content-Type: text/xml; charset=utf-8` 

`SOAPAction:` "http://www.webserviceX.NET/getAirportInformationByAirportCode" 

A-Shell Reference 

Page 2495 

```
<xml doc here>
```

Assuming that our generated request file is called "airport.req", we can then call the web service as follows: 

```
flags = XHTTPF_REQPOST                               ! POST request (typical for SOAP)
```

```
flags = flags or XHTTPF_FILEREQ or XHTTPF_FILERESP   ! request and response are both filespecs
flags = flags or XHTTPF_HDRBODY                      ! request body contains header lines
```

`url =` "http://www.webserviceX.NET/airport.asmx" 

```
xcall HTTP, 1, status, flags, url, "airport.req", "airport.rsp"
```

To examine the final headers as sent to the service, add the XHTTPF_DEBUG flag and then check the resulting debug.req file, which should look something like: 

```
POST /airport.asmx HTTP/1.1
```

`Host:` www.webservicex.net 

```
Content-Type: text/xml; charset="utf-8"
```

`SOAPAction:` "http://www.webserviceX.NET/getAirportInformationByAirportCode" 

```
Content-Length: 418
```

```
<?xml version="1.0" encoding="utf-8"?>
```

" - " `<soap:Envelope xmlns:xsi=` http://www.w3.org/2001/XMLSchema instance `xmlns:xsd=` "http://www.w3.org/2001/XMLSchema" 

`xmlns:soap=` "http://schemas.xmlsoap.org/soap/envelope/" `>` 

A-Shell Reference 

Page 2496 

```
  <soap:Body>
```

`<getAirportInformationByAirportCode xmlns=` "http://www.webserviceX.NET" `>` 

```
      <airportCode>LAX</airportCode>
```

```
    </getAirportInformationByAirportCode>
```

```
  </soap:Body>
```

```
</soap:Envelope>
```

Note that the POST, Host:, and Content-Length headers are added automatically, but the Content-Type and SOAPAction headers are copied from the request file. 

The program AIRPORT in EXLIB:[908,25] demonstrates this service. 

A-Shell Reference 

Page 2497 

## **DEBUGGING HTTP.SBR** 

These kinds of web service transactions can be difficult to debug, because you are usually dealing with multiple layers of separation between your app and the web server that is generating cryptic errors over unidentified minutiae. Fortunately, these web service transactions can be reduced to simple streams of text. You send it some text and, assuming you can connect at all, it sends some text back. So debugging almost always starts with obtaining copies of the details of the request and response so that you can compare them to samples provided by the web service, or send to their tech support people to ask for guidance. 

To obtain this debugging information, set the XHTTPF_DEBUG flag, repeat your request, and then examine the following files: 

- debug.req - a copy of the full request, including the generated headers 

- ashnet.log - summary details about the connection, port, protocol, and return status will be appended here 

- <response file> - assuming you get a response, and have the XHTTPF_FILERESP flag set, the response will be in the file specified 

- by the _response_ parameter. 

- debug.le - for lower level failures (like a failure to connect at all), details possibly of interest to MicroSabio will be written here 

- debug.log - contains internal details of the operation, plus a transcript of what was sent and received over the wire. 

Often you will find that there are differences between the generated headers of your request and those provided in the web service's specifications or samples, in which case you will need to determine whether they are significant, and if so, how to achieve the necessary changes. In some cases of POST transactions, you will be able to use the technique described above (Customizing POST headers). In other cases, you may want to tinker with some of the flags, such as adding XHTTPF_SETFROMURL changing between XHTTPF_REQUPLOAD and XHTTPF_REQPOST, to see what effect it has on the generated request. If you know what the request should look like, but don't know how to generate it, please contact us with the above details. 

An all-too-common scenario is that the web service has cryptic specifications, no sample request documents to model your request on, and the tech support people point you to some utility, tool or web page that works, for you to use as a model. Unless the tool provides a copy of the request text that it generates, and assuming you can run the test in plain HTTP (not HTTPS) you can use a packet sniffing tool, such as WireShark, to capture the raw message and then use it as your model. If the target service uses a secure port, that technique won't help you, but you may want to inquire whether they have a parallel non-secure sample or test version of the service which you can use to debug the basic request format. 

A-Shell Reference 

Page 2498 

## **History** 

- 2018 May, A Shell 6.4.1555, ASHNET 1.11.162:  Append Connection Failure Codes to the XHTTPF_GETSTSTXT return string, as well as the ashnet.log, to assist with debugging failed connections 

A-Shell Reference 

Page 2499 

## **RETRIEVING HTTP STATUS TEXT** 

In cases where the routine succeeds in connecting to the server, the _status_ parameter will return the numeric HTTP status code, which is generally sufficient, along with the body of the response, to determine if the operation was a logical success. In some cases however, the HTTP status code may be ambiguous, and the server may augment it with a non-obvious text message returned on the HTTP status line (rather than something more formal/detailed returned as the body of the response). You can retrieve that status string by making a second XCALL HTTP call following the initial one. The example below illustrates a case where upon receiving status 400 (bad request), we retrieve the HTTP status string, which hopefully contains some further detail helping clarify what is bad about the request, such as "unrecognized part number format:" 

```
xcall HTTP, 1, status, flags, url$, request$, response$
```

```
if status = 400 then
    xcall HTTP, 1, status, XHTTPF_GETSTSTXT, "", "", status'text$
```

```
endif
```

Note that the HTTP status text may also be found at the end of the ashnet.log entry if the XHTTPF_DEBUG flag is set. 

## **History** 

- 2018 May, A Shell 6.4.1555, ASHNET 1.11.162:  Append Connection Failure Codes to the XHTTPF_GETSTSTXT return string, as well as the ashnet.log file to assist with debugging failed connections 

A-Shell Reference 

Page 2500 

## **CONNECTION FAILURE CODES** 

## _Written May 2018_ 

To help with debugging failed connections, a connection failure code from the following table is included in the status text (XHTTPF_GETSTSTXT) and ashnet.log file messages: 

|**Code**|**Meaning / Description**|
|---|---|
|0|Sucess|
||**Non-secure Connections**|
|1|empty hostname|
|2|DNS lookup failed|
|3|DNS timeout|
|4|Aborted by application.|
|5|Internal failure.|
|6|Connect Timed Out|
|7|Connect Rejected (or failed for some other reason)|



A-Shell Reference 

Page 2501 

|**Code**|**Meaning / Description**|
|---|---|
|50|HTTP proxy authentication failure.|
|98|Async operation in progress.|
|99|Product is not unlocked.|
||**Secure Connections (SSL/TLS)**|
|100|TLS internal error.|
|101|Failed to send client hello.|
|102|Unexpected handshake message.|
|103|Failed to read server hello.|
|104|No server certificate.|
|105|Unexpected TLS protocol version.|
|106|Server certificate verify failed (the server certificate is<br>expired or the cert's signature verification failed).|



A-Shell Reference 

Page 2502 

|**Code**|**Meaning / Description**|
|---|---|
|107|Unacceptable TLS protocol version.|
|109|Failed to read handshake messages.|
|110|Failed to send client certificate handshake message.|
|111|Failed to send client key exchange handshake message.|
|112|Client certificate's private key not accessible.|
|113|Failed to send client cert verify handshake message.|
|114|Failed to send change cipher spec handshake message.|
|115|Failed to send finished handshake message.|
|116|Server's Finished message is invalid.|



## **History** 

- 2018 May, A Shell 6.4.1555, ASHNET 1.11.162:  Append Connection Failure Codes to the XHTTPF_GETSTSTXT return string, as well as to ashnet.log, to assist with debugging failed connections 

A-Shell Reference 

Page 2503 

## **OTHER HTTP VERBS** 

_Added November 20242_ 

To create an HTTP request using a method not explicitly supported by the XHTTPF_xxx flags, you can add a special custom header "Verb: xxxxxx", where xxxxxx is any valid HTTP verb, e.g. "Verb: PATCH", to replace the HTTP method. 

Building on the example in Customizing POST headers, if you insert the "Verb: PATCH" header into the request, e.g. 

```
Content-Type: application/json; charset=utf-8
```

```
Authorization: Basic YWdlYmFwaTpCN2VyQDhhYw==
```

```
Verb: PATCH
```

```
<body of request here>
```

... and submit it using XHTTPF_REQPOST + XHTTPF_HDRBODY + XHTTPF_FILEREQ, the resulting request will start with the PATCH method/verb instead of POST, e.g. 

```
PATCH /my/web/service HTTP/1.1
```

```
Host: mydomain.com
```

```
Content-Type: application/json; charset="utf-8"
```

```
Authorization: Basic YWdlYmFwaTpCN2VyQDhhYw==
```

```
Content-Length: 84
```

```
<body of request here>
```

A-Shell Reference 

Page 2504 

Note that the only effect of the Verb: PATCH header was to replace the first token in the raw request above (previously POST) with the new verb PATCH. 

This works with both HTTPF_REQPOST and HTTPF_REQGETX flags; in either case XHTTPF_HDRBODY is required. 

## **History** 

2022 June, Ashnet 1.14.182  Support for the Verb: xxxxxx custom header added. Note that the code implementing this is entirely within the Ashnet library, which can be updated independently of the A-Shell executable. 

A-Shell Reference 

Page 2505 

## **IDTIM** 

## **xcall IDTIM, stringfmt, idate, itime, flags, status** 

IDTIM converts a string format date and/or time into so called internal format. (Internal format dates are also referred to as separated format, and is the format returned by the DATE system function. Internal format time is simply the number of seconds since midnight.) The inverse function is ODTIM, which converts an internal format date and/or time to a string format. 

## **Parameters** 

## _stringfmt_ 

should be set to the date and/or time be converted, with the time following the date (with a space separator) if both date and time are included. (Also see _flags_ parameter, which indicates if date and/or time are present.) The date, if present, should be in `MM-DD-{CC}YY` or `DD-MM-{CC}YY` format, depending on your language definition file specification for date order. The separator character, however, need not be a dash or even match the language definition file; it can be any non-numeric character. The time format is `HH:MM{:SS} {AM/PM}` . Legal examples would be: 

```
12/30/24 13:01
```

```
01-01-2024 10:15:33 PM
```

```
23:01:10
```

```
05.03.1915
```

If only two digits are specified for the year, it is assumed to be in the twentieth century (19xx) unless the SBR=CCYY statement is included in miame.ini, in which case it will determine the YY cutoff below which we assume 20xx instead of 19xx. 

## _idate_ (F,6) 

will return the internal format date, or zero if the date is not included in the input string. Note, however, that to access the individual separated fields within it, you need to assign the F,6 value to a B,4 which is mapped on top of the separated date structure, as in the following example: 

A-Shell Reference 

Page 2506 

```
MAP1 Sepdate
```

```
   MAP2 Mon,B,1              ! Month 1-12
   MAP2 Day,B,1              ! Day 1-31
   MAP2 Yr,B,1               ! Year-1900
   MAP2 Dow,B,1              ! Day of week (0=Mon, 6=Sun)
MAP1   Bdate,B,4,@Sepdate    ! B,4 version of Sepdate, as used by
                             !  the DATE system function
MAP1   Idate,F,6             ! F,6 version as needed by IDTIM
```

```
xcall IDTIM, StringFmt, Idate, Itime, Flags, Status
```

```
Bdate = Idate
```

```
Print "Separated date: ";Mon;Day;Yr;Dow
```

```
Bdate = DATE                 ! Get today's date (for comparison)
```

```
Print "Today's separated date: ";Mon;Day;Yr;Dow
```

## _itime_ (F,6) 

will return the internal format time (i.e. seconds since midnight) or zero if the time is not present. 

## _flags_ (Num) 

should be set to 0 to process both the date and time; 1 if the string is expected to contain only the time, and 2 if it is expected to contain only the date. 

_status_ (F,6) 

A-Shell Reference 

Page 2507 

will return a code of 0 to indicate a successful conversion, or –1 to indicate an error (such as an invalid format or invalid date). 

A-Shell Reference 

Page 2508 

## **INCOM** 

## **xcall INCOM, name, packet, opcode, stpos, length, status** 

INCOM is a variation of COMMON, allowing you to read and write a packet of information in memory, generally for the purpose of passing information between programs run in sequence on one job. 

## **Parameters** 

_name_ (String ,10) 

name.ext of module. Note that only the first six characters will be used. 

_packet_ (Any type, 1 to 1024 bytes) 

Packet to read or write. You must use the SBR=MSGSIZ:# setting in miame.ini to set the necessary maximum packet length if your _packet_ variable will be longer than the default 150 bytes. 

_opcode_ (Num)  [in] 

0 to read, 1 to write 

_stpos_ (Num)  [in] 

position of first byte in _packet_ . 

_length_ (Num)  [in] 

number of bytes to read or write 

_status_ [out] 

1 for success, otherwise 0 

## **Comments** 

The old AMOS version of this routine used a memory module that was loaded into system or user memory. The A-Shell version, on the other hand, actually uses COMMON, which has been enhanced in A-Shell to support many variations, and thus there does 

A-Shell Reference 

Page 2509 

not need to be an associated file on disk or even a memory module. The _name_ parameter, however, is needed to identify the packet within COMMON, but any extension will be ignored. 

The main differences between INCOM and COMMON are that INCOM allows you to read/write an arbitrary subset of the packet (rather than the whole packet) and that the INCOM read operation is always non-destructive (whereas COMMON’s read is normally destructive but can be overridden by the SBR=COMMONNDR setting in miame.ini). 

A-Shell Reference 

Page 2510 

## **INFLD** 

INFLD is a powerful and flexible field-level input and display routine, operating in both text and GUI modes. In GUI mode, it takes on the form of a edit control, combo box, date/time picker, or up/down (spinner) control, depending on the parameter options. INFLD's GUI mode is generally application-compatible with text mode, but of course requires either A-Shell/Windows or ATE. INFLD is also used internally to implement the A-Shell command prompt, VUE and EZTYP command lines, INMEMO, and several other subroutines involving keyboard input. 

See the subtopics listed below for more information. 

## **See Also** 

- SBXINP, a higher level variation of INFLD 

## **Historical Note** 

Originally developed as an upward-compatible replacement for the AlphaACCOUNTING subroutine INFLD.SBR, INFLD was sold and widely used as a standalone tool by developers in the AMOS operating system environment in the 1980s and 90s. 

## **Subtopics** 

- INFLD Parameters 

- INFLD External Parameters 

- INFLD Miscellaneous Topics 

A-Shell Reference 

Page 2511 

## **INFLD PARAMETERS** 

## **xcall INFLD, row, col, xmax, xmin, type, entry, inxctl, parentid, opcode, exitcode, timer, cmdflg, defpt, maxpt, funmap, setdef, infclr, hlpidx, maxchrs** 

## **Parameters** 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|row|Int|in|Row for input|
|col|Int|in|Starting column.|
|xmax|®|in|(Int<br>or ST_INFXMAX structure) Maximum size (width; seemaxchrs<br>).|
|xmin|Num|in|Minimum number of characters to accept. Note that if the<br>**O**(optional)_type_code is<br>used, the minimum is only in effect if at least one printable character is entered.|
|type|String|in|Codes specifying types, formats, etc.|
|entry|String|in/out|String field contents sent and returned in|
|inxctl|(Int<br>or S,1)|out|Special exit codes compatibile withINPUT.|
|**Parameters above are required; those below are optional.**||||



A-Shell Reference 

Page 2512 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|parentid|®|in|(<br>String or Num) If zero, multiplies (row) by two|
|opcode|Int|in|Used to specify pre-load, output, other options|
|exitcode|SignedInt|out|Extended exit codes (how field exited)|
|timer|Int|in/out|Used to specify time-out duration|
|cmdflg|Int|in|Controls whether command file input allowed|
|defpt|SignedInt|in|Specifies default decimal point|
|maxpt|SignedInt|in|Specifies maximum digits to right of decimal|
|funmap|Bitmap 32|in|Controls interpretation of function keys|
|setdef|String or<br>Ordmap|in|Defines list or set of allowable inputs|
|infclr|®|in|ST_INFCLR or ST_INFCLRX or literal 0|
|hlpidx|String|in|Various expansion features|



A-Shell Reference 

Page 2513 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|maxchrs|Int|in|Maximum number of characters allowed (independent of_xmax_)|



A-Shell Reference 

Page 2514 

## **ROW** 

_Updated July 2024_ 

_row_ specifies the starting row of  the  field . Note that if the _parentid_ is missing or is numeric and evaluates to 0, the _row_ is multiplied by 2. (Historians differ on the exact origin of this unusual feature, but we believe it arose during the epochal moment when display terminals suddenly increased from 12 to 24 display lines.) 

You can also specify _row_ relative to the bottom of the screen (determined dynamically from the terminal driver at runtime) by using a negative number: -1 = the bottom row, -3 = third row up from the bottom, etc. 

If you set both _row_ and _col_ to zero, INFLD will operate in position-relative mode, starting from where the cursor was when you called INFLD. (This is similar to how BASIC INPUT works.) 

If _row_ >= 200, it is interpreted as Millirows , which see for more information. 

If the IMXF_PIXCOORDS flag is set (see _xmax_ ), then _row_ , _col_ and _xmax_ are interpreted as pixels. 

A-Shell Reference 

Page 2515 

## **COL** 

_col_ specifies the starting column of the field. 

Right justified fields will be re-displayed so that they align in the rightmost column (as determined by _col_ and _xmax_ ). 

If _col_ >= 200, it is interpreted as Millicolumns, which see for more information. 

If the IMXF_PIXCOORDS flag is set (see _xmax_ ), then _row_ , _col_ and _xmax_ are interpreted as pixels. 

A-Shell Reference 

Page 2516 

## **XMAX** 

_xmax_ specifies the editing (or display) width of the field. Unless _maxchrs_ is set to another non-zero value, _xmax_ is also equivalent to the maximum number of characters which can be entered. Additional GUI-related attributes may be specified via the ST_INFXMAX structure; see below. 

In text mode (with a non-GUI-enabled terminal emulation), the field width will be indicated by marker characters (typically underlines, unless _type_ **|p** or _type_ **i** or _type_ **I** is specified). In text mode with a GUI enabled emulation (i.e. PCTDVG, AM76G or AM62CG), a pseudo-Windows-style sunken panel is used. (This may be hard to see unless the background color is pastel or gray; if not, you may want to force the use of underlines with _type_ **|_** .) 

In full GUI mode (GUI-enabled driver, _type_ **|G** ), the field size will be indicated by the size of the Windows control (edit box, combo box, checkbox, radio button, time/date, up/down) used. The overall width of the control, however, may be somewhat larger than the number of grid width units specified, in order to allow for parts of the control outside of the input area (like dropdown buttons), or, when _xmax_ is very small, to allow for the fact that upper case GUI characters may be wider than their text equivalents. See _type_ **||]** to disable this auto-expansion feature. 

## **ST_INFXMAX** 

The ST_INFXMAX structure may be used in place of _xmax_ to specify additional GUI-related attributes not previously available via the INFLD interface but otherwise available with AUI_CONTROL. 

## `defstruct ST_INFXMAX` 

```
    map2 erow,b,4           ! rows, millirows or pixels
```

```
    map2 ecol,b,4           ! columns, millicolumns, or pixels
```

```
    map2 flags,b,4          ! see IMXF_xxx below
```

```
    map2 fontattr,b,4       ! same as in AUI_CONTROL
```

```
    map2 fontscale,b,4      ! " "   "
    map2 fontface,s,32      ! " "   "
```

```
endstruct
```

A-Shell Reference 

Page 2517 

```
define IMXF_FNTPTSIZE  = &h00000001    ! fontscale is in points*10
define IMXF_PIXCOORDS  = &h00000002    ! all coordinates in pixels [101]
define IMXF_XMAXONLY   = &h40000000    ! erow=xmax; all other fields ignored
```

## A structure definition include file, ASHINC:INFLD.SDF defines the ST_INFXMAX structure. 

## **Notes** 

- Minus signs in numeric fields do not count against the maximum number of characters. 

- The specified _xmax_ value may be trimmed by INFLD to be no greater than the physical size of the entry parameter. One 

- situation where this can be unexpected is when using Coded Lists. 

- When using pixel coordinates, INFLD checks that _maxchrs_ <> 0, since otherwise there is no way to determine the character 

- limits on the field size. If 0, it displays a warning message and sets it to 132. 

## **History** 

- 2012 June, A Shell 6.1.1312:  ST_INFXMAX structure added 

A-Shell Reference 

Page 2518 

## **TYPE** 

_type_ is a string containing a sensible combination of the codes listed in the following sections. Note the following: 

- Case is significant. 

- The codes are generally additive, and you can use as many as you want. For example, specifying both the codes for 

- alphabetic and numeric types will result in an alphanumeric field. 

- The codes many be either single-character codes, or double or even triple character codes. All of the double-character codes 

- begin with the lead-in character | (vertical bar.) All of the triple character codes begin with a pair of vertical bars. 

The codes are organized into the categories shown in the following topics. The final topic in this section, Type Codes Summary, shows all of the _type_ codes in a single table. 

Note that in addition to the _type_ parameter, INFLD also adds any default type codes set via the system parameter (miame.ini) SBR=INFDEF directive or via the SET INFDEF command. Use CTRL+V while editing a field to see the complete list of type codes active for that field. 

## **Subtopics** 

- Character Type Acceptance 

- Numeric Formatting Codes 

- Date/Time-Related Codes 

- LDF-Related Codes 

- Timer-Related Codes 

- GUI-Related Codes 

- Miscellaneous Codes 

- Exit Key Enabling Codes 

A-Shell Reference 

Page 2519 

- Type Codes Summary 

A-Shell Reference 

Page 2520 

## **CHARACTER TYPE ACCEPTANCE** 

You must have at least one of these. Note that a blank in the first character position of _type_ is treated like an **A** to maintain compatibility with an AlphaAccounting quirk. 

|**Valu**<br>**e**|**Description**|
|---|---|
|#|(number sign) Numeric (0-9). If nothing entered, displays a "0" (but returns just a blank<br>string.) Also see<br>**N**.|
|$|(dollar sign) Currency Field.|
|*|(asterisk) Accept all characters. Same as<br>**A**.|
|,|(comma) Punctuation allowed. Punctuation is anything other than a number or letter.|
|@|(at sign) Control Character Input.|
|{|(open brace) Character acceptance is limited to the set of characters specified in setdef.<br>Typically you would combine this with<br>*****, else the characters may be rejected before<br>even considering the setdef list.|
|a|Alphabetic characters allowed (a-z, A-Z), or as defined by the LDF (language definition<br>file).|
|A|All characters allowed (subject to code b). Note that<br>**A**is used for compatibility with<br>INPUT, but to most people,<br>*****makes more sense. Note that<br>**A**or<br>*****is equivalent to the|



A-Shell Reference 

Page 2521 

||combination<br>**a#**, (alphabetic, numeric, and punctuation).|
|---|---|
|C|CARRIAGE RETURNonly.|
|d|Date Input, Today.|
|D|Date Input.|
|H|Hours field. Like<br>**$**but omits the $ from the display.|
|||h|Accept hexadecimal digits (A-F, a-f, 0-9).|
|J|Accepts alphanumeric input, and if the input is wholly numeric, right justifies and fills<br>with leading zeroes.|
|N|No/Yes Field.|
|P|Phone Number Or Zip Code Input.|
|t|Time Field.|
|U|European Date.|
|X|Specifies a Y/N field, but with no default. May be used to force the operator to make a|



A-Shell Reference 

Page 2522 

||choice, or, with_xmin_=0, to allow a third option (blank).|
|---|---|
|Y|Yes/No Field.|



A-Shell Reference 

Page 2523 

## **NUMERIC FORMATTING CODES** 

Except for **-** (hyphen) and **.** (period), the formatting and miscellaneous codes do not affect the characters which can be entered; rather, they only affect the way the characters are formatted. Note that unless otherwise indicated, formatting codes only affect the way a field is displayed on the screen and not how it is returned to the calling program. 

|**Valu**<br>**e**|**Description**|
|---|---|
||#|(bar hash) Disables the automatic display of "0" in a numeric field when nothing entered.|
|-|(hyphen)Allow Minus Sign<br>.|
|.|(period)Allow Decimal Point<br>.|
|$|(dollar sign) Currency field.|
|G|May be useful for aligning decimal points in column of variable precision numbers.|
|H|Hours field. Like $ but omits the "$" from the display.|
|M|Thousands Separator<br>.|
|R|Right Justify Field<br>.|
|u|LDF-Related Codes<br>.|



A-Shell Reference 

Page 2524 

|v|Value Range Checking<br>.|
|---|---|
|Z|Zero Fill<br>.|



Additional details below. 

## **Allow Minus Sign** 

[ _Type_ code = **-** (hyphen / minus sign)] May be typed anywhere in the field, but is always displayed (during entry) to the left of the field. On exit, it is redisplayed as a trailing minus sign (for codes **$, H, M** ), and relocated to the beginning for the returned variable. For example, if "1234-" is entered, it will be redisplayed as "12.34-" (assuming decimal points are not allowed) and returned to the calling program as "-1234." 

## **Allow Decimal Point** 

[ _Type_ code = **.** (period)] If used with types **$** or **H** and the decimal point is not entered, places the decimal point to right of last digit entered. For example, if "1234" is entered, it will be redisplayed as "1,234.00". Note that this code affects the action of the opcode parameter. When decimal points are allowed, default decimal points are inserted as actual characters into the returned field. If decimal points are not allowed, default decimal points are inserted in the display but not returned. 

Note: prior to A-Shell version 5.1.1199, INFLD always used the **.** (period) character for the decimal point, regardless of the LDF (Language Definition File). As of 5.1.1199, you can add the _type_ code **u** to force it to use the decimal point character specified in the LDF. Note that even in the latter case, it will accept a period from  the keyboard as equivalent to the defined decimal point character. 

## **See Also** 

- defpt, to set the position of a default decimal point. 

A-Shell Reference 

Page 2525 

- maxpt, to limit the number of digits past the decimal point. 

## **Thousands Separator** 

[ _Type_ code = **M** ] Triggers a numeric thousands separator between every 3 digits to the left of the decimal point in the final redisplay of the field. The actual character used is defined in the language definition table (comma for the USA table). (This is automatic for **$** and **H** fields.) 

## **Right Justify Field** 

[ _Type_ code = **R** ] Note that unlike most formatting codes, right justify (and zero fill) actually affect the way the field is returned as well as the way it is displayed. Additionally, whenever you preload a field using the **R** or **Z** codes, INFLD will automatically strip the leading fill characters prior to the initial display to simply editing. 

## **Value Range Checking** 

[ _Type_ code = **v** ] setdef parameter must be loaded with a string of the format ",min,max,," where _min_ is the minimum acceptable value and _max_ is the maximum acceptable value. See setdef for more info on proper formatting of range strings. Note that you will probably want to use code **s** along with **v** to stifle the "Choices:" message which otherwise appears on the bottom line when setdef is non null. 

## **Zero Fill** 

[ _Type_ code = **Z** ] Enough leading zeroes will be added to fill the field to the _xmax_ size. Note that unlike most INFLD formatting options, the leading zeroes are actually returned in the field. On preloading a **Z** field, the leading zeroes are removed prior to editing, except that if the field is blank, one zero is left. 

## **History** 

A-Shell Reference 

Page 2526 

- 2011 January, A Shell 5.1.1200: INFLD refinement: When using _type_ **Z** (zero fill), leading zeroes are no longer stripped on entering the field for date fields or form fields. Stripping the leading zeroes in such cases may mess up the alignment of the form or the interpretation of the individual digits in the date. 

A-Shell Reference 

Page 2527 

## **- DATE/TIME RELATED CODES** 

The following table shows the codes related to date and time fields. Note that determination of whether a date field will return the full century (CCYY), rather than just the year (YY), is determined by the larger of maxchrs and xmax. 

|**Valu**<br>**e**|**Description**|
|---|---|
|>|(greater than) Convert Date Format.|
|d|Date Input (Default Today).|
|D|Date Input.|
||D|Defaults century to 19xx. Applies for date formats which allow user to enter only the YY.<br>If not specified, century default is determined by the SBR=CCYY:## entry in miame.ini.|
|||D|Allows a date field to be filled with zeroes.|
||d|Allow Date Shortcuts.|
||h|HexaDecade Dates (2).|
|H|Hours field. Like<br>**$**but omits the "$" from the display.|
||H|HexaDecade Dates (1).|



A-Shell Reference 

Page 2528 

|j|Julian Date Format.|
|---|---|
|t|Time Field.|
|th|Same as<br>**t**but allows hh > 24. Not supported in the Windows date control, i.e. not<br>compatible with_type_<br>**|G**(use<br>**|g**instead).|
|||t|Same as<br>**t**(time) but in GUI mode returns the time in 12-hour format rather than 24<br>hour format.|
|u|LDF-Related Codes<br>.|
|U|European Date.|
|||u|May be used with the<br>**D**,<br>**d**,<br>**t**, and<br>**YN**codes to ignore the current LDF settings and just<br>use the (American) defaults. Without this, the LDF format was used, even in the absence<br>of the<br>**u**code.|



## **History** 

- 2011 January, A Shell 5.1.1200: INFLD enhancement: date fields (except for the GUI date picker) can now use a "form" ( _type_ **f** , SETDEF set to something like "99/99/99"). This provides a sort of middle way between the Windows date picker control (which some people don't like), and a standard date field (in which the separators don't appear until after hitting ENTER). 

A-Shell Reference 

Page 2529 

## **- LDF RELATED CODES** 

_Type_ **u** (LDF-Controlled Format) and **||u** (ignore LDF) have varying effects on dates, times, Y/N and numeric fields whose format options may vary based on the Language Definition File (LDF). Note that unlike most _type_ codes which act independent of the order they appear in, **u** and **||u** must generally precede the associated _type_ codes. 

For date fields ( **D** , **d** , and **U** ), **u** has no effect. The **D** and **d** date fields use the LDF format by default, and the European date ( **U** ) fields always use the European format. The only LDF-related option here is to precede the **D** or **d** with **||u** to force the American format even when the LDF specifies European format. (That could be a useful workaround for running a USA-developed app, which assumed American date format, in some other part of the world.) Note that a good strategy for avoiding confusion within an application related to differing date formats is to always add the **>** code to force {CC}YYMMDD format internally, regardless of the display and edit format. Also note that in a GUI environment where a date-specific control (such as a calendar control) is being used, the edit/display format will generally be determined by the regional settings of the client PC (making the **>** option even more important.) 

For Y/N fields, the affirmative and negative characters are determined by the LDF, unless you precede the _type_ **Y** or **YN** with **||u** , in which case it will use "Y" and no "N". In the GUI environment, you may want to use _type_ **||c** to convert your Y/N fields to checkboxes (which avoids all language and regional confusion). 

For numeric fields ( **#** , **H** , **$** ), **u** forces INFLD to use the decimal point and thousands separator characters specified in the LDF, rather than the USA default characters ("." and "," respectively). In this case, the **u** does not have to precede the numeric _type_ code. 

Note that this will only have an effect if the field would otherwise allow entry or display of decimals and thousands separators. See _type_ codes **.** , **M** , **$** , **H** as well as the defpt and maxpt parameters. 

## **See Also** 

The system parameter LANGUAGE for establishing the LDF, and GTLANG for how to query it. 

A-Shell Reference 

Page 2530 

## **- TIMER RELATED CODES** 

_Updated October 2020; see History_ 

These codes allow variations on the field time-out behavior. Note that except for the " **!** " code, all of the remainder have no effect unless the timer parameter is specified and is non-zero. 

|**Valu**<br>**e**|**Description**|
|---|---|
|!|(exclamation point) Activate return of elapsed time during input. This is only applicable when the timer<br>parameter is specified. Note that this can be used even if time-out is not specified (by setting timer=0).|
|/|(slash) Disable the timer-related messages that normally appear on the bottom line, such as "timing out",<br>except for the time remaining clock. Combine with<br>**+**to eliminate all of the timer displays.|
|+|(plus sign) Disable display of time remaining (on bottom line). Normally, the time remaining until time-out is<br>displayed (and updated every second) on the bottom right corner of the screen.|
|Q|Disable time-out suspend feature. (Normally, the operator can suspend the time-out counter for 10 minutes<br>by hittingCTRL+S. Suspending the timer is useful when you have to temporarily interrupt data entry, as<br>when answering the phone.) Note: Under A-Shell,CTRL+Bis the suspend key.|
|r|Time out reminder. This is similar in motivation to the<br>**w**code, except that it just causes a single beep,<br>without any message, after 10 seconds have elapsed (when the timer option is active.)|
||t|Reset timer to the initial value after every keystroke.|
||T|Overrides timer parameter to zero. Useful for disabling timer globally in programs that otherwise use it (by|



A-Shell Reference 

Page 2531 

||putting this in the SBR=INFDEF: string.)|
|---|---|
|w|Timer wake up warning. When added to any set of timer related codes, causes a warning beep and message<br>when only 10 seconds remain on the timer. The message blinks TIMING OUT in the lower right corner of the<br>screen, and any key hit during the remaining 10 seconds resets the timer to the original value. Note that<br>**w**<br>overrides<br>**/**to display the warning message and suspend message as well, if invoked.|
|||1|Modifies the timeout feature causing it to start out suspended. The first character typed reactivates the<br>timer. Note that all other timer-related options and_type_codes remain in effect, and that the initial timer<br>suspension, as with the normal manual timeout suspension, is for 10 minutes.<br>_type_code<br>**||1**processes the timer on each character received, as well as after one second of no characters,<br>allowing it to time out even in the middle of steady—faster than one  character per second—typing.<br>Normally, the timer logic is only processed at the end of each second without input. That makes sense from<br>standpoint of minimizing CPU overhead in idle fields, as well as user-friendliness—since timing out while the<br>user is actively typing isn't very friendly. But<br>**||1**is a special case, intended to accept only burst-style input,<br>such as might be received from a scanner.<br>Note that it is left to the application to weed out partial inputs deemed invalid after the timeout. Exitcode<br>will be set to 11 to indicate timeout. And also note that you probably want to disable most of the timer-<br>related messaging (see_type_codes<br>**/**and<br>**+**), but not<br>**Q**, since<br>**||1**starts by suspending the timeout until<br>the first character received.|



## **History** 

- 2020 October, A Shell 6.5.1691: Add _type_ ||1. 

A-Shell Reference 

Page 2532 

## **- GUI RELATED CODES** 

These codes activate various graphic user interface features within the A-Shell/Windows (or ATE) version of INFLD. Note that all of them require GUI mode to be activated with **|G** or **|g** . 

|**Valu**<br>**e**|**Description**|
|---|---|
|||]|(bar bar close bracket) Prevents field width from being automatically expanded by logic that attempts to<br>allow for the extra space needed by various GUI enhancements. For example, combo boxes smaller than<br>six characters wide typically get an extra three characters of width to account for the space needed for<br>the dropdown button. Similar rules apply to date and time pickers as well.|
|||[|(bar bar open bracket) causes the redisplayed field to grow as needed for the contents. (This was once<br>part of the<br>**||]**code but has been removed in order to avoid slight differences in field display widths<br>which give such screens a ragged look.)|
|||/|(bar bar slash) Removes the "client edge"—which combines a border and an internal margin—from the<br>edit box. This is useful mainly to make the edit control blend into a background, perhaps related to<br>creating a composite combining an edit control with other text on a static panel, and/or to achieve a<br>"clean" look.|
|||*|EnablePassword Encryption<br>.|
||*|DisablePassword Encryption<br>.|
|||a|ActivateAuto-Complete<br> mode.|
|||b|For checkboxes, causes the current state of the checkbox to override the normal default state (i.e. the|



A-Shell Reference 

Page 2533 

||default based on the_type_codes if opcode=0, or the contents of the entry parameter if opcode=1 or 2).<br>Useful when the checkbox statement may have been changed by clicking on it outside of the awareness<br>of the application. Same effect as cmdflg=4.|
|---|---|
|||c|Convert Y/N Field To Checkbox<br>.|
|||C|Causes a field which would normally appear as a combo box or a date picker while editing (see setdef,<br>dates) to also appear as a combo box when not actively being edited. Otherwise, these kinds of fields<br>revert to static text controls when not active. SeeActive Versus Inactive Behavior<br>.|
||E|Causes the field to retain the form of an edit control when not active. (Otherwise, fields normally revert<br>to static text controls when not active.) Also see<br>**||C**and Active Versus Inactive Behavior<br>.|
||f|Reserved for internal use ATE in GUI mode to control function key settings|
|||f|Force Fixed-Pitch Font<br>.|
|||F|Force Modified Fixed-Pitch Font<br>.|
||g|Implies<br>**|G**, but limits the GUI enhancements to just the Windows-style edit box—i.e. without some of<br>the other automatic enhancements such as date picker controls.|
||G|Activate GUI Enhancements<br>.|
|||g|Disable/override GUI mode. Used to temporarily cancel a global<br>**|G**or<br>**||G**or<br>**|g**.|



A-Shell Reference 

Page 2534 

|||G|Same as<br>**|G**except turns Y/N fields into checkboxes.|
|---|---|
|||H|Disable horizontal scrolling within control. Note that the ability to scroll is sometimes needed in order to<br>fit all of the allowed characters, if using proportional fonts and the field consists of wider-than-normal<br>(e.g. CAPS) characters.|
|||J|Right Justify Checkbox Text<br>.|
||K|Windows Keyboard Conventions<br>.|
|||K|Acts just like<br>**|K**but also disables theCTRL+Cabort while the field is active. This allows you to use<br>Ctrl+C for copy-to-clipboard without first having to disableCTRL+Cabort in the application. See also<br>Ctrl+C Behavior<br>.|
||m|Prevents theENTERkey, when used to select an item from the dropdown list in a combo box, from also<br>causing the field to exit.|
||M|Multi-line edit box._xmax_sets the display width of the box._maxchrs_sets the maximum number of<br>characters allowed (up to a maximum of 1024)._defpt_is reinterpreted as the height of the box. See<br>**||H**<br>for disabling horizontal scrolling (to enable word wrap).ENTER(along with any other enabled exit key)<br>exits. SeeMulti-line Edit Control (INFLD)<br>.|
|||m|Causes_exitcode_13 to be returned when an item is selected from the dropdown list (usingENTERor<br>click) in a combo box. This allows you to distinguish that event from merely hittingENTERto the field<br>when the dropdown is not displayed. The same effect also applies to fast mode checkboxes, allowing<br>you to distinguish betweenENTER(which returns_exitcode_0) and a click or other keystroke which<br>changes the checkbox value and then exits (with_exitcode_13).|



A-Shell Reference 

Page 2535 

|||M|Variation of multi-line edit. AllowsENTERto be used to manually break lines. Also, displays a vertical<br>scroll bar.|
|---|---|
|||r|Create A Radio Button<br>.|
|||s|Makes setdef list matching optional. Only applies to the combo box, in which case it allows the operator<br>to enter a value that is not in the list.|
|||S|Variation of combo box in which typing a character only selects the nearest matching item from the list.<br>Otherwise the user can type independently of the list, and useDOWN-ARROWto find the nearest match.<br>SeeCombo Box Control (INFLD)|
|||U|Create up/down ("spinner") control. SeeUp/Down Control (INFLD)<br>.|
|||v|Self Service Date Picker<br>.|
|||W|Disable the mousewheel within the context of a single combo box field. Added to A-Shell 6.5.1680, June<br>2020.|
|||x|Force coordinates (_row_,_col_) to be interpreted as pixels. This is an alternative to setting<br>IMXF_PIXCOORDS; see_xmax_.|



A-Shell Reference 

Page 2536 

## **ACTIVATE GUI ENHANCEMENTS** 

**|G** may be added globally to make INFLD act visually more like a typical Windows control while still maintaining API compatibility with existing applications. In most cases, this simply means that it will use a Windows-style edit box. If the _setdef_ parameter contains a list of allowed inputs, this is converted into a combo-box containing those inputs as choices. For dates, it uses a "date picker" control. For times, it uses a "time-picker" control. See Combo Box Control (INFLD), Date Picker Control (INFLD), Time Picker Control (INFLD), and Checkbox Control for examples and more details about these control types. See **||c** for checkboxes and |g. 

Note that by itself, **|G** does not force INFLD to use the standard Windows color scheme (white edit boxes with black text). Instead, it continues to use the _infclr_ parameter for setting the color scheme. As a convenience to allow you to quickly experiment with the standard Windows color scheme without tinkering with all of your _infclr_ settings, you can use the option in the Misc. Settings dialog to "Force standard colors in edit boxes", which overrides _infclr_ . 

A-Shell Reference 

Page 2537 

## **ACTIVE VERSUS INACTIVE BEHAVIOR** 

In nearly all cases (text and GUI), INFLD fields assume a different form when active (i.e. being edited) vs. when inactive (i.e. displayed). For example, when active, the data in the field is usually stripped of formatting characters and left justified, while the field itself may be underlined or appear in a different color. 

In the GUI mode, these active-versus-inactive differences may extend to the type of control object used to contain the field. By default, an edit control (or in some cases a date picker, checkbox, combo box, etc.) is used while the field is active, and a static text control is used when the field is not active. This makes it visually obvious which field has the focus, and may discourage users from wanting to move the cursor randomly about the form by clicking. But, it is different from the "typical" Windows form, where there is often no visual change to a field between its active and inactive state, other than the presence of the cursor. 

_type_ **|E** and **||C** may be used to achieve an effect more like the just-described "typical" Windows form. **|E** causes the field to appear as an edit control when inactive. This applies even to combo boxes and date pickers. **||C** is similar, but applies only to combo boxes and date pickers (and time pickers), causing them to retain their drop-down button as well. Neither applies to checkboxes, which always have the same form regardless of whether active or inactive. 

Note that when using either **|E** or **||C** , it is imperative that the field send a mouse-click exitcode string (see _hlpidx_ ) and that your program respond to these exit codes, so that when the user clicks on such a field, the program can detect the click and retain control. Otherwise, since these control types have their own user interface (independent of your application), the user will have the impression of being able to change the field, but the program will not realize that the change has been made. In the default case, where the field reverts to a static text control when inactive, this is not a problem, since a static text control does not offer any way for the user to directly interact with it, other than simply clicking. You can still define mouse-click exitcode strings and respond to the click by re-activating the field, but the point is that you do not have to. 

To make it more obvious to the user which input field has the focus, you can use the Active Background Color option (on the Misc Settings dialog) to define a special background color for edit boxes that have the focus, as shown below: 

To configure that option under program control, see MX_WINSETTINGS. 

A-Shell Reference 

Page 2538 

## **CONVERT Y/N FIELD TO CHECKBOX** 

_Updated April 2019_ 

[ _Type_ code = **||c** ] The text message associated with the checkbox must be placed in the _setdef_ parameter, and the _xmax_ parameter should be expanded to allow for the combined width of the text message (prompt or label) and the checkbox itself. Checkboxes may be toggled with the space bar, or set using the same keystrokes as for regular Y/N fields (i.e. either 1/0 for affirmative/negative, or by using the single-character affirmative/negative keys defined in the language definition file). They also return to the program the same field contents as they would have for normal Y/N fields, thus making it quite easy to convert existing Y/N fields to checkboxes. 

The **||b** code may be added so that the checkbox internal state stays in sync with its visual state, which might otherwise be changed outside the program's knowledge. Without the **||b** code, clicking on the checkbox field from another context will send the field's clickcode, allowing the program to activate the field. But it also would reset the checkbox status to that prior to the click, thus resulting in the need to click twice on the checkbox to change it: once to select the field and then again to toggle it. 

The color of the text label associated with the checkbox is determined by the OFCLR and OBCLR fields within the _infclr_ parameter. In Windows themed environments, you will need to add 64 to the OFCLR/OBCLR values to override the theme color. In most cases, you should just set all of the _infclr_ fields to -2 for maximum compatibility with the standard Windows color logic. 

By default, the text label goes on the left and the checkbox itself on the right. This can be reversed with the _type_ **R** which is normally used for right justification. But in either case, the text itself is left-justified within the space allotted to it. To right justify the text within its space, add SBR=INFLDCBRJ to miame.ini. 

Checkboxes are somewhat unusual, compared to typical INFLD uses, in that a single call combines both the text prompt and the data field. If your programming style divides the functions of displaying the text prompts and the data, you may want to modify the code that previously printed the text label to use INFLD _opcode_ 2 to display both the label and checkbox contents at the same time. Having done this, you can leave the _xmax_ parameter for the checkbox editing call set at 1 (as it would have been for a Y/N field); INFLD will recognize that it overlays an existing checkbox control object and use the existing one. 

See also Checkbox Alignment, Justification. 

A-Shell Reference 

Page 2539 

## **CREATE A RADIO BUTTON** 

[ _Type_ code = **||r** ] These are similar to checkboxes, but considerably trickier to use because they are must be grouped somehow since only one within a group can be set at one time. If there is only one set of radio buttons on the screen, then these form a single group. Otherwise you must use AUI_CONTROL to create a group box to contain the radio buttons. Note that because of these complexities, it is usually much easier to use a combo box to present a choice of mutually-exclusive options. (Combo boxes are easy to implement – just specify **|G** and use the _setdef_ parameter to list the choices.) See Radio button Control. 

A-Shell Reference 

Page 2540 

## **FIELD MARKERS** 

INFLD marks the position and size of the input field in a variety of ways. In text (non-GUI) mode, the standard marker is an underline character. If the prehistoric compatibility mode is selected ( **|p** ), then the field markers will be dots. You can make the markers invisible with _type_ **I** . 

When a GUI-enabled terminal emulation is used (one that ends in G, such as PCTDVG or AM62CG or AM75G), by default INFLD will use a sunken panel effect to identify the position and size of the field. This effect only works well (visually) when the screen background color is somewhere in the gray or pastel zone; otherwise it may be hard to see. You can disable the sunken panel effect and force it to use the underlines instead with _type_ **|_** (vertical bar, underline). 

In full GUI mode (a GUI-enabled terminal emulation and _type_ **|G** specified), the field becomes a Windows control (typically an edit control, but other possibilities are up/down controls, combo boxes, checkboxes, and radio buttons), and no other field markers are needed. 

A-Shell Reference 

Page 2541 

## **- FORCE FIXED PITCH FONT** 

**||f** forces INFLD to use a fixed-pitch font. The result is the same as if you selected the "Use Fixed Pitch Editing Font" option in the A-Shell/Windows Misc. Settings dialog, except that it only affects this field. Fixed pitch fonts look less Windows-like, but have the advantage of making the relationship between the width of the editing box and the number of characters that can be typed more predictable. 

The actual font used will be the same as the standard text mode font (whose dimensions are based on the size of the main window "grid", i.e., the main window size divided by the number of rows and columns established by Tab(-5,x) and Tab(-6,x) or by SET WIDTH and SET TERM HEIGHT or the default values of 24 row and 80 columns). Because of this, the effect works best for INFLD GUI fields embedded into text-based (or hybrid text/GUI) main window displays. **||f** should not be used with **||]** (prevent automatic expansion of the field), since without expanding the field width by a couple of pixels on both edges to account for the internal margins of the edit control, the actual usable width of the control may be just short of the amount needed to display the specified maximum number of characters. 

- See **||F** (Force Fixed Pitch Font) for a variation that may work better with dialogs, especially those using the MBF_ALTPOS grid system. 

A-Shell Reference 

Page 2542 

## **- FORCE MODIFIED FIXED PITCH FONT** 

- **||F** , like **||f** (Force Fixed Pitch Font), forces INFLD to use a fixed-pitch font. However, unlike **||f** , which uses the standard A-Shell text-mode font (based on the main window grid), **||F** selects a custom fixed-pitch font based on the actual field size (as rendered into pixels based on the resolution, grid units, scale adjustments, etc) to allow the specified maximum number of characters (according to xmax) to fit in the field. **||F** is generally more suitable than **||f** within dialogs, particularly those based on the MBF_ALTPOS (see AUI ctype) grid, since in that environment the grid units have no particular relationship to the main window grid units, and thus the main window text font may be too big or too small for the edit control. **||F** is also compatible with **||]** . The main downside to **||F** versus **||f** is that depending on the currently selected fixed pitch font type, the screen resolution, and limitations on the granularity of font scaling, the actual font selected at runtime may sometimes appear smaller than "ideal" (meaning that it may give the appearance that the field could accept more characters than the actual limit as set by the xmax parameter). Although this does somewhat undermine one of the objectives in using a fixed pitch font, the discrepancy is generally small, and certainly much smaller than the discrepancy that occurs with the standard proportional edit font, where the typist may hit the xmax or maxchrs limit long before filling the physical width of the control. 

A-Shell Reference 

Page 2543 

## **RIGHT JUSTIFY CHECKBOX TEXT** 

**||J** right justifies text within a check box control. Note that for combo boxes, _type_ **R** determines whether the box is on the right or left of the text, but within the text portion of the control (whichever side of the checkbox), the text would be left justified unless **|J** is specified. This is equivalent to—but more flexible than—SBR=INFLDCBRJ. 

A-Shell Reference 

Page 2544 

## **WINDOWS KEYBOARD CONVENTIONS** 

_Updated September 2024_ 

**|K** determines whether to adopt Windows or AMOS conventions related to data entry, when the two are in conflict. For example, without **|K** , the initial input mode is overwrite; with **|K** it is insert. (You can use the INSERT key to toggle insert mode on and off.) Without **|K** , the HOME key is considered a field exit key (returning _exitcode_ 9 if _type_ 9 is specified); with **|K** , HOME just moves the cursor to the start of the field. With **|K** , TAB acts like ENTER (returns _exitcode_ 0). Without **|K** , CTRL+V is delete word, with **|K** it is paste from clipboard. CTRL+C is more complex; see Ctrl+C Behavior for details. 

In most cases where the nature of the GUI version of the control introduces the possibility of navigating within the control using keys that might otherwise have been only used as exit keys (such as up/down arrows within a drop-down list), you can use the CTRL key in conjunction with the navigation key (e.g. ARROWS, HOME, etc.) to force it to act as an exit key, assuming the exit key is allowed by the _type_ codes. 

When **|K** (Windows keyboard mode) is NOT used, the SHIFT+ARROW keys work like function keys (same as they do in text mode), and will generate exitcodes based on the <tdv>.IFX translation table. The standard exitcodes for the shifted arrows are: -36, -37, -38 and -39. See FIXTRN.LIT for details on editing translation tables. When **|K** is specified, CTRL+LEFT and CTRL+RIGHT now navigate to previous and next word, equivalent to the traditional CTRL+A and CTRL+W; See History. 

## **History** 

2020 August, A-Shell 6.5.1688: CTRL+LEFT and CTRL+RIGHT now navigate to previous and next word. 

A-Shell Reference 

Page 2545 

## **SELF SERVICE DATE PICKER** 

The concept is similar to the self-service combo (where you put "..." in the _setdef_ parameter and it returns _exitcode_ 29 when you attempt to display the drop-down), except here you activate it by adding _type_ **||v** to the date _type_ codes. Presumably this might be useful in cases where you like the look of the edit portion of the date picker, but want to display a more specialized calendar when the user clicks the drop-down button. 

See Date Picker Control (INFLD) in AUI[XS] for related information. 

A-Shell Reference 

Page 2546 

## **- AUTO COMPLETE** 

Auto-complete is a mechanism to help the user enter data and to speed up the data entry process. It does this by displaying a list of choices or "suggestions" to complete the entry whenever (a) there is a pause of 0.5 seconds in the user’s typing (after a change has been made to the field), or (b) the user hits the down arrow to explicitly request a list. 

- See Auto Complete Illustrations for images and explanations of how auto-complete appears to the user. 

Unlike most field editing scenarios which typically involve only a single call to INFLD, the Auto-Complete scenario may involve several calls. Basically, since INFLD cannot reasonably know where to find your data, nor how you would like it displayed, it returns to the application with a special exitcode (30 or 31) whenever it thinks it would be appropriate to update the list of AutoComplete suggestions. The application is then responsible for taking the current contents of the field (from the entry parameter), building a corresponding list, and passing it back to INFLD. For example, the application code may look something like this: 

```
setdef = ""  ! typically start with an empty setdef
```

## `do` 

```
xcall INFLD, row, col, xmax, xmin, entry, inxctl, parid, opcode, exitcode, … ,setdef,…
```

```
if exitcode = 30 or exitcode = 31 then    ! INFLD requests a new or longer list
```

```
setdef = <updated list data, based on the returned entry>
```

```
else
```

```
<logic dealing with any other exitcodes>
```

- `exit       ! terminate the auto-completion loop` 

```
endif
```

```
loop
```

To activate auto-complete mode, add the following _type_ codes: **||a)|]** 

**||a** activates auto-complete mode, but in order for the re-entry process to work as expected, the **)** (re-enter at end of field) and **|]** (don't pad or strip trailing spaces) are strongly recommended. 

A-Shell Reference 

Page 2547 

You may also want to add **||S** if you want to prevent the user from entering anything other than one of the items you supply in the dropdown list. Otherwise, the items in the list are just suggestions and don’t prevent the user from entering other values. 

On re-entry (after INFLD exits with exitcode 30/31 to request a new list),the application is responsible for formatting setdef as follows: 

## **{[widthspec]}<coldef>~<set-list>** 

## _{[widthspec]}_ 

is an optional specification to adjust the width of the dropdown list. If not present, the dropdown list will be the same width as the field. Otherwise, the options are as follows: 

|**widthspec**|**Result**|
|---|---|
|+###|increase list width by ### columns|
|-###|increase list width by ### columns (but start ### columns to the<br>left of the field)|
|###|set width to ### columns (starting in the same column as field)|



## _<coldef>_ 

is an XTREE-style column definition (coldef) string defining the layout of the <set-list>. In the simplest and most typical case, it would specify just one column, using _Cformat_ **S** (for string), and whose width matches the width of the items in the <set-list>. (The column title is ignored.) Theoretically you can also use any of the _cformat_ or XTREE Advanced Coldef Options that made sense for the selection list (for example, to highlight certain items), but none are typically needed. If you define more than one column (as in the city/zip example in the illustrations), then only the first visible column is actively connected to the field; any additional columns are for display purposes only (i.e., the zip code column in the above illustration). 

A-Shell Reference 

Page 2548 

## _<set-list>_ 

is a standard _setdef_ List of Valid Inputs, except that each entry must be the same length. (Use space padding as needed to achieve this.) Note that unless you specify the **||S** _type_ code (see above), the length of the entries in the list doesn’t have to exactly match that of the field; they just have to all be the same length. With **||S** , if the list items, (or in the case of a multicolumn list, the first column of the list items) does not exactly match the field width (according to maxchars), then none of the list items will be accepted by INFLD as valid inputs. 

## **See Also** 

- See the sample programs INFAC1.BP and INFAC2.BP in EXLIB:[908,41] for simple working examples. 

- The INFLD-GUI Auto-complete discussion on the A-Shell forum. 

## AUTO-COMPLETE VARIATIONS 

## **Uncoupled Mode** 

In the normal mode, the list is coupled to the edit control. Even though the application is responsible for supplying the data to build the list, the application only needs to communicate with INFLD. It is INFLD’s responsibility to create the list control, update it, give it the focus, capture clicks, etc. But in the UNCOUPLED MODE, the application takes charge of the list control (typically using XTREE, but theoretically anything it likes), and INFLD is only responsible for returning the related exitcodes. No special _type_ codes are required for this mode. Instead, when the application receives exitcode 30 or 31, instead of building the list data in the setdef parameter and returning to INFLD, it must build and display the list control itself. When returning to INFLD to allow the user to continue typing, the setdef parameter should be left blank (which will prevent INFLD from trying to create/display the list itself). 

In addition to responding to exitcodes 30 and 31, the application should also respond to whatever exitcode it assigned to the list control that it builds. (For example, in the case of XTREE, via XTR.KBDSTR.) When the user clicks on the list control built and displayed by the application, the natural response would be for the application to put the focus on that list control, allowing the user to scroll among the choices with the arrow keys and select one by hitting ENTER. The application must also respond to the exitcode returned from the list control (i.e. XTREE), so that it can allow the user to return to the edit field either by up-arrowing out of the list control, or clicking directly on the edit control. 

A-Shell Reference 

Page 2549 

Uncoupled mode allows the application maximum flexibility, but requires considerably more programming effort. The only benefit being derived from INFLD in this case is the auto-complete time-out mechanism. (In comparison, the normal field time-out is too simple-minded to work well in this situation.) 

## **- - Auto Complete with Self Service Combo Box** 

In this variation, the control starts out as a combo box rather than an edit control. As in the normal case of a Self Service Combo Box, you must set `setdef="…"` to activate it, and clicking on the drop-down button returns exitcode 29. Although the application can do whatever it wants with that exitcode, the normal plan would be to respond to it just like you would to _exitcode_ 30 (i.e. build a list by passing a properly formatted _setdef_ backto INFLD.) Note that on return to INFLD, the control would then change from a combo to an edit box, and from that point would act like the normal Auto-Complete case. 

## **- Auto Complete with Coded Lists** 

Auto-Complete can be combined with Coded Lists ( **||L** ) rather than standard _setdef_ lists of complete entries, although the main effect is only felt on the final exit from the field. In the interim exits (with exitcode 30/31), the raw field contents will be returned to the application (since that’s what the auto-complete list would be based on), and the application can return either the coded or raw field contents on re-entry. (INFLD will first try to convert the entry string as if it were a coded value, but if that fails, uses it as is.) In almost all cases, you would want to also specify the **||s** (list matching optional), unless you planned to fill your list with all of the valid possibilities. In that case, it isn’t clear how Auto-Complete would really be of any advantage, vs. just using a regular combo box. 

## AUTO-COMPLETE ILLUSTRATIONS 

For illustration, in the example below, the user has entered "Wood" into a field expecting a city name, but then paused, resulting in the auto-completion list containing cities whose names start with those characters: 

The above example illustrates the possibility of the dropdown list containing additional information-only columns, in this case the zip codes. It also illustrates the possibility of making the dropdown list a different width than the field. See the discussion of Coldef for details. 

Once the list is displayed, the user can either select one of the choices from the list, either with the mouse or by using the DOWNARROW / UP-ARROW and ENTER, or just continue typing, as in the example below (adding an "s" and then pausing again): 

A-Shell Reference 

Page 2550 

To complete our example, let’s assume that the user spotted the intended city, "Woods Hole", in the list and decides that it is easier to arrow down to it than to type the remaining characters: 

Hitting ENTER at that point closes the list and puts the selected item into the field: 

## AUTO-COMPLETE EXAMPLES 

The following two examples illustrate valid _setdef_ formats which sent back to INFLD in response to _exitcode_ 30 or 31. Note that for the initial call to INFLD, you would normally set _setdef_ to ""(unless you wanted the list displayed immediately). 

## Simple example: 

```
SETDEF = "1~7~x~S~~~,ACME   ,Adams  ,Affleck,Azure  ,,"
```

The above _setdef_ string does not contain an optional [widthspec] and instead starts with a simple column definition (Coldef) string defining a single column of seven characters. The _coldef_ string is normally (in standard XTREE usage) terminated by two tildes (~~), but in the context of INFLD auto-complete, a third tilde (~~~) is required to act as a delimiter between the _coldef_ and the actual list items. Also note the trailing spaces on the list elements to give them each 7 characters. Finally, following the _coldef_ string and the three tildes, we show four entries in the list, each delimited by a comma and space-padded to seven characters. Note that as with a standard _setdef_ List of Valid Inputs, the first character of the list specifies the list item delimiter (comma in this example), and two delimiters mark the end of the list. 

## More complex example: 

```
SETDEF = "[+3]0~0~x~H~RGBbg=220,230,240,A~~1~10~x~S~~11~1~x~bH~~~" &
```

```
+ ",Apples    A,Bananas    ,Peaches   A,Watermelon ,,"
```

In the above list, we started with a [widthspec] of "[+3]" so that the dropdown list would be 3 grid-columns wider than the field. Then we used a more complex Coldef string to define an RGBbg value associated with a pseudo-column, plus 2 real columns - the first ten characters long (the primary column) and the last one character to contain the color code. The list then specifies the 

A-Shell Reference 

Page 2551 

color code "A" for Apples and Peaches, so those two items would appear in the auto-complete list with the specified background color. Note that each item in the list (as measured by the space between the delimiters) must match the total length of all the real columns (11 in this example): 

## See the sample programs INFAC1 and INFAC2 in EXLIB:[908,41] for more complete examples. 

## AUTO-COMPLETE COMMENTS 

- Auto-complete can only be used with "simple" text fields (no radio buttons, checkboxes, date pickers, spinners, multi-line or 

- forms). 

- The visible space occupied by the list will be the equivalent of about 5 "grid rows" below the INFLD control, unless the control 

- is too close to the bottom of the parent window, in which case the list will display above the field. Note that even when the list displays above the field, you still use the DOWN-ARROW to move from the field to the list, the UP-ARROW to move back to the field from the list, and the DOWN-ARROW (or CTRL+ DOWN-ARROW) from the last item of the list to request more items. 

- Internally, the list control is assigned _exitcode_ -63 (VK_xF63). You should not have any controls in that range (-33 to -99 is 

- generally reserved for A-Shell.) 

- When INFLD exits with _exitcode_ 30 (asking the app to refresh the list data) or _exitcode_ 31 (requesting more data), you must 

- re-enter with a proper _setdef_ string (as described above), or manually remove the existing list control. To make it easy to remove, list controls created by INFLD have the name "xtrInfldAutoComplete", and thus can be deleted using: 

```
xcall AUI, AUI_CONTROL, CTLOP_DEL, "xtrInfldAutoComplete"
```

- Obviously, you want to minimize the time the application takes to respond to _exitcode_ 30. Characters typed during that 

- interval should be queued up but won't appear until the application returns to INFLD. 

• There is no particular limit to how many items can be in the list, but as a matter of practicality or efficiency, you should keep it reasonably short. (For example, if the user enters "A" and pauses, you may not necessary want to generate a list with all of the items that start with "A".) The user can effectively request more items by pressing CTRL+DOWN-ARROW from the bottom of the list. 

A-Shell Reference 

Page 2552 

• Requesting more items: If the user wants to see more items in the list, she can either type some more characters (effectively refreshing and narrowing the choices), or she can press CTRL+DOWN-ARROW from the last item in the list, which generates _exitcode_ 31. Applications can respond to _exitcode_ 31 by either building a longer list, or by replacing the current list with the next several items in sequence. Note that if you don't want to require the Control key for this purpose, add the advanced _coldef_ option ScrollMode=Tree. 

A-Shell Reference 

Page 2553 

## **PASSWORD ENCRYPTION** 

## _Written October 2019_ 

Beginning with A-Shell 6.5.1670, password data is encrypted within the edit control, preventing it from being snooped on by external system utilities. To help manage the feature, two new _type_ codes have been defined: 

|**Value**|**Meaning**|
|---|---|
|||*|enable password encryption|
||*|disable password encryption|



Eventually the feature will become enabled by default, but initially during beta testing, it has to be explicitly enabled. The recommended way to do this is by adding `SBR=INFDEF:||*` to miame.ini, or use the `SET INFDEF` command from the dot prompt for ad hoc testing.) 

The feature only applies when the following _type_ codes are also set: 

|**Value**|**Meaning**|
|---|---|
|S|security field|
||G|GUI|
||E|field remains displayed as a edit control|



A-Shell Reference 

Page 2554 

**Value Meaning** when inactive 

When all of the conditions have been met, password edit controls will exhibit the following behavior: 

- The contents are encrypted as they are loaded into the control and decrypted as read back out again. 

- You can TAB through the field without changing it, but any data entry into the field will first clear it. So you can't just change 

- or add a single character to an existing password field. 

- An "eye" icon will be displayed at the end of the field. Clicking down on the icon reveals the password, clicking back up re- 

- masks it. Note that due to some display-related mysteries within the implementation of the Windows edit control, the eye may not always be visible; in such a case, moving the mouse over the end of the field should redisplay it. 

## **History** 

- 2019 October, A Shell 6.5.1670: Add INFLD password encryption to A-Shell. 

A-Shell Reference 

Page 2555 

## **MISCELLANEOUS CODES** 

|**Valu**<br>**e**|**Description**|**Description**|**Description**|
|---|---|---|---|
|&|(ampersand)Enable protected fields<br>.|||
||&|(bar ampersand) Works like a "smart" version of<br>**&**, re-enabling protected mode on exit only if it was<br>previously enabled. The<br>**&**feature always re-enables protected mode, which was the way it worked<br>historically under AMOS. Beginning with A-Shell 6.3.1540: when specified in the INFDEF string, now<br>affects BASIC INPUT fields. (Normally, the INFDEF options only apply to XCALL INPUT, XCALL INFLD,<br>etc.) This can be handy in an application that uses protected fields along with BASIC INPUT, assuming<br>that the BASIC INPUT does not deactivate the protection (which INFLD would otherwise do).|||
|(|(open parenthesis)||Strip leading blanks from_entry_before pre-load.|
|)|(close parenthesis)||Start cursor at end<br>.|
||/|(bar slash) Disables the display of theINFLD"about" box, which is normally triggered by CTRL+SLASH.<br>This is mainly a workaround for a problem where the about box is being triggered unexpectedly.|||
|||`|(vertical bar, vertical bar, grave) Forces unconditional destructive CR; text mode only.|||
|:|(colon)|Disable bright and dim<br>.||
|;|(semicolon) Turn cursor on while waiting for input; turn it off again on exit from field.|||



A-Shell Reference 

Page 2556 

|[|(open bracket) Force cursor to blink during input.|(open bracket) Force cursor to blink during input.|
|---|---|---|
|\|(backslash)|Clear bottom line<br>.|
|]|(close bracket) Strip trailing blanks. Otherwise_entry_field is filled up with trailing blanks, like in the<br>original AlphaAccounting version ofINPUT. The stripped blanks are not counted toward_xmin_. (See ].)||
||]|(bar close bracket) Defeats both the padding and stripping of trailing blanks, so that you get back exactly<br>what you typed. (See ].)||
|^|(carat)Convert to upper case (1)<br>.||
|_|(underscore) Use clear-to-end-of-line function (-1,9) to clear field.||
||_|(bar underscore) Use underline to mark designated field (instead of default auto-beveling). SeeField<br>Markers<br>.||
|`|(grave accent)Force destructive Enter<br>.||
||.|(bar period) ForcesINFLDto use periods rather than underlines for the field marker in text mode.<br>Previously you had to use prehistoric compatibility mode, or allow decimal points, to achieve this.||
|}|(close brace) Activates "INMEMO" mode. This is a specialINFLDmode used internally by the A-Shell<br>implementation ofINMEMO.||
||}|(bar close brace) Activates horizontal scrolling mode. Set automatically when_maxchrs_>_xmax_.||



A-Shell Reference 

Page 2557 

|||
|---|---|
|||}|(bar bar close brace) Activates "command-line" mode. This is a specialINFLDmode used internally by<br>the A-Shell implementation of the dot prompt and for BASIC INPUT statements.|
|<|(less than) Echo a carriage return on exit from the field. This is useful especially with the<br>**F**and<br>**@**codes<br>to let the operator know immediately that the input is being processed.|
|=|(equals) Do not reformat the field on exit. Also see<br>**|R**, do not redisplay on exit.|
||A|Activates simulation ofXCALL AMBTOA.|
|b|Disallow blanks<br>.|
|B|Disable character blanking<br>.|
|c|Capitalize first letter of each word.|
|e|Force non-destructive RETURN (or ENTER). This is the default for most field types except numeric. See<br>code<br>**`**<br> (grave accent) above.|
|E|Abort allowed<br>.|
|f|Form Field<br>.|



A-Shell Reference 

Page 2558 

|F|Fast input<br>.|Fast input<br>.|
|---|---|---|
||F|**|F**is similar to<br>**F**(fast) except that it affects the preload operation, rather than interactive typing. When<br>specified, if the preloaded characters satisfy the minimum field size, then the field will exit immediately<br>(without waiting for input).||
|||F|Forces the current field to use the fixed pitch font, regardless of the setting of the "Use Fixed Pitch In Edit<br>Boxes" option in the Misc. Settings menu. This can be useful when specific fields do not work well in a<br>proportional font.||
|g|Return updated field contents<br>.||
|h|Disables the help message display<br>`"Hit ? for Help"`. This may be desirable when you have help on<br>virtually every field, or when you need to use that area for some other message.||
|i|(lower case I) Completely invisible field. Similar to<br>**S**except that nothing is echoed (so you cannot even<br>see how many characters are allowed, or how many were typed.)_type_<br>**i**<br> silences the beveling so that<br>the field remains totally invisible—i.e. no cursor, no indication of field position or size, no echoing of<br>characters.||
|I|(upper case letter "eye".)|Use invisible field markers<br>. See alsoField Markers<br>.|
||I|(bar upper case letter "eye") ForcesINFLDto start in insert mode, rather than the default, which may be<br>either insert or replace mode, depending on several factors.||
|||I|(bar bar upper case letter "eye") Forces INSERT mode off / REPLACE mode on). This overrides the<br>remembered state for the current field, but does not change the remembered state for subsequent fields.||



A-Shell Reference 

Page 2559 

|||k|Disables internal too-fast input filter, which may otherwise cause characters fed via a burst to be<br>dropped.|
|---|---|
||l|(bar lower case letter "el") Forces lower case.|
|||l|(bar bar lower case letter "el") Same as<br>**||L**except that_entry_will return a complete<br><code>,<description> pair (e.g. "01,North") instead of just the code item. SeeCoded Lists<br>.|
|||L|(bar bar upper case letter "el") List substitution._setdef_consists of <code>,<descr> pairs, e.g.:<br>,01,North,02,South,03,Middle Earth,, Application uses the code items (01, 02, ...) while the operator<br>sees and uses the description items. SeeCoded Lists<br>.|
|m|Disable default type codes.|
|n|Return null<br>.|
|O|(Upper case letter "O") Optional field. Allows operator to skip the field, even if the_xmin_specified is non-<br>zero. However, if 1 or more characters are entered, then the minimum goes back into effect.|
|p|Overrides_cmdflg_parameter, setting it to 1—i.e. forces command file input to be active. See also<br>MX_SETCMDINP<br>.|
||p|Prehistoric Compatibility Mode<br>.SeeField Markers<br>.|
|||p|Disables the use of the clipboard paste option.|



A-Shell Reference 

Page 2560 

||P*|This three-character_type_combination (vertical bar, P, followed by any character A-Z, [, ], ^, _) enables<br>CTRL+ (whatever the third character of the sequence is) to launch the pop-up utility ASHPOP.RUN.|
|---|---|
|||P|This may be used with the security_type_field<br>**S**to automatically decrypt/encrypt a password, using A-<br>Shell's standard password encryption scheme. SeeMX_PWCRYPT<br>.<br>**||P**supportsMX_PWCRYPTmodes 1<br>and 2.|
|q|Causes field to be edited in reverse video.|
||r|Read only<br>.|
||R|Do not redisplay field<br>.|
|s|Disable display of_setdef_options, which are otherwise displayed along the bottom line of the screen. Not<br>applicable in GUI mode, where the_setdef_options are loaded into a combo box.|
|S|Security field: echo all characters as "*". Also see<br>**i**<br> above.|
||s|Provides support for regular expressions in SETDEF. When<br>**|s**is specified, SETDEF is interpreted as a<br>single regular expression, which the data field must match. Note that to invoke regular expression flags<br>such as PCRE_CASELESS, you will need to use the Perl-style internal option settings, e.g. "(?i)[AP]M" will<br>match AM, PM, am, pm, etc. Also note that in this mode, setdef should contain only the regex pattern,<br>with no leading or trailing delimiters.|
||S|Causes an automatic screen capture to be appended to the capture file on exit from the field. See<br>MX_SCRNPIC<br> for more info on screen captures.|



A-Shell Reference 

Page 2561 

||u|Convert to upper case (2)<br>.|
|---|---|
|W|Disallow record abort key<br>.|
||X*|Program Ctrl+X<br>.|
|0|(zero) Strip away all characters typed ahead into the input buffer before inputting the field. Useful when<br>you want to make sure that the operator reads a message or prompt before answering it.|



A-Shell Reference 

Page 2562 

## **FORCE DESTRUCTIVE ENTER** 

_Reviewed and revised August 2020_ 

[ _Type_ code = **`** ] This forces a destructive ENTER key—e.g. make it always truncate field at position of the cursor. When using this code, the field is automatically cleared as soon as you enter the first character, except an exit key. Except for numeric fields, ENTER usually exits a field without truncating or erasing any characters. See **e** code (force non-destructive) for information on how INFLD determines whether to use destructive or non-destructive CARRIAGE RETURNS. 

When the Force destructive ENTER option is combined with the Force non-destructive ENTER option ( _type_ **e** ), **INFLD** tries to be smart about the decision of whether to truncate the field at the point of hitting Enter, as follows: If you use any field editing keys (ARROWS, INSERT, DELETE, etc.), or if the first key you strike is ENTER, then it assumes you are working in WYSIWYG mode and does not truncate the field, otherwise it does. 

A-Shell Reference 

Page 2563 

## **ENABLE PROTECTED FIELDS** 

[ _Type_ code = **&** ] Use this code when you have the screen protected. This is necessary since INFLD is forced to disable protected fields in order to display reduced intensity field markers. When it exits, it will enable protected fields if you use this code. (Also note that disabling protection during input is not a problem since it is impossible to move the cursor out of the field, unlike Alpha's INPUT.SBR.) Before using this code you may want to reconsider your use of protected fields. If you are only using them to allow you to clear the data from the screen quickly, then you only need protection enabled when you perform the screen clear function (e.g. `print tab(-1,13); tab(-1,10);tab(-1,14)` ) 

A-Shell Reference 

Page 2564 

## **FAST INPUT** 

[ _Type_ code = **F** ] Exits as soon as the maximum ( _xmax_ ) number of characters entered, or an enabled exit code is used; no RETURN or ENTER needed. See code **<** . To alert the operator, INFLD will make the cursor blink while editing fast fields. 

**F** generally has the same effect in a GUI field as in a text input field—i.e., causing the field to exit automatically when the maximum number of characters are entered. There are some special GUI situations, however, where it takes on additional meaning. One occurs with drop-down controls (combo boxes or date pickers), where it causes a single-click on an entry in the drop-down list to cause the item to be selected the field to exit. Otherwise, single-click in this case would normally just close up the drop-down list and return to the edit field. 

A-Shell Reference 

Page 2565 

## **CONVERT TO UPPER CASE** 

## **Convert to upper case (1)** 

[ _Type code_ = **^** ] Has no effect on non-alphabetic characters. You do not have to specify this for Y/N fields, since they already force upper case. When **^** is used in combination with one of ( **$** , **H** , **M** ), it takes on a new meaning: forcing the minus signs to be displayed in leading rather than trailing format. Note that for numeric codes **#** and **N** , this is unnecessary since leading minus display format is the default. Also see **|u** . 

## **History** 

- 2017 June, A Shell 6.4.1550:  Windows Password refinement: stifle the CAPS LOCK warning bubble if the force upper case option is enabled (type ^ or |u). 

## **Convert to upper case (2)** 

[ _Type code_ = **|u** ] This code (vertical bar, lower case u) provides an alternate way to force the field contents to upper case. The other method, type **^** (caret), causes problems with d/VUE which sometimes wants to treat the caret as a literal control character lead-in character in your program source code. This would not only fail to give you the upper case flag, but would also combine with the next type code in your list of type codes to produce a control character which would be, at best, ignored by INFLD. 

## **History** 

- 2017 June, A Shell 6.4.1550:  Windows Password refinement: stifle the CAPS LOCK warning bubble if the force upper case option is enabled (type **^** or **|u** ). 

A-Shell Reference 

Page 2566 

## **EXIT KEY ENABLING CODES** 

_Updated October 2025; see History_ 

These codes are used to selectively enable individual exit keys (and corresponding return codes) you wish to process. For example, if you want to process a CTRL+R by returning the cursor to home or previous screen, then you will have to enable use of the CTRL+R. Where possible, the codes are equal to the _exitcode_ value returned to make them easier to remember. An attempt at exiting a field with a disabled exit key produces a beep. 

Note that not all of the available exit keys are enabled in this manner. The ENTER key is always enabled; any field may be exited with ENTER. The abort key CTRL+E is always enabled unless disabled with the **W** code. The time-out abort is activated by specifying a non-zero value for the _timer_ parameter. 

The following table, like the others, is organized by the alphabetical order of the _type_ code characters. See the exitcode parameter for a table ordered by _exitcode_ values. 

|**Valu**<br>**e**|**Description**|
|---|---|
|?|Help key allowed. Displays message on bottom line "Hit `?' for Help", and returns_exitcode_= 8 if help<br>key entered. Leaves the value of_entry_as it was before callingINFLD. Note that the help key, message,<br>and message location may be customized.|
||{|(bar open-curly-bracket) Causes the setdef parameter to be treated as a list of immediate exit<br>characters, which is similar to the ExitChars feature in XTREE. Receipt of any of the characters specified<br>causes the field to exit with exitcode set to -51. The existing contents of the field are returned, minus<br>the character causing the exit.|
|||<|Type<br>**||<**may be used with<br>**||S**(selection-only combo boxes) to force an exit with EXITCODE 32<br>whenever the selection changes due to the user typing a keyboard character. The concept is the same<br>as for<br>**||5**and<br>**||3**as described below.|



A-Shell Reference 

Page 2567 

||a|EnableCTRL+A(when cursor already at start of field) to return_exitcode_=19.CTRL+Anormally moves<br>cursor tostart of previous word.|
|---|---|
||B|EnableCTRL+Bto return_exitcode_=16, andCTRL+Oto return_exitcode_=17.|
||C|EnableCTRL+Sto return_exitcode_=26.|
|||E|CausesENTERto return exitcode 23 instead of the normal 0. This can be useful in certain dialog<br>situations (particularly involvingAUI_EVENTWAIT) where either the correct response toENTER, or the<br>meaning of a response of exitcode 0, might otherwise be ambiguous.|
|k|EnableCTRL+Eto return_exitcode_=15 (rather than its normal use as the record abort key, which sets<br>_inxctl_=1.)|
|L|EnableCTRL+L(RIGHT-ARROW). Returns_exitcode_=12 if right arrow hit when cursor already at right end<br>of field.|
||L|The combination<br>**|L**(vertical bar, L) is the same as_type_<br>**L**(without the vertical bar) in that it triggers<br>_exitcode_12. The difference is that with<br>**L**by itself, you can only exit from the far right side of the field.<br>(If there are characters to the right of the cursor, then the right arrow key will simply move the cursor<br>to the right.) With<br>**|L**, you can exit the field from any position, provided you have not already used other<br>editing or cursor motion keys first. This mode is useful forRIGHT-ARROWto skip from one field to the<br>next.|
||N|EnableCTRL+Nto return_exitcode_=22 instead of just moving the cursor to the end of the field.|
||Q|EnableCTRL+Pto return_exitcode_=25 instead of initiating a screen snapshot.|



A-Shell Reference 

Page 2568 

|||
|---|---|
|T|AllowTABkey as a terminator. Sets inxctl to 3 and_exitcode_to 7.|
|||T|CausesENTERto act likeTAB(returning_exitcode_7). This might help simplify dialog logic, particularly<br>when using EVENTWAIT with theEVW_EXCDFOCUSoption, by eliminating the need for special treatment of<br>the_exitcode_0 case.|
||U|EnableCTRL+Uto return_exitcode_=21 (instead of just moving the cursor to the start of the field).|
|V|TrapCTRL+Cand return_exitcode_=10 (instead of the normal mode which aborts to the ASB error<br>trapping routine). Note that you must specify the_exitcode_parameter for this to work. See alsoCtrl+C<br>Behavior<br>.|
||w|EnableCTRL+Wto return_exitcode_=20 (when at the start of an empty field)|
||W|EnableCTRL+Wto return_exitcode_=1 and_inxctl_=1, instead of moving the cursor to the start of the next<br>word.|
||XX|EnableCTRL+Xto return_exitcode_=27. Note that this is a special case of the general three-character<br>_type_sequence<br>**|X?**which causesCTRL+Xto be interpreted asCTRL+*(where * is any character<br>compatible with theCTRLkey).|
||Z|EnableCTRL+Zto return_exitcode_=18 (instead of clearing the field).|
|1|EnableESCAPE, returns_exitcode_=1. Note that this is only effective when used without the<br>**E**code (see|



A-Shell Reference 

Page 2569 

||above). This differs fromESCAPEwith the<br>**E**code in that the contents of the field are not overwritten<br>with "END". Also note that theCTRL+Eabort key also returns_exitcode_=1.|
|---|---|
|2|EnableLEFT-ARROW(BACKSPACEon most PCs), returns_exitcode_=2. This is only effective without the<br>**E**<br>code, and is intended to be processed as a move to previous field.|
||2|(vertical bar followed by 2) (Windows/ATE) (GUI mode only) ForcesSHIFT+TABto return_exitcode_2<br>(like left arrow would if_type_<br>**2**was specified). OtherwiseSHIFT+TABacts exactly likeUP-ARROW,<br>meaning it will exit with_exitcode_set to 3 if_type_<br>**3**specified. Unlike left arrow,SHIFT+TABdoes not<br>require that the cursor be in the home position in order to be treated as an exit key. Note that_type_<br>**|2**<br>neither requires_type_<br>**2**nor implies it. In other words,_type_<br>**|2**by itself will enableSHIFT+TABexits<br>(setting_exitcode_2) but will not enable theLEFT-ARROWexit. Use_type_<br>**2|2**or<br>**|22**to allow both<br>methods of exiting.|
|3|EnableUP-ARROW, returns_exitcode_=3. Should be processed as either a return to previous field, or to<br>next field above cursor in same column.|
||3|Types<br>**|3**and<br>**|5**are equivalent to the existing types<br>**3**and<br>**5**, respectively, except that if used with a<br>combo box, they also cause the up/down arrows to exit immediately (with the corresponding exitcode),<br>rather than scroll among the choices in the combo box, PROVIDED THAT the combo box is not already in<br>the dropdown position. (This is directly analogous to theXTREEcoldef option ScrollMode=Tree.) An<br>additional side-effect of<br>**|3**and<br>**|5**(versus 3 and 5) is thatSHIFT+UP-ARROWandSHIFT+DOWN-ARROW<br>will now act as they do in text mode (i.e. get translated via the function key translation system), even if<br>**|K**(Windows keyboard mode) is in effect.|
|||3|Types<br>**||5**and<br>**||3**act just like<br>**|5**and<br>**|3**respectively, except that the exit occurs AFTER updating the<br>display (with the next or previous item in the list), instead of BEFORE. Thus they work similarly to the<br>SelChgExit feature ofXTREE, allowing you to update some other display element to correspond with the<br>currently displayed item in the combo box.|



A-Shell Reference 

Page 2570 

|4|EnableCTRL+R, returns_exitcode_=4. Should be processed as a return to first field in screen, or to<br>previous screen (in multi-screen applications).|
|---|---|
|5|EnableCTRL+J(down arrow), returns_exitcode_=5. Should be processed as an advance to next field or<br>next line (skipping fields on current line).|
||5|See<br>**|3**.|
|||5|See<br>**||**3.|
|6|EnableCTRL+T, returns_exitcode_=6 and should be processed as an exit out of screen (usually to the<br>ANY CHANGE? prompt). This is particularly useful to terminate change mode when the cursor is allowed<br>to be moved about freely between fields (with the above codes).|
|7|EnableSPACEBAR, returns_exitcode_=13.|
|8|EnableRUBOUTorDELETE, returns_exitcode_=14 if cursor is in the first position of the field.|
|9|EnableCTRL+^(HOME). Returns_exitcode_=9 ifCTRL+^(HOME) key hit, and should be processed as a<br>return to first field of screen.|
||9|CausesCTRL+HOMEto exit with exitcode 9. This is mainly intended for use with Windows keyboard mode<br>(<br>**|K)**where you would probably want theHOMEkey to just move the cursor to the start of the field (like<br>CTRL+U), in which case you would want to omit the type 9 and just use |9.|



A-Shell Reference 

Page 2571 

## **History** 

2025 October, A-Shell 7.0.1778: Added code **|{** . 

2020 August, A-Shell 6.5.1688:  Added code **|9** . 

A-Shell Reference 

Page 2572 

## **TYPE CODES SUMMARY** 

The following table shows all of the _type_ codes and is intended as a kind of "quick reference" for the codes. 

|**Type**|**Value**|**Description**|**Description**|
|---|---|---|---|
|Numeric|-|(hyphen)Allow Minus Sign<br>.||
|Timer|!|(exclamation point) Activate return of elapsed time during input. This is only applicable when the<br>timer parameter is specified. Note that this can be used even if time-out is not specified (by<br>setting timer=0).||
|Character|#|(number sign) Numeric (0-9). If nothing entered, displays a "0" (but returns just a blank string.)<br>Also see N.||
|Character|$|(dollar sign)|Currency Field<br>.|
|Misc|&|(ampersand)Enable protected fields<br>.||
|Misc||&|(bar ampersand) Works like a "smart" version of "&", re-enabling protected mode on exit only if<br>it was previously enabled. The "&" feature always re-enables protected mode, which was the<br>way it worked historically under AMOS.||
|Exit||{|(bar open-curly-bracket) Causes the setdef parameter to be treated as a list of immediate exit<br>characters, which is similar to the ExitChars feature in XTREE. Receipt of any of the characters<br>specified causes the field to exit with exitcode set to -51. The existing contents of the field are<br>returned, minus the character causing the exit.||



A-Shell Reference 

Page 2573 

|ll Reference||||
|---|---|---|---|
|Misc|(|(open parenthesis)|Strip leading blanks from_entry_before pre-load.|
|Misc|)|(close parenthesis)|Start cursor at end<br>.|
|Character|*|(asterisk) Accept all characters. Same as A.||
|Character|,|(comma) Punctuation allowed. Punctuation is anything other than a number or letter.||
|Numeric|.|(period)Allow Decimal Point<br>.||
|Misc||.|(bar period) ForcesINFLDto use periods rather than underlines for the field marker in text<br>mode. Previously you had to use prehistoric compatibility mode, or allow decimal points, to<br>achieve this.||
|Numeric||#|(bar hash) Disable the automatic display of "0" in a numeric field when nothing entered.||
|Timer|/|(slash) Disable all timer displays. This differs from the "+" code in that the "+" code leaves the<br>message "timing out" on the bottom line (but does not show the time)||
|Misc||/|(bar slash) Disables the display of theINFLD"about" box (normally triggered by CTRL+\). This is<br>mainly a workaround for a problem where the about box is being triggered unexpectedly.||
|GUI|||/|(bar bar slash) Removes the "client edge"—which combines a border and an internal margin—<br>from the edit box. This is useful mainly to make the edit control blend into a background,<br>perhaps related to creating a composite combining an edit control with other text on a static<br>panel, and/or to achieve a "clean" look.||



A-Shell Reference 

Page 2574 

|ll Reference||||||
|---|---|---|---|---|---|
|Misc|:|(colon)|Disable bright and dim<br>.|||
|Misc|;|(semicolon) Turn cursor on while waiting for input; turn it off again on exit from field.||||
|Exit|?|Help key allowed. Displays message on bottom line "Hit `?' for Help", and returns_exitcode_= 8 if<br>help key entered. Leaves the value of_entry_as it was before callingINFLD. Note that the help<br>key, message, and message location may be customized.||||
|Character|@|(at sign)||Control Character Input<br>.||
|Misc|[|(open bracket) Force cursor to blink during input.||||
|Misc|\|(backslash)|||Clear bottom line<br>.|
|Misc|]|(close bracket) Strip trailing blanks. Otherwise_entry_field is filled up with trailing blanks, like in<br>INPUT. The stripped blanks are not counted toward xmin.||||
|Misc||]|(bar close bracket) Defeats both the padding and stripping of trailing blanks, so that you get<br>back exactly what you typed. (See ].)||||
|GUI|||]|(bar bar close bracket) Prevents field width from being automatically expanded by logic that<br>attempts to allow for the extra space needed by various GUI enhancements. For example,<br>combo boxes smaller than six characters wide typically get an extra three characters of width to<br>account for the space needed for the dropdown button. Similar rules apply to date and time<br>pickers as well.||||
|GUI|||[|(bar bar open bracket) causes the redisplayed field to grow as needed for the contents. (This||||



A-Shell Reference 

Page 2575 

|ll Reference|||
|---|---|---|
|||was once part of the ||] code but has been removed in order to avoid slight differences in field<br>display widths which give such screens a ragged look.)|
|Misc|`|(grave)Force destructive Enter<br>.|
|Misc|||`|(vertical bar, vertical bar, grave) Forces unconditional destructive CR; text mode only.|
|Misc|^|(carat)Convert to upper case (1)<br>.|
|Misc|_|(underscore) Use clear-to-end-of-line function (-1,9) to clear field.|
|Misc||_|(bar underscore) Use underline to mark designated field (instead of default auto-beveling). See<br>Field Markers<br>.|
|Character|{|(open brace) Character acceptance is limited to the set of characters specified in setdef.<br>Typically you would combine this with "*", else the characters may be rejected before even<br>considering the setdef list.|
|Misc|}|(close brace) Activates "INMEMO" mode. This is a specialINFLDmode used internally by the A-<br>Shell implementation ofINMEMO.|
|Misc||}|(bar close brace) Activates horizontal scrolling mode. Set automatically when_maxchrs_>_xmax_.|
|Misc|||}|(bar bar close brace) Activates "command-line" mode. This is a specialINFLDmode used<br>internally by the A-Shell implementation of the dot prompt and for BASIC INPUT statements.|



A-Shell Reference 

Page 2576 

|ll Reference||||
|---|---|---|---|
|Timer|+|Disable display of time remaining (on bottom line). Normally, the time remaining until time-out<br>is displayed (and updated every second) on the bottom right corner of the screen.||
|Misc|<|(less than) Echo a carriage return on exit from the field. This is useful especially with the F and<br>@ codes to let the operator know immediately that the input is being processed.||
|Exit|||<|Type ||< may be used with ||S (selection-only combo boxes) to force an exit with EXITCODE 32<br>whenever the selection changes due to the user typing a keyboard character. The concept is the<br>same as for ||5 and ||3 as described below.||
|Misc|=|(equals) Do not reformat the field on exit. Also see |R (do not redisplay on exit).||
|Date/Time|>|(greater than)|Convert Date Format<br>.|
|GUI|||*|EnablePassword Encryption<br>.||
|GUI||*|DisablePassword Encryption<br>.||
|Character|a|Alphabetic characters allowed (a-z, A-Z), or as defined by the LDF (language definition file).||
|Character|A|All characters allowed (subject to code b). Note that A is used for compatibility with INPUT, but<br>to most people, "*" makes more sense. Note that A or "*" is equivalent to the combination "a#,"<br>(alphabetic, numeric, and punctuation).||
|Exit||a|Enable CTRL+A (when cursor already at start of field) to return_exitcode_=19. (CTRL+A normally<br>moves cursor to start of previous word.)||



A-Shell Reference 

Page 2577 

|ll Reference|||
|---|---|---|
|GUI|||a|ActivateAuto-Complete<br> mode.|
|Misc||A|Activates simulation ofXCALL AMBTOA.|
|Misc|b|Disallow blanks<br>.|
|Misc|B|Disable character blanking<br>.|
|Exit||B|Enable CTRL+B to return_exitcode_=16, and CTRL+O to return_exitcode_=17.|
|GUI|||b|For checkboxes, causes the current state of the checkbox to override the normal default state<br>(i.e. the default based on the_type_codes if opcode=0, or the contents of the entry parameter if<br>opcode=1 or 2). Useful when the checkbox statement may have been changed by clicking on it<br>outside of the awareness of the application. Same effect as cmdflg=4.|
|Misc|c|Capitalize first letter of each word.|
|Character|C|CARRIAGE RETURN only.|
|Exit||C|Enable CTRL+S to return_exitcode_=26.|
|GUI|||c|Convert Y/N Field To Checkbox<br>.|
|GUI|||C|Causes a field which would normally appear as a combo box or a date picker while editing (see<br>setdef, dates) to also appear as a combo box when not actively being edited. Otherwise, these|



A-Shell Reference 

Page 2578 

|ll Reference|||
|---|---|---|
|||kinds of fields revert to static text controls when not active. SeeActive Versus Inactive Behavior<br>.|
|Character|d|Date Input, Today<br>.|
|Character|D|Date Input<br>.|
|Date/Time||D|Defaults century to 19xx. Applies for date formats which allow user to enter only the YY. If not<br>specified, century default is determined by the SBR=CCYY:## entry inmiame.ini.|
|Date/Time|||D|Allows a date field to be filled with zeroes.|
|Date/Time||d|Allow Date Shortcuts<br>.|
|Misc|e|Force non-destructive RETURN (or ENTER). This is the default for most field types except<br>numeric. See code "`" (grave accent) above.|
|Misc|E|Abort allowed<br>.|
|GUI||E|Causes the field to retain the form of an edit control when not active. (Otherwise, fields normally<br>revert to static text controls when not active.) Also see ||C andActive Versus Inactive Behavior<br>.|
|Exit|||E|Causes ENTER to return exitcode 23 instead of the normal 0. This can be useful in certain dialog<br>situations (particularly involvingAUI_EVENTWAIT) where either the correct response to ENTER,<br>or the meaning of a response of exitcode 0, might otherwise be ambiguous.|
|Misc|f|Form Field<br>.|



A-Shell Reference 

Page 2579 

|ll Reference|||
|---|---|---|
||||
|Misc|F|Fast input<br>.|
|Misc||F||F is similar to F (fast) except that it affects the preload operation, rather than interactive<br>typing. When specified, if the preloaded characters satisfy the minimum field size, then the field<br>will exit immediately (without waiting for input).|
|GUI||f|Reserved for internal use ATE in GUI mode to control function key settings|
|GUI|||f|Force Fixed-Pitch Font<br>.|
|GUI|||F|Force Modified Fixed-Pitch Font<br>..|
|Misc|g|Return updated field contents<br>.|
|Numeric|G|May be useful for aligning decimal points in column of variable precision numbers.|
|GUI||g|Implies |G, but limits the GUI enhancements to just the Windows-style edit box (i.e. without<br>some of the other automatic enhancements such as date picker controls).|
|GUI||G|Activate GUI Enhancements<br>.|
|GUI|||g|Disable/override GUI mode. (Used to temporarily cancel a global |G or ||G or |g)|



A-Shell Reference 

Page 2580 

|ll Reference||||
|---|---|---|---|
|GUI|||G|Same as |G except turns Y/N fields into checkboxes.||
|Misc|h|Disables the help message display<br>`"Hit ? for Help"`. This may be desirable when you have<br>help on virtually every field, or when you need to use that area for some other message.||
|Character|H|Hours field. Like $ but omits the "$" from the display.||
|Date/Time||h|HexaDecade Dates (2)<br>.||
|Character|||h|Accept hexadecimal digits (A-F, a-f, 0-9).||
|Date/Time||H|HexaDecade Dates (1)<br>.||
|GUI|||H|Disable horizontal scrolling within control. Note that the ability to scroll is sometimes needed in<br>order to fit all of the allowed characters, if using proportional fonts and the field consists of<br>wider-than-normal (e.g. CAPS) characters.||
|Misc|i|(lower case I) Completely invisible field. Similar to**S**except that nothing is echoed (so you<br>cannot even see how many characters are allowed, or how many were typed.)_type_i silences the<br>beveling so that the field remains totally invisible (no cursor, no indication of field position or<br>size, no echoing of characters).||
|Misc|I|(upper case letter "eye".)|Use invisible field markers<br>. See alsoField Markers<br>.|
|Misc||I|(bar upper case letter "eye") ForcesINFLDto start in insert mode, rather than the default (which<br>may be either insert or replace mode, depending on several factors).||



A-Shell Reference 

Page 2581 

|ll Reference|||
|---|---|---|
|Misc|||I|(bar bar upper case letter "eye") Forces INSERT mode off / REPLACE mode on). This overrides<br>the remembered state for the current field, but does not change the remembered state for<br>subsequent fields.|
|Date/Time|j|Julian Date Format<br>.|
|Character|J|Accepts alphanumeric input, and if the input is wholly numeric, right justifies and fills with<br>leading zeroes.|
|GUI|||J|Right Justify Checkbox Text<br>.|
|Exit|k|Enable CTRL+E to return_exitcode_=15 (rather than its normal use as the record abort key, which<br>sets_inxctl_=1.)|
|Misc|||k|Disables internal too-fast input filter, which may otherwise cause characters fed via a burst to be<br>dropped.|
|GUI||K|Windows Keyboard Conventions<br>.|
|GUI|||K|Acts just like |K but also disables the CTRL+C abort while the field is active. This allows you to<br>use CTRL+C for copy-to-clipboard without first having to disable CTRL+C abort in the<br>application. See alsoCtrl+C Behavior<br>.|
|Misc||l|(bar lower case letter "el") Forces lower case.|
|Misc|||l|(bar bar lower case letter "el") Same as ||L except that_entry_will return a complete|



A-Shell Reference 

Page 2582 

|ll Reference|||
|---|---|---|
|||<code>,<description> pair (e.g. "01,North") instead of just the code item. SeeCoded Lists<br>.|
|Exit|L|Enable CTRL+L RIGHT-ARROW. Returns_exitcode_=12 if right arrow hit when cursor already at<br>right end of field.|
|Exit||L|The combination |L (vertical bar, L) is the same as_type_L (without the vertical bar) in that it<br>triggers_exitcode_12. The difference is that with L by itself, you can only exit from the far right<br>side of the field. (If there are characters to the right of the cursor, then the right arrow key will<br>simply move the cursor to the right.) With |L, you can exit the field from any position, provided<br>you have not already used other editing or cursor motion keys first. This mode is useful for<br>RIGHT-ARROW to skip from one field to the next.|
|Misc|||L|(bar bar upper case letter "el") List substitution._setdef_consists of <code>,<descr> pairs, e.g.:<br>,01,North,02,South,03,Middle Earth,, Application uses the code items (01, 02, ...) while the<br>operator sees and uses the description items. SeeCoded Lists<br>.|
|Misc|m|Disable default type codes.|
|Numeric|M|Thousands Separator<br>.|
|GUI||m|Prevents the ENTER key, when used to select an item from the dropdown list in a combo box,<br>from also causing the field to exit.|
|GUI||M|Multi-line edit box._xmax_sets the display width of the box._maxchrs_sets the maximum number<br>of characters allowed (up to a maximum of 1024)._defpt_is reinterpreted as the height of the<br>box. See ||H for disabling horizontal scrolling (to enable word wrap). ENTER (along with any<br>other enabled exit key) exits. SeeMulti-line Edit Control (INFLD)<br>.|



A-Shell Reference 

Page 2583 

|ll Reference|||
|---|---|---|
|GUI|||m|Causes_exitcode_13 to be returned when an item is selected from the dropdown list (using<br>ENTER or click) in a combo box. This allows you to distinguish that event from merely hitting<br>ENTER to the field when the dropdown is not displayed. The same effect also applies to fast<br>mode checkboxes, allowing you to distinguish between ENTER (which returns_exitcode_0) and a<br>click or other keystroke which changes the checkbox value and then exits (with_exitcode_13).|
|GUI|||M|Variation of multi-line edit. Allows ENTER to be used to manually break lines. Also, displays a<br>vertical scroll bar.|
|Misc|n|Return null<br>.|
|Character|N|No/Yes Field<br>.|
|Exit||N|Enable CTRL+N to return_exitcode_=22 (instead of just moving the cursor to the end of the field).|
|Misc|O|(Upper case letter "O") Optional field. Allows operator to skip the field, even if the_xmin_specified<br>is non-zero. However, if 1 or more characters are entered, then the minimum goes back into<br>effect.|
|Misc|p|Overrides_cmdflg_parameter, setting it to 1—i.e. forces command file input to be active. See also<br>MX_SETCMDINP<br>.|
|Character|P|Phone Number Or Zip Code Input<br>.|
|Misc||p|Prehistoric Compatibility Mode<br>.SeeField Markers<br>.|
|Misc||P*|This three-character_type_combination (vertical bar, P, followed by any character A-Z, [, ], ^, _)|



A-Shell Reference 

Page 2584 

|ll Reference|||
|---|---|---|
|||enables CTRL + (whatever the third character of the sequence is) to launch the pop-up utility<br>ASHPOP.RUN.|
|Misc|||p|Disables the use of the clipboard paste option.|
|Misc|||P|This may be used with the security type field (S) to automatically decrypt/encrypt a password,<br>using A-Shell's standard password encryption scheme. SeeMX_PWCRYPT<br>.|
|Misc|q|Causes field to be edited in reverse video.|
|Timer|Q|Disable time-out suspend feature. (Normally, the operator can suspend the time-out counter for<br>10 minutes by hitting CTRL+S. Suspending the timer is useful when you have to temporarily<br>interrupt data entry, as when answering the phone.) A-Shell Note: Under A-Shell, CTRL+B is the<br>suspend key.|
|Exit||Q|Enable CTRL+P to return_exitcode_=25 (instead of initiating a screen snapshot).|
|Timer|r|Time out reminder. This is similar in motivation to the w code, except that it just causes a single<br>beep, without any message, after 10 seconds have elapsed (when the timer option is active.)|
|Numeric|R|Right Justify Field<br>.|
|Misc||r|Read only<br>.|
|Misc||R|Do not redisplay field<br>.|



A-Shell Reference 

Page 2585 

|ll Reference|||
|---|---|---|
|GUI|||r|Create A Radio Button<br>.|
|Misc|s|Disable display of_setdef_options, which are otherwise displayed along the bottom line of the<br>screen. Not applicable in GUI mode, where the_setdef_options are loaded into a combo box.|
|Misc|S|Security field: echo all characters as "*". Also see**i**above.|
|Misc||s|Provides support for regular expressions in SETDEF. When |s is specified, SETDEF is interpreted<br>as a single regular expression, which the data field must match. Note that to invoke regular<br>expression flags such as PCRE_CASELESS, you will need to use the Perl-style internal option<br>settings, e.g. "(?i)[AP]M" will match AM, PM, am, pm, etc. Also note that in this mode, setdef<br>should contain only the regex pattern, with no leading or trailing delimiters.|
|Misc||S|Causes an automatic screen capture to be appended to the capture file on exit from the field.<br>SeeMX_SCRNPIC<br> for more info on screen captures.|
|GUI|||s|Makes setdef list matching optional. Only applies to the combo box, in which case it allows the<br>operator to enter a value that is not in the list.|
|GUI|||S|Variation of combo box in which typing a character only selects the nearest matching item from<br>the list. (Otherwise the user can type independently of the list, and use DOWN-ARROW to find<br>the nearest match.) SeeCombo Box Control (INFLD)|
|Date/Time|t|Time Field<br>.|
|Date/Time|th|Same as "t" but allows hh > 24. Not supported in the Windows date control, i.e. not compatible<br>with TYPE "|G" (use "|g" instead).|



A-Shell Reference 

Page 2586 

|ll Reference|||
|---|---|---|
|Exit|T|Allow TAB key as a terminator. Sets inxctl to 3 and_exitcode_to 7.|
|Timer||t|Reset timer to the initial value after every keystroke.|
|Timer||T|Overrides timer parameter to zero. Useful for disabling timer globally in programs that otherwise<br>use it (by putting this in the SBR=INFDEF: string.)|
|Date/Time|||t|Same as t (time) but in GUI mode returns the time in 12-hour format rather than 24 hour<br>format.|
|Exit|||T|Causes ENTER to act like TAB (returning_exitcode_7). This might help simplify dialog logic,<br>particularly when using EVENTWAIT with theEVW_EXCDFOCUSoption, by eliminating the need for<br>special treatment of the_exitcode_0 case.|
|LDF|u|Observe LDF rules. See LDF-Related Codes.|
|Character|U|European Date<br>.|
|Misc||u|Convert to upper case (2)<br>.|
|Exit||U|Enable CTRL+U to return_exitcode_=21 (instead of just moving the cursor to the start of the<br>field).|
|GUI|||U|Create up/down ("spinner") control. SeeUp/Down Control (INFLD)<br>.|
|LDF|||u|Ignore LDF; seeLDF-Related Codes<br>.|



A-Shell Reference 

Page 2587 

|ll Reference|||
|---|---|---|
||||
|Numeric|v|Value Range Checking<br>.|
|GUI|||v|Self Service Date Picker<br>.|
|Exit|V|Trap CTRL+C and return_exitcode_=10 (instead of the normal mode which aborts to the ASB error<br>trapping routine). Note that you must specify the_exitcode_parameter for this to work. See also<br>Ctrl+C Behavior<br>.|
|Timer|w|Timer wake up warning. When added to any set of timer related codes, causes a warning beep<br>and message when only 10 seconds remain on the timer. The message blinks TIMING OUT in the<br>lower right corner of the screen, and any key hit during the remaining 10 seconds resets the<br>timer to the original value. Note that w overrides / to display the warning message and suspend<br>message as well, if invoked. See r|
|Misc|W|Disallow record abort key<br>.|
|Exit||w|Enable CTRL+W to return_exitcode_=20 (when at the start of an empty field)|
|Exit||W|Enable CTRL+W to return_exitcode_=1 and_inxctl_=1, instead of moving the cursor to the start of<br>the next word.|
|GUI|||W|Disable the mousewheel within the context of a single combo box field. Added to A-Shell<br>6.5.1680, June 2020.|
|GUI|||x|Force coordinates (_row_,_col_) to be interpreted as pixels. This is an alternative to setting|



A-Shell Reference 

Page 2588 

|ll Reference|||
|---|---|---|
|||IMXF_PIXCOORDS; see_xmax_.|
|Character|X|Specifies a Y/N field, but with no default. May be used to force the operator to make a choice,<br>or, with_xmin_=0, to allow a third option (blank).|
|Misc||X*|Program Ctrl+X<br>.|
|Exit||XX|Enable CTRL+X to return_exitcode_=27. Note that this is a special case of the general three-<br>character_type_sequence |X* which causes CTRL+X to be interpreted as CTRL+* (where * is any<br>character compatible with the control key).|
|Character|Y|Yes/No Field<br>.|
|Numeric|Z|Zero Fill<br>.|
|Exit||Z|Enable CTRL+Z to return_exitcode_=18 (instead of clearing the field).|
|Misc|0|(zero) Strip away all characters typed ahead into the input buffer before inputting the field.<br>Useful when you want to make sure that the operator reads a message or prompt before<br>answering it.|
|Exit|1|Enable ESCAPE, returns_exitcode_=1. Note that this is only effective when used without the E<br>code (see above). This differs from ESCAPE with the E code in that the contents of the field are<br>not overwritten with "END". Also note that the CTRL+E abort key also returns_exitcode_=1.|
|Timer|||1|Modifies the timeout feature causing it to start out suspended. SeeTimer-Related Codes<br>for|



A-Shell Reference 

Page 2589 

|ll Reference|||
|---|---|---|
|||more detail.|
|Exit|2|Enable LEFT-ARROW (BACKSPACE on most PCs), returns_exitcode_=2. This is only effective<br>without the E code, and is intended to be processed as a move to previous field.|
|Exit||2|(vertical bar followed by 2) (Windows/ATE) (GUI mode only) Forces SHIFT+TAB to return<br>_exitcode_2 (like left arrow would if_type_2 was specified). Otherwise SHIFT+TAB acts exactly like<br>UP-ARROW, meaning it will exit with_exitcode_set to 3 if_type_3 specified. Unlike left arrow,<br>SHIFT+TAB does not require that the cursor be in the home position in order to be treated as an<br>exit key. Note that_type_|2 neither requires_type_2 nor implies it. In other words,_type_|2 by itself<br>will enable SHIFT+TAB exits (setting_exitcode_2) but will not enable the LEFT-ARROW exit. Use<br>_type_2|2 or |22 to allow both methods of exiting.|
|Exit|3|Enable UP-ARROW, returns_exitcode_=3. Should be processed as either a return to previous field,<br>or to next field above cursor in same column.|
|Exit||3|Types |3 and |5 are equivalent to the existing Types 3 and 5, respectively, except that if used<br>with a combo box, they also cause the up/down arrows to exit immediately (with the<br>corresponding exitcode), rather than scroll among the choices in the combo box, PROVIDED<br>THAT the combo box is not already in the dropdown position. (This is directly analogous to the<br>XTREEcoldef option ScrollMode=Tree.) An additional side-effect of |3 and |5 (versus 3 and 5) is<br>that SHIFT+UP-ARROW and SHIFT+DOWN-ARROW will now act as they do in text mode (i.e. get<br>translated via the function key translation system), even if |K (Windows keyboard mode) is in<br>effect.|
|Exit|||3|Types ||5 and ||3 act just like |5 and |3 respectively, except that the exit occurs AFTER updating<br>the display (with the next or previous item in the list), instead of BEFORE. Thus they work<br>similarly to the SelChgExit feature ofXTREE, allowing you to update some other display element<br>to correspond with the currently displayed item in the combo box.|



A-Shell Reference 

Page 2590 

|ll Reference|||
|---|---|---|
|Exit|4|Enable CTRL+R, returns_exitcode_=4. Should be processed as a return to first field in screen, or<br>to previous screen (in multi-screen applications).|
|Exit|5|Enable CTRL+J (down arrow), returns_exitcode_=5. Should be processed as an advance to next<br>field or next line (skipping fields on current line).|
|Exit||5|See |3.|
|Exit|||5|See ||3.|
|Exit|6|Enable CTRL+T, returns_exitcode_=6 and should be processed as an exit out of screen (usually to<br>the ANY CHANGE? prompt). This is particularly useful to terminate change mode when the<br>cursor is allowed to be moved about freely between fields (with the above codes).|
|Exit|7|Enable SPACEBAR, returns_exitcode_=13.|
|Exit|8|Enable RUBOUT or DELETE, returns_exitcode_=14 if cursor is in the first position of the field.|
|Exit|9|Enable CTRL+^ (HOME). Returns_exitcode_=9 if CTRL+^ (HOME) key hit, and should be<br>processed as a return to first field of screen|
|Exit||9|Causes CTRL+HOME to exit with exitcode 9. This is mainly intended for use with Windows<br>keyboard mode (|K) where you would probably want the HOME key to just move the cursor to<br>the start of the field (like CTRL+U), in which case you would want to omit the type 9 and just<br>use |9.|



A-Shell Reference 

Page 2591 

## **ENTRY** 

_entry_ is a fixed or dynamic string parameter in which the response is returned. Depending on the value of the _opcode_ parameter, it may also be used to preload the contents of the field. 

Note that when preloading the field, trailing blanks are stripped (unless _type_ **|]** is specified). When returning the field, trailing blanks are added (up to the length specified by _xmax_ ), unless _type_ **]** is specified, in which case they are stripped, or _type_ **|]** is specified, in which case they are neither added nor removed. 

## **Comments** 

If the mapped length of entry is fixed (i.e. not S,0), then it should be at least as large as the larger of _xmax_ and _maxchrs_ .  If less than _xmax_ , _xmax_ will be reduced accordingly.  If less than _maxchrs_ , the returned contents may be truncated. Be aware of cases where _entry_ may need to be larger than _xmax_ , such as in list substitution ( _type_ **||L** ) where data returned may be longer than the data as entered or displayed. 

A-Shell Reference 

Page 2592 

## **INXCTL** 

INXCTL returns a code indicating how field was exited. If a numeric parameter is specified, then it will return one of the following: 

|**Value **|**Description**|
|---|---|
|0|Input OK, no message.|
|1|Affirmative answer to yes/no field (see type codes<br>**Y**,<br>**N**,<br>**X**) orCTRL+Eentered (indicating desire to abort)|
|2|Negative answer to yes/no field, orLEFT-ARROWorESCAPEentered (when enabled by the<br>**E**code)|
|3|Tab key used to terminate input when enable for the T code.|



If the parameter is specified as an S,1 variable, then it will return the actual character that caused the field to exit. Virtual function key sequences will be indicated by chr(250). 

Note that INXCTL is mostly a holdover from its AlphaACCOUNTING precursor INPUT.SBR and is largly superseded by _exitcode_ which offers a much wider variety of information. 

A-Shell Reference 

Page 2593 

## **PARENTID** 

If _parentid_ is not specified, or contains a numeric 0, the value of _row_ is multiplied by two. This code is believed to be a holdover from the days when the first 24 line terminals appeared, replacing the 12 line models. (This parameter was previously called _V_ , apparently a reference to the original VT-xxx terminals that made the transition from 12 to 24 lines.) Note that despite the "parent" in the parameter name, it is also possible to use it to name the current control, but that "parent" was chosen because in the vast majority of cases, that will be the main significance of the parameter. 

(GUI) If _parentid_ is numeric and greater than 1, it is interpreted as referencing the parent control whose ID is _parentid_ -1. The current field is treated as a child of that control, which among other things means that its coordinates are taken as relative to the parent, allowing them to be relocated simply by relocated the parent, e.g. dialog, groupbox, tab control, etc. 

(GUI) If _parentid_ is a string, it can identify the name of the parent control rather than its ID number. It can also assign a name to the current control by preceding it with the character ">". If specifying both, start with the parent control name, then the ">", then the current (edit) control name. For example: 

```
MAP1 PARENTID,S,50
```

```
   parentid = "dlgCustomer"
```

```
   parentid = "dlgCustomer>editName"
```

```
   parentid = ">editfName"
```

Note that if _parentid_ contains the name to be assigned to the current INFLD control, it must be preceded by a ">", and it must follow the parent control name, if present (as in the examples above). The maximum length of a control name is 24 characters. See Control names for more details on the concept of identifying controls with names. 

A-Shell Reference 

Page 2594 

## **OPCODE** 

## _opcode_ specifies operational options such as pre-load, output vs. input, or format conversion: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|INFOP_EDIT|&h0000|Normal operation (input). Field is cleared first.|
|INFOP_PRELOAD|&h0001|Like INFOP_EDIT (0) except contents of_entry_are preloaded into the field<br>and displayed before input. Note that for codes d, Y, and N (Y/N),_entry_<br>overrides the standard default only when_entry_is non-null. Also note that<br>leading fill characters in R and Z fields, and trailing blanks in all field types<br>will be stripped to simplify editing. You can, however, force it to keep one<br>or more trailing blanks by supplying them as CHR$(160) (which is a blank<br>with the eighth bit set).This can be useful in conjunction with the ")" code|
|INFOP_DISPLAY|&h0002|Format and output contents of_entry_. (No input)|
|INFOP_SIMPLE|&h0004|Speed and cursor motion optimized version of_opcode_2; assumes screen<br>already clear. Relevant only for text mode.|
|INFOP_FORMATTED|&h0008|Like INFOP_EDIT (0) except returns_entry_formatted.|
|INFOP_PRELOAD +<br>INFOP_FORMATTED|&h0009|Like INFOP_PRELOAD (1) except returns_entry_formatted. Note that you<br>must de-format the field (somehow) between successive_opcode_=9 calls to<br>the same field.|



A-Shell Reference 

Page 2595 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|INFOP_PRELOAD +<br>INFOP_DISPLAY|&h000A|Like INFOP_DISPLAY (2), except returns_entry_formatted.|
|INFOP_FMTONLY|&h001C|Format conversion only. Takes_entry_unformatted and returns it formatted.|
|INFOP_READONLY|&h0021|Read-only input mode. Field loaded with_entry_, but cannot be changed.<br>_Exitcodes_however are still possible. This might be useful in a case were<br>you want to allow a user to review previous entry fields, but only change<br>them by first hitting some kind of special_exitcode_and then entering a<br>password. This has the same effect as_type_<br>**|r.**|



A-Shell Reference 

Page 2596 

## **EXITCODE** 

_exitcode_ , if specified, receives a value to indicate how the field was exited. Note that for a specific value (except 0) to be returned, it must be activated by a corresponding _type_ code (for the positive EXITCODEs), or by the _funmap_ parameter controlling function key usage (for the negative _exitcodes_ ). 

The number of command or function keys is limited by your terminal and function key translation module, subject to a maximum of 127 for direct function keys, and 999 for "virtual" function keys using the chr(7)+chr(250)+###. sequence.. Note that we use the terminology _Command Keys_ (Cmdx) in place of _Function Keys_ (Fxx) to underscore the idea that they can be mapped on to the physical function keys any way you like. 

When **|K** (Windows keyboard mode) is NOT used, the SHIFT+ARROW keys work like function keys (same as they do in text mode), and will generate exitcodes based on the <tdv>.IFX translation table. The standard exitcodes for the shifted arrows are: -36, -37, -38 and -39. See FIXTRN.LIT for details on editing translation tables. 

|**Value **|**Symbol**|**Description**|
|---|---|---|
|0||RETURN (ENTER), orTABwhen<br>**|K**code used.|
|1|EXC_ESC|ESCAPE(if neither E nor W codes used), orCTRL+Wif the<br>**|W**code<br>used.|
|2|EXC_LEFT|LEFT-ARROW(^H) orESCAPE(when E code used), orSHIFT+TAB<br>when<br>**|2**used.|
|3|EXC_UP|UP-ARROW(^K) when enabled with 3 code, , orSHIFT+TABwhen in<br>GUI mode (**|G**)|
|4|EXC_PGUP|PAGE-UP (^R)when enabled with 4 code|



A-Shell Reference 

Page 2597 

|**Value **|**Symbol**|**Description**|
|---|---|---|
|5|EXC_DOW<br>N|DOWN-ARROW (^J)when enabled with 5 code|
|6|EXC_PGDN|PAGE-DOWN (^T)when enabled with 6 code|
|7|EXC_TAB|TAB(when enabled with<br>**T**code)|
|8|EXC_HELP|HELP (?)when enabled with<br>**?**code|
|9|EXC_HOME|HOME (CONTROL ^)when enabled with<br>**9**code|
|10|EXC_CTRL<br>C|Ctrl+C Trap (when enabled with<br>**V**code). See alsoCtrl+C Behavior<br>.|
|11|EXC_TIME|Field timed out|
|12|EXC_RIGH<br>T|RIGHT-ARROW (^L)when enabled with<br>**L**code|
|13||SPACEBAR(when enabled with<br>**7**code) or user selected an item in<br>the dropdown area of combo box usingENTERorCLICK(when<br>enabled with<br>**||m**code).|



A-Shell Reference 

Page 2598 

|**Value **|**Symbol**|**Description**|
|---|---|---|
|14||RUBOUTorDELETE(when enable with<br>**8**code)|
|15||CTRL+E(when enabled with the<br>**k**code)|
|16||CTRL+B(when enabled with the<br>**|B**code)|
|17||CTRL+O(when enabled with the<br>**|O**code)|
|18||CTRL+Z(when enabled with the<br>**|Z**code)|
|19||CTRL+A(when enabled with the<br>**|a**code)|
|20||CTRL+W(when enabled with the<br>**|w**code)|
|21||CTRL+U(when enabled with the<br>**|U**code)|
|22||CTRL+N(when enabled with the<br>**|N**code)|
|25||CTRL+P(when enabled with the<br>**|Q**code)|
|26||CTRL+S(when enabled with the<br>**|S**code)|



A-Shell Reference 

Page 2599 

|**Value **|**Symbol**|**Description**|
|---|---|---|
|27||CTRL+X(when enabled with the<br>**|XX**three-character code)|
|29||User clicked on dropdown button inSelf Service Combo Box|
|30||(Auto-Complete<br>)User has modified the field and then paused or hit<br>Down-Arrow;INFLDrequests an updated setdef parameter<br>containing the drop-down list configuration and contents.|
|31||(Auto-Complete<br>)User has hitCTRL+DOWN-ARROWfrom bottom item<br>of auto-complete list request additional items. Application may<br>replace list with new data, or just add to the existing list, at its<br>option.|
|-1||(Cmd1) (When enabled via translation table and/or (_funmap_))|
|-2||(Cmd2) etc.|
|-35||SHIFT+TAB; note 1|
|-65||CTRL+PAGE-DOWN; note1|
|-66||CTRL+PAGE-UP; note1|



A-Shell Reference 

Page 2600 

|**Value **|**Symbol**|**Description**|
|---|---|---|
|-67||CTRL+HOME; note 1|
|-68||CTRL+END; note 1|
|-69||Click on close-tab "x" button in TabX control|
|-75||File(s) dragged-and-dropped on to a control with the<br>WS_EX_ACCEPTFILES attribute. SeeMX_DRAGDROP<br>.|
|-###||(Virtual function key) Triggered by a function key or a mouse-click<br>on a field which was programmed to send the sequence<br>chr(7)+chr(250)+"###." where ### is any number. See_hlpidx_.|



## **Comments** 

The upper bit of the _funmap_ parameter must be set in order to enable the specified _exitcode._ This can be accomplished by setting _funmap_ = -1, enabling all function key exits as well, or by adding 2^31 to any other _funmap_ value. 

## **See Also** 

- Exit Key Enabling Codes 

A-Shell Reference 

Page 2601 

## **TIMER** 

_timer_ , when specified and non-zero, causes the field to time-out (returning _exitcode_ =11) after the number of seconds specified (in _timer_ ). If _type_ **!** is not specified, then _timer_ is not modified on exit from INFLD. This allows you to use a fixed time-out value on every field without having to reset it each time. 

However, if _type_ **!** code is specified, then the elapsed time (in seconds) is returned in _timer_ . Stand advised that although the elapsed time is quite accurate, the time-out period may become elongated by up to 15% due to heavy system activity. This should not cause any inconvenience, as long as you check for time-out by seeing if _exitcode_ =11 and not by comparing the elapsed time (returned in _timer_ ) to the original _timer_ value. For example, if you set _timer_ to 30, and the field times out, the elapsed time (returned in _timer_ ) may actually be 29-32 seconds. So check the _exitcode_ to see if time-out occurred, and if you want to know the precise elapsed time, use the returned value of _timer_ . 

## **Comments** 

- See Timer-Related Codes for a complete list of the _type_ codes that affect the timer 

- feature. 

- If you only care about the elapsed time (and don't want to time out), then you need to set the initial timer value to 

- something suitably large. The elapsed time feature doesn't work if the initial timer value is 0. You would also probably want to disable the timer displays with the **/+** _type_ codes. 

A-Shell Reference 

Page 2602 

## **CMDFLG** 

_cmdflg_ may be set to one or more of the following flags. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|INFCF_CMDFIL|1|Enable command file input. This flag causes INFLD to attempt to read from a command file. If no<br>characters are available, it will then accept input from the keyboard. Command file input can be<br>turned on and off on a field-by-field basis. Note that you can override cmdflg (force it on) using<br>the type code p.|
|INFCF_DROPDOWN|2|(GUI only) Force drop-down display. This flag applies only when INFLD is used in GUI mode (see<br>type |G) and the field is implemented using a control type that has a drop-down option (e.g. date<br>picker, combo box). In such a case, the drop-down display will be triggered automatically at the<br>start of the field editing operation (as if the user had clicked on the drop-down button).<br>Note that this usage is often appropriate when the field is being called in response to a mouse<br>click. One way to detect that within a centralized INFLD wrapper routine would be to check if the<br>incoming value of exitcode matches the value associated with the current field (as defined in the<br>hlpidx parameter).|
|INFCF_EXISTING|4|(GUI only) Set initial value based on existing control. This flag applies only to checkboxes, in<br>which case it causes the initial field value to be loaded from the current state of the existing<br>checkbox (assuming there is an existing checkbox control at the specified coordinates) rather<br>than the entry parameter. This helps deal with the fact that clicking on a checkbox (even when it<br>is not currently under the control of INFLD) may toggle the value of the checkbox (in addition to<br>sending the keyboard string associated with the field). If your app responded to the resulting<br>exitcode by calling INFLD to edit the clicked-on checkbox, the app's copy of the checkbox's value<br>(stored from the previous time it was edited with INFLD) may be out of sync with the new actual<br>state of the checkbox, in which case it would appear to the user that it sometimes takes two<br>clicks to get the checkbox to change value.|



A-Shell Reference 

Page 2603 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||This is equivalent to setting type ||b.|
|INFCF_DISABLE|8|Disable the control. Use of this flag causes the field to be set to the disabled state. This is mainly<br>useful in GUI mode with opcode 2 (display) to display a field value but indicate to the user (by<br>the fact that it is in dim gray) that it is not presently applicable (and cannot be edited). Since you<br>cannot edit a disabled field, attempting to use this flag with opcode 0 or 1 will cause it to act just<br>like opcode 2, except that any incoming positive exitcode value is preserved (instead of being<br>reset to 0 as would normally be the case with a display operation). This should help your existing<br>field navigation logic to jump over disabled when moving backwards through them.<br>Note that a normal field display operation (i.e. opcode 2 and cmdflg not containing<br>INFCF_DISABLE) will cause a previously disabled field to be re-enabled. Thus it might be<br>necessary for your program to maintain a separate copy of the cmdflg parameter for every field<br>that might be disabled, in order to preserve its state.|



A-Shell Reference 

Page 2604 

## **DEFPT** 

_defpt_ may be used to specify the default decimal point position relative to the right of the field. A value of zero indicates a default just following the last digit entered. If this parameter is omitted, there will be no default. (If this parameter is passed but you do not want a default, set it to -1.) 

The action of _defpt_ depends on whether the **.** (allow decimal point) _type_ code is used. If it is, then any default decimal points will actually be inserted into (and returned in) the field. If the **.** code is not specified, any default decimal points will be inserted for display purposes only. 

Note that the _type_ codes **$** and **H** will automatically set _defpt_ to 2 if "." not specified, and 0 if it is specified. However, you can over-ride this by setting _defpt_ to anything you want. Also note that you can set _defpt_ to -2 to edit currency in whole numbers without a decimal point. 

Note also that in multi-line mode (i.e. when _type_ **|M** or **||M** is specified), _defpt_ is re-interpreted as the display height of the control in rows. 

A-Shell Reference 

Page 2605 

## **MAXPT** 

_maxpt_ may be used to specify the number of digits after a decimal point If the **.** code is used, then INFLD will prohibit the operator from entering any more than < _maxpt_ > digits past a hard decimal point. In any case, the display will be padded with enough zeroes or blanks (depending on the G code) to have < _maxpt_ > digits after the decimal point. 

If the parameter is omitted, no such checking will take place. However, if you specify the parameter and the value is zero, it will not allow any digits past the decimal point. If you need to specify the parameter but do not want any such checking, set it to -1. 

Note that the **$** and **H** codes automatically set _maxpt_ to 2 (unless you set it otherwise), and it will always be set to the same as _defpt_ , if _defpt_ is specified and _maxpt_ is not specified 

A-Shell Reference 

Page 2606 

## **FUNMAP** 

_funmap_ is interpreted as a bitmap controlling the function key translation. If _funmap_ is not specified, all function keys will be translated exactly as in the function key translation module. Depending on which of the three function key translation architectures you decide to use (FIXTRN, SET PFK, or the A-Shell "virtual" method), _funmap_ may be used to override editing translations to return an _exitcode_ (F#=-#) or select which functions keys are enabled. Since _funmap_ contains only 32 bits, it can only enable/disable F1 through F32 directly. Any function key value beyond F32 is enabled by the high bit of _funmap_ (2**31). Set _funmap_ to -1 to enable all F1 thru F128. 

A-Shell Reference 

Page 2607 

## **INFLD FUNCTION KEY TRANSLATION** 

**A-Shell Note:** The only function key translation method which is strictly binary compatible between AMOS and A-Shell is the FIXTRN method. Tables created by FIXTRN.LIT under AMOS and FIXTRN.LIT under A-Shell are binary compatible, assuming equivalent terminal drivers. (The PCTDV and PCTDVG drivers used by A-Shell/Windows are function-key compatible with the AMOS AM65 driver.) SET PFK style translations are operationally compatible between A-Shell and AMOS but the tables themselves are not binary compatible. 

When using the FIXTRN or SET PFK function key translation architectures, it is not possible for a single key to have both _editing_ and _command_ translations, so to get **command** EXITCODEs, you have to set the translation table up to do that directly. The procedure is to translate the function key to CTRL+G (ASCII value 7) followed by the ASCII character whose value is the _exitcode_ (negative) you want. For example, you might translate **F5** to CTRL+G CTRL+E. Since the ASCII value of CTRL+E is 5, INFLD will translate this sequence to _exitcode_ -5. (CTRL+G was chosen as the lead-in since it is generally reserved for some non-editing auxiliary function in other editing utilities. Prior to version 6.1 however, INFLD used CTRL+B for this function.) 

Since you have to translate all function keys directly to EXITCODEs in the translation table when using FIXTRN or SET PFK to make your tables, the _funmap_ parameter only controls which function keys will have command translations enabled. The standard plan would be to set up the .IFX module to translate all the F keys (that could ever be used for command EXITCODEs) as discussed in the preceding paragraph. Then the _funmap_ parameter is set at runtime to enable selected function keys, according to the table above. For example, to enable F1, F3, and F5, you would set _funmap_ = 1 + 4 + 16. The main difference here between using the proprietary translation architecture module and either of the SET PFK or FIXTRN architectures is that with the proprietary format, merely setting the appropriate bit in the ( _funmap_ ) parameter will enable the function key, while with the SET PFK/FIXTRN formats, you have to both set the appropriate bit in _funmap_ and define the appropriate translation within the .IFX module. 

There are two other possibilities for command function key EXITCODEs. One is to key them in directly from the keyboard at run time. From a programming standpoint, the _funmap_ parameter is used exactly the same with the alternate keyboard sequences as with the SET PFK or FIXTRN translations. 

The other is to use the new A-Shell "virtual" function key codes, which are typically associated with clicking the mouse on a field or button. These are defined using the sequence chr(7) + chr(250) + "###." where ### may be any number, 1 through 99999. This method allows you associate a (negative) _exitcode_ value with just about every object or command in your entire application. See the _hlpidx_ parameter for associating such sequences with inactive INFLD objects, and AUI_CONTROL for associating them with other kinds of control objects (buttons, static text fields, etc.) 

A-Shell Reference 

Page 2608 

## **SETDEF** 

_Updated and reviewed April 2013_ 

_setdef_ is is used for any of the following: 

List of Valid Inputs 

Dummy List of Inputs 

List of Paired Inputs 

Date or Value Range Checking 

Form Field 

Character Acceptance List 

## Regular Expression 

Note that since the typical length requirement for the _setdef_ string can vary widely, it is particularly convenient to map it as a dynamic string; see S and X variables in Dynamically Sized Variables. 

## **See Also** 

- Invalid Input Message 

- Setdef Limits 

A-Shell Reference 

Page 2609 

## **LIST OF VALID INPUTS** 

If the field is not a date, and the type **{** (character set list) is not specified, then _setdef_ is interpreted as a list of possible complete entries. In text mode, the choices will display on the bottom line of the terminal (as many as will fit) to assist the operator, unless disabled with the **s** code. A null string disables the feature—i.e., accepts all inputs. 

If _setdef_ is specified as a string, the format is: 

```
/x1/x2/x3/x4/..../xn//)
```

## Where: 

`/` Represents the element delimiter. It may be any non-numeric character except the minus sign. We suggest slash or comma. Note that the delimiter character must appear once in the first position, once between each element in the list (all blanks are significant), and twice at the end of the list. 

`xn -` The elements x1, x2, etc., represent the allowable inputs. They may be any length (up to the length of the field) and may differ in length. All characters are significant, as is upper/lower case. 

The list elements may contain any of the following wildcards: 

|**Wildcard**|**Result**|
|---|---|
|*|Matches anything. Used only at the end of an element.|
|?|Matches any one character.|
|#|Matches any numeric digit.|
|@|Matches any alphabetic digit.|



A-Shell Reference 

Page 2610 

_setdef_ may also be specified as an ordered map (see _History_ below), whose keys will be used as the items in the list (x1, x2, ... in the string version described above), and the values are ignored. For example: 

```
dimx $colors, ordmap(varstr; varstr)
```

```
$colors("red") = ""        ! values ignored here
```

```
$colors("green") = ""
```

```
$colors("blue") = ""
```

```
xcall INFLD, row, col, xmax, xmin, entry, inxctl, pid, op, exitcode, timer, cmdflg, defpt, maxpt, funmap,
$colors()
```

The string equivalent of the above would be: 

```
map1 setdef$,s,0
```

```
setdef$ = "\red\green\blue\\"
```

```
xcall INFLD, row, col, xmax, xmin, entry, inxctl, pid, op, exitcode, timer, cmdflg, defpt, maxpt, funmap,
setdef$
```

The string version is actually simpler to set up, but the ordered map version may be handier in situations where the map already exists for other reasons. 

In GUI mode (type code **|G** ), a field with this type of _setdef_ list will be converted to a drop-down combo box or spinner. (See - GUI Related Codes for additional type codes that adjust the behavior of the combo box, particularly **||C** , **|M** , **||S** , **||s** , **||U** and **|| W** ). Note that in this mode, the length of the items in the list may be longer than _xmax_ , in which case the entry only has to match the first _xmax_ characters of an item in the list—and only the first _xmax_ characters are returned to the calling program. An example of a situation where this would be useful is a list of states, where you are only interested in the 2 character code, but to 

A-Shell Reference 

Page 2611 

be helpful to the operator, the drop-down list could also contain the full name of each state.  Also see List of Paired Inputs for an alternate way to handle this scenario. 

## **See Also** 

- _type_ **||C** for forcing the field to be displayed as a combo box even when inactive. Without **||C** , after exiting from the combo 

- box editing mode, the field will be redisplayed as a normal sunken, static text field. 

- **||S** and **||s** for variations on the combo box matching logic. 

- cmdflg INFCF_DROPDOWN flag to force drop-down to open automatically 

- Auto-Complete 

## **History** 

- 2023 March, A Shell 6.5.1727:  Add support to _setdef_ for Ordered Maps 

A-Shell Reference 

Page 2612 

## **DUMMY LIST OF INPUTS** 

In GUI mode, if _setdef_ is set to three dots (" `...` "), then INFLD appears as combo box, but any action that would cause the dropdown box to appear (clicking on the drop down button or hitting ALT+DOWN) instead causes INFLD to exit with _exitcode_ 29. The idea is to allow the application to then build its own list of choices based on the partial data entered in the field. See Self Service Combo Box. 

## **See Also:** 

- Coded Lists 

A-Shell Reference 

Page 2613 

## **LIST OF PAIRED INPUTS** 

If type **||L** or **||l** is specified, then _setdef_ is interpreted as list of pairs, where the first item in each pair is the abbreviated form and the second member is the descriptive form, i.e.: 

- `/01/South/02/North/03/Middle Earth/04/Purgatory//` 

In the list above, 01,02,03 and 04 are the abbreviated forms what will be used by the application internally, whereas "South", "North", etc. are the descriptive forms that the user will user and type or select from the combo box. 

Alternately, the same information can be specified in the form of an ordered map, similar to the method described in List of Valid Inputs, except here the map keys are the abbreviated forms and the values are the descriptive (display) forms, e.g.: 

```
dimx $regions, ordmap(varstr; varstr)
```

```
$regions("01") = "South"
```

```
$regions("02") = "North"
```

```
$regions("03") = "Middle Earth"
```

```
$regions("04") = "Purgatory"
xcall INFLD, row, col, ...., funmap, $regions()
```

- See the GUI Related Codes for more details and variations. 

## **History** 

- 2023 March, A Shell 6.5.1727:  Add support to _setdef_ for Ordered Maps 

A-Shell Reference 

Page 2614 

## **DATE OR VALUE RANGE CHECKING** 

For numeric fields, when the type **v** is specified, the _setdef_ parameter must contain a two-element list consisting of the minimum allowed value and the maximum allowed value. For example, ",23,99,," would allow a range from 23 to 99. Note that the delimiter used to separate the two values must be a valid AMOS numeric delimiter, such as space, comma, or backslash. 

For date fields, type **v** is not specified, and the _setdef_ parameter may be used to specify the first and last allowable dates. To use this feature, specify a standard format _setdef_ list with only two elements: the beginning and ending dates. The dates must be in YYMMDD ( _xmax_ =6) or YYYYMMDD ( _xmax_ =8) format (regardless of the input format). 

## Examples: 

|**setdef string**|**Result**|
|---|---|
|/M/F//|Matches only `M' or `F'|
|,TALL,SHORT,PORTLY,PETI<br>TE,,|Matches `TALL', `SHORT', `PORTLY', or `PETITE'.|
||##-*|@@#|||Matches anything starting with 2 numeric digits followed by a dash,<br>or any 3 character field in which the first two are alphabetic and the<br>third numeric.|
|\M@*\\|least two alphabetic characters, with the first one `M'. (MR., MRS.,<br>MS., etc.)|
|\850101\851231\\|When used with a date_type_code (<br>**D**,<br>**d**, or<br>**U**), will match any date<br>between 1-Jan-85 and 31-Dec-85, inclusive.|
|,-40,49,,|When used with_type_<br>**v**in a numeric field, will match only values|



A-Shell Reference 

Page 2615 

|**setdef string**|**Result**|
|---|---|
||ranging from negative 40 to positive 49.|



A-Shell Reference 

Page 2616 

## **CHARACTER ACCEPTANCE LIST** 

_setdef_ may specify a list of acceptable characters rather than complete field entries. To use this method, specify the **{** code and then load _setdef_ with a string of the characters you want to accept. Note that any input characters must first pass the normal _type_ code test and then must be in the _setdef_ string, so you may wish to specify the A _type_ code as well. For example: 

```
setdef = " 123ABCabc+-"
```

This would limit input to the numbers 1, 2, and 3; the letters A, B, C, a, b, and c; the plus sign, minus sign, and space. Note that upper and lower case must be listed independently. 

A-Shell Reference 

Page 2617 

## **REGULAR EXPRESSION** 

When the **|s** _type_ code is specified, _setdef_ is treated as a regular expression which the field contents must match. 

Note that unlike most or all of the other _setdef_ cases, in this case, no leading or trailing delimiters are used, just the regular expression itself. 

Also note that in general, regular expressions can match anywhere in the field, which means that the field could contain additional leading or trailing characters which don't have any connection with the pattern. Typically this is not what you intended. To force the expression to match at the start and/or end of the field, you may want to include the regular expression anchor characters **^** (start of field) and **$** (end of field).  For example, let's say you want to only accept fields starting with an optional numeric digit and ending with a mandatory character in the range of a-z.  Now consider the following two regular expressions: 

```
setdef = "\d?[a-z]"
```

```
setdef = "^\d?[a-z]$"
```

The first expression is close, but would match a field containing "a!", since the first part of the pattern (the numeric digit) is optional, the "a" matches the second part of the pattern, and there is nothing preventing additional characters after that.  The second version closes that loophole by forcing the start of the pattern to match at the start of the field, and the end of the pattern to match at the end of the field, eliminating the possibility of extra characters not envisioned by the pattern. 

A-Shell Reference 

Page 2618 

## **INVALID INPUT MESSAGE** 

(GUI mode only) When _setdef_ is used to enforce a pattern or range or other limitation on the field, if the input does not pass muster, INFLD will display an error message saying "Invalid Input". The actual text of the message comes from SYS:SBRMSG.xxx message number 011,010. Since this can be frustrating for the user if the pattern or range is not obvious, INFLD will display the pattern string from _setdef_ if you add a trailing "%s" to the message definition as shown here: 

```
011,010,Invalid Input %s
```

A-Shell Reference 

Page 2619 

## **FORM FIELD** 

- [ _Type_ code = **f** ] 

If the type code **f** is specified, _setdef_ is used to specify a "form" (or "masked input") using the following special characters: 

- **9** matches any digit 

- **A** matches any alphabetic character 

- **X** matches any character 

Anything else is a "form background" character, which magically appear in the field when the field gets to the required size, and the cursor jumps over them as you type. 

## **Examples** 

```
(999) 999-9999      (North American telephone number)
```

```
99-XXX-99           (e.g. 05-Feb-09)
```

## **Comments** 

- The form characters will appear automatically within the field as needed, and cannot be moved by the user, thus both 

- simplifying and enforcing data entry rules. However, they are not returned with the field data (unless you add +8 to the opcode). 

- In text mode, the form characters will appear even in an empty field, but in GUI mode, they do not appear until required by 

- the number of characters entered. (This is because GUI mode usually involves proportional text, and since proportional spaces are so narrow, the form characters would probably initially confuse users.) If you want the entire form to be apparent at the start of entering a field, you may want to pre-fill it with (non-space) filler characters, such as "0" or "X". 

- Any characters entered must satisfy both the form characters and the _type_ codes, so generally you would use _type *_ (all 

- characters accepted) and rely on the form characters to further limit it. 

- If xmin is shorter than the form length, the user will not be required to enter the remaining characters. For example, an 

- extended zip form of "99999-9999" would allow an entry of "12345" if xmin <= 5. 

A-Shell Reference 

Page 2620 

• As of 5.1.1200, forms may be used with date fields, although the form must contain only two separator characters and they must be in the 3rd and 6th position of the form, which must otherwise contain all 9's. (For example, "99/99/99" and "99-999999" are acceptable, but " 99 - 99 - 99" would not be, because of the extra spaces.) 

A-Shell Reference 

Page 2621 

## **SETDEF LIMITS** 

There is no particular limit to the length of _setdef_ when running in text mode or in local Windows, but in the ATE environment, the default maximum length is 3072 bytes. Beyond that, you may be better off using a control such as XTREE. But if you can expand that limit using the AG_BUFSIZ command. The buffer size specified must be large enough to handle all of the arguments of INFLD, which in this context usually just means the maximum size of _setdef_ , plus perhaps another 1K to handle the rest of the parameters. 

A-Shell Reference 

Page 2622 

## **INFCLR** 

_Reviewed July 2020_ 

_infclr_ allows the specification of various color palettes which are then automatically invoked for the corresponding situations. If specified, it must be mapped as instance of the ST_INFCLR or ST_INFCLRX structures as defined in the file INFLD.SDF, or equivalent. You may use a literal zero as a placeholder if you don't care about the parameter but need to specify a subsequent parameter.  The remainder of this topic discusses the ST_INFCLR version; see the following sub-topic for the ST_INFCLRX version. 

The effect of any of these colors can be disabled by setting it to -1, which causes INFLD to use the color setting which was in effect when INFLD was called. The standard AM72 color selections range from 0-15, where 0 is usually black, so if your field seems to disappear, you should check if you accidentally left any of the color palettes 0 on 0 (black on black). 

|**Color**|**Codes**|**Description**|
|---|---|---|
|Display|DFCLR, DBCLR|Used whenINFLDis called to display a field (OPCODES 2, 4, 10 and 12). The editing<br>colors (EFCLR and EBCLR) are used while you are editing a field (unless it is a negative<br>number). Setting DFCLR and/or DBCLR to a palette index value +64 overrides the<br>theme color (provided you don't have the Settings > Misc option to "Force standard<br>colors in edit boxes" set).|
|Negative|NFCLR, NBCLR|Override the editing palette whenever the field contains a negative number. The color<br>change occurs instantly whenever you enter the minus sign or plus sign keys to change<br>a number's sign.|
|Negative<br>foreground|NFCLR|Also overrides the display and update foreground colors (DFCLR and UFCLR) whenever<br>the field is negative. Typically, NFCLR will be red (#4 on the standard AM72 palette).|
|Update|UFCLR, UBCLR|Used to redisplay the field after editing, regardless of whether the field was changed.|



A-Shell Reference 

Page 2623 

|**Color**|**Codes**|**Description**|
|---|---|---|
|||The intent of this feature is to indicate which fields have been edited on a "CHANGE"<br>screen; we recommend a color very similar to the display color.|
|Message|MFCLR, MBCLR|Used for displaying any auxiliary messages, like time out, invalid entry, help available,<br>etc.|
|Original|OFCLR, OBCLR|Used when clearing any messages. You should set them to match the normal color<br>scheme of the area where messages will be displayed. These are also used to specify<br>the color scheme for the text portion of a checkbox or radio box. See TYPEs "||c" and<br>""||r" in theGUI-Related Codes<br>section.|
|Forms|FFCLR, FBCLR|Used to display the literal characters embedded in a form string (see_type_f.)|



INFLD will automatically return to the pre-existing color scheme on exiting from a field, so you do not need to worry about it changing your ambient colors. 

INFLD does not check whether your terminal supports color, relying instead on your terminal driver to discard unsupported commands. You should program as if color was supported, since in most cases, color will have no effect on monochrome screens (unlike the PC where color commands may be interpreted as other video effects on monochrome monitors). However, by passing all color commands to the terminal driver, we leave you the option of modifying the driver to substitute color commands for some other attribute. (Should you attempt this, note that the color commands should not occupy a space, and operate as mode attributes.) 

Note: In GUI mode, there is a convenient option in the Misc. Settings dialog which overrides _infclr_ to force INFLD to use the standard Windows color scheme (typically black text within a white edit box). See History, below. 

A-Shell Reference 

Page 2624 

The _infclr_ parameters will be ignored in both of the following situations: 1) When the "Force standard Windows colors in edit boxes" option is checked (in the Misc. Settings Dialog); 2) When Windows Themes are active. 

As a convenience to those not interested in infclr but who want to use a subsequent parameter, the _infclr_ parameter (normally a mapped structure) may be reduced to numeric zero. Thus, for example, you can call INFLD to input an alphanumeric scrolling field with an editing window width of 60 characters and a maximum width of 150 characters as follows: 

```
xcall INFLD, row, col, 60, 0, "a", entry, inxctl, 1, 0, exitcode, timer, 0, -1, -1, 0, "", 0, "", 150
```

## **History** 

2013 August, 6.1.1360: Added topic ST_INFCLRX, which see for details. 

2013 July, 6.1.1355:  When the "Force standard colors in edit boxes" option is set in the Misc. Settings dialog, INFLD will now **-** display negative values (for fields with the _type_ code) in red, regardless of the INFCLR settings. INFCLR is largely ignored when the "Force standard colors" option is set. 

2011 June, 5.1.1220: Checkboxes and radiobuttons now automatically use the transparent background feature, UNLESS the OBCLR field of the INFCLR parameter is greater than zero. 

2010 June, 5.1.1184: Setting the DFCLR and/or DBCLR fields of the INFCLR structure to a palette index value +64 now overrides the theme color (provided you don't have the Settings > Misc option to "Force standard colors in edit boxes" set). 

## **Subtopics** 

- ST_INFCLRX 

A-Shell Reference 

Page 2625 

## **ST_INFCLRX** 

_Added August 2013_ 

The ST_INFCLRX structure (defined in INFLD.SDF) may be used for the _infclr_ parameter in place of the ST_INFCLR structure to define arbitrary foreground and background (RGB) colors that will be used by INFLD when displaying and optionally when editing the field. The structure format is as follows: 

```
defstruct ST_INFCLRX
```

```
    map2 sig,s,2       ! must be set to "x1" to activate
    map2 flags,b,2     ! INFCLRXF_EDTCLR (=1) to use d?rgb for edit also
    map2 dfrgb,b,4     ! display foreground
    map2 dbrgb,b,4     ! display background
endstruct
```

## **Notes** 

- The sig member must be set to "x1" or the structure will be ignored. It allows A-Shell to distinguish between the ST_INFCLRX 

- structure and the old INFCLR structure, which is still supported. You may set it to "" if you are passing the new structure but want to continue to use the default color logic. 

- The d?rgb colors are used when INFLD displays the field, either after or instead of editing, and also when "editing" read-only 

- fields. In addition, they will be used for editing other field types if the flags member is set to INFCLRXF_EDTCLR (1). 

- To override only the background or only the foreground color, set the other color field to -2. 

- The new structure is intended for the GUI environment; for text mode programs, you should stick with the old INFCLR 

- structure. 

- The ST_INFCLRX structure is intended for the GUI environment; for text mode programs, you should stick with the original 

- ST_INFCLR structure (or omit the parameter entirely). 

A-Shell Reference 

Page 2626 

## **HLPIDX** 

_hlpidx_ may used to specify a variety of primarily GUI-oriented auxiliary features such as Tool tips, Mouse Click Strings, Help Keys, Context Menu Handling, and Placeholders. Note that since the typical length requirement for the _hlpidx_ string can vary widely, it is particularly convenient to map it as a dynamic string; see S and X variables in Dynamically Sized Variables. 

A-Shell Reference 

Page 2627 

## **TOOL TIPS** 

In GUI mode, you may specify a "tool tip" (a short text message which appears automatically when the mouse idles over the field position for a second or two). These are handy for giving the user additional prompt information that would otherwise clutter up the screen. The format is simply a ">" followed by the text you want to appear. 

## **Example** 

```
hlpidx = ">This is a tool tip"
```

A-Shell Reference 

Page 2628 

## **MOUSE CLICK STRINGS** 

In order to implement the effect of allowing a user to be able to click on a field in order to edit it (as is typical in Windows forms), you need some way of telling your application that the click event has happened. The recommended way to do this is to encode unique high-numbered pseudo-function-key exit codes with each field. The format for this is: 

```
"~" + chr(7) + chr(250) + "###."
```

```
or
```

```
"~VK_xF###"
```

In the above examples, note that each starts with a tilde, i.e. "~" or chr(126) which signals the end of any prior clause and the start of the click string definition. The two variations are equivalent, with the second one being the newer (easier to type and to read as text) format. Note that the trailing decimal point is mandatory in the first format, and not used in the second format. The ### characters (which can be as few as 1 digit and as many as 6) indicate the number of the pseudo-function key. For example, the number 231 would indicate the pseudo-function key 231, and would cause the current event-sensitive operation (INFLD, XTEXT, XTREE, AUI_EVENTWAIT, etc.) to return with _exitcode_ -231. 

To further clarify with an example, let's say you have a screen with 20 fields, each using the above technique to associate itself with a pseudo-function key 201 thru 220. If the user is currently editing field 1 and then clicks on field 15, the INFLD call to edit field 1 will return with _exitcode_ -215, allowing the program to do any post-field processing on field 1 and then proceed to edit field 15. Obviously this requires more programming effort than a purely sequential input scheme, but is amenable to various systematic approaches, including AUI Eventwait. 

If _hlpidx_ contains both a tool tip and a mouse click string, the tool tip must be in the first position, followed by the chr(126) (or tilde), and then the mouse click string, e.g.: 

```
hlpidx = ">Tool tip first" + "~VK_xF231"
```

## **Comments** 

The click string syntax and behavior is common to most other GUI-enabled controls / subroutines, including AUI_CONTROL, XTREE and XTEXT, with the only difference being INFLD's requirement of the leading tilde—which is required because _hlpidx_ is used for multiple things. 

A-Shell Reference 

Page 2629 

INFLD also supports a more primitive (now deprecated) mouse click response mechanism termed Mouse Cursor Reporting. When active, INFLD treats a click outside of the field as an exit condition, returning exitcode -47. You can then retrieve further information about the last click by calling MX_MCRS. 

A-Shell Reference 

Page 2630 

## **HELP KEYS** 

The original intended use for _hlpidx_ was to store a string to be used as key to link to some information in a help database. Sadly, this has yet to implemented as originally envisioned (i.e. as something INFLD would respond to without the application being aware of it), but the possibility remains. And until then, many applications may find it useful to use the parameter as envisioned in order to implement their own help logic in a routine which serves as a wrapper to INFLD. 

If HLPDIX contains a traditional help key in addition to a tool tip and/or mouse click string, then the help key string must be first, e.g.: 

```
hlpidx="Traditional help key>Tool tip next" + chr(126) + Chr(7) + chr(250) + "213."
```

A-Shell Reference 

Page 2631 

## **CONTEXT MENU HANDLING** 

You may replace the standard context menu for normal INFLD edit controls and also INFLD combo box controls by adding the desired context menu definition string to the tooltip string (which is itself part of the _hlpidx_ parameter). The syntax is: 

## **>tooltip\menudef** 

The backslash marks the end of the tooltip definition and the beginning of the menudef string. The menudef syntax is the same as that for XTREE PopupMenu definitions, i.e.: 

## **text,command;text,command; ... ;text,command** 

The command fields may be either virtual keycode strings (e.g. VK_xF101), or arbitrary text (optionally containing control sequences using ^ as the lead-in), or $CUT, $COPY, or $PASTE (for the standard clipboard operations). 

The text fields will be displayed in the context menu as-is, with the exception of "--------" which displays a separator line. For example: 

```
>tip\Cancel,VK_ESCAPE;All,*^m;--------,;Cut,$CUT;Copy,$COPY;Paste,$PASTE
```

The above tooltip string defines a tooltip "tip" and a context menu with the following options: 

"Cancel" sends an escape (VK_ESC). "All" enters the character "*" into the field followed by a carriage return (*^m). "Cut", "Copy", and "Paste" act like the standard operations. 

Note that the _hlpidx_ parameter may contain a help key, a tooltip, a context menu definition, and/or a click command, but they must be in the following order: 

```
help key >tooltip \menudef ~clickcmd
```

Furthermore, if you have a menudef but not a tooltip, you must specify the ">" anyway, e.g.: 

```
help key >\menudef ~clickcmd
```

This latter condition avoids compatibility issues with help keys that might contain "\", although any existing tooltips which contain "\" will be effectively truncated at that point, with a probably non-functional context menu replacing the standard one. 

A-Shell Reference 

Page 2632 

While this could be annoying, it seems remote enough and not critical enough to go to additional lengths with cumbersome syntax to avoid. 

A-Shell Reference 

Page 2633 

## **PLACEHOLDERS** 

_Added October 2015_ 

Placeholders, also called cues, are short messages that appear inside an INFLD/EDIT control when the control is otherwise empty. They are useful for giving the user tips as to what the field would or should contain, without requiring additional screen real estate for labels/prompts or user action to display a tooltip. 

To specify a placeholder, embed it at the start of the tooltip string, enclosed in [brackets]. Note that INFLD tooltips are defined within the hlpidx parameter, starting with ">", for example: 

```
hlpidx$ = ">[tax id]For businesses use the employer id~VK_xF123"
```

Compatibility: No dependency on the server version. Requires client 6.1.1419 to recognize the placeholder; older clients will treat it as part of the tooltip, which should be harmless. 

## **History** 

- 2015 October, A Shell 6.1.1419: Added feature to A-Shell 

A-Shell Reference 

Page 2634 

## **MAXCHRS** 

May be used to separate the display width of the field from the maximum number of characters that can be entered. Normally the objective here is to allow a longer string to be input than screen real estate would otherwise allow. This is accomplished by scrolling the field horizontally within the display width defined by _xmax_ . A secondary motivation presents itself in the GUI proportional font environment, where you might want to make _xmax_ larger than _maxchrs_ in order to allow for the possibility that all the characters entered are wider than average, and thus would not fit within the display box size based on _xmax_ . 

For example, a two-character state field is likely to have this problem. The field display width is calculated based on the fixed pitch font size times the _xmax_ value. In most cases, this is more than wide enough for proportional fonts, which "on average" are more compact than fixed pitch fonts of the same point size. But capital letters, particularly in a combination like "WY", are likely to require more space. In this case, setting _maxchrs_ to 2 and _xmax_ to 3 might be a good idea. 

If _maxchrs_ is omitted or equals zero, it is treated as being equal to _xmax_ . 

**Horizontal scrolling:** _maxchrs_ may also be used to specify a maximum horizontal scrolling width. If specified, and if larger than _xmax_ (the field editing width) then the field will support up to _maxchrs_ characters, scrolling horizontally as required within the display window defined by _row, col_ and _xmax_ . 

As a convenience, especially to those interested in using the horizontal scrolling feature but who do not care about color, the _infclr_ parameter (normally a mapped structure) may be reduced to numeric zero. Thus, for example, you can call INFLD to input an alphanumeric scrolling field with an editing window width of 60 characters and a maximum width of 150 characters as follows: `xcall INFLD, row, col, 60, 0, "a", entry, inxctl, 1, 0, exitcode, timer, 0, -1, -1, 0, "", 0, "", 150` 

A-Shell Reference 

Page 2635 

## **INFLD EXTERNAL PARAMETERS** 

In addition to the calling parameters, there are several external parameters which affect the operation of INFLD. 

|**Parameter**|**Description**|
|---|---|
|Language<br>Definition File|INFLDgets a number of format and character symbol options from the<br>Language Definition File (LDF) for your job. If no LDF file is in effect (on older<br>versions of AMOS), the USA defaults are used.|
|Set_type_code|_AMOS only._SeeINFLD Default Type Codes.|
|Set_type_code|This is the A-Shell equivalent to INFLD.DEF. The command<br>SBR=INFDEF:<TYPE CODE STRING>is placed inmiame.iniand processed<br>when A-Shell starts up. After that, the specified_type_code string is added to<br>the end of the_type_parameter each timeINFLDis called (except when the<br>**m**<br>code is used.)|
|Century<br>Definition|Themiame.inisettingSBR=CCYY:##may be used to change the cutoff for<br>which years are assumed to be part of the current 19xx century. Any year<br>greater than ## will be assumed to be 19##, while any year equal or less<br>than ## will be assumed to be 20## (unless overridden by some other<br>parameters). Note that this applies toODTIMandIDTIMas well asINFLD.|
|SBR=|Because many dealers have modified their version ofINFLDand want their<br>modifications to be standard in A-Shell, we have added a number of other<br>option switches that can be installed into A-Shell using theSBR=setting in<br>miame.ini.|



A-Shell Reference 

Page 2636 

A-Shell Reference 

Page 2637 

## **INFLD DEFINITION FILE** 

_Rewritten October 2024_ 

Each time the INFLD subroutine is called, whether directly or indirectly, such as via SBXINP, an INPUT statement, the command line, etc., in addition to any type codes explicitly passed it will append a set of default type codes that can be defined in two ways: 

- Via the SBR=INFDEF directive in the system  configuration file (affecting all users) 

- Via a SET INFDEF command (overriding the system configuration and affecting just that user) 

You can disable the default codes at the individual field level by specifying the m type code.  And you can display the combined set of codes (explicit plus default) by hitting CTRL+\ within a field. 

A-Shell Reference 

Page 2638 

## **INFLD MISCELLANEOUS TOPICS** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Keyboard Commands 

- Screen snapshots 

- Pop-up Utilities 

- Telnet Keepalive 

- Ctrl+C Behavior 

- INFLD Font Size Calculation 

A-Shell Reference 

Page 2639 

## **KEYBOARD COMMANDS** 

|**Key**|**Description**|
|---|---|
|Ctrl+A|If |K, select field, else if |a,_exitcode_19. Else previous word.|
|Ctrl+B|If |B,_exitcode_16, else ignored|
|Ctrl+C|SeeCtrl+C Behavior<br>.|
|Ctrl+D|Same asDELETE|
|Ctrl+E|Same asEND|
|Ctrl+F|Insert space|
|Ctrl+G|If SBR=TTI_PGRW,_exitcode_8, else ignored|
|Ctrl+H|Same asLEFT-ARROW|
|Ctrl+I|Same asTAB|
|Ctrl+E|Same asEND|



A-Shell Reference 

Page 2640 

|**Key**|**Description**|
|---|---|
|Ctrl+F|Insert space|
|Ctrl+G|If SBR=TTI_PGRW,_exitcode_8, else ignored|
|Ctrl+H|Same asLEFT-ARROW|
|Ctrl+I|Same asTAB|
|Ctrl+J|Same asDOWN-ARROW|
|Ctrl+K|Same asUP-ARROW|
|Ctrl+L|Same asRIGHT-ARROW|
|Ctrl+M|Same asENTER|
|Ctrl+N|Move cursor to end of field|
|Ctrl+O|If |B,_exitcode_17, else ignore|
|Ctrl+P|If |Q,_exitcode_25, else launch Screen Pictures utility|



A-Shell Reference 

Page 2641 

|**Key**|**Description**|
|---|---|
|Ctrl+Q|Toggle insert/replace  mode (see INS)|
|Ctrl+R|Same asPAGE-UP|
|Ctrl+S|If |C,_exitcode_26, else ignore|
|Ctrl+T|Same asPAGE-DOWN|
|Ctrl+U|If |U,_exitcode_21, else move cursor to start of field|
|Ctrl+V|If |K paste contents of clipboard, else delete word|
|Ctrl+W|If |W, display "Not Processed" message and set_exitcode_1|
|Ctrl+X|If |X*, treat like Ctrl+*; else fold the field contents. See note 1 below.|
|Ctrl+Y|Delete to end of field|
|Ctrl+Z|If |Z,_exitcode_18, else if |K undo last delete, else delete entire field|
|Ctrl+[|Same asESCAPE|



A-Shell Reference 

Page 2642 

|**Key**|**Description**|
|---|---|
|Ctrl+\|Display information dialog showing currentINFLDparameters|
|Ctrl+^|Same asHOME|
|Enter|If ||T,_exitcode_7 (as if Tab); else_exitcode_0.  See Force destructive enter|
|Esc<br>(Escape)|If E,_exitcode_2, else if 1,_exitcode_1|
|Del<br>(Delete)|Delete character (or all selected characters)  (Same asCTRL+D)|
|Ins (Insert)|If GUI mode (|G) or |K, toggles insert/replace mode (same asCTRL+Q); else<br>inserts a space (same asCTRL+F)|
|Home|If 9,_exitcode_9, else if |K or |M treat likeCTRL+U(move to beginning of field or<br>line) (Same as ^^)|
|End|If k,_exitcode_15, else if |K, end of field, else if neither W nor C,_exitcode_1 (Same<br>asCTRL+E)|
|Tab|If T,_exitcode_7, else if |K tret likeENTER|



A-Shell Reference 

Page 2643 

|**Key**|**Description**|
|---|---|
|Shift+Tab|If |G (GUI mode), then if |2,_exitcode_2, else if treat likeUP-ARROW. Ignored in<br>non-GUI (text) mode.|
|PageUp|If 4,_exitcode_4, else ignore (same asCTRL+R)|
|Page-Down|If 6,_exitcode_6, else ignore (same asCTRL+T)|
|Left-Arrow|If cursor not in first position, move cursor to left, else if E or 2,_exitcode_2, else if |<br>p treat likeENTER. See note 1 below.|
|Up-Arrow|If 2,_exitcode_2, else if 3 or |3_exitcode_3, else ignore.  See note 1 below.|
|Right-<br>Arrow|If |L_exitcode_12, else if L and cursor at right end of field,_exitcode_12, else move<br>cursor right. See note 1 below.|
|Down-<br>Arrow|If ||a jump into drop-down (auto-complete) box, else if 5 or |5_exitcode_5. See<br>note 2 below.|
|Alt+Backsp<br>ace|If |K, undo last delete|
|Alt+<any<br>character>|If a control in the current window context uses the specified character as an<br>accelerator, acts like the control had been clicked (typically this will generate the<br>exitcode associated with the control)  See theAUI_CONTROL cmd<br>parameter for|



A-Shell Reference 

Page 2644 

|**Key**|**Description**|
|---|---|
||more information on defining the click action for a control.|



_Note 1:_ In CTRL+*, the * (asterisk) may be any character A through Z plus [,],\,^,_). The fold operation is a three-way toggle between all upper case, all lower case, title case. 

_Note 2:_ In some contexts, like within special-purpose GUI controls such as the date picker or up/down control, the arrow keys may only work within the control. In such cases, to get the exitcode behavior described in the table above, you can use CTRL+ARROW. 

A-Shell Reference 

Page 2645 

## **SCREEN SNAPSHOTS** 

Most of the differences between the AMOS and A-Shell versions are only relevant to system-level programs, but there are some differences that may affect ordinary users. One is that the CTRL+P command, under the A-Shell version of INFLD, brings up a screen snapshot utility. The utility gives you the option of printing a copy of the screen, and/or just saving it in the file <jobname>.buf. If saved, subsequent pictures will be appended to this file, creating a snapshot log which could be useful in a variety of situations (documentation, error reporting, etc). 

The name of the screen snapshot capture file can be changed using the **–b** and **–ba** A-Shell command line switches. 

A-Shell Reference 

Page 2646 

## **- POP UP UTILITIES** 

Another unusual feature implemented only in the A-Shell version of INFLD is the pop-up utility command. This command will launch a new session directly on top of the existing one and start it running BAS:ASHPOP.RUN, which is intended to be a small pop-up utility (or menu of utilities). The command itself is defined and activated by means of the _type_ code string **|Px** (where **x** is the command letter to be combined with the Control key). For example, if _type_ contained **|P]** then CTRL+] would launch the ASHPOP utility. A-Shell is released with a sample ASHPOP that displays a simple menu of two choices, one of which then refers to another utility, ASHCAL, a simple calculator. The source for both can be found in DSK0:[7,376] As an added convenience, the calculator will write the accumulated result to a file `MEM0:<jobnam>.CLP[1,1]` if you exit with Tab, and INFLD will pick up the results from that file and load it into the current field. This of course requires that the disk device MEM0: be defined and that a ppn [1,1] exists. If you want this feature available all the time, then add the _type_ code to the default string in miame.ini—e.g. SBR=INFDEF:|P]. You may want define a control key other than CTRL+] though, since CTRL+] is the terminator key for some telnet utilities. 

A number of differences between the two versions can be adjusted by means of SBR keys in miame.ini. 

If your application was previously using INPUT.SBR, and you want to preserve all of the idiosyncrasies of INPUT.SBR, then use SBR=INFDEF:|p in miame.ini to invoke "prehistoric compatibility mode." 

A-Shell Reference 

Page 2647 

## **TELNET KEEPALIVE** 

(A-Shell/Unix only) Adding SBR=INFLD_KEEPALIVE to miame.ini causes a harmless byte sequence to be sent every 15 seconds while waiting for input within INFLD (which includes the dot prompt and BASIC INPUT statements). This serves two purposes. First, it will prevent connections from being dropped due to lack of activity while they are actually in a program waiting for input. Second (and perhaps more important), it provides a mechanism for Unix servers to detect connections that have been dropped (without having to wait for the standard keep alive timers to expire, which by default may run to 2 hours). This way, within 15 seconds of the connection being dropped, the server will send a packet, which cannot be delivered. This should trigger a retry timer which will try to resend the packet some number of times before concluding that the connection is dead. This process is generally much quicker than the keep alive detections process. 

The _inxctl_ parameter to INFLD may now be specified as a one byte string or binary, in which case it returns the actual character used to exit the field. This is more useful to many people than the rather limited information provided by the traditional _inxctl_ . 

A-Shell Reference 

Page 2648 

## **CTRL+C BEHAVIOR** 

The following chart summarizes the behavior of ^C in various situations: 

|**Ctrl+C**<br>**Status**|**Type**<br>**V**|**Type**<br>**||K**|**Type**<br>**|K**|**Result of Pressing**<br>**Ctrl+C**|
|---|---|---|---|---|
|*|V|*|*|Exitcode 10|
|*||||K|*|Copy to clipboard|
|disable<br>d||||K|Copy to clipboard|
|disable<br>d||||Nothing|
|enabled|||*|ASB error 1|



* Indicates that the setting doesn't matter, given the other settings on the line. Blank indicates that the specified TYPE code is NOT set. 

A-Shell Reference 

Page 2649 

## **INFLD FONT SIZE CALCULATION** 

When using scaled fonts in the main window, the INFLD font size is no longer reduced to agree with the combo box font unless the "Force edit box height to match combo" option is selected (in the Settings > Misc dialog). To clarify the effect of the "Force edit box height to match combo" option: 

When checked, then both the combo box and edit box will have the same height, which will be just slightly less than the row height (subject to the "allow edit boxes to use leading" option). They will also use the same font. Because the combo box has more internal margin than the edit box, the resulting edit font size will be somewhat smaller than it otherwise could be, given the height of the edit box. 

When not checked, the edit box will still be the same size as before, but the scaled font size will not be constrained by the combo box metrics. Instead, the combo box height will adjust to the font. The result will usually be a larger font, but at the possible cost of the combo box being taller than a row. This may be ok if you rarely use combo boxes or allow extra space below them. 

## **History** 

- 2012 November, A Shell 6.0.1262:  Feature added 

A-Shell Reference 

Page 2650 

## **INIX** 

_Updated February 2024; see History_ 

## **xcall INIX, inifile, opcode, section, item, value {, dftvalue}** 

INIX.SBX reads/writes from standard "INI" files, which are ordinary text files, typically with a .INI or .CFG extension, which are made up of one or more groups (sections) of item=value pairs as follows: 

```
[section]
```

```
item1=value
```

```
item2=value
```

```
etc.
```

Because these files can be edited in a standard text editor, and because comment lines beginning with a semicolon may be inserted anywhere, the format is both easy to use and self-documenting. There is no particular limit to the number of items or sections, but each item name within a section must be unique. 

Source, samples and related functions can be found in SOSLIB:[907,26]. 

_inifile_ (String)  [in] 

File spec of the ini file. 

_opcode_ (Num)  [in] 

Operation to perform: 

A-Shell Reference 

Page 2651 

|**Value**|**Meaning**|
|---|---|
|0|Read single item=value pair|
|1|Write single item=value pair|
|2|Delete single item=value pair|
|3|Delete complete section|



In addition, you may add either or both of the following options in the ATE environment: 

|**Value**|**Meaning**|
|---|---|
|+16|redirect the operation to the ATE client|
|+32|first sync INIX.SBX from the server to the ATE client|



_section_ (String)  [in] 

Name of section; without the brackets, case insensitive. See History. 

_item_ (String)  [in] 

Name of item to read or write; case insensitive 

A-Shell Reference 

Page 2652 

## _value_ (String)  [in/out] 

For the read operation, the value is returned here. Note that if the item is not found within the specified section, the default value will be returned here, assuming the _dftvalue_ parameter was specified. For the write operation, this will be the value to write. 

_dftvalue_ (String)  [in] 

For the read operation, supplies the default value of the item if the item is not defined 

When writing, if the file does not exist, it will be created, and if the specified section does not exist, the section and item will be added to the end of the file. For example: 

```
xcall INIX, "foo.ini", 1, "Favorites", "Beatle", "Ringo"
```

## If the foo.ini file didn't previously exist, then after the above call, it would exist and contain: 

```
[Favorites]
```

```
Beatle=Ringo
```

If we then wrote another item using ... 

```
xcall INIX, "foo.ini", 1, "Favorites", "Position", "On Top"
```

... the file would be updated to contain: 

```
[Favorites]
```

```
Beatle=Ringo
```

```
Position=On Top
```

Note that neither the order of the sections nor the order of the items is significant. 

A-Shell Reference 

Page 2653 

If we then retrieve three values from the file with the following ... 

```
xcall INIX, "foo.ini", 0, "Favorites", "Beatle", fabguy$, "Paul"
xcall INIX, "foo.ini", 0, "preferences", "Position", pos$, "upside down"
xcall INIX, "foo.ini", 0, "Favorites", "Musician", player$, "Leadbelly"
```

The results would be: 

- `? fabguy$    ! "Ringo";  (default "Paul" ignored)` 

- `? pos$       ! "upside down" (no such section "preferences"; use default)` 

- `? player$    ! "Leadbelly" (no such item "Musician"; use default)` 

Attempting to read from a non-existent ini file is equivalent to attempting to retrieve non-existent items; you get back the default value specified in each read operation, or "" if no default specified. 

Despite the lack of order or indexing, INIX is quite efficient, particularly at reading, since the file gets cached in memory on the first access. Updates to the file do require the entire file to be rewritten, but this is still reasonably efficient, particularly if the total file size is "reasonable" (say, under 32K or so), and if read operations outnumber writes, as they usually do with these kinds of configuration files. 

INIX.SBX in SOSLIB:[907,26] was initially created and contributed to the SOSLIB by Steve Evans. It has since been adopted as a standard A-Shell routine, and is used extensively by many A-Shell modules. 

## **History** 

- 2024 February, A Shell 7.0.1755, INIX.SBX 5.1(522): Files without [sections] are now supported. Set 'section' parameter to "". Also: spaces and tabs are now allowed between the item key and the "=". Value returned on read operation will be trimmed of leading/trailing spaces and tabs. 

A-Shell Reference 

Page 2654 

## **INMEMO** 

## **xcall INMEMO, opcode, text, channel, strow, stcol, endrow, endcol, link, xpos, vspec, mmoclr, extctl** 

INMEMO.SBR was originally developed in the 1980s for use under AMOS. Its purpose is to provide an easy way for programmers to store and manipulate variable-length text structures. Although these structures may include light-bar menus, help screens and lookup tables, the most common and traditional use is to include free form, expandable memo pads within file maintenance programs. A-Shell contains a runtime implementation of INMEMO[XS] (and XFRMMOXS) which is about 95% compatible with the AMOS version. 

Full documentation for INMEMO is provided in a separate document called the INMEMO Reference, which see for detailed - information (available on the main A Shell documentation page). The abbreviated notes provided here are intended for programmers who are familiar with the routine but just need a quick reference to the parameter list. 

Note that XTEXT offers similar basic functionality with a GUI interface. 

PCKLST acts as a front-end to INMEMO to create pop-up pick-list boxes. 

The A-Shell version of INMEMO is slightly more advanced than the AMOS version in the implementation of free-form menus, in that it supports hidden text associated with an option (following a backslash as with regular vertical menus). For example, assuming the menu item delimiters were brackets, the text "[Mystery Option\secret]" would display as "Mystery Option", but if selected, would return the full "Mystery Option\secret". 

## _opcode_ (Num) 

specifies a combination of flags from the following table. 

|**Symbol**|**Value**|**Description**||**Symbol**|**Value**|**Description**|
|---|---|---|---|---|---|---|
|MMO_DSP|&h00000000|Display||MMO_UWE|&h00010000|Update without edit|



A-Shell Reference 

Page 2655 

|**Symbol**|**Value**|**Description**||**Symbol**|**Value**|**Description**|
|---|---|---|---|---|---|---|
|MMO_BDR|&h00000002|Border||MMO_RSA|&h00040000|Restore screen area on exit|
|MMO_LID|&h00000004|Smart line insert and delete||MMO_CXY|&h00080000|Start at position EXTROW,EXTCOL|
|MMO_DEL|&h00000008|Delete||MMO_NOA|&h00100000|Do not display navigation arrows|
|MMO_LIN|&h00000010|Return one line of memo text||MMO_AAH|&h00200000|Auto adjust (shrink) height to fit data|
|MMO_OPN|&h00000020|Open memo file||MMO_IPG|&h00400000|Intelligent paging mode|
|MMO_CLS|&h00000040|Close memo file||MMO_DBM|&h00800000|Start display at bottom|
|MMO_NBR|&h00000080|Do not redraw border||MMO_ISL|&h01000000|Insert into sorted list|
|MMO_NMR|&h00000100|Do not redraw border or text||MMO_APS|&h02000000|Alternate prompt style|
|MMO_SCH|&h00000200|Search||MMO_NAF|&h04000000|No auto formatting (wrapping)|
|MMO_SIL|&h00000400|Silent operations (no display)||MMO_OTX|&h08000000|Output memo to TEXT|
|MMO_DPG|&h00000800|Display with paging control||MMO_FFM|&h10000000|Free form menu or dialog box mode|



A-Shell Reference 

Page 2656 

|**Symbol**|**Value**|**Description**||**Symbol**|**Value**|**Description**|
|---|---|---|---|---|---|---|
|MMO_MNU|&h00001000|Menu mode||MMO_OPT|&h20000000|Disk optimized mode (n/a under A-Shell)|
|MMO_TBL|&h00002000|Table lookup||MMO_RAW|&h40000000|Save/retrieve raw text|
|MMO_FST|&h00004000|Fast menu mode||MMO_HDR|&h80000000|Output invisible headers with CHR$(26)<br>delimiters|
|MMO_EWU|&h00008000|Edit without update||MMO_RET|&h80000000|Return key exits memo|
|**Definition file:**ashinc:mmosym.def|||||||



|**Symbol**|**Value**|**Description**||**Symbol**|**Value**|**Description**|
|---|---|---|---|---|---|---|
|MMO_MNU|&h00001000|Menu mode||MMO_OPT|&h20000000|Disk optimized mode (n/a under A-Shell)|
|MMO_TBL|&h00002000|Table lookup||MMO_RAW|&h40000000|Save/retrieve raw text|
|MMO_FST|&h00004000|Fast menu mode||MMO_HDR|&h80000000|Output invisible headers with CHR$(26)<br>delimiters|
|MMO_EWU|&h00008000|Edit without update||MMO_RET|&h80000000|Return key exits memo|
|**Definition file:**ashinc:mmosym.def|||||||



## _text_ (String) 

has various uses, from titles to preloaded key sequences, retrieved lines, menu selections, and even entire memo or menu contents. 

## _channel_ (Num _)_ 

is generally the file channel that the memo file is open on. If the CHANNEL parameter is a string, it will be interpreted as the name of the memo file, in which case the memo file will be automatically opened, closed, and even created, if necessary. 

## _strow, stcol, endrow, endcol_ (Num _)_ [in] 

specify the dimensions of the memo box, around which the border, if applicable, will be drawn. 

_link_ (B,2 or B,4) 

A-Shell Reference 

Page 2657 

is the link to the memo record. 

## _xpos_ 

## is a control variable, which should be mapped as follows 

```
MAP1 XPOS
```

```
   MAP2 POS,B,4
   MAP2 POS2,B,2
```

## _vspec_ 

controls the maximum scrollable width and height of the memo, and must be mapped as: 

```
MAP1 VSPEC
```

```
MAP2 VWIDTH,B,2
```

```
MAP2 VROW,B,2
```

## _mmoclr_ (B,1) 

if specified, controls the colors for various parts of the memo display, and must be mapped as follows: 

|**Symbol**|**Description**||**Symbol**|**Description**|
|---|---|---|---|---|
|BFCLR|border foreground||PBCLR|prompt (title) bg|
|BBCLR|border background||WFCLR|warning mssg fg|



A-Shell Reference 

Page 2658 

|**Symbol**|**Description**||**Symbol**|**Description**|
|---|---|---|---|---|
|TFCLR|text foreground||WBCLR|warning mssg bg|
|TBCLR|text background||SFCLR|status line fg|
|AFCLR|arrows foreground||SBCLR|status line bg|
|ABCLR|arrows background||RFCLR|ruler/reserved fg|
|PFCLR|prompt (title) fg||||



## _extctl_ 

may optionally be specified for extended control parameters, mapped as follows: 

```
MAP1 EXTCTL
```

```
   MAP2 EXTCOD,B,2  ! exit code
```

```
   MAP2 EXTERR,B,2  ! exit error status
   MAP2 EXTMAP,B,4  ! exit code enable bitmap
   MAP2 EXTROW,B,2  ! cursor row
   MAP2 EXTCOL,B,2  ! cursor column
   MAP2 EXTBYT,B,4  ! # bytes in memo
   MAP2 EXTHIT,B,2  ! # rows
```

A-Shell Reference 

Page 2659 

```
   MAP2 EXTWID,B,2  ! longest row length
   MAP2 EXTPRW,B,2  ! # protected rows
   MAP2 EXTSMI,S,1  ! start menu item char
   MAP2 EXTEMI,S,1  ! end menu item char
   MAP2 EXTMRW,B,2  ! error message row
   MAP2 EXTTOP,B,2  ! top window offset
   MAP2 EXTLFT,B,2  ! left window offset
   MAP2 EXTPCL,B,2  ! # protected columns
   MAP2 EXTTIM,B,2  ! max inter-character timeout
   MAP2 EXTOTH,B,2  ! other menu exit keys:
                    ! 02 = left arrow (EXITCODE -40)
                    ! 04 = right arrow (EXITCODE -41)
```

```
                    ! 08 = up arrow (EXITCODE -42
                    ! 16 = down arrow (EXITCODE -43)
                    ! 32 = tab key (EXITCODE -44)
```

```
   MAP2 EXTJNK,X,14 ! for expansion
```

Of the above parameters, perhaps the most important are _extcod_ and _exterr_ , whose values are shown in the tables below. The former is similar to the _exitcode_ parameter in INFLD, receiving a code indicating how the memo was exited. The latter indicates various other error conditions. The variable/symbol names in the first column of the tables below are defined in mmosym.bsi. 

A-Shell Reference 

Page 2660 

|**Symbol**|**Description**|
|---|---|
|MMX_OK|Normal Updated exit|
|MMX_QUI|Non-Updated exit (CTRL+C)|
|MMX_VTS|Non-Updated exit (VSPEC too small)|
|MMX_TIM|Updated exit (time out)|
|MMX_TAB|Tab used to select menu item|
|MMX_SPC|SPACEBARused to select menu item|
||Command function exits are returned as negative numbersF1= -1, etc.|



|**Symbol**|**Description**|
|---|---|
|MME_ERR|abnormal exit (see POS)|
|MME_SAF|failure to save or restore area|
|MME_OK|normal exit|



A-Shell Reference 

Page 2661 

**Symbol Description** 

A-Shell Reference 

Page 2662 

## **MMO_RAW** 

Flag MMO_RAW may be combined with MMO_UWE (update without edit) to save the string contents of the TEXT parameter in a raw state, and with MMO_OTX (output to text) to retrieve the raw data into the TEXT parameter. In this mode, there is no formatting: no line breaking, no special interpretation of space compression, invisible headers, etc. Nor does it pay any attention to the coordinates or VSPEC specification. 

The new raw mode is mainly intended to allow applications to tap into the variable-length storage capabilities of INMEMO, independent of the memo display and editing capabilities. In particular, it could be useful as a storage system for XTEXT. 

## **Examples** 

- `! save TEXT$ (any length) raw to file TEST.MMO, return LINK` 

```
xcall INMEMO, MMO_UWE+MMO_RAW+MMO_SIL, TEXT$, "TEST.MMO", 0, 0, 0, 0, link, XPOS, VSPEC, MMOCLR, EXTCTL
```

- `! retrieve memo from LINK into TEXT$` 

```
xcall INMEMO, MMO_OTX+MMO_RAW+MMO_SIL, TEXT$, "TEST.MMO", 0, 0, 0, 0, LINK, XPOS, VSPEC, MMOCLR, EXTCTL
```

Note that the string retrieved from the file will be truncated to fit the TEXT$ destination variable. If using a dynamic string (S,0), you must pre-initialize it to a suitable max size, e.g. `TEXT$ = FILL$(" ",MAX_MEMO)` . 

See MMOSYM.DEF and MMOSYM.BSI for the flag definition. Also see THE sample program XTXMMO2 in EXLIB:[908,40] which demostrates the feature in conjunction with XTEXT. 

A-Shell Reference 

Page 2663 

## **ISMBLD** 

## **xcall ISMBLD, opflags, status, fspec, keysiz, keypos, recsiz, reccnt {, idadev, infile, maxrecs, idxblksiz, idxlvls, extrablks, exprecs}** 

ISMBLD.SBX, the subroutine version of ISMBLD.LIT, may be more convenient for building files than having to first generate a CMD file. The file is actually identical to ISMBLD.LIT which is why it has the same version (and hash, for that matter). It determines whether to act as a subroutine or LIT command based on how it is called. It was introduced in A-Shell as part of an ISAM overhaul that vastly improved ISAM Performance, which see for an in-depth discussion of performance issues. 

## _opflags_ (Num)  [in] 

## Operation flags (see IBF_xxx in AHSINC:ISMDEF.BSI) 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|IBF_SECONDARY|&h0002|build secondary index|
|IBF_AUTOBLKLVL|&h0004|auto compute block size|
|IBF_EXISTING|&h0008|process existing file (|
|IBF_PROGRESS1|&h0100|progress style 1 (% at cursor location)|



_status_ (F,6)  [out] 

Return status: 

A-Shell Reference 

Page 2664 

|**Valu**<br>**e**|**Description**|
|---|---|
|0|success|
|-1|param error|
|-2|load terminated in mid-record|
|-3|file doesn't exist (IBF_EXISTING)|
|-4|file already exists|
|-5|load file doesn't exist|
|-6|expanded version/blocks size requires newer A|
|-7|main idx doesn't exist (for secondary load)|
|30+|erf values (during load)|



_fspec_ (String)  [in] 

File to create (no extension) 

A-Shell Reference 

Page 2665 

_keysiz_ (Num)  [in] 

size of key 

_keypos_ (String)  [in] 

key position _recsiz_ (String)  [in] 

record size 

_reccnt_ (String)  [in] 

# recs (initial allocation) 

_idadev_ (String)  [in] 

IDA device (e.g. "DSK7:") if not same as IDX 

_infile_ (String)  [in] 

Seq file to load from, or name of main IDX if creating a secondary IDX 

_maxrecs_ (String)  [in] 

Expected max # recs (for auto-determination of optimum idxblksiz and idxlvls; 0 to ignore) 

_idxblksiz_ (String)  [in] 

IDX block size (default 512) 

_idxlvls_ (String)  [in] 

IDX levels (default 3) 

_extrablks_ (String)  [in] 

Extra IDX blocks (if omitted, use 50%). 0.05 - 1.00 = % x 100, e.g. 0.5 = add 50%) 

A-Shell Reference 

Page 2666 

_exprecs_ (String)  [in] 

Expected / eventual number of records, to improve the IBF_AUTOBLKLVL (auto configure index) calculations. 

Note that although ISMBLD.SBX shares much of the same code as ISMBLD.LIT, it offers the option of allowing ISMBLD to autodeterming appropriate values for the IDX block size and levels, based on the key size and expected maximum records (while only allocating the file for the desired initial size). Use `ISMDMP XXX /V` afterwards to confirm the configuration. 

## **See Also** 

- ISMBLD.LIT 

- ISMDMP.LIT 

- ISMROK 

A-Shell Reference 

Page 2667 

## **ISMPAR** 

## **xcall ISMPAR, ifname, ismpak {,lvl1cnt, keyalc}** 

ISMPAR.SBX is a variation of the internal ISMROK[XS] , with the main distinction being that it takes a filespec rather than an open file channel and thereby avoids potential file locking conflicts. The source for the routine can be found in ISMPAR.BP in SOSLIB: [907,22]. 

## **Parameters** 

```
MAP1 ISMPAK
```

```
    MAP2 I'DEV,S,4            device name (ASCII)
    MAP2 I'UNIT,B,2           unit #
    MAP2 I'UPDCNT,B,4         update counter
    MAP2 I'RECSIZ,B,2         rec size
    MAP2 I'KEYSIZ,B,2         key size
    MAP2 I'KEYPOS,B,2         key position
    MAP2 I'IDAFRE,B,4         IDA free pointer
    MAP2 I'IDAFRC,B,4         IDA freecount
    MAP2 I'IDXFRE,B,4         IDX free pointer
    MAP2 I'IDXFRC,B,4         IDX freecount
    MAP2 I'RECALC,B,4         records allocated *
    MAP2 I'TOPDIR,B,4         top directory block
    MAP2 I'LEVELS,B,2         # IDX levels
    MAP2 I'BLKSIZ,B,2         IDX blk size
```

A-Shell Reference 

Page 2668 

```
    MAP2 I'IDXTYP,B,2         IDX type flags
```

```
MAP1 IFNAME,S,64            IDX filespec
```

```
MAP1 LVL1CNT,B,2            # of idx blocks at top level (max 100)
```

```
MAP1 KEYALC,B,4             # of keys allocated in the IDX file. In a typical file, this should match idaalc—
i.e. one key per data record.
```

## **History** 

- 2022 February, A Shell 6.5.1711: Add new optional argument _keyalc_ to return the new keys allocated value. 

A-Shell Reference 

Page 2669 

## **ISMROK** 

_Updated February 2022; see History_ 

## **xcall ISMROK, ch, idaalc, idaavl{, recsiz, keysiz, keypos, devdrv, idxalc, idxavl, idanxt, idxnxt, idx'lvls, idx'blk'siz, idx'type, keyalc}** 

ISMROK reads the "rock" of the traditional ISAM file, returning various attributes of the file configuration and state. 

## **Parameters** 

_ch_ (Num)  [in] 

File channel the file is open on. Note that this is actually the index file channel  (ISAM files are opened by their index; the IDA file is opened internally.)   For files with multiple index  (IDX)  files, the IDX-related parameters below will refer to that IDX. 

_idaalc_ (Num)  [out] 

Number of data records allocated  (in the IDA file) 

_idaavl_ (Num)  [out] 

Number of unused data records available 

_recsiz_ (Num)  [out] 

Data record size 

_keysiz_ (Num)  [out] 

Size of key 

_keypos_ (Num)  [out] 

Position of key relative to start of record  (first position is 1) 

_devdrv_ (String)  [out] 

A-Shell Reference 

Page 2670 

Device and drive number  (e.g. "DSK1")  for the IDA file  (if not same as the IDX) 

_idxalc_ (Num)  [out] 

Number of IDX blocks allocated. 

_idxavl_ (Num)  [out] 

Number of unused IDX blocks available 

_idanext_ (Num)  [out] 

Next available data record number 

_idxavl_ (Num)  [out] 

Next available index block number 

_idx'lvls_ (Num)  [out] 

Number of levels in the IDX file  (3-9) 

_idx'blk'siz_ (Num)  [out] 

Size of IDX blocks  (512, 1024, 2048, 4096, 8192, ...) 

_idx'type_ (Num)  [out] 

bitmap indicating the index type: 

|**Value**|**Description**|
|---|---|
|&h0002|secondary index|
|&h0800|A-Shell extensions; requires A-Shell version 5.1.1122 or later|



A-Shell Reference 

Page 2671 

_keyalc_ (Num)  [out] 

Number of keys allocated in the IDX file. In a typical file, this should match idaalc—i.e. one key per data record. 

## **See Also** 

- ISMBLD.LIT 

- ISMDMP.LIT 

- ISMPAR.SB in SOSLIB:[907,22] 

## **History** 

- 2022 February, A Shell 6.5.1711: ISAM 1.X enhancement: IDX rock now contains a count of the keys allocated (additions minus deletions) along with the records allocated. This may be useful as a quick way to compare the number of keys with the number of records. Typically these should be the same, except in cases where the application deliberately adds more or less than one key to the IDX per record. Note that the keys allocated value will only be valid for files that have been rebuilt under A-Shell 6.5.1711+. 

- 2022 February, A Shell 6.5.1711: Add optional argument _keyalc_ to return the new keys allocated value. 

A-Shell Reference 

Page 2672 

## **ITC** 

## **xcall ITC, func, type, mesg, retv** 

(Unix only) ITC allows programs to send and receive messages between jobs. 

## **Parameters** 

```
MAP1 FUNC,<any numeric type>     ! opcode
MAP1 TYPE,<any numeric type>     ! message type or process ID
MAP1 RETV,B,1                    ! return code (0=ok)
```

```
MAP1 MESG                        ! message
MAP2 MTYPE,B,4                ! internal code
MAP2 MESGX,X,<any size>       ! message contents
```

## _func_ 

indicates the operation to perform, as described in the following table. 

|**Value **|**Meaning**|
|---|---|
|0|Send message to cooperating receiver|
|1|Receive message (do not wait if not available)|
|2|Receive message (wait until available)|



A-Shell Reference 

Page 2673 

**Value Meaning** 3 Send message and signal receiver 

## _type_ 

identifies the type of message, or the process ID of the target job to signal. In the case of _func_ 3, it must be the process ID of the target job to signal. (In this operation, the contents of the message may not be important; since the signal itself could be used to notify the target job to look for subsequent messages.) For the other operations, it must be a value that both sender and receiver agree on, because the receive operation will ignore messages not sent with the specified _type_ . (The idea here is to allow multiple message formats or priorities to be used simultaneously.) The exception is that the receiver may set _type_ =0 to receive the first message in the queue, regardless of its type. To avoid confusion between types that are process IDs and types that are message types, it is recommended that you adopt a standard of using message _type_ values higher than the range of process IDs (which might extend as high as 2**24 on very large systems. _Type_ should also be below 2**31 to avoid confusing them with negative _type_ numbers, which are used to request to read any message whose _mtype_ is less than or equal to the absolute value of the specified _type_ . 

## _mesg_ 

contains the message to send or receive. Obviously, the communicating programs need to agree in advance on the layout corresponding to each message type. It must begin, as shown above, with a 4 byte field which is reserved for internal use by the subroutine. (Actually, it plugs the _type_ value into _mtype_ for outgoing messages, and ignores any incoming messages whose _mtype_ does not match the _type_ specified.) 

## _retv_ 

returns a 0 or 1 indicating the success of the operation (0 = success). 

## **Comments** 

Unix systems do not allow one user to signal another unless they are both share the same effective user ID or if the sender is root. For this reason, some sites set the "setuid" flag on the ashell executable to make all A-Shell users effectively the same 

A-Shell Reference 

Page 2674 

user, or else they rely on the system administrator being able to switch to root in order to use operations which require signaling other users. Such operations include ITC FUNC=3, KILL.LIT, CHAT.LIT, SEND.LIT, FORCE.LIT, and JSTAT.LIT. 

A-Shell Reference 

Page 2675 

## **JSON** 

## **xcall JSON, opcode, {, parameters...}** 

JSON performs various JSON-related utility functions. 

## **Parameters** 

_opcode_ [in] 

specifies operation to be performed, described in detail below. 

## u **Opcode 1: Load a JSON string into an ordered map** 

## **xcall JSON, 1, handle, status, jsontext$, $ordmap()** 

## **Parameters** 

_handle_ (B4+ or F)  [out] 

returns a handle to the JSON structure in memory (for future expansion) 

_status_ (Signed Num)  [out] 

returns the status of the operation: 

|**Code**|**Status**|
|---|---|
|>= 0|indicates success (# nodes parsed)|
|< 0|indicates an error:|



A-Shell Reference 

Page 2676 

|**Code**|**Status**|
|---|---|
|-1|out of memory|
|-3|out of JSON library handles|
|-5|invalid map reference|
|-6|ordered maps not supported in this A-Shell version|



## _jsontext$_ (String) [in] 

The JSON object to load into the ordered map. Note that you can use the function Fn'FileToStr$(fspec$) from fnfilestr.bsi in SOSLIB[907,10] to load a JSON file into _jsontext$_ . 

## _$ordmap()_ (ordered map)  [out] 

Returns an ordered map representation of the JSON object, using XPATH-like syntax, consisting of a key representing the path to the value and the value representing the value. For example, the following JSON excerpt describing a program menu bar ... `{ "menu": {` 

```
    "header": "SVG Viewer",
```

```
    "items": [
        {"id": "Open"},
        {"id": "OpenNew", "label": "Open New"},
```

A-Shell Reference 

Page 2677 

```
        null,
        {"id": "ZoomIn", "label": "Zoom In"},
        ...
```

... would be converted to an ordered map something like this: 

```
/menu/header -> SVG Viewer
/menu/items[1]/id -> Open
/menu/items[2]/id -> OpenNew
/menu/items[2]/label -> Open New
/menu/items[4]/id -> ZoomIn
/menu/items[4]/label -> Zoom In
...
```

Note that the output _$ordmap()_ is not automatically pre-cleared, so if using the same _$ordmap()_ for additional calls to this function, you'll need to use the .CLEAR statement first. 

## u **Opcode 2: Free the JSON memory associated with the HANDLE** 

## **xcall JSON, 2, handle, status** 

**Parameters** 

A-Shell Reference 

Page 2678 

_handle_ (B4+ or F)  [in] 

handle returned from _opcode_ 1 

_status_ (Signed Num)  [out] - 

0 for success 

## u **Opcode 3: Escape the JSON text** 

## **xcall JSON, 3, status, jsontext$** 

## **Parameters** 

_status_ (Signed Num)  [out] 

returns the number of special characters escaped 

_jsontext$_ (String)  [in/out] 

JSON text, both source and destination 

This function applies JSON escaping rules to special characters in the specified JSONTEXT$, returning the resulting string in the same variable. Note that since escaping increases the size of the text, the JSONTEXT$ parameter should be sufficiently large to handle the worst case, which could be up to six times the original, or be a dynamic string. The algorithm assumes that the JSONTEXT$ is encoded using the Latin1 character set, and supports the following: 

|**Character**|**Esc Seq**||**Character**|**Esc Seq**|
|---|---|---|---|---|
|" (quote)|\"||chr(13) (CR)|\r|



A-Shell Reference 

Page 2679 

|**Character**|**Esc Seq**||**Character**|**Esc Seq**|
|---|---|---|---|---|
|\ (backslash)|\\||chr(9) (tab)|\t|
|/ (slash)|\/||chr(1) - chr(31)|\u0001 - \u001F|
|chr(8) (backspace)|\b||chr(160) - chr(255)|\u00A0 - \U00FF|
|chr(12) (formfeed)|\f||||



Note that aside from eliminating the need to reinvent the wheel in a BASIC function, the subroutine operates much faster than you could possibly do in BASIC. 

## u **Opcode 4: Unescape the JSON text** 

## **xcall JSON, 4, status, jsontext$** 

## **Parameters** 

_status_ (Signed Num)  [out] 

returns the number of escaped characters unescaped 

_jsontext$_ (String)  [in/out] 

A-Shell Reference 

Page 2680 

JSON text, both source and destination 

This is the reverse of _opcode_ 3, converting the escaped sequences into their original raw form. Note that here the output will never be longer than the input. 

## u **Opcode 5: Form a "name":"value" pair** 

## **xcall JSON, 5, status, name$, value$, jsonpair$ {,flags}** 

## **Parameters** 

_status_ 

not used 

_name$_ (String)  [in] 

the name part of the name:value pair 

_value$_ (String)  [in] 

the value part of the name:value pair 

_jsontext$_ (String)  [out] 

the "name":"value" result is returned here 

_flags_ (Num)  [in] 

optional flags from the table below 

A-Shell Reference 

Page 2681 

|**Symbol**|**Value**|**Description**|:"".|
|---|---|---|---|
|XJSONF_NUMBER|&h0001|treat_value$_as a number (don't quote it)||
|XJSONF_LCS|&h0002|fold_name$_lower case||
|XJSONF_UCS|&h0004|fold_name$_upper case||
|XJSONF_NOTRIM|&h0010|don't trim leading/trailing spaces from value (else do)||
|XJSONF_NONULLVAL|&h0020|If_value$_="", output will be a null string (without a trailing comma) instead of "name"||
|XJSONF_NOCOMMA|&h0040|no trailing comma (else output pair ends with a comma)||
|**Definition file:**ashinc:json.def||||



Although this may seem like a minimal operation that can easily be accomplished in a simple BASIC function, as with _opcode_ 3 and 4, the big advantage is speed, which might matter when dealing with large datasets involving hundreds of thousands or millions of such pairs. 

Note that unless the XJSONF_NOCOMMA flag is specified, the output will contain a trailing comma so that you can call the function in a loop without having to explicitly output a comma between each pair. 

## **History** 

A-Shell Reference 

Page 2682 

- 2025 October, A Shell 7.0.1779 Change XJSONF_NONULLVAL behavior; previously output "". 

- 2021 October, A Shell 6.5.1708: Routine added to A-Shell. 

A-Shell Reference 

Page 2683 

## **JOBCMD** 

## **xcall JOBCMD, command** 

JOBCMD allows you to specify a command string which is automatically executed whenever the job returns to the A-Shell command prompt. Setting the command to a null string disables the feature, which effectively makes it possible again for the user to interactively type commands when at the prompt. This feature is often used to force users back into some kind of a menu in case they somehow manage to drop out of a program. You have to be careful with this facility, since once you set it, there is no way to exit except by making another call to JOBCMD with a null string as the argument. 

The maximum length of the command string is 29 characters plus a trailing null byte. 

A-Shell Reference 

Page 2684 

## **JOBDAT** 

## **xcall JOBDAT, job'info** 

JOBDAT is yet another example of a subroutine which returns a variety of information about the current job. This one seems to have been connected with the InSight juggernaut. 

## **Parameters** 

```
MAP1 JOB'INFO
```

```
    MAP2 JD'JOBNAM,S,6      ! Job name
    MAP2 JD'JOBNUM,F,6      ! Job number
    MAP2 JD'JOBLOG,S,20     ! e.g. "DSK0:[150,277]"
    MAP2 JD'USRNAM,S,20     ! User login name
    MAP2 JD'PRGNAM,S,6      ! Program name
    MAP2 JD'PRGVER,S,16     ! Program version
    MAP2 JD'TRMROW,F,6      ! Current # display rows
    MAP2 JD'TRMCOL,F,6      ! Current # display cols
    MAP2 JD'TRMFGC,F,6      ! Foreground color #
    MAP2 JD'TRMBGC,F,6      ! Background color #
    MAP2 JD'TRMFLG(32),B,1  ! Terminal flags (see below)
```

Each entry in the JD’TRMFLG() array corresponds to a terminal feature from the following table. The array item is set to 1 if the feature is supported by the current display device, else 0. 

A-Shell Reference 

Page 2685 

|**Ite**<br>**m**|**Meaning**||**Ite**<br>**m**|**Meaning**|
|---|---|---|---|---|
|1|Alternate page||16|Line insert|
|2|Block fill||17|Auxiliary printer port|
|3|Column insert||18|80/132 column|
|4|Color||19|Smooth scroll|
|5|Multi-byte* translations||20|Box commands|
|6|Alpha terminal||21|Mode attributes|
|7|Addressable status lines||22|AM70-style color commands|
|8|Split screen||23|No-space attributes|
|9|Erase to end of line||24|"True" graphics|
|10|Erase to end of screen||25|Gray scale|
|11|Underscore||26|Proportional space fonts|



A-Shell Reference 

Page 2686 

|12|Blink||27|Variable rows|
|---|---|---|---|---|
|13|Dim||28|8 bit support|
|14|Reverse video||29|InSight Support|
|15|Character insert||||



Many of the terminal features in the table above can be accessed via Tab Functions. 

- (function key) 

A-Shell Reference 

Page 2687 

## **JOBTRM** 

_Rewritten May 2026_ 

## **xcall JOBTRM, jobnam, trmnam, tdvnam {,ctljob, ctltrm, ctltdv}** 

JOBTRM returns the job name, terminal name, and terminal driver name of the current job, and optionally, of the "controlling job". The idea of the "controlling job" is mainly applicable in serial environments, where it multitasking utilities (such as MULTI and PolyShell) may be employed to allow a single real terminal and job to dynamically attach to and thereby control multiple virtual terminals and jobs. In such cases, an application may want to identify the "controlling" or "real" terminal/job in order to associate some real resource with it, such as a nearby printer. In the modern A-Shell environment where virtually all terminal connections are made from smart workstations capable of supporting multiple such connections over TCP, the terminal name is virtually always the same as the job name. Except for the case of PolyShell, the controlling job / terminal is the same as the current one—and even in the PolyShell case, the control job / terminal will share the same first five characters as its spawned child jobs -- PSHAA1, PSHAA2, etc. 

## **Parameters** 

_jobnam_ (String,6+)  [out] 

Returns the job name. 

_trmnam_ (String,6+)  [out] 

Returns the terminal name. The terminal name under A-Shell is virtually always the same as the job name.  In predecessor environments involving serial connections, it made sense to define terminals (ports), known as "TRMDEFs", separately from jobs (processes) and then attach one to another.  But this technique has largely gone by the wayside. 

_tdvnam_ (String,6+)  [out] 

Returns the terminal driver (i.e. terminal emulation) name. 

The remaining parameters have no practical use and are generally omitted, except in the PolyTrack environment: 

_ctljob_ (String,6+)  [out] 

Returns the job name for the controlling terminal. (See notes above.) 

A-Shell Reference 

Page 2688 

_ctltrm_ (String,6+)  [out] 

Returns the terminal name for the controlling terminal. 

_ctltdv_ (String,6+)  [out] 

Returns the terminal driver / emulation for the controlling terminal. 

## **See Also** 

- Dot Variables (.JOBNAME, .TERMINAL) 

- TRMDEF 

- GETJOB 

- GETJTB 

A-Shell Reference 

Page 2689 

## **JULCVT** 

_Updated September 2017_ 

## **xcall JULCVT, sepdat, juldat, flag {,status}** 

JULCVT converts between a separated date format and Julian date format. 

## **Parameters** 

sepdate  (Num)  [in/out] 

is the date to convert to Julian (if _flag_ = 0), or the return date (if _flag_ = 1). It is in AMOS "separated" format, typically mapped as follows: 

```
MAP1 sepdate,B,4
```

```
MAP1 sepdateX,@sepdate
   MAP2 mon,B,1         ! Month (1-12)
   MAP2 day,B,1         ! Day of month (1-31)
   MAP2 yr,B,1          ! Offset from 1900 (2023=123)
   MAP2 dow,B,1         ! Day of week (Mon=0, Sun=6)
```

Note that sepdate can be of any numeric type large enough to hold a 32 bit integer, but you would need to assign it to an overlay as in the map statements above in order to easily split out the individual fields. 

_juldat_ (Num) 

is the Julian date equivalent of _sepdate_ (if _flag_ = 0) or the date to convert to separated format (if _flag_ = 1). This is the number of days since "The Beginning" (about 4716 BC). 

_flag_ (Num)  [in] 

A-Shell Reference 

Page 2690 

should be set to 0 to convert from _sepdate_ to _juldat_ , else 1 to convert the other way. 

_status_ (Num)  [out] 

returns 0 in all cases. This is essentially a dummy variable here to match a legacy version of this routine under AMOS. 

## **Comments** 

The BASIC system variable DATE can be used to set _sepdat_ to the current date (i.e. `sepdat = DATE` ). 

## **See Also** 

- GRECNV and DATES for other date conversion routines. 

A-Shell Reference 

Page 2691 

## **LOKOUT** 

## **xcall LOKOUT, flags {,wait, lokmsg}** 

LOKOUT.SBX provides an application-friendly interface to the lock-out feature in which the file %MIAME%/ashell.lok is used to prevent users from logging into to A-Shell. This routine does nothing about users that are already in, but if you first manage to get them out, this will make sure that they stay out. 

Tools you may use in your strategy to deal with the existing users include SENDXS, FORCEXS, KILJOB.SBX and MX_KILLXS. See Locking Users Out for additional details. 

Source, samples and related functions can be found in SOSLIB:[907,32]. 

## **Parameters** 

_flags_ (Signed Num)  [in/out] 

On input: 

- 0: clear the existing lockout 

- 1: set a lockout (requires _wait_ and _lokmsg_ parameters) 

Returns <0 on error: 

- -1 = too few parameters 

- -n = ASB error n 

_wait_ (Num)  [in] 

- 0: users logging in can wait as long as they want for lock to clear 

#: maximum seconds they can wait 

A-Shell Reference 

Page 2692 

## _lokmsg_ (String)  [in] 

Message to display to users trying to log into A-Shell. Should be consistent with the _wait_ flag, and possibly mention that they can use ESCAPE to abort the wait. Use an embedded "\n" to indicate line breaks as needed. 

A-Shell Reference 

Page 2693 

## **LOG** 

_Updated June 2016; see History_ 

## **xcall LOG, logstr {,qflag, status}** 

## **xcall LOG, dev, p, pn** 

LOG allows you to log to a new disk and PPN, using an ersatz or traditional specification, with an option to silence the normal output (start message) that you would otherwise see with an AMOS LOG command. It may also be used to return your current device, project, and programmer number. 

## **Parameters** 

## _logstr_ (String)  [in] 

A string specifying the desired device and/or PPN to log to.  Any of the formats accepted by LOG.LIT are accepted here.  See examples below. 

## _qflag_ (String)  [in] 

If specified and non-null, silences the normal confirmation message that you would see when logging into a new location. By convention, _qflag_ is set to "Q" to indicate this "quiet" mode. 

_status_ (F6)  [in/out] 

If specified and set to a non-zero value on input, the routine will validate the target device and ppn, and return 0 for success, or a system error number for failure.  Note that you must initialize the variable to a non-zero value for this validation to occur. Otherwise, it will still return -1 if the target device is invalid, but it will not validate the PPN, and thus it would appear to allow you to log into a non-existent PPN. See History. 

## _dev_ (String)  [out] 

Returns current logged-in device, in upper case, with no trailing spaces or punctuation, e.g. "DSK0". 

_p_ (String)  [out] 

A-Shell Reference 

Page 2694 

Returns decimal string representation of current "project"(1st part of PPN), e.g. "1" or "200" 

## _pn_ (String)  [out] 

Returns decimal string representation of current "programmer number" (2nd part of PPN), e.g. "4" or "921" 

## **Examples** 

```
xcall LOG,"SYS:"               (log to SYS:)
xcall LOG,"LOG DSK0:[1,4]      ('LOG' is optional)
xcall LOG,"SYS:","Q"           (silence output)
xcall LOG,DEV$,P$,PN$          (return current login)
```

## **Comments** 

The routine determines which operation to perform—log to a new location or return the current location—based on the number and type of parameters passed. If 3 arguments are passed and the 3rd argument is not a floating point variable, it returns the current location; in all other cases it treats the operation as a request to log to a new location. 

Note that by returning the PPN as a pair of decimal-formatted strings, this routine avoids the issues related to octal vs. decimal representation and single-byte overflow that may affect routines that manipulate the PPN as a pair of binary values. 

## **History** 

- 2016 June, A Shell 6.3.1515: _Status_ now returns numeric error codes on failure rather than just -1. 

A-Shell Reference 

Page 2695 

## **LSTLIN** 

_Rewritten May 2026_ 

## **xcall LSTLIN, cmdline** 

LSTLIN retrieves the complete command line from which the current program was launched. 

## **Parameters** 

_cmdline_ (String)  [out] 

Returns the complete command line, optionally stripped of trailing comments 

## **Comments** 

The returned cmdline will be similar to the CMDLIN{$} system variable, except: 

- It is not folded to upper case, while CMDLIN is. 

- It includes the name—and any device or PPN, if specified—of the current program, while CMDLIN only includes the part of 

- the command line following the current program name, i.e. its arguments. 

- It does not require COMPIL /X:1 or higher, while CMDLIN does. Otherise, it is treated as a ordinary variable with no special 

- meaning. 

For example: 

```
Program LSTLIN,1.0(100)
```

```
MAP1 A$,S,100
```

- `? "CMDLIN$ = [";CMDLIN$;"] (requires /X:1+)"` 

- `? "CMDLIN = [";CMDLIN;"] (same as CMDLIN$)"` 

A-Shell Reference 

Page 2696 

```
xcall LSTLIN,A$
```

- `? "XCALL LSTLIN = [";A$;"]"` 

If the program above is compiled with COMPLP (or COMPIL /X:1 or /X:2), the command line below will produce the following output: 

```
.run dsk0:lstlin[150,277]/hello world
```

```
CMDLIN$ = [/HELLO WORLD] (requires /X:1+)
```

```
CMDLIN = [/HELLO WORLD] (same as CMDLIN$)
```

```
XCALL LSTLIN = [dsk0:lstlin[150,277]/hello world]
```

## **See Also** 

- SBR=LSTLINSTRIP (strip trailing comments) 

- CMDLIN 

A-Shell Reference 

Page 2697 

## **MATCH** 

## **xcall MATCH, rtncod, value, range** 

MATCH is useful in building flexible record selection logic. With it, you can easily allow the users to specify a list of acceptable values, or ranges of values, for a particular field. Then for each candidate record, just pass the value and range specification to the subroutine and let it worry about numeric, string, and date comparisons. 

## **Parameters** 

_rtncod_ (Signed Num) 

returns the results: 

|**Value **|**Meaning**|
|---|---|
|0|No match; value is not within the specified list or range|
|1|Match; value is within range|
|-1|Parameter error|
|-2|Value type not supported|
|-3|Range string too long|
|-4|Syntax error in range|



A-Shell Reference 

Page 2698 

_value_ (F,6, (String), or B#) 

is the value which you want to check against the range. 

## _range_ 

is the range specification in the form: 

```
r1,r2,r3,...,rn
```

Each of the _rx_ entries in the range string may be either a single value or a from-to range expressed as a beginning and ending value, separated by a dash. Each item in the range list is interpreted according to the type of the _value_ parameter. String entries are case sensitive. If both _value_ and _range_ are of type string, and _value_ is in the form: 

## `mm/dd/ccyy` 

then each entry in the _range_ string is interpreted as a date in a similar format. `mm/yy` is interpreted as `mm/01/ccyy` if followed by a dash, or `mm/31/ccyy` if preceded by a dash. The `cc` value is assumed to be 19 unless specified or unless the SBR=CCYY:## setting in miame.ini has been established. 

On return, _range_ is converted into a "compiled" format to eliminate the need for parsing it out on the next call. (If used for file record selection, you would typically be calling this routine hundreds or even thousands of times, with different _value_ parameters but the same (or a limited number of) _range_ strings. 

A NULL _range_ string matches all, as does a NULL _value_ (for String ranges). Examples: 

|**Range String**|**Meaning**|
|---|---|
|"AA-CZ,F,JA*"|Match any string starting with "AA" through "CZ" ("ABCD" matches, "CZ1" does<br>not). Also match if Value = "F", or if it equals anything starting with "JA".|
|"91300-91399,93132,95555"|Match any number 91300 through 91399, or match 93132 or 95555.|



A-Shell Reference 

Page 2699 

|**Range String**|**Meaning**|
|---|---|
|"03/15/97,04/17-2/18,3/02/2025"|Date match, including 15 March 1997, or 1 April 1 2017 through 28 Feb 2018,<br>or 2 March 2025, assuming SBR=CCYY<br>:##  with 18 < ## < 97.|



A-Shell Reference 

Page 2700 

## **MIAMEX** 

## **xcall MIAMEX, function-id {,param1, param2, ... paramN}** 

MIAMEX is a collection of utility functions referencing system internals that are gathered together here for efficiency or because they do not fall nicely into other categories. Each of the functions is listed in the following two topics, with links to detailed documentation. Interested programmers should also consult the sample program MIAMEX.BP in EXLIB:[908,30] which contains examples of the more generally useful functions. Note that functions which are listed in the following tables but do not have additional details are A-Shell internal functions not intended for use by A-Shell programmers. 

In all of the MIAMEX specifications, the first parameter is _function-id,_ as specified using the variable name (MX_xxx) defined in ashell.def. These functions are shown in the following two tables, MIAMEX Functions by Number and MIAMEX Functions by Symbol. 

Note that good programming techniques require that the MIAMEX _function-id_ be identified by symbol rather than literal number so as to make your code more understandable. Seeing a reference to MX_FINDFIRST five years from now will be much more informative than seeing MIAMEX 20. 

Similarly, many MIAMEX functions reference coded numeric arguments for which the defined symbolic names, if available (typically in ashell.def) would be preferable to the literal numeric value. The most common example are the symbols MXOP_GET (0) and MXOP_SET (1) which are used as the _opcode_ parameter in many functions. 

A-Shell Reference 

Page 2701 

## **MIAMEX FUNCTIONS BY NAME** 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_ABOUT|93|Get license info (used byABOUT<br>.LIT)|
|MX_AGINTERPROC|179|Send AG commands between instances of A-Shell/Windows|
|MX_AGWRAPPER|177|Wraps "raw" ATE commands|
|MX_AMOUSEXLT|112|Set AutoMouse translations (Windows only)|
|MX_AS3264|200|Get A-Shell architecture (32- or 64-bit)|
|MX_ASHFILE|130|Retrieve startup command and/or name of A-Shell executable|
|MX_ASHLOG|124|Output STRING message toashlog.log|
|MX_ATE|98|Start ATE|
|MX_ATEFILEXFR|183|Performs ATE/ATSD file transfer|
|MX_AUTOPARENT|141|Set parent controls|
|MX_BEVEL|90|Get / set bevel options (Windows only)|



A-Shell Reference 

Page 2702 

|**Symbol**|**Value**|**Function**|
|---|---|---|
||||
|MX_BROWSEFOLDER|170|Selects a folder or other non-file object (such as a computer)|
|MX_CALLSTACK|189|Returns information about the call stack|
|MX_CHAINTO|121|Get / set chain-to on privilege violation|
|MX_CHKPCNET|176|Checks network state of PC|
|MX_CHKPPN|10|Check for ppn|
|MX_CHOOSECOLOR|164|Display color selection dialog|
|MX_CHOOSEFONT|165|Display font selection dialog|
|MX_CLFLAGS|103|Get / set ashell command line switches|
|MX_CLIPBOARD|105|Get / set clipboard (Windows only)|
|MX_CLRINBUF|184|Clears input buffer and type ahead|



A-Shell Reference 

Page 2703 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_CLRSIG|55|Clear signal received flags (Unix only)|
|MX_CMD_STATUS|1|Get / set command file status|
|MX_CMDKBD|142|Retrieve CMD file variables|
|MX_COMPIL|15|COMPIL|
|MX_COPYFILE|27|Copy file|
|MX_CSVDELIM|181|Get / set the CSV delimiter character|
|MX_DEBUG|144|Get / set DEBUG level|
|MX_DEFTABXYZ|154|Set "3D" Tab attributes|
|MX_DIRCLEAN|204|Counts or deletes files based on various filter attributes|
|MX_DIRSEP|22|Get directory separator|
|MX_DRAGDROP|199|Accept drag drop|



A-Shell Reference 

Page 2704 

|**Symbol**|**Value**|**Function**|**Function**|
|---|---|---|---|
|MX_DYNFUNC|193|Used for DYNFUNC-related utilities||
|MX_DYNSTRUCT|192|Implements A-Shell's dyanamic structures||
|MX_ERRNOMSG|86|Get operating system error message by errno||
|MX_EVENTWAIT|135|Deprecated. UseAUI_EVENTWAIT<br>.||
|MX_EXIT|2|Exit A-Shell||
|MX_EXITSBX|82|Exit to dot prompt (even from with an|SBX<br>)|
|MX_EXPFIL|133|Expand / reduce a file in place||
|MX_FILECHINFO|161|Returns info about open file based on file channel||
|MX_FILEHOOK|178|Establish file "hooks" on specific files and file events||
|MX_FILEPOS|118|Get / set file pointer within stream||
|MX_FILESOCK|187|Binds a TCP socket to a sequential file channel||



A-Shell Reference 

Page 2705 

|**Symbol**|**Value**|**Function**|**Function**|
|---|---|---|---|
|MX_FILESTATS|131|Retrieve stats for specified path||
|MX_FILETIMES|196|Get / set a file's modification, creation or access time||
|MX_FILEVAR|195|Get / set the value of the file record number variable||
|MX_FINDEND|23|End directory processing||
|MX_FINDFIRST|20|Find first matching file||
|MX_FINDNEXT|21|Find next matching file||
|MX_FINDWINDOW|157|Find window by_title_and/or_class_and/or_handle_||
|MX_FLINES|147|Count lines, maximum line length in file||
|MX_FLSET|89|Clone file channel (within|SBX<br>) (similar to M68 FLSET)|
|MX_FLUSHBUF|88|Flush stream file buffer||
|MX_FSPEC|3|Translate DevPPN filespec to native||



A-Shell Reference 

Page 2706 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_FTFORMAT|132|Reformat filetime fromMX_FILESTATS|
|MX_GDICALC|148|Calculate String length or height|
|MX_GETCISAM|34|Get CISAM/DISAM version|
|MX_GETCMDINP|52|Return CMDINP flags|
|MX_GETCTRLC|4|GetCTRL+Cstatus|
|MX_GETDEV|19|Get next device|
|MX_GETDPI|197|Get monitor resolution|
|MX_GETECHO|5|Get echo status|
|MX_GETENV|31|Return environment variable value|
|MX_GETERSATZ|11|Return ersatz|
|MX_GETFKW|83|GetFKEYWAITvalue (Unix only)|



A-Shell Reference 

Page 2707 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETGDO|78|Get global DO parameters|
|MX_GETHASH|36|Get hex status|
|MX_GETHEX|7|Get hex output status|
|MX_GETIP|128|Get IP address|
|MX_GETLOKSER|50|Return LOKSER flags|
|MX_GETODBC|40|Is ODBC available?|
|MX_GETOFD|95|Windows Open File dialog (Windows only)|
|MX_GETOPTIONS|59|Return OPTIONS flags|
|MX_GETPFK|64|Return PFK name|
|MX_GETPID|104|Get process ID (pid)|
|MX_GETPROMPT|24|Get prompt|



A-Shell Reference 

Page 2708 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETQUEUE|30|Return queue block|
|MX_GETRC|94|Get current cursor position|
|MX_GETREG|99|Retrieve registry value (Windows only)|
|MX_GETSHELLPATH|171|Retrieves the path for a specified Windows directory ID|
|MX_GETSIG|54|Return signal received flags (Unix only)|
|MX_GETSW|101|Get swap wait value (in ms) (Unix only)|
|MX_GETTIME|75|Get current system time|
|MX_GETTRACE|61|Return TRACE flags|
|MX_GETUMSK|69|Return umask (Unix only)|
|MX_GETUPTIME|198|Get system uptime|
|MX_GETVER|12|Return A-Shell version|



A-Shell Reference 

Page 2709 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETWINFILEVERS|194|Retrieves version of a Windows DLL or executable|
|MX_GTOCT|160|Convert hex or octal to decimal|
|MX_GUIFLG|129|Deprecated. UseAUI_ENVIRONMENT<br>.|
|MX_HASHFILE|25|Get hash|
|MX_HOTKEY|92|Enable / disable PolyShell hot keys|
|MX_HTMLHELP|137|Deprecated. UseAUI_HTMLHELP<br>.|
|MX_IATIMEOUT|180|Get / set the inactivity timeout period|
|MX_INFDEF|143|Get / set INFLD default TYPE codes|
|MX_INICLR|116|Process an INI.CLR file|
|MX_INSTNUM|156|Return instance number|
|MX_IXCALL|115|Indirect XCALL|



A-Shell Reference 

Page 2710 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_KILL|57|Kill job|
|MX_LANGUAGE|190|Retrieves or sets the current language|
|MX_LASTLNO|146|Retrieve last line number of program|
|MX_LASTPRTFIL|186|Returns specs of the last file written by the PDFX printer driver|
|MX_LITMSG|72|Display LITMSG.xxx message|
|MX_LOCALE|205|Queries the native OS locale information.|
|MX_LOGDIR|206|Changes the location of the ashlog.log file directory.|
|MX_MALLOCLIMIT|185|Get / set theMALLOCLIMIT|
|MX_MAPI|117|MAPI Send Mail (Windows only)|
|MX_MARSHAL|114|Marshall parameters for remote subroutine|
|MX_MATCHWILD|33|Match cmdlin|



A-Shell Reference 

Page 2711 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_MCRS|125|Retrieve information about last mouse click|
|MX_MEMORY|113|Change user partition size|
|MX_MKDIR|97|Create directory (Windows only)|
|MX_MKPATH|38|Create directory|
|MX_NOBUF|87|Disable stream file buffering|
|MX_NXTCMD|18|Get next command file line|
|MX_OCVT|9|Octal conversion (OCVT)|
|MX_ODBCEND|44|ODBC end|
|MX_ODBCFIRST|42|Return first ODBC table|
|MX_ODBCNEXT|43|Return next ODBC table|
|MX_OSVER|106|Get operating system version|



A-Shell Reference 

Page 2712 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_PLAYSOUND|100|Play a sound file (Windows only)|
|MX_PREBAS|16|CPRE|
|MX_PRFSPEC|26|Print filespec|
|MX_PRINTERR|28|Output error message|
|MX_PWCRYPT|172|Provides simple password encryption|
|MX_QLOCK|67|Lock queue|
|MX_QRBLD|66|Force queue rebuild|
|MX_QUNLOK|68|Unlock queue|
|MX_READJCB|73|Returnjobtbl.sysrecord|
|MX_REGISTRY|138|Registry operations|
|MX_RELEASEKBD|153|Set / release keyboard hold|



A-Shell Reference 

Page 2713 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_RENAMERR|29|Output rename error message|
|MX_RMPATH|39|Delete directory|
|MX_ROUND|127|Get / set rounding factor|
|MX_RUNPROF|203|Generates a run profile log|
|MX_SBRFLG|123|Get / set options that are normally set withSBR=inmiame.ini|
|MX_SCRNPIC|65|Take screen snapshot|
|MX_SETCMDINP|53|Set CMDINP flags|
|MX_SETCRM|35|Set Console Redirection Mode|
|MX_SETENV|56|Change TERM environment variable (Unix only)|
|MX_SETERR|182|Triggers an ASB error|
|MX_SETERSATZ|208|Adds/updates ERSATZ devices without relaunch.|



A-Shell Reference 

Page 2714 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_SETEXT|32|Set default extension|
|MX_SETFKW|84|Set FKEYWAIT value (Unix only)|
|MX_SETGDO|79|Set global DO parameters|
|MX_SETHASH|37|Set / reset AMOS hash flag|
|MX_SETHEX|8|Set / reset hex mode|
|MX_SETLOKSER|51|Set LOKSER flags|
|MX_SETMEMFLAGS|163|Change memory module flags|
|MX_SETOPTIONS|60|Set OPTIONS flags|
|MX_SETPFK|63|Set function key translation or PFK|
|MX_SETPROMPT|6|Set command prompt|
|MX_SETSW|102|Set swap wait value (in ms) (Unix only)|



A-Shell Reference 

Page 2715 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_SETTRACE|62|Set TRACE flags|
|MX_SETUMSK|70|Set umask (Unix only)|
|MX_SETUSRNAM|169|Set / override user name|
|MX_SHELLEX|96|Shell Execute (open/print registered file type)|
|MX_SHORTCUT|173|Create shortcut|
|MX_SHOWLIC|58|Display license|
|MX_SHOWWINDOW|77|Deprecated. UseAUI_WINDOW<br>.|
|MX_SINK|126|Sink / unsink specified box|
|MX_SRCHPATH|191|Searchs for a file in the system path|
|MX_STRCMP|174|Compare two strings in various ways|
|MX_SYNC|134|Invokes operating system sync command|



A-Shell Reference 

Page 2716 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_SYNC_CWD|17|Synchronize A-Shell PPN with system path|
|MX_SYSBCLR|91|Define BG color # to track system COLOR_3DFACE|
|MX_SYSLOG|207|Outputs text to the Linux syslog facility|
|MX_TELSER|76|Launch Telnet server mode (Windows only)|
|MX_TITLE|85|Get / set Window title|
|MX_TRANSCOPY|202|Copy and translate a file|
|MX_UNLOADLIB|145|<reserved>|
|MX_USRDEL|109|Delete module from USRMEM|
|MX_USRIO|111|Read / write USRMEM data directly|
|MX_USRLOD|108|Load module (or variable) into USRMEM|
|MX_USRMAP|107|Get USRMEM module information|



A-Shell Reference 

Page 2717 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_USRSAV|110|Save module from USRMEM to disk|
|MX_VERINODE|167|Verify file information|
|MX_VUE|14|VUE|
|MX_WEBCACHE|188|Provides operations related to A-Shell's web cache feature|
|MX_WINCTL|119|Deprecated. UseAUI_CONTROL<br>.|
|MX_WINMNU|71|Deprecated. Use AUI_MENU<br>.|
|MX_WINPTR|120|Prompt for Windows printer (Windows only)|
|MX_WINSETTINGS|149|Get / set A-Shell GUI Settings|
|MX_WRITEJCB|74|Writejobtbl.sysrecord|
|MX_WSET_STATUS|13|Get / set WSET flags|
|MX_XCBDATAX|81|Deprecated.|



A-Shell Reference 

Page 2718 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_XCBINFOX|80|Reserved|
|MX_ZAPQUEUE|41|Zap queue|



A-Shell Reference 

Page 2719 

## **MIAMEX FUNCTIONS BY NUMBER** 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_CMD_STATUS|1|Get / set command file status|
|MX_EXIT|2|Exit A-Shell|
|MX_FSPEC|3|Translate DevPPN filespec to native|
|MX_GETCTRLC|4|GetCTRL+Cstatus|
|MX_GETECHO|5|Get echo status|
|MX_SETPROMPT|6|Set command prompt|
|MX_GETHEX|7|Get hex output status|
|MX_SETHEX|8|Set / reset hex mode|
|MX_OCVT|9|Octal conversion (OCVT)|
|MX_CHKPPN|10|Check for ppn|
|MX_GETERSATZ|11|Return ersatz|



A-Shell Reference 

Page 2720 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETVER|12|Return A-Shell version|
|MX_WSET_STATUS|13|Get / set WSET flags|
|MX_VUE|14|VUE|
|MX_COMPIL|15|COMPIL|
|MX_PREBAS|16|CPRE|
|MX_SYNC_CWD|17|Synchronize A-Shell PPN with system path|
|MX_NXTCMD|18|Get next command file line|
|MX_GETDEV|19|Get next device|
|MX_FINDFIRST|20|Find first matching file|
|MX_FINDNEXT|21|Find next matching file|
|MX_DIRSEP|22|Get directory separator|



A-Shell Reference 

Page 2721 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_FINDEND|23|End directory processing|
|MX_GETPROMPT|24|Get prompt|
|MX_HASHFILE|25|Get hash|
|MX_PRFSPEC|26|Print filespec|
|MX_COPYFILE|27|Copy file|
|MX_PRINTERR|28|Output error message|
|MX_RENAMERR|29|Output rename error message|
|MX_GETQUEUE|30|Return queue block|
|MX_GETENV|31|Return environment variable value|
|MX_SETEXT|32|Set default extension|
|MX_MATCHWILD|33|Match cmdlin|



A-Shell Reference 

Page 2722 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETCISAM|34|Get CISAM/DISAM version|
|MX_SETCRM|35|Set Console Redirection Mode|
|MX_GETHASH|36|Get hex status|
|MX_SETHASH|37|Set / reset AMOS hash flag|
|MX_MKPATH|38|Create directory|
|MX_RMPATH|39|Delete directory|
|MX_GETODBC|40|Is ODBC available?|
|MX_ZAPQUEUE|41|Zap queue|
|MX_ODBCFIRST|42|Return first ODBC table|
|MX_ODBCNEXT|43|Return next ODBC table|
|MX_ODBCEND|44|ODBC end|



A-Shell Reference 

Page 2723 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETLOKSER|50|Return LOKSER flags|
|MX_SETLOKSER|51|Set LOKSER flags|
|MX_GETCMDINP|52|Return CMDINP flags|
|MX_SETCMDINP|53|Set CMDINP flags|
|MX_GETSIG|54|Return signal received flags (Unix only)|
|MX_CLRSIG|55|Clear signal received flags (Unix only)|
|MX_SETENV|56|Change TERM environment variable (Unix only)|
|MX_KILL|57|Kill job|
|MX_SHOWLIC|58|Display license|
|MX_GETOPTIONS|59|Return OPTIONS flags|
|MX_SETOPTIONS|60|Set OPTIONS flags|



A-Shell Reference 

Page 2724 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETTRACE|61|Return TRACE flags|
|MX_SETTRACE|62|Set TRACE flags|
|MX_SETPFK|63|Set function key translation or PFK|
|MX_GETPFK|64|Return PFK name|
|MX_SCRNPIC|65|Take screen snapshot|
|MX_QRBLD|66|Force queue rebuild|
|MX_QLOCK|67|Lock queue|
|MX_QUNLOK|68|Unlock queue|
|MX_GETUMSK|69|Return umask (Unix only)|
|MX_SETUMSK|70|Set umask (Unix only)|
|MX_WINMNU|71|Deprecated. Use AUI_MENU<br>.|



A-Shell Reference 

Page 2725 

|**Symbol**|**Value**|**Function**|**Function**|
|---|---|---|---|
|MX_LITMSG|72|Display LITMSG.xxx message||
|MX_READJCB|73|Returnjobtbl.sysrecord||
|MX_WRITEJCB|74|Writejobtbl.sysrecord||
|MX_GETTIME|75|Get current system time||
|MX_TELSER|76|Launch Telnet server mode (Windows only)||
|MX_SHOWWINDOW|77|Deprecated. UseAUI_WINDOW<br>.||
|MX_GETGDO|78|Get global DO parameters||
|MX_SETGDO|79|Set global DO parameters||
|MX_XCBINFOX|80|**Deprecated**||
|MX_XCBDATAX|81|**Deprecated**.||
|MX_EXITSBX|82|Exit to dot prompt (even from with an|SBX<br>)|



A-Shell Reference 

Page 2726 

|**Symbol**|**Value**|**Function**|**Function**|
|---|---|---|---|
|MX_GETFKW|83|Get FKEYWAIT value (Unix only)||
|MX_SETFKW|84|Set FKEYWAIT value (Unix only)||
|MX_TITLE|85|Get / set Window title||
|MX_ERRNOMSG|86|Get operating system error message by errno||
|MX_NOBUF|87|Disable stream file buffering||
|MX_FLUSHBUF|88|Flush stream file buffer||
|MX_FLSET|89|Clone file channel (within|SBX<br>) (similar to M68 FLSET)|
|MX_BEVEL|90|Get / set bevel options (Windows only)||
|MX_SYSBCLR|91|Define BG color # to track system COLOR_3DFACE||
|MX_HOTKEY|92|Enable / disable PolyShell hot keys||
|MX_ABOUT|93|Get license info (used byABOUT<br>.LIT)||



A-Shell Reference 

Page 2727 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETRC|94|Get current cursor position|
|MX_GETOFD|95|Windows Open File dialog (Windows only)|
|MX_SHELLEX|96|Shell Execute (open/print registered file type)|
|MX_MKDIR|97|Create directory (Windows only)|
|MX_ATE|98|Start ATE|
|MX_GETREG|99|Retrieve registry value (Windows only)|
|MX_PLAYSOUND|100|Play a sound file (Windows only)|
|MX_GETSW|101|Get swap wait value (in ms) (Unix only)|
|MX_SETSW|102|Set swap wait value (in ms) (Unix only)|
|MX_CLFLAGS|103|Get / set ashell command line switches|
|MX_GETPID|104|Get process ID (pid)|



A-Shell Reference 

Page 2728 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_CLIPBOARD|105|Get / set clipboard (Windows only)|
|MX_OSVER|106|Get operating system version|
|MX_USRMAP|107|Get USRMEM module information|
|MX_USRLOD|108|Load module (or variable) into USRMEM|
|MX_USRDEL|109|Delete module from USRMEM|
|MX_USRSAV|110|Save module from USRMEM to disk|
|MX_USRIO|111|Read / write USRMEM data directly|
|MX_AMOUSEXLT|112|Set AutoMouse translations (Windows only)|
|MX_MEMORY|113|Change user partition size|
|MX_MARSHAL|114|Marshall parameters for remote subroutine|
|MX_IXCALL|115|Indirect XCALL|



A-Shell Reference 

Page 2729 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_INICLR|116|Process an INI.CLR file|
|MX_MAPI|117|MAPI Send Mail (Windows only)|
|MX_FILEPOS|118|Get / set file pointer within stream|
|MX_WINCTL|119|Deprecated. UseAUI_CONTROL<br>.|
|MX_WINPTR|120|Prompt for Windows printer (Windows only)|
|MX_CHAINTO|121|Get / set chain-to on privilege violation|
|MX_SBRFLG|123|Get / set options that are normally set withSBR=inmiame.ini|
|MX_ASHLOG|124|Output STRING message toashlog.log|
|MX_MCRS|125|Retrieve information about last mouse click|
|MX_SINK|126|Sink / unsink specified box|
|MX_ROUND|127|Get / set rounding factor|



A-Shell Reference 

Page 2730 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_GETIP|128|Get IP address|
|MX_GUIFLG|129|Deprecated. UseAUI_ENVIRONMENT<br>.|
|MX_ASHFILE|130|Retrieve startup command and/or name of A-Shell executable|
|MX_FILESTATS|131|Retrieve stats for specified path|
|MX_FTFORMAT|132|Reformat filetime fromMX_FILESTATS|
|MX_EXPFIL|133|Expand / reduce a file in place|
|MX_SYNC|134|Invokes operating system sync command|
|MX_EVENTWAIT|135|Deprecated. UseAUI_EVENTWAIT<br>.|
|MX_HTMLHELP|137|Deprecated. UseAUI_HTMLHELP<br>.|
|MX_REGISTRY|138|Registry operations|
|MX_AUTOPARENT|141|Set parent controls|



A-Shell Reference 

Page 2731 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_CMDKBD|142|Retrieve CMD file variables|
|MX_INFDEF|143|Get / set INFLD default TYPE codes|
|MX_DEBUG|144|Get / set DEBUG level|
|MX_UNLOADLIB|145|<reserved>|
|MX_LASTLNO|146|Retrieve last line number of program|
|MX_FLINES|147|Count lines, maximum line length in file|
|MX_GDICALC|148|Calculate String length or height|
|MX_WINSETTINGS|149|Get / set A-Shell GUI Settings|
|MX_RELEASEKBD|153|Set / release keyboard hold|
|MX_DEFTABXYZ|154|Set "3D" Tab attributes|
|MX_INSTNUM|156|Return instance number|



A-Shell Reference 

Page 2732 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_FINDWINDOW|157|Find window by_title_and/or_class_and/or_handle_|
|MX_GTOCT|160|Convert hex or octal to decimal|
|MX_FILECHINFO|161|Returns info about open file based on file channel|
|MX_SETMEMFLAGS|163|Change memory module flags|
|MX_CHOOSECOLOR|164|Display color selection dialog|
|MX_CHOOSEFONT|165|Display font selection dialog|
|MX_VERINODE|167|Verify file information|
|MX_SETUSRNAM|169|Set / override user name|
|MX_BROWSEFOLDER|170|Selects a folder or other non-file object (such as a computer).|
|MX_GETSHELLPATH|171|Retrieves the path for a specified Windows directory ID.|
|MX_PWCRYPT|172|Provides simple password encryption.|



A-Shell Reference 

Page 2733 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_SHORTCUT|173|Create shortcut.|
|MX_STRCMP|174|Compare two strings in various ways.|
|MX_CHKPCNET|176|Checks network state of PC.|
|MX_AGWRAPPER|177|Wraps "raw" ATE commands.|
|MX_FILEHOOK|178|Establish file "hooks" on specific files and file events.|
|MX_AGINTERPROC|179|Send AG commands between instances of A-Shell/Windows.|
|MX_IATIMEOUT|180|Get / set the inactivity timeout period.|
|MX_CSVDELIM|181|Get / set the CSV delimiter character.|
|MX_SETERR|182|Triggers an ASB error.|
|MX_ATEFILEXFR|183|Performs ATE/ATSD file transfer.|
|MX_CLRINBUF|184|Clears input buffer and type ahead.|



A-Shell Reference 

Page 2734 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_MALLOCLIMIT|185|Get / set theMALLOCLIMIT<br>.|
|MX_LASTPRTFIL|186|Returns specs of the last file written by the PDFX printer driver.|
|MX_FILESOCK|187|Binds a TCP socket to a sequential file channel.|
|MX_WEBCACHE|188|Provides operations related to A-Shell's web cache feature.|
|MX_CALLSTACK|189|Returns information about the call stack.|
|MX_LANGUAGE|190|Retrieves or sets the current language|
|MX_SRCHPATH|191|Searchs for a file in the system path|
|MX_DYNSTRUCT|192|Implements A-Shell's dyanamic structures.|
|MX_DYNFUNC|193|Used for DYNFUNC-related utilities.|
|MX_GETWINFILEVERS|194|Retrieves version of a Windows DLL or executable.|
|MX_FILEVAR|195|Get / set the value of the file record number variable|



A-Shell Reference 

Page 2735 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_FILETIMES|196|Get / set a file's modification, creation or access time.|
|MX_GETDPI|197|Get monitor resolution|
|MX_GETUPTIME|198|Get system uptime|
|MX_DRAGDROP|199|Accept drag drop|
|MX_AS3264|200|Get A-Shell architecture (32- or 64-bit)|
|MX_TRANSCOPY|202|Copies and translates a file|
|MX_RUNPROF|203|Generates a run profile log|
|MX_DIRCLEAN|204|Counts or deletes files based on various filter attributes|
|MX_LOCALE|205|Queries the native OS locale information.|
|MX_LOGDIR|206|Changes the location of the ashlog.log file directory.|
|MX_SYSLOG|207|Outputs text to the Linux syslog facility|



A-Shell Reference 

Page 2736 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|MX_SETERSATZ|208|Adds/updates ERSATZ devices without relaunch.|



A-Shell Reference 

Page 2737 

## **MX_CMD_STATUS** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_CMD_STATUS, cmdcode** 

MX_CMD_STATUS (MIAMEX 1) sets the command file status, returning the previous status. 

## **Parameters** 

## _cmdcode_ (Unsigned Int)  [in/out] 

Sets the new command file status and retrieves the prior status, based on the following table. 

|**Value **|**Meaning**|
|---|---|
|0|No command file currently running|
|1|Command file is in silent (:S) mode|
|_2_|Command file is in response (:R) mode|
|3|Command file is in trace (:T) mode|
|4|Command file is executing last line while in silent mode|



## **Comments** 

To retrieve the current status without changing it, make a copy of the returned status and call it a second time. For example: 

```
map1 cmdcode,b,1
```

A-Shell Reference 

Page 2738 

```
map1 cmdcode2,b,1
```

```
xcall MIAMEX, MX_CMD_STATUS, cmdcode      ! retrieve current status, set new status to 0
cmdcode2 = cmdcode                        ! copy of original status
xcall MIAMEX, MX_CMD_STATUS, cmdcode2     ! reset the original status
```

```
? "Current status is "; cmdcode
```

A-Shell Reference 

Page 2739 

## **MX_EXIT** 

## **xcall MIAMEX, MX_EXIT** 

MX_EXIT (MIAMEX 2) causes an immediate exit from A-Shell, returning control to whatever context it was launched from. 

## **See Also** 

- MX_EXITSBX 

A-Shell Reference 

Page 2740 

## **MX_FSPEC** 

_Reviewed and Revised April 2024_ 

## **xcall MIAMEX, MX_FSPEC, spec, locpath, ext, flags, ddb, status** 

MX_FSPEC (MIAMEX 3) deconstructs a DevPPN filespec into its constituent parts of Device name, File name, and extension _(ddb_ ). It also optionally returns the host machine pathname corresponding to the DevPPN specification in _locpath_ . 

## **Parameters** 

## _spec_ (String)  [in] 

should contain the DevPPN-format file specification that you want to parse or convert to native format. If the device and/or PPN are omitted, they will be supplied by your current login directory. If the extension is omitted, it will be supplied by the _ext_ parameter. Note that the file does not need to exist, but it must have valid syntax (e.g. "a.a") and not be null (or else an invalid filespec error will result and the returned locpath will either be null or the previously processed filespec). See _Comments_ , below, for information on how to retrieve the current native directory. 

## _locpath_ (String)  [out] 

is only used if you wish to return the host machine pathname for the file specification given in spec. This is specified by the FS_TOH bit in the _flags_ parameter, in which case the variable _locpath_ should be mapped to an appropriate length for the longest path you expect to deal with. (The maximum path length under Windows is 260 characters.) Otherwise, the parameter may be specified as a null string (""), and it will be set to "" in case of error. 

## _ext_ (String)  [in] 

is the default extension to use when processing a full file specification. It will be used if the given specification contains only a filename and no extension. The extension used is returned in the extension field of the _ddb_ structure variable, and is used in the host format pathname if one is returned. 

## _flags_ (Num)  [in] 

is used to determine exactly how the file specification processing is to take place. It is bit-mapped, and each bit may be set by adding together the symbolic values defined in the include file ashell.def. 

A-Shell Reference 

Page 2741 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|FS_DRV|1|indicates that the drive name and number only are to be processed. When used in conjunction<br>with FS_FMA (2), the device specification given in_spec_ is returned in the_ddb_ structure<br>parameter.|
|FS_FMA|2|indicates that the file specification given in the_spec_ parameter is to be used. Otherwise the<br>already processed specification given in its constituent parts in the_ddb_ structure parameter will<br>be used. It only makes sense to omit this bit if the FS_TOH (4) bit is set, indicating that a host<br>machine pathname is to be returned.|
|FS_TOH|4|indicates that the host machine path name corresponding either to the file specification in_spec_<br>or in the_ddb_ structure parameter is to be returned in the_locpath_ parameter. If this bit is not<br>specified then_locpath_ may be given as a null string ("")|
|**Definition file: ashell.def**|||



## _ddb_ (Structure)  [in/out] 

a structure defined in ashell.sdf as one of the following. The routine will detect which version was passed based on its size. `! original version...` 

```
defstruct ST_DDB
```

```
    map2 DEV,s,6        ! 6 characters AMOS device
```

```
    map2 FILNAM,s,32    ! 10 characters AMOS or 32 host
```

A-Shell Reference 

Page 2742 

```
    map2 EXT,s,8        ! 3 characters AMOS or 8 host
    map2 PRJ,s,3        ! 3 character justified P
    map2 PRG,s,3        ! 3 character justified PN
    map2 SPECTYPE,b,2   ! [104] see SPECTYPE_ xxx  (optional in 6.5.1613.0+; ignored before)
endstruct
```

```
! extended version (see History below)...
```

```
defstruct ST_DDBX
```

```
    map2 DEV,s,6        ! 6 characters AMOS device
    map2 FILNAM,s,72    ! 72 characters filename
    map2 EXT,s,8        ! 8 characters extension
    map2 PRJ,s,3        ! 3 character justified P
    map2 PRG,s,3        ! 3 character justified PN
    map2 SPECTYPE,b,2   ! see SPECTYPE_ xxx
endstruct
```

It is used to receive either the output of the function call if FS_FMA is specified, or the input to it if FS_TOH is specified, or both. Note the size of the _filnam_ and _ext_ fields. If the FS_FMA bit is specified, then the DevPPN format file specification passed, can actually be in the format of a local pathname (with long filename), in which case the filename and extension will be processed correctly. 

Note that if you are only interested in translating an AMOS-style specification into the equivalent native specification (i.e. using _code_ FS_FMA+FS_TOH) then you do not really need the fields of the _ddb_ parameter and can just supply an X or S variable of 52+ bytes. 

A-Shell Reference 

Page 2743 

_status_ (Num)  [out] 

returns a non-zero value if the device name (in the _spec_ or _ddb_ parameter/structure) does not exist and the FS_TOH bit is set in the _flags_ parameter. Otherwise it should return zero. 

## **Comments** 

A common objective is to determine the host directory corresponding to a particular AMOS-style DEVICE:[P,PN] or ersatz device. One way to accomplish this is to start with a dummy filename, like A.A, e.g. "DSK0:A.A[100,222]" or "MYERZ:A.A". Since the A.A will be the last 3 characters of the resulting filespec, you can easily trim them using a substring qualifier, e.g. DIR$ = LOCAL[1,-4]. 

## **History** 

- 2019 June, A Shell 6.5.1662:  The 32.8 FILNAM.EXT limit increased to 72.8 via introduction of ST_DDBX. Function determines which version passed by its size. 

A-Shell Reference 

Page 2744 

## **MX_GETCTRLC** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_GETCTRLC, ccon** 

MX_GETCTRLC (MIAMEX 4) retrieves the current CTRL+C status. 

## **Parameters** 

_ccon_ (Integer)  [out] 

Returns non-zero if CTRL+C interrupts are currently enabled, else zero. 

## **Comments** 

You can enable/disable CTRL+C interrupts using CCON[xs] or SET.LIT. 

A-Shell Reference 

Page 2745 

## **MX_GETECHO** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_GETECHO, echon** 

MX_GETECHO (MIAMEX 5) retrieves the current status of terminal echo. 

## **Parameters** 

_echon_ (Integer)  [out] 

Returns non-zero if terminal echo is currently enabled, else zero. 

## **Comments** 

You can enable/disable echo using calling ECHO/NOECHO. 

A-Shell Reference 

Page 2746 

## **MX_SETPROMPT** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_GETPROMPT, prompt** 

## **xcall MIAMEX, MX_SETPROMPT, prompt** 

MX_GETPROMPT (MIAMEX 24) gets, and MX_SETPROMPT (MIAMEX 6) sets, the prompt used at the command level. 

## **Parameters** 

_prompt_ (String)  [in for SET, out for GET] 

## **Comments** 

The maximum allowable prompt length is 20 characters. 

The prompt can also be set via the SET command. 

The system prompt or command level prompt is also known as the "dot prompt" because the default prompt is a single dot. 

A-Shell Reference 

Page 2747 

## **MX_GETHEX** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_GETHEX, hexon** 

## **xcall MIAMEX, MX_SETHEX, hexon** 

MX_GETHEX (MIAMEX 7) gets, and MX_SETHEX (MIAMEX 8) sets, the default radix for non-decimal numeric displays. 

## **Parameters** 

_hexon_ (Integer)  [in for SET, out for GET] 

If non-zero, mode is hex, else octal. 

## **Comments** 

Mainly this affects functions such as DUMP which display data in either octal or hex format, depending on the current radix. The option can also be displayed and set via the  SET command, i.e. `SET OCTAL` or `SET HEX` . 

A-Shell Reference 

Page 2748 

## **MX_OCVT** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_OCVT, number, size, flags {,strbuf}** 

MX_OCVT (MIAMEX 9) outputs a number in either hex or octal format. 

## **Parameters** 

_number_ (Unsigned Int)  [in] 

Number to display. 

_size_ (Unsigned Int)  [in] 

Width (number of digits) for the formatted display. If zero, the width will be set automatically to just enough to fit. Otherwise the display is padded leading zeroes or spaces to the specified size. Maximum _size_ is 64 digits. 

_flags_ (Bitmap, 8 bits)  [in] 

Zero or more options from the following table. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|OT_ZER|&h0001|Leading zero blanking|
|OT_TRM|&h0002|Output to terminal|
|OT_MEM|&h0004|Output to memory|
|OT_LSP|&h0010|Output leading space|



A-Shell Reference 

Page 2749 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|OT_TSP|&h0020|Output trailing space|
|OT_OCT|&h0040|Force output in octal|
|OT_HEX|&h0080|Force output in hex|
|**Definition file: ashell.def**|||



- Hex Decimal Values 

strbuf  (String)  [out] 

String variable to receive the formatted number if OT_MEM flag set. Otherwise this parameter can be omitted. 

## **Comments** 

If neither OT_OCT nor OT_HEX set, it will use the current default radix. See MX_GETHEX, MX_SETHEX. 

The confusingly named OT_ZER bit causes leading zeroes to be converted to spaces; see _size_ and _History_ . The OT_TRM bit should always be specified, and is included for compatibility reasons. The OT_LSP and OT_TSP bits output an additional leading space and trailing space respectively. 

The OT_MEM bit indicates that the output is to be stored in memory (and not output directly to the terminal). If this bit is specified, then the fifth parameter (String) must be present, which is a string or unformatted variable into which the formatted numerical output is returned. 

See the wrapper functions Fn'Dec2Hex$(decval,flags,width) and Fn'Hex2Dec(hex$) in the SOSLIB:[907,10]. 

A-Shell Reference 

Page 2750 

## **History** 

- 2025 August, A Shell 7.0.1775:  Maximum supported _size_ (width) increased from 8 to 64. 

- 2016 June, A Shell 6.3.1516:  MX_OCVT now supports 48 bit values, up from 32. This is equivalent to 12 hex characters or 16 octal characters. Note that the standard Fn'Dec2Hex$() in SOSLIB[907,10] function has been updated accordingly. 

A-Shell Reference 

Page 2751 

## **MX_CHKPPN** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_CHKPPN, dev, proj, prog, valid** 

MX_CHKPPN (MIAMEX 10) checks for the existence of the specified PPN on the specified device. 

## **Parameters** 

_dev_ (String)  [in] 

Must be set to a true (non-ersatz) device, including the trailing digit(s) but no colon, e.g. "DSK0" 

_proj, prog_ (Num)  [in] 

Must be set to the two parts of the PPN. Note that for historical reasons, going back to when PPNs were limited to octal values, if passed as B1 variables, they are interpreted octally. In other words, if proj = 64 (decimal) and _prog_ = 99 (decimal), the equivalent PPN would be [100,143]. However, if _proj_ and _prog_ are any other types, they are interpreted decimally, the same _proj_ and _prog_ values would represent PPN [64,99]. 

_valid_ (Num)  [out] 

Returns zero if the directory does not exist; else non-zero. 

## **Comments** 

Since A-Shell devices and PPNs map to host machine directories, this routine is equivalent to checking for the existence of the SP host machine directory which corresponds to the specified device and PPN according to the DEVICE statements in miame.ini. 

A-Shell Reference 

Page 2752 

## **MX_GETERSATZ** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_GETERSATZ, ersatz, dev, proj, prog, status** 

MX_GETERSATZ (MIAMEX 11) is used to obtain information about the defined ERSATZ devices. Each call returns the next defined ERSATZ device in sequence. 

## **Parameters** 

_ersatz_ (String, 10+)  [in/out] 

Returns the next defined ERSATZ device name without the trailing colon. To start from the beginning, set ersatz to "". Any other value is ignored on input, as it uses a static internal cursor to maintain its position in the table of definitions. 

_dev_ (String, 6+)  [out] 

Returns the real device corresponding to the ersatz device, e.g. "DSK0" 

_proj, prog_ (Num)  [out] 

Return the two parts of the PPN corresponding to the ersatz device. 

Warning: if B1 variables are used here, the routine will translate the PPN parts into octal, which is almost certainly not what you want except in certain legacy situations. Any other type will return the normal decimal PPN values, each of which ranges from 0 to 999. See PPN Numbering for the complete back story. 

_status_ (Num)  [out] 

Returns zero if not yet past the end of the table, i.e. indicating that the rest of the returned parameters are valid. Returns one indicating that the end of the table has been reached and the other parameters should be ignored. The next call will start over at the beginning of the table. See the _ersatz_ above for how to force it to start over at the beginning. 

## **Comments** 

A-Shell Reference 

Page 2753 

Note that a short-cut is available to reset to the first ERSATZ device. If the _ersatz_ parameter is a null string, then information on the first ERSATZ device will be returned; it is not necessary to go around a loop waiting for a returned status of one. 

## **See Also** 

- MX_GETDEV scans the table of real, i.e. non-ersatz devices 

A-Shell Reference 

Page 2754 

## **MX_GETVER** 

_Reviewed April 2024; rewritten September 2017_ 

## **xcall MIAMEX, MX_GETVER, verstr$ {,vmajor, vminor, vedit, vpatch {,ate'vmajor, ate'vminor, ate'vedit, ate'vpatch}}** 

MX_GETVER (MIAMEX 12) returns the current A-Shell version, as well as—optionally and if applicable—the ATE version. . 

## **Parameters** 

_verstr_ $  (String, 28+)  [out] 

String which will receive the version formatted as "A-Shell Version #.#.###.#" 

## _vmajor, vminor, vedit, vpatch_ (Num)  [out] 

These variables return the individual parts of the A-Shell version, broken out from _verstr_ $ for convenience. Note that _vmajor_ , _vminor_ and _vpatch_ can be mapped as B1, while _vedit_ needs to be at least B2. 

_ate'vmajor, ate'vminor, ate'vedit, ate'vpatch_ (Num)  [out] 

These variables return the individual parts of the ATE client version (if applicable). As with the parts of the A-Shell version, the _ate'vmajor, ate'vminor_ and ate' _vpatch_ can be mapped as B,1, while _ate'vedit_ needs to be at least B2. If there no ATE client, these parameters will all return zero. 

## **Example** 

Sample return values: 

```
VERSTR$ : "A-Shell Version 6.4.1544.2"
```

```
VMAJOR  : 6
```

```
VMINOR  : 4
```

```
VEDIT   : 1544
```

A-Shell Reference 

Page 2755 

```
VPATCH  : 2
```

## **See Also** 

- GETVERXS returns version of the currently running program. . 

- MX_OSVERXS returns the operating system version information 

- Fn'MinAshVer() in SOSLIB:[907,10] provides an easy way to check that A-Shell and/or ATE are at least a specified version. 

- Fn'FileVer$() in SOSLIB:[907,10] retrieves the version of a program file on disk 

A-Shell Reference 

Page 2756 

## **MX_WSET_STATUS** 

_Reviewed and revised Ocril 2024_ 

## **xcall MIAMEX, MX_WSET_STATUS, switches {,opcode, ztver}** 

MX_WSET_STATUS (MIAMEX 13) is used by WSET.LIT in order to control operation of the screen tracking system, which enables the ability to save/restore screen areas. 

## **Parameters** 

_switches_ (Bitmap, 16)  [in/out] 

(combine) is a bit-mapped floating-point parameter whose values are as follows: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|WSET_NARROW|&h0001|132 column mode disabled|
|WSET_MONO|&h0002|Color disabled|
|WSET_NOFLDATR|&h0004|Field attributes on mode devices disabled|
|WSET_FLDEMU|&h0008|Force field emulation (Windows only)|
|WSET_ZTERM|&h00010|ZTERM has been detected|
|WSET_NOZTERM|&h00020|ZTERM was probed for but not detected|



A-Shell Reference 

Page 2757 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|WSET_DISABLE|&h00040|Screen area save/restore disabled|
|WSET_TRKTOPSTS|&h0080|Include top status in save/restore|
|WSET_NOWRAP|&h0100|No wrap|
|WSET_NOSPACEATR|&h0200|Don't output extra space on field on/off attributes|
|WSET_PAGEMODE|&h0400|PAGE mode active; seePAGE.LIT<br>.|
|**Definition file: ashell.def**|||



## _opcode_ (Unsigned Int)  [in] 

0 (mxop_get) to retrieve the current settings, or 1 (mxop_set)to update the current settings and retrieve the original settings back into the _switches_ parameter. If not specified, 1 is assumed. 

## _ztver_ (String, 10+)  [in/out] 

will receive the ZTERM build number if applicable. Note that the format will be something like "ZV2.0.143a." (The ZV prefix is constant for builds 74+.) 

## **Comments** 

MX_WSET_STATUS is used internally by MSBOXX, EZTYP, SWPSBR, PAGE.LIT and other A-Shell routines and commands. 

A-Shell Reference 

Page 2758 

## **MX_VUE** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_VUE, filecmd, gostring** 

MX_VUE (MIAMEX 14) is used by the A-Shell VUE.LIT program to invoke the A-Shell VUE editor (which is coded in C), but could be used by any program requiring full text editing facilities. 

## **Parameters** 

## _filecmd_ (String)  [in] 

Name of the file to edit followed by optional switches. File name may be in DevPPN or host format, and may include embedded %envvar% references. If it contains embedded spaces, must be enclosed in double-quotes. You may append of the valid VUE.LIT switches (/R, /Y, /C, /W, etc.) to the end of the parameter, but you must convert them to "Unix format", i.e. use a dash instead of a slash and make them lower case. For example: 

```
FILENAME = "MYFILE.TXT /W /R"     ! (wrong)
```

```
FILENAME = "MYFILE.TXT –w –r"     ! (correct)
```

## _gostring_ (String)  [out] 

Will return the list of commands associated with the GO directive in the VUE INI file if the session is terminated by executing the GO command.  It is up to the calling program to process the _gostring,_ typically by chaining to it as in in-memory command file, which is what VUE.LIT does. 

## **Comments** 

If you only want to display a file but not allow editing of it, then you should specify the –r (read only) switch, or better yet, use EZTYP (which see). 

A-Shell Reference 

Page 2759 

## **MX_COMPIL** 

_Reviewed and revised May 2024_ 

## **xcall MIAMEX, MX_COMPIL, filename, switches {,defbuf, vcpattern, status, memreq}** 

MX_COMPIL (MIAMEX 15) is used to implement the A-Shell command programs COMPIL.LIT, OCMPIL.LIT, PRE.LIT and OPRE.LIT, by calling into the ASB compiler embedded within the A-Shell executable; see Comments. See the documentation on COMPIL for more information about the switches and variations of COMPIL. 

## **Parameters** 

_filename_ (String)  [in] 

is the DevPPN file specification or host pathname of the program to be compiled. The compiler itself will default the extension to BAS if necessary. 

_defbuf_ (String)  [in] 

contains one or more "define sym = value" statements (corresponding to /C:sym=value command line switches). Each statement must be terminated with chr(10). String values must be quoted. For example, the defbuf equivalent of the command line: 

```
compil prog/x:2/c:MODE=1/c:PLATFORM$=Win
```

would be: 

```
defbuf = "define MODE = 1" + chr(10) + "PLATFORM$ = ""Win"""+ chr(10)
```

_vcpattern_ (String)  [in] 

contains the pattern specified in /VC:pattern; see Version Copy 

_status_ (Integer)  [out] 

returns 0 if the compile succeeds, else failure. 

_memreq_ (Num)  [in] 

A-Shell Reference 

Page 2760 

number of bytes (not kilo or mega) requested. Is used to request an amount of memory for the compiler that is larger than the current memory partition. Request only has an effect if it exceeds the amount of memory currently allocated and available to the job. 

## _switches_ (Bitmap 48 bits)  [in] 

is a bitmap of switch values as listed below: 

|**Symbol**|**Value**|**Corresponding COMPIL.LIT switch or variation**|
|---|---|---|
|COMPIL_A|&h00000001|/A, use 24-bit instead of 16-bit transfer addresses|
|COMPIL_M|&h00000002|/M, treat first instance of unmapped variable as an error|
|COMPIL_O|&h00000004|/O, omit line numbers from compiled program|
|COMPIL_13|&h00000008|Act asOCMPILinstead ofCOMPIL|
|COMPIL_S|&h00000010|/S, silent output – omit ++include lines|
|COMPIL_N|&h00000020|/N, omit phase two compilation statistics|
|COMPIL_X1|&h00000040|/X:1, act asCOMPLP– BASIC_plus_mode|
|COMPIL_D|&h00000080|/D, limited d/BASIC support|
|COMPIL_X2|&h00000100|/X:2, A-Shell extensions|



A-Shell Reference 

Page 2761 

|**Symbol**|**Value**|**Corresponding COMPIL.LIT switch or variation**|
|---|---|---|
||||
|COMPIL_V1|&h00000200|/V:1, BASIC 1.4a compatibility|
|COMPIL_T|&h00000400|/T, Trace – output source while compiling|
|COMPIL_I|&h00000800|/I, assume old ISAM in ambiguous OPEN statements|
|COMPIL_AV|&h00001000|/AV, handle &gt65K variable space|
|COMPIL_B|&h00002000|/B, output errors toprog.lst|
|COMPIL_MX|&h00004000|/MX, like /M but complain for_every_occurrence of each unmapped variable|
|COMPIL_X3|&h00008000|/X:3 SBX compile|
|COMPIL_DBG|&h00010000|/DEBUG|
|COMPIL_RC|&h00020000|/RC|
|COMPIL_G|&h00040000|/G|



A-Shell Reference 

Page 2762 

|**Symbol**|**Value**|**Corresponding COMPIL.LIT switch or variation**|
|---|---|---|
|COMPIL_LSM|&h00040000|/LSM|
|COMPIL_LF|&h00080000|/LF|
|COMPIL_CI|&h00100000|/CI|
|COMPIL_C|&h00200000|/C:sym = value|
|COMPIL_IEEE|&h00400000|/IEEE|
|COMPIL_VC|&h00800000|/VC:pattern|
|COMPIL_LI|&h01000000|/LI|
|COMPIL_P|&h02000000|/P|
|COMPIL_CTAGS|&h08000000|CTAGS|
|COMPIL_XTAGS|&h10000000|/XTAGS|
|COMPIL_PX|&h20000000|/PX|



A-Shell Reference 

Page 2763 

|**Symbol**|**Value**|**Corresponding COMPIL.LIT switch or variation**|
|---|---|---|
|COMPIL_IGOO|&h40000000|/IGOO|
|COMPIL_L|&h80000000|(-l applies only to compil.exe)|
|COMPIL_NOTRC|&h100000000|/NOTRC|
|COMPIL_F1|&h200000000|/F1|
|**Definition File:**ashinc:compil.def|||



## **Comments** 

The compiler is also available as a standalone executable (see Compiler), mostly to facilitate integration with external program editors such as APN.LIT. 

## **History** 

## - 2024 February, A Shell 7.0.1756: Add _memreq_ parameter. 

- 2014 January, A Shell 6.1.1371:  Add support for /P. 

A-Shell Reference 

Page 2764 

## **MX_PREBAS** 

_Reviewed and revised May 2024_ 

## **xcall MIAMEX, MX_PREBAS, filename, status** 

MX_PREBAS (MIAMEX 16) invokes the PREBAS pre-compiler, scanning the input file for $COPY directives and merging the result into an output file with a "cpy" extension. 

## **Parameters** 

_filename_ (String)  [in] 

the file to be pre-compiled in DevPPN or host format. Default extension is "bas". 

_status_ (Integer)  [out] 

returns 0 for success, else 1 for error 

A-Shell Reference 

Page 2765 

## **MX_SYNC_CWD** 

_Reviwed and revised May 2024_ 

## **xcall MIAMEX, MX_SYNC_CWD {, status}** 

MX_SYNC_CWD (MIAMEX 17) synchronizes the host OS's current working directory location with A-Shell's current working directory location. 

## **Parameters** 

status  (Integer)  [out] 

returns 0 for success, else error 

Although A-Shell DevPPN directories generally correspond one-to-one with native directories on the host operating system, it is not automatically the case that the operating system’s idea of your current working directory will always match up to your A- Shell login directory. MX_SYNC_CWD (MIAMEX 17) may be used at any point to resolve this problem by synchronizing the current working directory with that of the current PPN. This is generally only of interest when interfacing to some host operating facility or executing a native operating system command. 

A call to this function is automatically made by LOG.LIT and by HOST.LIT in order to minimize problems. If a different utility is written to change PPN or execute a host command, it might be advantageous to synchronize the working directory. 

See MX_GETENV for a way to query the current host operating system working directory. 

A-Shell Reference 

Page 2766 

## **MX_NXTCMD** 

_Reviewed and revised May 2024_ 

## **xcall MIAMEX, MX_NXTCMD, cmdline, status {,flag}** 

MX_NXTCMD (MIAMEX 18) returns the next line of the current command (.CMD or .DO) file in memory, with an option to preview it without actually consuming it. 

## **Parameters** 

_cmdline_ ho  (String)  [out] 

should be a string variable long enough to return any expected command line. 

_status_ (Integer)  [out] 

returns zero if there is nothing to input—i.e. no command file is currently running or its end has already been reached—else returns one. 

_flag_ (Integer)  [in] 

if specified and set to a non-zero value, the operation becomes "preview" or "non-destructive read", i.e. the next line is returned in _cmdline_ but the internal command line position is unchanged. 

## **Comments** 

This function is used in the implementation of GOTO.LIT in order to skip over the command line contents up to the target label. The technique can also be useful in a case where you want to effectively abort a command file execution in response to some data or environmental condition, perhaps chaining to another command file instead. 

A-Shell Reference 

Page 2767 

## **MX_GETDEV** 

_Reviewed May 2024_ 

## **xcall MIAMEX, MX_GETDEV, dev, proj, prog, drbase, status {,devflags}** 

MX_GETDEV (MIAMEX 19) returns information about the next device in the device table. 

## **Parameters** 

## _dev_ (String), 6)  [in/out] 

On input, if null (""), resets the scan to the start of the device table—i.e. returns the first device in the table. On output, returns the next device in the table, e.g. "DSK1", with no trailing colon. See _status_ . 

## _proj_ , _prog_ (B1 or B2)  [out] 

For normal device definitions, whose PPNs are implicitly defined by the existence of ###### subdirectories, these parameters will return 0. Only for devices that are explicitly defined with only a single PPN will these parameters be returned with non-zero values. In that case, if _proj_ and _proj_ are mapped as B2 (preferred), the two parts of the PPN will be returned as decimal values ranging from 0-999. Although deprecated, for backwards compatibility, if _proj_ and _prog_ are mapped as B1 variables, the values will be encoded as if octal (with a range of 0-377). 

## _drbase_ (String), 100+)  [out] 

The base path for the device or device/ppn combination is returned here. It will be terminated with a trailing directory separator character, e.g. c:\vm\miame\dsk0\. 

## _status_ (Num)  [out] 

Returns 0 on success, else 1 if it hits the end of the device table, in which case the rest of the return parameters should be ignored. Note that the next call after hitting the end of the table will return the first device in the table. 

## _devflags_ (Num)  [out] 

If specified, returns attribute flags related to the device (zero or more of the following): 

A-Shell Reference 

Page 2768 

|**Value**|**Meaning**|
|---|---|
|&h01|Read-only device|
|&h02|Memory device|



## **Comments** 

See the DEVICE system parameter for information about how the devices in the device table are defined. When MX_GETDEV hits the end of the device table, it returns a _status_ code and then starts over at the beginning on the next call. You can also force it to restart at the beginning by setting the _dev_ parameter to "". 

MX_GETDEV is very similar to MX_GETERSATZ, but returns information about "real" devices rather than ersatz devices. 

## **See Also** 

- PPN Numbering 

A-Shell Reference 

Page 2769 

## **MX_FINDFIRST** 

_Reviewed May 2024_ 

## **xcall MIAMEX, MX_FINDFIRST, directory, status, filename, size, attrib {,cdate, ctime, udate, utime {, adate, atime}}** 

MX_FINDFIRST (MIAMEX 20), combined with its sister function, MX_FINDNEXT, is used to scan directories for subdirectories or files. 

## **Parameters** 

## _directory_ (String)  [in] 

This must be set to the directory which is to be scanned for files. This directory specification must be in host operating system format, and include the terminating directory separator. See MX_FSPEC (Perform FSPEC on AMOS string) for information on converting an AMOS-style directory to the equivalent host directory. 

## _status_ (Num)  [out] 

On return, _status_ is set to zero to indicate success. A non-zero status indicates an error, most likely that no files or directories match the specification you gave in _directory_ . 

## _filename_ (String)  [out*] 

The first entry in the specified directory will be returned in _filename_ . Typically this is a regular file (in _name.ext_ format) but may be a special file, such as another directory or the "." and ".." entries which typically appear at the start of each directory, which you can determine by the _attrib_ flags (below). The returned name will be truncated to fit, but you should specify a reasonably large variable, since Unix and Windows filenames can be quite long. 

_size_ (F6)  [out] 

returns the size of the found file, in bytes. 

_attrib_ (Num)  [out] 

A-Shell Reference 

Page 2770 

is a bit-mapped numeric field into which are placed the various attributes of the file or sub-directory represented by _filename_ , according to the following table: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|FATR_NORMAL|1|Normal file|
|FATR_SUBDIR|2|Subdirectory|
|FATR_READONLY|4|You (current user) have read-only permission for this file or directory|
|**Definition file: ashell.def**|||



## _cdate_ , _udate_ , _adate_ (String, 10+ bytes)  [out] 

are the create/status change date, update/modify date, and access date of the file or directory, using the format dd-mon-yr (e.g. "01-Jan-08"). Note that under Unix systems, the CDATE will be changed when the privileges or ownership of the file is changed. 

_ctime_ , _utime_ , _atime_ (String, 5+ bytes)  [out] 

are the create/status change time, update/modify time, and last access time for the file or directory, using the format (hh:mm). 

## **Comments** 

* Under Windows, you can actually set _directory_ to a literal or wildcard filename to skip directly to the first matching file. However, this is not recommended, since under Unix you must specify a directory (not a file path) with a trailing directory separator. 

## **History** 

A-Shell Reference 

Page 2771 

- 2026 April, A Shell 7.0.1785:  Logging refinement: MX_FILESTATS and MX_FINDFIRST no longer output messages to ashlog for file-not-found errors. Any other errors will continue to be logged. Setting the FOPENS TRACE flag will restore the logging of filenot-found errors. 

- 2021 October, A Shell 6.5.1708: Extend the maximum number of nesting levels from 3 to 20. This was done years ago for the Windows version but somehow overlooked for the Unix version. 

- 2020 October, A Shell 6.5.1690: Expand the limit on the maximum length of a filename from 123 to 255 characters. 

A-Shell Reference 

Page 2772 

## **MX_FINDNEXT** 

_Reviewed and revised May 2024_ 

## **xcall MIAMEX, MX_FINDNEXT, status, filename, size, attrib {,cdate, ctime, udate, utime {, adate, atime}}** 

MX_FINDNEXT (MIAMEX 21) returns the next file or subdirectory in the directory specified in MX_FINDFIRST, which must be called first to initialize this operation. 

## **Parameters** 

The parameters are the same as for MX_FINDFIRST except that the first parameter, _directory,_ is omitted here since it is maintained internally after being established by the initial MX_FINDFIRST call. 

## **Comments** 

MX_FINDNEXT does not automatically descend directory levels; it merely scans the items in the directory initialized by the prior MX_FINDFIRST. If you want to do a recursive scan, descending levels, you need to execute another MX_FINDFIRST for each item directory item, as indicated by the _attrib_ parameter. 

The return _status_ will be non-zero when you hit the end of the directory—i.e., there are no more files. MX_FINDEND (which see for an example) must be executed at the end of each directory scan to clear the resources allocated by the MX_FINDFIRST and, in the case of a nested scan, to pop the status back to the parent directory where you can continue the that scan. 

See MX_FINDEND for additional information and a program example, and the History note in MX_FINDFIRST. 

## **History** 

- 2021 October, A Shell 6.5.1708: MX_FINDFIRST refinement: Overflowing the directory processing stack now generates ASB error 33, stack overflow. Previously it only returned a non-zero status, making it too easy for the calling program to continue running without recognizing the error, leading to incorrect or inconsistent directory scan results. Furthermore, after such an error, the stack was not getting reset, leading to more errors on subsequent multi-level directory scans. 

A-Shell Reference 

Page 2773 

- 2021 October, A Shell 6.5.1708: Extend the maximum number of nesting levels from 3 to 20. This was done years ago for the Windows version but somehow overlooked for the Unix version. 

- 2020 October, A Shell 6.5.1690: Expand the limit on the maximum length of a filename from 123 to 255 characters. 

A-Shell Reference 

Page 2774 

## **MX_DIRSEP** 

_Reviewed and revised May 2024_ 

## **xcall MIAMEX, MX_DIRSEP, character** 

MX_DIRSEP (MIAMEX 22) returns a single byte parameter (usually a string) into which the directory separator character is placed. This is the character used in specifying host pathnames, and is usually a forward slash ( / ) for Unix systems, and a backslash ( \ ) for Windows systems. Knowing this is useful when parsing native filespecs and also as a quick way of determining which of the two classes of operating systems you are running on. 

A-Shell Reference 

Page 2775 

## **MX_FINDEND** 

_Reviewed and revised May 2024_ 

## **xcall MIAMEX, MX_FINDEND** 

MX_FINDEND (MIAMEX 23) must be called at the end of each directory scan to release the resources established in the prior call to MX_FINDFIRST. In the case of a nested (or recursive) scan, MX_FINDEND also restores the context so that the next MX_FINDNEXT call will get the next entry in the parent directory. Failure to call MX_FINDEND for each MX_FINDFIRST will eventually lead to a stack overflow. 

Following is an example of a single directory scan. See fndirscan.bsi in SOSLIB:[907,010] for a set of functions for performing a nested or recursive directory scan. 

## **Example** 

```
xcall MIAMEX, MX_FINDFIRST, directory, status, filename, size, attrib
```

```
do while status = 0
    ....
```

```
    .. Process directory item here
    ....
    XCALL MIAMEX, MX_FINDNEXT, status, filename, size, attrib
```

```
loop
```

```
! terminate directory search and free resources
```

```
xcall MIAMEX,MX_FINDEND
```

A-Shell Reference 

Page 2776 

## **MX_GETPROMPT** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_GETPROMPT, prompt** 

## **xcall MIAMEX, MX_SETPROMPT, prompt** 

MX_GETPROMPT (MIAMEX 24) gets, and MX_SETPROMPT (MIAMEX 6) sets, the prompt used at the command level. 

## **Parameters** 

_prompt_ (String)  [in for SET, out for GET] 

## **Comments** 

The maximum allowable prompt length is 20 characters. 

The prompt can also be set via the SET command. 

The system prompt or command level prompt is also known as the "dot prompt" because the default prompt is a single dot. 

A-Shell Reference 

Page 2777 

## **MX_HASHFILE** 

_Rewritten June 2020_ 

## **xcall MIAMEX, MX_HASHFILE, path, hash1, hash2, hash3, hash4** 

MX_HASHFILE (MIAMEX 25) returns a hash code for the file specified in the path argument. The hash code consists of four integer values. 

## **Parameters** 

_path_ (String)  [in] 

specification of file being hashed. May be in native or DevPPN format. 

_hash1...4_ (Num)  [out] 

receive the four parts of the hash. Each part if an integer from zero to 255. 

## **Comments** 

The hash algorithm is the same as that used by the AMOS DIR/H command. 

For display purposes, the AMOS and A-Shell hash-total formats treat the numeric values as octal. 

## **Example** 

The following example illustrates the use of this function to display a hash total in the format used by DIR/H: 

```
MAP1 HSHSTR,s,4 ! Octal string byte
```

```
MAP1 STRING'HASH,s,15 ! Display format hash-total (###-###-###-###)
```

```
xcall MIAMEX,MX_HASHFILE,THISIPATH,HASH1,HASH2,HASH3,HASH4
```

```
xcall MIAMEX,MX_OCVT,HASH1,3,OT_MEM+OT_OCT,HSHSTR
```

A-Shell Reference 

Page 2778 

```
STRING'HASH = HSHSTR+"-"
```

```
xcall MIAMEX,MX_OCVT,HASH2,3,OT_MEM+OT_OCT,HSHSTR
```

```
STRING'HASH = STRING'HASH+HSHSTR+"-"
```

```
xcall MIAMEX,MX_OCVT,HASH3,3,OT_MEM+OT_OCT,HSHSTR
```

```
STRING'HASH = STRING_HASH+HSHSTR+"-"
```

```
xcall MIAMEX,MX_OCVT,HASH4,3,OT_MEM+OT_OCT,HSHSTR
```

```
STRING'HASH = STRING'HASH+HSHSTR
```

```
print STRING'HASH
```

## **See Also** 

- DIGEST. 

- HASHXS 

A-Shell Reference 

Page 2779 

## **MX_PRFSPEC** 

## **xcall MIAMEX, MX_PRFSPEC, string** 

MX_PRFSPEC (MIAMEX 26) retrieves the last processed file specification and formats it in standard DevPPN format (i.e. dev#:file.ext[p,pn]) where dev# and [p,pn] are omitted if the file is on the current device or in the current directory. As a practical matter, the last processed filespec will be the one last processed via MX_FSPEC. 

A-Shell Reference 

Page 2780 

## **MX_COPYFILE** 

_Reviewed and revised April 2024_ 

## **(1) xcall MIAMEX, MX_COPYFILE, src$, dst$ {,flags, status}}** 

## **(2) xcall MIAMEX, MX_COPYFILE, chin, chout** 

The MX_COPYFILE (MIAMEX 27) first syntax moves or copies files based on their names. The second syntax copies the contents of the source to the destination using file channels and thus requires that the input and output files be opened and closed by the calling application. The routine distinguishes between the two calling formats based on the data type of the second argument. If it is a string (S or X) then it is treated as the _src$_ parameter and the first syntax is used. If it is numeric (B or F) then it is treated as _chin_ and the second syntax is used. 

In most cases, the first syntax is preferable, as it is easier to use, more flexible, more efficient, and with fewer side effects. See Comments _,_ below, for details on the differences between the two methods. 

## **Parameters** 

_src$, dst$_ (String)  [in] 

source and destination file specifications, either AMOS-style or native 

## _chin, chout_ (Num)  [in] 

input and output file channels. _chin_ must be opened for INPUT or RANDOM. _chout_ must be opened for OUTPUT (or APPEND), or RANDOM. It is up to the application to properly close these channels on return from the subroutine. 

_flags_ (Bitmap 8)   [in]  (default 0) 

zero or more bit flags from the following table: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|CPYF_MOVE|&h0001|Move file instead of copy file|



A-Shell Reference 

Page 2781 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||||
|CPYF_REPL|&h0002|Allow replacement of existing destination|
|CPYF_SETRO|&h0010|Force read-only bit to be set on output|
|CPYF_CLRRO|&h0020|Clear read-only bit on output|
|CPYF_ENCRYPT|&h0040|force output file to be encrypted; requires EFS|
|CPYF_DECRYPT|&h0080|force output file to be decrypted; requires EFS|
|**Definition file: ashell.def**|||



If neither of the read-only flags are set, then the status of the read-only flag is preserved, unless copying from a device with the ,RO flag, in which case the read-only flag will be cleared. The read-only flags only have meaning in WINDOWS. 

## _status_ (Signed Int)  [out] 

|**Value**|**Meaning**|
|---|---|
|0|Success|



A-Shell Reference 

Page 2782 

|**Value**|**Meaning**|
|---|---|
|-1|Destinations exists and CPYF_REPL flag not specified|
|-2|Source does not exist|
|-3|Invalid parameter types|
|<other>|System error code. For Unix, this will be the return code from the<br>mv or cp utility. For Windows, it will be a Windows system error<br>code (translatable by MIAMEX,86). See_Comments_.|



Note that under Unix, the operation invokes the mv or cp utilities, which must be available in the PATH. 

## **Comments** 

Advantages of the new (filespec, syntax #1 above) method over the old (file channel, syntax #2 above) method include: 

- The Move option (CPYF_MOVE) is much more efficient than normal Copy, provided source and destination are on the same 

- volume or file system. If not, then the move is simulated by a Copy followed by a Delete of the source. 

- Move preserves the file creation and file modification times. 

- Copy preserves the file modification time, but updates the file creation time because it is creating a new file. The old syntax, 

- by contrast, causes both the creation time and modification time to be updated. 

- Simplifies the logic for protecting against accidental overwrite, as well as for detecting common errors in the operation. With 

- the old method, in addition to needing the separate file opens and closes, you would have needed to also use lookup operations to check for the most common considerations of source-does not-exist or destination-already-exists. 

A-Shell Reference 

Page 2783 

On the other hand, the old (file channel) syntax offers the following capabilities that are not possible with the (new) filespec syntax: 

- You can append the source file to the destination by opening the destination for APPEND.LIT. 

- If the destination exists, you can overlay the source on it, starting at an arbitrary position, by first opening the destination 

- channel for APPEND, and then using the MX_FILEPOS to position the destination stream pointer prior to the copy operation. 

**Warning** : when intermixing two kinds of output to an open file channel (e.g. MX_COPYFILE and PRINT #CH statements), you should first disable file buffering for that channel (MX_NOBUF), lest the different buffering schemes used by the two methods result in jumbled output. 

A-Shell Reference 

Page 2784 

## **MX_PRINTERR** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_PRINTERR, errnum** 

MX_PRINTERR (MIAMEX 28) outputs the standard error message associated with the last processed DDB error. 

## **Parameters** 

_errnum_ (Unsigned Int)  [out] 

Receives the so-called DDB error code. 

## **Comments** 

Note that the DDB error codes differ from the ASB error codes returned by ERR and are typically only relevant within System Commands, which, although now written in ASB like other application programs, were originally developed in assembly language apart from the ASB error framework. 

See ERRMSG for a more powerful and flexible method of handling error messages. 

A-Shell Reference 

Page 2785 

## **MX_RENAMERR** 

## **xcall MIAMEX, MX_RENAMERR** 

MX_RENAMERR (MIAMEX 29) displays a specialized error message of the type associated with a failure to rename a file. It is probably only used with the RENAME.LIT program. 

A-Shell Reference 

Page 2786 

## **MX_GETQUEUE** 

_Rewritten April 2024_ 

## **xcall MIAMEX, MX_GETQUEUE, blkno, qblock** 

MX_GETQUEUE (MIAMEX 30) reads queue blocks from the system queue file (qflock.sys). 

## **Parameters** 

_blkno_ (Unsigned Int)  [in] 

Block (record) number to read. 

## _qblock_ (Struture)  [out] 

Structure to receive the block. The two structure definitionsm, ST_QHEADER for the control record and ST_QBLOCK for the other blocks, are defined in the file ashinc:qflock.sdf as follows: 

```
defstruct ST_QHEADER              ! Queue header block
   map2 QFREE,b,2            ! Free queue pointer
   map2 QUSED,b,2            ! Used queue pointer
```

```
   map2 Q'HIGHWATER,b,2      ! Highest used record #
```

```
   map2 LOG'COUNT'NOMORE,b,2 ! Logical users (instances) count [13]
```

```
   map2 Q'VERSION,s,4        ! version
```

```
   map2 Q'TOTOPS,i,4         ! total q adds & deletes
```

```
   map2 Q'TOTREADS,i,4       ! total q adds & deletes
   map2 Q'TOTWRITES,i,4      ! total q adds & deletes
```

```
   map2 DUMMY1,x,16          ! Dummy filler was 24 [13] was 28 [34] was 24
```

```
endstruct
```

A-Shell Reference 

Page 2787 

```
defstruct ST_QBLOCK         ! qflock record
```

```
   map2 QNEXT,b,2          ! Pointer to next queue block
```

```
   map2 QTYPE,b,2          ! Queue block id type
```

```
   map2 QOWNER,b,2         ! Owner of queue block
   map2 QJUNK,b,2          ! (get back to 4x alignment)
   map2 QDATA              ! 32 bytes of data  (was 34)
```

```
   map2 QD'FLOCK,@QDATA    ! Format of FLOCK record
```

```
      map3 ACTION,b,2     ! Action
      map3 MODE,b,2       ! Mode
      map3 RECORD,b,4     !  Record number
```

```
      map3 CHANNEL,b,4    ! Channel number [12] was 2
```

```
   map2 QD'IFLOCK,@QDATA   ! Format of inactive FLOCK record
```

```
   map2 QD'XLOCK,@QDATA    ! Format of XLOCK record
```

```
      map3 LOCK1,i,4      ! Primary lock code (INTEGER!)
      map3 LOCK2,i,4      ! Secondard lock code (INTEGER!)
```

```
      map3 LOCK3,b,2      ! New lock class (0=xlock,1=lock)
```

```
endstruct
```

The ST_QBLOCK structure supports multiple layouts via overlays; the QTYPE field indicates which of the overlays to use, according to the following table: 

A-Shell Reference 

Page 2788 

|**Value **|**Queue block type**|
|---|---|
|0|Unused block|
|3|FLOCK – normal|
|4|XLOCK|
|6|FLOCK – inactive|
|7|ZLOCK (proprietary format)|
|8|RLOCK (proprietary format)|
|9|FLOCK – pending|



## **Comments** 

MX_GETQUEUE is used primarily to track various kinds of inter-process locks or semaphores, in particular by the subroutines XLOCK and FLOCK. 

The number of queue blocks is set by the QUEUE statement in miame.ini. 

Logically, the queue blocks are organized into two linked lists, one for the blocks that are in use (starting with the block number specified in the ST_QHEADER.QUSED field), and the other (ST_QHEADER.QFREE) for the available blocks. In either case, you can follow the linked list via the ST_QBLOCK.QNEXT field. 

A-Shell Reference 

Page 2789 

Note that in a multi-user environment, the two linked lists may be actively updated. In order to traverse one of the lists safely, you should first lock the control via MX_QLOCK and unlock it when done using MX_QUNLOK. 

## **See Also** 

- QUTL.LIT (various interactive utility functions) 

- XLOCK[XS] (general purpose locking API functions) 

- FLOCK[XS] (file-specific locking API functions) 

A-Shell Reference 

Page 2790 

## **MX_GETENV** 

_Updated October 2014; see History_ 

## **xcall MIAMEX, MX_GETENV, envvar, value {,flag}** 

MX_GETENV (MIAMEX 31) retrieves the definition of an environment variable; use MX_SETENV to define environment variables. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _envvar_ (String)  [in] 

The name of the environment variable (e.g. "MIAME"). Use of the % delimiters surrounding the name is optional, i.e. "MIAME" and "%MIAME%" are equivalent. Environment variables are not case sensitive under Windows, but they are under Unix, so it it best to stick with the convention of using all upper case. There is no particular limit to the length of an environment variable name. 

## _value_ (String)  [out] 

Returns the definition of the specified environment variable. If not defined, returns a null string. There is no particular limit to the length of an environment variable definition. It will be truncated if needed to fit into the variable provided. 

## _flag_ [in] 

If specified and set to 1, then the returned value will be de-mangled—i.e., converted from the DOS 8.3 compressed format to the full long format, if possible. See Get ATE Environment Variable for samples. 

## **Comments** 

MX_GETENV only works relative to the system that the program is running on, i.e., it will not retrieve an environment variable definition from the remote telnet client. To accomplish that for ATE, see AG_GETENV. 

Environment variables may be defined in various ways depending on the host operating system. Under Windows, you can use the Control Panel "System" applet. Under Unix, they are set by shell commands, e.g. "MIAME=/vm/miame". The **set** command will typically display the current definitions. 

A-Shell Reference 

Page 2791 

In addition to system defined environment variables, A-Shell understands a few special variables which do not have to be set externally. One is "%CurrentDirectory%", which will return the current working directory in the host operating system. Two others, which are only available under Windows, are "%WindowsDirectory%" and "%SystemDirectory%", which return the directory spec of the "Windows" and "Windows System" directories. Another two are set by A-Shell when it launches: %MIAME% is the directory where miame.ini is located, and %MIAMEFILE% is the full path spec of miame.ini. 

## **History** 

- 2014 October, A Shell version 6.1.1391: Passing an empty environment variable name parameter now causes MX_GETENV to return the entire list of environment variable definitions, delimited by a chr(10) character between each NAME=VALUE string. Also, you can now specify a dynamic string variable (S,0) for the return parameter, which will expanded as needed. 

## **See Also** 

- AG_GETENV 

A-Shell Reference 

Page 2792 

## **MX_SETEXT** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_SETEXT, ext** 

MX_SETEXT (MIAMEX 32) may be used to set the default file extension for a subsequent file open operation. 

## **Parameters** 

_ext_ (String)  [in] 

up to four bytes long, specifying the desired default extension such as "DAT", "xlsx", etc. 

A-Shell Reference 

Page 2793 

## **MX_GETCISAM** 

## **xcall MIAMEX, MX_GETCISAM, fspec, version, serial** 

MX_GETCISAM (MIAMEX 34) returns the version number and serial number of the ISAM or ODBC library associated with the specified _fspec_ . _version_ and _serial_ should be mapped as strings of 33+ bytes. It is mainly used within ISMUTL. 

ISAM-A support requires an add-on license to A-Shell. If not licensed, the _serial_ string will be returned as "<not licensed>". 

A-Shell Reference 

Page 2794 

## **MX_SETCRM** 

_New October 2025_ 

## **xcall MIAMEX, MX_SETCRM, pageop** 

MX_SETCRM (MIAMEX 35) sets options related to console output paging, used mainly by PAGE.LIT. 

## **Parameters** 

_pageop_ (Num)  [in] 

One of the following: 

|**Value **|**Meaning**|
|---|---|
|0|Clear output paging mode (resume normal scrolling mode)|
|>0|Set paging mode (number of lines per page of output)|
|<0|NOP|



A-Shell Reference 

Page 2795 

## **MX_GETHASH** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_GETHASH, status** 

## **xcall MIAMEX, MX_SETHASH, status** 

MX_GETHASH (MIAMEX 36) returns _status_ indicating whether you are in AMOS hash compatibility mode. In this mode, the hash algorithm (used by DIR/H) treats LF line terminators the same as CRLF pairs, so that normal text files will have the same hash code under Unix, which typically uses LF line terminators, as they do under AMOS, which typically uses CRLF terminators. 

MX_SETHASH (MIAMEX 37) allows you to set or reset the AMOS hash compatibility mode. 

## **Parameters** 

_status_ (Integer)   [in for SET, out for GET] 

For GETHASH, returns zero if not in AMOS hash compatibility mode, else non-zero. 

For SETHASH, set to zero to reset (clear) AMOS hash compatibility mode, else non-zero to set it. 

## **Comments** 

Note that the SET.LIT command also allows you to query and set/reset this option. 

A-Shell Reference 

Page 2796 

## **MX_MKPATH** 

_Revised and revised April 2024_ 

## **xcall MIAMEX, MX_MKPATH, dirspec, status** 

## **xcall MIAMEX, MX_RMPATH, dirspec, status** 

MX_MKPATH (MIAMEX 38) creates a new native operating system directory. MX_RMPATH (MIAMEX 39) deletes the specified native directory. 

## **Parameters** 

_dirspec_ (String)  [in] 

the directory name. This should be in native file format, but may include embedded environment variables (e.g. %miame% \newdir). 

_status_ (Integer)  out 

will return 0 for success, else an error number. You may use MX_ERRNOMSG to translate the error number to a text message. 

## **Comments** 

MX_MKDIR will be invoked automatically if this function is requested under Windows. Therefore, it may be best to always use MX_MKPATH in your application and let A-Shell decide when to convert it to MX_MKDIR. The exception would be if your application which is running on a server (with ATE clients) wants to explicitly create a directory on the ATE client. In this case, you must use MX_MKDIR and set the remoteflag parameter to "R." 

Note that this function supports embedded environment variables, e.g.: 

```
xcall MIAMEX,MX_MKPATH,"%MIAME%\901902",STATUS
```

In general this function will not succeed if the parent directory doesn't already exist. 

## **See Also** 

A-Shell Reference 

Page 2797 

- AG_MKDIR 

A-Shell Reference 

Page 2798 

## **MX_ZAPQUEUE** 

## **xcall MIAMEX, MX_ZAPQUEUE, jobno** 

MX_ZAPQUEUE (MIAMEX 41) removes the jobtbl record and any associated queue blocks for the specified job number. As one might expect, this will not be appreciated if the user is actively running, and should only be used in extreme circumstances or when you are sure the user is no longer active. _jobno_ is the job number of the user to zap. 

MX_ZAPQUEUE is used by KILL, QUTL and `SYSTAT/K/Z` commands. The last of these, `SYSTAT/K/Z` , is the preferred and best way to remove resources left over from a job that has aborted without cleaning itself up. 

A-Shell Reference 

Page 2799 

## **MX_GETLOKSER** 

## **xcall MIAMEX, MX_GETLOKSER, lokflag** 

## **xcall MIAMEX, MX_SETLOKSER, lokflag** 

MX_GETLOKSER (MIAMEX 50) returns a flag indicating if LOKSER is active or not. MX_SETLOKSER (MIAMEX 51) allows you to turn LOKSER on or off. 

## **Parameters** 

_lokflag_ (F6)  [out for GET, in for SET] 

SET: set to 0 to turn LOKSER off, or non-zero to turn it on. GET: will be returned as 0 if LOKSER is not active, while a non-zero value indicates that it is active. 

## **Comments** 

You may also use SET.LIT to query or change the LOKSER status. 

A-Shell Reference 

Page 2800 

## **MX_GETCMDINP** 

## **xcall MIAMEX, MX_GETCMDINP, cmdinfld {,cmdinput}** 

## **xcall MIAMEX, MX_SETCMDINP, cmdinfld {,cmdinput}** 

MX_GETCMDINP (MIAMEX 52) allows you to determine if command file input is enabled or disabled for the two main modes of keyboard input. 

MX_SETCMDINP (MIAMEX 53) allows you to enable or disable command file input for the two main modes of keyboard input. 

## **Parameters** 

_cmdinfld_ (Num)  [out for GET, in for SET]] 

For GET: returns 1 if command file input for INFLD is enabled, else 0. For SET: set to 1 to enable commmand file input for INFLD 

_cmdinput_ (Num)  [out for GET, in for SET]] 

For GET: returns 1 if command file input for INPUT and INPUT LINE enabled, else 0. For SET: set to 1 (default) to enable command input for INPUT and INPUT LINE enabled, else 0 to disable. 

## **Comments** 

The first mode, sometimes referred to as "low-level", "raw", "unbuffered" or "character-oriented", is used by some XCALL subroutines (primarily INFLD and SBXINP) which process characters individually as they are typed. By default, characters in the current command file are ignored in character-oriented mode but can be enabled via this function. Note that INFLD and SBXINP can also enable command file via their own parameter options, but they cannot disable it if previously enabled globally. 

The second mode, sometimes referred to as "buffered" or "line-oriented", is used by the INPUT and INPUT LINE statements (as well as the command prompt). By default, command file input is enabled for line-oriented mode but can be disabled by this function. 

The main reasons why you might want to disable command file input for line-oriented input mode are: 

A-Shell Reference 

Page 2801 

• To prevent the accidental use of command file input for certain critical kinds of inputs (passwords, etc.) which you want to force the user to handle interactively even amid an otherwise scripted process. 

• To allow command file wrappers to be created for programs which may perform interactive line-oriented input but then return to the command file at the completion of the program. 

Note that setting the _cmdinput_ flag to 0 only disables command file input for INPUT and INPUT LINE within programs (i.e. when not at the dot prompt). Command file input is always enabled when at the dot prompt. Furthermore it is automatically reenabled (set to 1) when you end up at the command prompt and there is no more command file input available. 

## **Example** 

A program—perhaps a utility menu—may create and then chain to the following command file: 

```
RUN PROGRAM1
```

```
RUN PROGRAM2
```

If PROGRAM1 performs an INPUT operation, it will normally grab the next line ("RUN PROGRAM2") from the command file, which clearly isn’t what you want here. To prevent that, MX_SETCMDINP can be used in advance of chaining to this command file to disable command file input. When PROGRAM1 ended, the command prompt executive would see and execute "RUN PROGRAM2," since command file input is always enabled when not currently running a program, and the normal command file input would be re-enabled once the process reached the end of its command file. 

## **History** 

- 2023 August, A Shell 6.5.1738:  Added _cmdinput_ parameter. 

A-Shell Reference 

Page 2802 

## **MX_GETSIG** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_GETSIG, sigmask** 

## **xcall MIAMEX, MX_CLRSIG, sigmask** 

(Unix only) 

MX_GETSIG (MIAMEX 54) returns a bitmap indicating which signals have been received since the MX_CLRSIG call was last used to reset the signal received bitmap. 

MX_CLRSIG (MIAMEX 55) allows you to clear specific bits in the signal received mask. This would be useful in a situation where you wanted to check whether a certain signal was received during a certain time frame. First you would clear the bit for that signal, then later you would check, using MX_GETSIG, if the bit was set. 

## **Parameters** 

_sigmask_ (Signed Num)  [in] 

CLRSIG: Should be set to the sum of the signals from the table below that you want cleared. Use –1 to clear all of the signal flags. 0 does nothing. 

GETSIG: Returns with zero or one of the following bits set to indicate which signal (if any) was received: 

|**Symbol**|**Value**|**Name***|**Meaning**|
|---|---|---|---|
|SR_INT|&h0001|SIGINT|Ctrl+C|
|SR_CHLD|&h0002|SIGCHLD|Child process terminated|
|SR_USR1|&h0004|SIGUSR1|Receipt of ITC or IJC message|



A-Shell Reference 

Page 2803 

|**Symbol**|**Value**|**Name***|**Meaning**|
|---|---|---|---|
|||||
|SR_USR2|&h0008|SIGUSR2|PolyShell swap operation|
|SR_HUP|&h0010|SIGHUP|Hangup (telnet or terminal session disconnected)|
|SR_KILL|&h0020|SIGKILL|Kill (cannot be trapped so will never be seen)|
|SR_TSTP|&h0040|SIGTSTP|Background task waiting for terminal context to perform input operation|
|SR_ALARM|&h0080|SIGALRM|Alarm signal (used by sleep timers andWAKNOXS)|
|SR_TERM|&h0100|SIGTERM|Default kill signal|
|SR_PIPE|&h0200|SIGPIPE|Broken pipe or socket connect (other end has terminated)|
|SR_SYSCALL|&h4000|Not<br>applicable|Pseudo signal flag used by A-Shell to indicate that it is waiting on a<br>system() call such asHOSTEXXS|
|**Definition file: ashell.def**||||



- Hex Decimal Values 

A-Shell Reference 

Page 2804 

* The terms in the "Name" column are the standard POSIX signal names for the subset of signals recognized by A-Shell. Note the standard signal names are associated with integer values that may vary between Unix flavors; the bit values used by A-Shell are independent of the underlying operating system signal values, and uniform across all platforms. 

## **Comments** 

SUBMIT/W uses these functions. First it clears the SIGCHLD signal flag (2), then submits the task, then sleeps, checking every second to see if the SIGCHLD signal flag has been set, which it will be when the submitted task terminates. 

A-Shell Reference 

Page 2805 

## **MX_SETENV** 

## **xcall MIAMEX, MX_SETENV, envdef {,status}** 

MX_SETENV (MIAMEX 56) is used to define environment variables for the current process, including the special case of TERM, for which see _Comments_ , below. To set environment variables for the remote ATE client, see Set Environment Variable. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _envdef_ (String)  [in] 

Contains a definition string of the form "name=value" specifying the name of the environment variable to be set (e.g. defined or modified) and its value. For example, "TERM=AM62CG", or "MYNAME=Jack". To delete an environment variable, set its value to nothing, e.g. "MYNAME=". 

_status_ (Signed Num) [out] 

If specified, will return one of the following: 

|**Code**|**Meaningt**|
|---|---|
|0|Success|
|-1|General error|
|-2|Overflow of memory set aside for environment variables.|



**Comments** 

A-Shell Reference 

Page 2806 

In general, setting an environment variable doesn't have any immediate side effect. Instead the value is simply stored, for the purposes of retrieving it later, either using MX_GETENV, or indirectly by referencing the variable name in some other expression context, as in the examples below: 

```
xcall MIAMEX, MX_SETENV, "MYPATH=c:\vm\miame\jack", status
```

```
...
```

```
open #ch, "%MYPATH%\myfile.log", output
```

In the example above, we use the %envvar% syntax, which is recognized by Windows as well as by A-Shell, regardless of the platform, in nearly all contexts where a filespec may be used. If specifying an environment variable in a Unix shell context, use the syntax $env, e.g. $MYPATH. 

Environment variable definitions are available only to the current A-Shell prcess, and to those child processes launched by it (e.g. by HOSTEX or MX_SHELLEX). As an example of the former, under Unix: 

```
xcall MIAMEX, MX_SETENV, "MYPATH=/vm/miame/jack", status
```

```
...
```

```
xcall HOSTEX, "ls -l $MYPATH/a*", STDOUT$
```

A-Shell itself defines and recognizes several environment variables. 

The TERM environment variable, used by UNIX—and A-Shell—to indicate the type of terminal in use, is a special case. When set from within an A-Shell session connected to a remote terminal (e.g. a Telnet or SSH session), A-Shell also re-initializes its terminal configuration and possibly changes its internal terminal "driver" to match the terminal type. 

For A-Shell/Unix, the TERM variable is typically established automatically when the Telnet/SSH session is initiated. But you may also set it manually prior to launching A-Shell (from the shell prompt), or you can set it via the -td command line switch. 

## **See Also** 

A-Shell Reference 

Page 2807 

- AG_SETENV 

A-Shell Reference 

Page 2808 

## **MX_KILL** 

## **xcall MIAMEX, MX_KILL, pid, signal, status** 

(Unix only) MX_KILL (MIAMEX 57) allows you to send any Unix signal to another process, provided you have sufficient privileges. It provides essentially the same functionality as the Unix kill utility (which, despite its name, allows sending any signal). 

## **Parameters** 

## _pid_ (Num)  [in] 

is the process ID number of the target process. You can get this information from SYSTAT, or perhaps by reading the jobtbl directly. 

## _signal_ (Num)  [in] 

is the signal to send, from the following table. Note that the actual signal numbers associated with the names are not guaranteed to be uniform across versions of Unix, although these (taken from Linux) are fairly standard. Signals that have no plausible use in applications have been omitted. Also note that these numbers are not related at all to the numbers in the SIGMASK used in functions 55 and 56. Signal 0 is particularly useful for determining if a target process still exists. 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|None|0|Used to determine if target PID exists|
|SIGHUP|1|Hangup (telnet or terminal session disconnected)|
|SIGINT|2|CTRL+C|
|SIGQUIT|3|Abort foreground processes, without core dump|



A-Shell Reference 

Page 2809 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SIGABRT|6|Force abort; similar to SIGQUIT|
|SIGKILL|9|Kill (cannot be trapped)|
|SIGUSR1|10|User signal (used by ITC, IJC messages)|
|SIGUSR2|12|User signal (used by PolyShell)|
|SIGALRM|14|Alarm signal (used by sleep timers andWAKNOXS)|
|SIGTERM|15|Default kill signal; generates error 251|
|**Definition file: ashell.def**|||



## _status_ (Signed Num)  [out] 

Returns 0 to indicate success (i.e. the signal was delivered to the target process, or, in the case of the pseudo-signal 0, it indicates that the target process exists, regardless of whether the sender has sufficient privileges to send a real signal).   For any real signal (i.e. signal > 0), status will return -1 if the sender does not have sufficient privileges to deliver the signal. 

In order to deliver a signal to another process, it must be logged in as the same effective user as the sender, or the sender must be root. One way to ensure this is to use the "setuid" bit on the ashell executable to make all A-Shell users the same effective user. Search this doc for "ashkill" for further information on that subject. 

A-Shell Reference 

Page 2810 

## **MX_GETOPTIONS** 

_Updated March 2026 (grpno added)_ 

## **xcall MIAMEX, MX_GETOPTIONS, options1 {,options2, grpno}** 

## **xcall MIAMEX, MX_SETOPTIONS, options1 {,options2, grpno}** 

MX_GETOPTIONS (MIAMEX 59) returns a bitmap field indicating which _options1/options2_ have been set, MX_SETPOPTIONS (MIAMEX 60) allows you to set those same option  flags on the fly. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_option1_ (Bitmap 32 bits)  [in for SET, out for GET] 

Individual on/off options, referenced by the symbols GOP_xxx in the _Options 1_ table below 

_option2_ (Bitmap 32 bits)  [in for SET, out for GET] 

Optional second bank of on/off options, referenced by the symbols GOP2_xxx in the _Options 2_ table below 

_grpno_ (Num)  [in for SET, out for GET] 

The user's group number, range 0-255. If group licensing is active, _grpno_ will be assigned automatically during the startup and changing it via MX_SETOPTIONS will have no effect on that. Otherwise, the field can be set and later queried for any application purpose. 

## **Comments** 

These are the same options that are defined in the A-Shell initialization file miame.ini; see OPTIONS[SP] for the full listing. They may also be set by SET.LIT. 

When the flag in the tables below has an equivalent OPTIONS setting, it is listed in the table's last column. 

A-Shell Reference 

Page 2811 

When setting _options2_ values, you cannot avoid also setting the _options1_ values. So you should always first retrieve the current options with MX_GETPTIONS, then set or clear the desired flags in the _options1_ and _options2_ variables, then update the flags with MX_SETOPTIONS. 

## An example follows the second table below. 

|**Options1 Symbol**|**Value**|**Description**|**OPTIONS=**<br>**Equivalent**|
|---|---|---|---|
|GOP_CRNL|&h00000001|Force CRNL line terminators|CRNL|
|GOP_EXTFIO|&h00000002|Extended file I/O options|EXTFIO|
|GOP_AS400|&h00000004|AS400 telnet mode (strip 8s and 11s)|AS400|
|GOP_LATIN1|&h00000008|Latin1 character set|LATIN1|
|GOP_OEM|&h00000010|Set internally for OEM fonts||
|GOP_EFFUSR|&h00000020|Use effective rather than login user|EFFUSR|
|GOP_AMOSRUNSBR|&h00000040|ExecuteASHELLXSin-process|ASHELL_RUNSBR|
|GOP_BRKALC|&h00000080|Prefill random file allocations with ]]]|BRKALC|
|GOP_HEXDEC|&h00000100|"Hexadecade" dates|HEXDEC|



A-Shell Reference 

Page 2812 

|**Options1 Symbol**|**Value**|**Description**|**OPTIONS=**<br>**Equivalent**|
|---|---|---|---|
|GOP_NOLEADFF|&h00000200|Strip leading formfeeds from print files||
|GOP_NOAUTOXLT|&h00000400|Defeat certain auto F-key translations|NOAUTOXLT|
|GOP_NTTS|&h00000800|Force Windows Terminal Server mode|NTTS|
|GOP_FPROUND|&h00001000|Round floating point results to 48 bits|FPROUND|
|GOP_FLDEMU|&h00002000|Emulate field terminal (Windows)|FIELDEMU|
|GOP_EXITWAIT|&h00004000|Forces wait for confirmation before closing session launched<br>with –e|EXITWAIT|
|GOP_ABSLOOKUP|&h00008000|Return absolute value in LOOKUP|ABSLOOKUP|
|GOP_QCLOSE|&h00010000|Close qflock between accesses||
|GOP_QBUFFER|&h00020000|Normal qflock buffering||
|GOP_LOCALCOPIES|&h00040000|Implement multiple spool copies via multiple submissions||



A-Shell Reference 

Page 2813 

|**Options1 Symbol**|**Value**|**Description**|**OPTIONS=**<br>**Equivalent**|
|---|---|---|---|
|GOP_SHLPATH|&h00080000|Special search path for SHL||
|GOP_AUTOCCON|&h00100000|Auto-enableCTRL+Cat start of each program||
|GOP_RAWTABS|&h00200000|Raw tab output to terminal|RAWTABS|
|GOP_XABORT|&h00400000|Allow X out of window|XABORT|
|GOP_NOXABORT|&h00800000|Disable OK in X abort dialog|NOXABORT|
|GOP_STRICT|&h01000000|Strict AMOS compatibility|STRICT|
|GOP_NUMPAD_COMMA|&h02000000|Treat decimal point on Windows numpad as comma|NUMPAD_COMMA|
|GOP_AUTOX|&h04000000|Allow auto expansion of ISAM and memo files|NOISAM_AUTOX|
|GOP_IDXLOK|&h08000000|Lock entire ISAM IDX during update|ISAM_IDXLOK|
|GOP_MMAPTIME|&h10000000|Force update of modify time of mmaped files every minute||
|GOP_AUTO_MEMOPEN|&h20000000|Check user memory when opening file; open in memory if|AUTO_MEMOPEN|



A-Shell Reference 

Page 2814 

|**Options1 Symbol**|**Value**|**Description**|**OPTIONS=**<br>**Equivalent**|
|---|---|---|---|
|||present||
|GOP_STR0|&h40000000|Retain leading zero in str(x) for values between -1 and 1|STR0|
|GOP_NOJOBMAP|&h80000000|(Unix) prevent jobtbl from being memory mapped|NOJOBMAP|
|**Definition file: ashell.def**||||



## - Hex Decimal Values 

|**Options2 Symbol**|**Value**|**Description**|**OPTIONS=**<br>**Equivalent**|
|---|---|---|---|
|GOP2_NOPSDLG|&h00000001|Disable the print screen (CTRL+P) dialog and just print<br>directly; seePRINTER<br> system parameter.||
|GOP2_NODELSYS|&h00000002|Do not deletejobtbl.sysandqfock.sysfiles on exit, ever.||
|GOP2_GUISPCINDENT|&h00000008|Activate "intelligent" GUI indenting.|GUI_SPC_IND|
|GOP2_AUTOTPRINT|&h00000010|Treat PRINT statements asTPRINT<br>.|AUTOTPRINT|



A-Shell Reference 

Page 2815 

|**Options2 Symbol**|**Value**|**Description**|**OPTIONS=**<br>**Equivalent**|
|---|---|---|---|
|||||
|GOP2_AUTODLGSTATE|&h00000020|Automatically sets MBF2_DLGSTATE option when a dialog is<br>created viaAUI_CONTROL<br>.|AUTODLGSTATE|
|GOP2_FSPECNATIVE|&h00000040|Treat some AMOS-illegal specs as native.|FSPECNATIVE|
|GOP2_NOINSTRX_PCP|&h00000080|Disable precompiled regex patterns in INSTR(pos, subj,<br>pattern, flags), i.e. treat even single-character patterns as<br>literal rather than as pre-compiled pattern indices.||
|GOP2_EFS_OUT_AMOS|&h00000100|Auto encrypt output files opened with AMOS specs; requires<br>EFS.|EFS|
|GOP2_EFS_OUT_HOST|&h00000200|Auto encrypt output files opened with native/host specs;<br>requires EFS.|EFS|
|GOP2_EFS_ALLOCATE|&h00000400|Auto encrypt on allocate; requires EFS.|EFS|
|GOP2_EFS_ALCINDEX|&h00000800|Auto encrypt on ALLOCATE’INDEXED; requires EFS.|EFS|
|GOP2_INI_AV|&h00001000|VUE looks for ini.av instead ofini.vue.||



A-Shell Reference 

Page 2816 

|**Options2 Symbol**|**Value**|**Description**|**OPTIONS=**<br>**Equivalent**|
|---|---|---|---|
|GOP2_SBX_RUNDIR|&h00002000|Search for SBX in same directory as RUN first.|SBX_RUNDIR|
|GOP2_NOSPOOL|&h00004000|Disable spooling.||
|GOP2_NOCAPTURE|&h00008000|Disable screen capture (CTRL+P).||
|GOP2_MSYNC_MAP|&h00010000|Sync entire map on write to memory mapped file.||
|GOP2_MSYNC_PAGE|&h00020000|Sync page on write to memory mapped file.||
|GOP2_NTTS|&h00040000|Variation of NTTS.||
|GOP2_SEQLOK|&h00080000|Sequential file locking (Unix).|SEQLOK|
|GOP2_LONGDIR|&h00100000|Use long (10.4) directory format (DIR/L).|LONGDIR|
|GOP2_ISAMDISAM|&h00200000|Emulate ISAM w/ DISAM.||
|GOP2_MANIFEST|&h00400000|Look for mft files.||
|GOP2_3DTAB|&h00800000|Allow TAB(X,Y,Z).||



A-Shell Reference 

Page 2817 

|**Options2 Symbol**|**Value**|**Description**|**OPTIONS=**<br>**Equivalent**|
|---|---|---|---|
|GOP2_AUTOX_RAN|&h01000000|Auto-expand "random" files, record by record as needed. See<br>the sample programAUTOX.BP in EXLIB:[908,39]<br>.||
|GOP2_RCDIMX|&h02000000|COMPIL /RC allowsDIMX.|RC_DIMX|
|GOP2_TCPNODELAY|&h04000000|(ATS only) Set TCP "No Delay" option (i.e. disable the "Nagle<br>algorithm").||
|GOP2_NOWHEEL|&h20000000|Disable mousewheel scrolling.|NOWHEEL|
|GOP2_XTAUTOFILTER|&h40000000|Enable XTREE auto-filter.||
|**Definition file: ashell.def**||||



- Hex Decimal Values 

MIAMEX.BP in EXLIB:[908,30] 

## **Example** 

To set the GOP2_RUNDIR flag and clear the GOP_ABSLOOKUP flag (and then restore the original settings), use code similar to the following: 

A-Shell Reference 

Page 2818 

```
MAP1 options1,b,4
```

```
MAP1 options2,b,4
```

```
MAP1 save'options1,b,4
```

```
MAP1 save'options2,b,4
```

```
xcall MIAMEX, MX_GETOPTIONS, options1, options2   ! retrieve current options
save'options1 = options1                          ! save original settings for later restore
save options2 = options2
```

- `!  NOTE: when setting/clearing flags, use logical operators and/or/not rather` 

```
!         than +/-; otherwise be careful not to add a flag that is already set
```

- `!         or subtract one that is already clear!!` 

```
options1 = options1 and not GOP_ABSLOOKUP         ! clear GOP_ABSLOOKUP flag
```

```
options2 = options2 or GOP2_RUNDIR                ! set GOP2_RUNDIR flag
xcall MIAMEX, MX_SETOPTIONS, options1, options2   ! update options
```

```
!  Later, to restore the original options:
```

```
xcall MIAMEX, MX_SETOPTIONS, save'options1, save'options2
```

**See Also** 

A-Shell Reference 

Page 2819 

- AG_OPTIONS 

## **History** 

- 2026 March, A Shell 7.0.1785:  Add _grpno_ parameter. 

- 2023 December, A Shell 7.0.1753:  Add GOP2_NOINSTRX_PCP 

A-Shell Reference 

Page 2820 

## **MX_GETTRACE** 

_Reviewed and revised, April 2024_ 

## **xcall MIAMEX, MX_GETTRACE, trflags** 

## **xcall MIAMEX, MX_SETTRACE, trflags** 

MX_GETTRACE (MIAMEX 61) retrieves the current set of trace options, MX_SETTRACE (MIAMEX 62) allows you to set those options on the fly. 

## **Parameters** 

_trflags_ (Bitmap 48 bits)  [in for SET, out for GET] 

Individual trace on/off options, referenced by the symbols TROP_xxx in the table below, where xxx matches the name of the trace as specified in the TRACE system parameter directives, as well as in the SET command. For example, the flag set via TRACE=BASERR in miame.ini is referenced here by the symbol TROP_BASERR. 

## **Comments** 

Most traces result in messages logged to ashlog.log, although some, like TROP_LP, output directly the screen. Any trace that gets written to ashlog.log can also be written to the System Message Window if it is open and enabled. Note that you can activate any of the traces from System Messages Window by right-clicking on it and picking Properties. 

Tracing flags may also be set with the TRACE system parameter or with the TRACE options in the SET command. See those discussions for more details about these options. 

See Event Tracing for a detailed description of tracing functionality. 

|**Symbol**|**Value**|**Notes**|
|---|---|---|
|TROP_AMSORT|&h00000001|Display sorting trace dialog|



A-Shell Reference 

Page 2821 

|**Symbol**|**Value**|**Notes**|
|---|---|---|
|TROP_SYSERR|&h00000002|Display system error dialog|
|TROP_SQL|&h00000004|SQL tracing|
|TROP_LP|&h00000008|Line printer tracing display|
|TROP_SIGNAL|&h00000010|Display received signals|
|TROP_SIGHUP|&h00000020|Log hang-ups|
|TROP_LOCKS|&h00000040|Display lock trace|
|TROP_LOG|&h00000080|Log various details|
|TROP_JOBS|&h00000100|Log job info|
|TROP_QOPEN|&h00000200|Log qflock.sys operations such as XLOCK|
|TROP_GDIPRT|&h00000400|Display GDI print directives|
|TROP_FOPENS|&h00000800|Log file opens|



A-Shell Reference 

Page 2822 

|**Symbol**|**Value**|**Notes**|
|---|---|---|
|TROP_XCALL|&h00001000|Log XCALLs|
|TROP_AMOS|&h00002000|LogXCALL ASHELLoperations|
|TROP_DEBUG|&h00004000|Log maximum details|
|TROP_INOUT|&h00008000|Log ins & outs|
|TROP_BASERR|&h00010000|Log ASB errors|
|TROP_ISAM|&h00020000|Log ISAM operations|
|TROP_USRMEM|&h00040000|Log user memory operations|
|TROP_MALLOC|&h00080000|Log memory allocations|
|TROP_RW|&h00100000|Log reads and writes|
|TROP_SOCKS|&h00200000|Log socket operations|
|TROP_XLOCKS|&h00400000|LogXLOCKcalls|



A-Shell Reference 

Page 2823 

|**Symbol**|**Value**|**Notes**|
|---|---|---|
|TROP_XDEBUG|&h00800000|Combine with other flags to increase detail|
|TROP_PERF|&h01000000|Log performance for certain operations|
|TROP_GUI|&h02000000|Log internal GUI operations|
|TROP_EFS|&h04000000|Log Encrypted File System (EFS) operations|
|TROP_ATE|&h08000000|Log ATE commands|
|TROP_KBD|&h10000000|Log keyboard data and operations|
|TROP_XTREE|&h20000000|LogXTREEoperations|
|TROP_CGI|&h40000000|Log CGIUTL operation|
|TROP_EXEC|&h80000000|RUN, CHAIN, CMDLIN|
|TROP_JOBLCK|&h100000000|Causes all unresolved lock/unlock operations on thejobtbl.sysfile to be<br>traced in the filejobtbl.lck. Note that the bit TROP_JOBLCK is beyond the<br>32 bit range of the typical 32 bit flags word, so you need to use B5, B6, I6,<br>or F6/F8 to retrieve or set this bit.|



A-Shell Reference 

Page 2824 

|**Symbol**|**Value**|**Notes**|
|---|---|---|
|**Definition file: ashell.def**|||



- Hex Decimal Values 

## **History** 

2022 May: Rewrite two paragraphs before table. 

2016 September, A-Shell 6.3.1526:  Add TROP_JOBLCK. 

A-Shell Reference 

Page 2825 

## **MX_SETPFK** 

## **xcall MIAMEX, MX_SETPFK, pfkspec {,status)** 

## **xcall MIAMEX, MX_GETPFK, pfkspec** 

MX_SETPFK (MIAMEX 63) loads a private (PFK-style) function key translation module into memory. MX_GETPFK (MIAMEX 65) returns the name of the currently loaded PFK translation file, if any. 

## **Parameters** 

_pfkspec_ (Num)  [in for SET, out for GET] 

contains the file specification of a translation table created by FIXTRN which has a PFK extension (e.g. mydir:abcde.pfk). 

_status_ (Num)  [out] 

will be set to 0 on success, or 1 if the file was not found 

## **Comments** 

Unlike the IFX and VUX translation tables, which are named after the terminal driver and loaded by default, a PFK-style translation table may have any name (with a PFK extension). When loaded, such a translation table will override any existing translations in the IFX file. Thus, they are handy for loading translations that are specific to a particular program or perhaps even a particular user. 

Use `FIXTRN <name>.pfk` to create a PFK style translation table. You can also use `LOAD <name>.PFK` to load it into memory, and DEL to delete it. To delete it within a program, use MX_USRDEL. 

A-Shell Reference 

Page 2826 

## **MX_SCRNPIC** 

_Reviewed and revised May 2024_ 

## **xcall MIAMEX, MX_SCRNPIC, flags** 

MX_SCRNPIC (MIAMEX 65) invokes the text-based screen picture routine to print or capture a picture of the current screen. This is the same routine that is called when you hit CTRL+P in most input fields, except that here you have the ability to eliminate the pop-up dialog. 

## **Parameters** 

## _flags_ (Bitmap, 16 bits)  [in] 

may be any combination of the following: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SPICF_APPEND|&h0001|Append screen picture to current picture file, if any. (Otherwise overwrite it.)|
|SPICF_SPOOL|&h0002|Print the picture file to the default screen picture printer; else just create the print<br>file (in<jobnam>.buf).|
|SPICF_DIALOG|&h0004|Display the screen picture dialog, otherwise just do the operation silently.|
|SPICF_DELETE|&h0008|Delete the picture file after printing.|
|SPICF_DLGOPT|&h0010|Same as option 4 (display dialog) except that it may be overridden|
|SPICF_STRIP|&h0040|Strips trailing blanks from each line of the output file|



A-Shell Reference 

Page 2827 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||||
|SPICF_FINAL|&h0080|Adds "FINAL" to header|
|SPICF_GUICSV|&h0100|Dump GUI Control Table|
|**Definition file: ashell.def**|||



The default screen picture printer may be set via the PRINTER=p1,p2{,NODLG} statement in miame.ini. The first printer(p1), is the default printer for other print operations, and the second printer, if specified (p2) is the default screen picture printer. If the third parameter is specified as "NODLG", then screen pictures that are requested via the CTRL+P command will print without displaying the dialog. 

## **See Also** 

- Screen Pictures (GUI version) 

A-Shell Reference 

Page 2828 

## **DUMP GUI CONTROL TABLE** 

This option dumps the current GUI control table to <jobnam>.CSV. The intent is to make it possible for developers who are using GUI-enhanced text (e.g. TPRINT, DPRINT, INFLD) to extract the information about the resulting text and edit controls and combine it with the text-based screen dump information to create an "enhanced text" screen picture. The details of how to do that have been left to the individual developer. The layout of the CSV data is similar to that of the "Dump Control Info to Spreadsheet" function, but simplified and improved somewhat by adding the explicit font information. The columns headers should help identify the data. 

A-Shell Reference 

Page 2829 

## **MX_QRBLD** 

## **xcall MIAMEX, MX_QRBLD** 

MX_QRBLD (MIAMEX 66) forces the qflock.sys file to be rebuilt. This will be done automatically if any broken links are detected, so the possibility of invoking it manually is of only academic interest. 

A-Shell Reference 

Page 2830 

## **MX_QLOCK** 

## **xcall MIAMEX, MX_QLOCK** 

## **xcall MIAMEX, MX_QUNLOK** 

MX_QLOCK (MIAMEX 67) locks the qflock.sys file. It should be called before trying to read the qflock.sys file, and should then be followed by MX_QUNLOK. 

MX_QUNLOK (MIAMEX 68) removes the lock on the qflock.sys file which was placed by a prior call to MX_QLOCK. 

A-Shell Reference 

Page 2831 

## **MX_GETUMSK** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_GETUMSK, umask** 

## **xcall MIAMEX, MX_SETUMSK, umask** 

(Unix only) 

MX_GETUMSK (MIAMEX 69) retrieves the current UMASK setting. _umask_ (Num) will return with the current value of the UMASK, treating it as if it were a decimal number. For example, if the UMASK is 111 (which is actually an octal pattern), the returned _umask_ value will be 111 (decimal). 

MX_SETUMSK (MIAMEX 70) establishes a new UMASK setting. 

_umask_ (Num) should be set to the 3-digit decimal number, which if interpreted as octal, represents the desired UMASK setting. For example, to set the UMASK to 117, simply set _umask_ =117. (In other words, you can ignore the fact that the UMASK is actually an octal representation of a bit pattern.) 

A-Shell’s default UMASK is 111. If you set _umask_ =000, A-Shell will instead use the mask set by the shell. Otherwise it will use the specified mask. 

Note that the bits in the umask clear the corresponding bits in the file creation mask, which starts at 666 (rw-rw-rw-). So setting UMASK to 111 will result in no change to the rw-rw-rw- mask. But setting UMASK to 137 would result in rw-r---- (rw by the file owner, read only by members of the group, otherwise no access). 

You may also set the UMASK in miame.ini, using UMASK=xxx. 

A-Shell Reference 

Page 2832 

## **MX_LITMSG** 

## **xcall MIAMEX, MX_LITMSG, cat, msgno {, row, col, var, msgfile, arg, default'msg}** 

MX_LITMSG (MIAMEX 72) is mainly used within LIT utilities to display language-independent messages, although you can add use it to reference your own (properly formatted) message files as well. A "properly formatted" message file consists of lines in the following format: 

```
<cat>,<msgno>,<message>{,<arg>}
```

```
<cat>,<msgno>,<message>{,<arg>}
```

## `etc` 

<cat> and <msgno> are typically formatted as three digit numbers, as in the example below. Any message may optionally be followed by a comma a numeric value which can optionally be returned to the calling program for whatever purpose. Comments are typically inserted by using <cat> and/or <msgno> values of 000. The lines of the file must be sorted, first by <cat> and then by <msgno>. 

When a message file is accessed, it is loaded into user memory (for efficiency in handling subsequent accesses). When testing/updating the message file, remember to use DEL * to clear the user memory in order to get a fresh copy of the message file. 

## **Parameters** 

## _cat_ (Num) 

is the message category number. In the case of the LITMSG.xxx files, each LIT utility has its own _cat_ value. Here is a brief extract of the symbols defined in msgtbl.def, which see for the complete list. 

|**Symbol**|**Value**|**Notes**|
|---|---|---|
|MSG_CMDLIN|0|Misc CMDLIN messages|



A-Shell Reference 

Page 2833 

|**Symbol**|**Value**|**Notes**|
|---|---|---|
||||
|MSG_ABOUT|1|ABOUT.LIT messages|
|MSG_TELSER|2|TELSER.LIT messages|
|MSG_SEND|3|SEND.LIT messages|
|MSG_FORCE|4|FORCE.LIT messages|
|**Definition file:**msgtbl.def|||



## _msgno_ (Num) 

is the message number within the _cat_ category. 

## _row_ , _col_ (Num) 

may be optionally specified to have the message displayed at the given row and column position. If either is zero, or they are omitted, then the message will be displayed at the current cursor position. If _row_ is negative, then the message is not displayed but instead only returned in the _var_ parameter. 

## _var_ (String) 

will return the text of the message if specified. The maximum supported line length is 256. 

A-Shell Reference 

Page 2834 

_msgfile_ (String) 

may optionally give the complete filespec of the message file. If the extension is missing, it will be set to match the current language (as defined in the LDF or language definition file specified in the LANGUAGE statement in miame.ini, e.g. USA, SPA, FRE, etc.). If the parameter is blank or omitted, the default is "DSK0:LITMSG[1,4]" (with the extension being supplied as just described). For non-fully-qualified filespecs, the search path is: memory, ppn, [p,0], sys: 

_arg_ (Num) 

if specified, will return the optional <arg> field of the current message, if any. 

## _default'msg_ (String) 

specifies the default message text to be used if the message is not located in the message (or the message file does not exist). Often, for maximum program readability, this parameter is specified as a literal string to make it obvious what the expected text of the message is. See the example below. 

## **Example** 

Here is an excerpt from the LITMSG.USA file: 

```
000,000,#
```

```
000,000,# A-Shell LIT command message table
```

```
000,000,# Language: English (US Only)
```

```
000,000,#
```

```
000,000,# Following 000,### messages are generic lit/cmdlin messages
```

```
000,000,#           001,### messages are from about.lit
000,000,#           002,### message are from telset.lit, etc.
```

```
000,001,?Exceeded maximum number of devices
```

```
000,002,?Cannot read
```

A-Shell Reference 

Page 2835 

```
000,003,greater than
```

```
000,004,^ Specification error
```

```
000,005,?Device not found or mounted
```

```
000,006,file
```

```
000,007,disk block
000,008,Total of
000,009,%No files transferred
000,010,transferred
000,011,%No files deleted
000,012,deleted
001,000,# ABOUT.LIT messages...
001,001,Serial #
001,002,Licensed to:
001,003,Nodes Licensed:
001,004,Nodes in Use:
001,005,Jobs in Use:
```

```
xcall MIAMEX, MX_LITMSG, 1, 2, -1, -1, msg$, msgfil$, 0, "License Issued to"
```

The above call, assuming that msgfil$ was blank or set to "LITMSG" and the current language extension was "USA", and the above file was stored as LITMSG.USA, would return msg$ = "Licensed to". If the file was not found, then it would return "License Issued to" (because of the _default'msg_ parameter). 

A-Shell Reference 

Page 2836 

## **MX_READJCB** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_READJCB, jobno, buffer {,lokflg {,status}}** 

## **xcall MIAMEX, MX_WRITEJCB, jobno, buffer {,lokflg {,status}}** 

MX_READJDB (MIAMEX 73) reads a job control block or record from jobtbl.sys, and MX_WRITEJCB (MIAMEX 74) writes a jobtbl record. 

## **Parameters** 

## _jobno_ (Num) 

the job number of the block to read. This is equivalent to the record number, starting at 1 for the first job. _jobno_ 0 refers to the control record, which should not be accessed. 

## _buffer_ 

the record buffer to receive the data. For _jobno_ 0 (header), the buffer should be mapped per the JCB'HDR map statements in JOBTBL.MAP in SOSLIB:[907,16] or as an instance of the ST_JCBHDR defstruct in JOBTBL.SDF in SOSLIB:[907,16]. For all other _jobno_ values (individual job table records), _buffer_ should be mapped per the JCB'REC map statements in JOBTBL.MAP in SOSLIB: [907,16] or as an instance of the ST_JCBREC defstruct in JOBTBL.SDF in SOSLIB:[907,16]. 

For relevant symbol definitions, see JOBTBL.DEF in SOSLIB:[907,16]. 

## _lokflg_ (Num) 

may optionally be set to 1 to lock the record prior to reading it (leaving it locked thereafter). To unlock it you would then need to write the record back, using MX_WRITEJCB, and also specifying the same _lokflg_ =1. 

_status_ (Num)  [out] 

returns 0 for success, else an error code 

## **Comments** 

A-Shell Reference 

Page 2837 

To scan all of the job table records, start at JOBNO=1 and keep incrementing it, skipping records with JCB'JOBTYP = JOBTYP'FREE, and quitting when you hit a record with JCB'JOBTYP = JOBTYP'EOF. 

As is hopefully obvious, MX_READJDB should used with extreme caution, since writing invalid information to jobtbl.sys could cause undesirable results. 

## **History** 

- 2023 December, A Shell 1753:  Add current SBX name to the job control block, taking the last ten bytes from the end of the message field 

A-Shell Reference 

Page 2838 

## **MX_GETTIME** 

_Reviewed and Revised May 2024_ 

## **xcall MIAMEX, MX_GETTIME, secs {,usecs, utcoffset}** 

MX_GETTIME (MIAMEX 75) returns the number of seconds, and optionally microseconds, since 00:00:00 January 1, 1970, Coordinated Universal Time (aka the "Epoch"). 

## **Parameters** 

_secs_ (Unsigned Integer, preferably B6) 

will receive the number of seconds elapsed since the beginning of the "Epoch," midnight, Jan 1, 1970. See History note below. 

_usecs_ (Signed Num) 

will be set to -1 if the feature is not supported (e.g. AIX, SCO) or else the number of microseconds to add to SECS. Note that under Windows, the actual resolution is only milliseconds, so USECS will always be a multiple of 1000. The microseconds value is probably not useful in itself but could be useful for measuring the amount of time that a very short operation takes (by calling MX_GETTIME twice, once before and once after). The sample program MIAMEX.BP in EXLIB:[908,30] has been updated to do just that, showing the time to execute a FOR/NEXT loop of 10000 iterations. 

_utcoffset_ (Signed Num)  [out] 

Returns offset in seconds between local time and UTC (Universal Coordinated Time, aka Greenwich Mean Time). Offset will be negative for timezones West of Greenwich. A value of -1 indicates an error. Verions of A-Shell prior to 6.3.1518 will ignore the parameter; so unless you check the version, you should probably set your utcoffset value to -2 before calling the routine so that you can detect if it worked. 

## **Comments** 

If you are using this function to measure an interval, keep in mind the possibility that the system clock might get updated during that interval, rendering your results meaningless. 

The TIME system variable in ASB returns the number of seconds since midnight. 

A-Shell Reference 

Page 2839 

## **See Also** 

- TIMESXS for a better way to measure precise intervals. 

- MX_FTFORMATXS to format the time. 

- TIME system variable 

## **History** 

- 2023 August, A Shell 6.5.1740:  Add support for additional timestamp bits (beyond 32) to resolve the Year 2038 problem. B6 was previously supported, for the _secs_ parameter but the result was still limited to 32 bits. 

- 2016 July, A Shell 6.3.1518: Add _utcoffset_ parameter. 

A-Shell Reference 

Page 2840 

## **MX_TELSER** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_TELSER, port, status {,wait}** 

(Windows only) MX_TELSER (MIAMEX 76) allows you to turn your current A-Shell/Windows client into a telnet server for a single remote client. 

## **Parameters** 

_port_ (Num) 

specifies the port number to accept the incoming connection request on. 

## _status_ (F6) 

returns a code indicating the success of the operation, from the following table: 

|**Value **|**Meaning**|
|---|---|
|0|Success|
|-1|Unable to load Winsock library|
|-2|Winsock 1.1+ not present|
|-3|Unable to create listening socket|
|-4|User abort (CTRL+Cwhile waiting for connection)|



A-Shell Reference 

Page 2841 

## _Wait_ (Num) 

may be used to specify options (combine zero or more from the following table): 

|**Value **|**Meaning**|
|---|---|
|1|Minimize window immediately and wait for connection before returning<br>from subroutine.  (Otherwise it returns immediately with the wait<br>operation waiting in background for the connection.)|
|2|Launch a new instance to wait for a subsequent connection upon accepting<br>the first connection|
|4|Make waiting window totally invisible|



## **Comments** 

Your session will continue to run normally until a telnet client connects; at that point, your window will be hidden and all terminal I/O redirected to the remote telnet client. 

Passing 0 for the port value closes/releases any socket resources opened by a prior MX_TELSER call. This allows the operation to be cleaned up and restarted. Also, when the client disconnects, the server job reliably receives error 250. 

You can restore visibility to an invisible window waiting for a connection by using SEND.LIT or SEND[XS] to send it a message consisting of just an exclamation point (!). 

A-Shell Reference 

Page 2842 

## **MX_GETGDO** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_GETGDO, status, p0 {,p1, p2, ... , p9}** 

## **xcall MIAMEX, MX_SETGDO, status, p0 {,p1, p2, ... , p9}** 

MX_GETGDO (MIAMEX 78) and MX_SETGDO (MIAMEX 79) provide the means to retrieve (GET) or SET the global DO parameters. 

## **Parameters** 

_status_ (Signed Num)   [out] 

returns 0 for success or –1 to indicate failure. 

_p0_ through _p9_ (String)  [in for SET, out for GET] 

values of the up-to-ten global DO file parameters. 

## **Comments** 

In the SET operation, all ten DO file parameters are set at once, replacing any prior values. Even if you specify only _p0_ , the prior values of _p1_ through _p9_ will be set to null. For more information on this topic, see Global DO File Parameters. 

A-Shell Reference 

Page 2843 

## **MX_EXITSBX** 

## **xcall MIAMEX, MX_EXITSBX** 

MX_EXITSBX (MIAMEX 82) may be used to abort from an SBX subroutine directly to the dot prompt. This is necessary, since merely ending an SBX routine (with the END statement) will return to the calling program. 

Refer to SBX Subroutines for more information on this and related MIAMEX functions. 

## **See Also** 

- MX_EXIT 

A-Shell Reference 

Page 2844 

## **MX_GETFKW** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_GETFKW, waitms** 

## **xcall MIAMEX, MX_SETFKW, waitms** 

(Unix only) 

MX_GETFKW (MIAMEX 83) retrieves the current FKEYWAIT (function key sequence completion wait) value for this terminal. MX_SETFKW (MIAMEX 84) sets the current FKEYWAIT value for this terminal. 

## **Parameters** 

_waitms_ (Num) 

wait time in milliseconds. 

## **Comments** 

For related information, see the discussion of FKEYWAIT[SP] . 

A-Shell Reference 

Page 2845 

## **MX_TITLE** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_TITLE, opcode, title** 

MX_TITLE (MIAMEX 85) gets or sets the title string which will be displayed in the Windows title bar or applicable terminal emulator. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 (mxop_get) to retrieve the current title or 1 (mxop_Set) to set it. 

## _title_ (String)  [in/out] 

is the title string, either returned for _opcode_ 0 (mxop_get) or to set for _opcode_ 1 (mxop_set). _title_ may contain any of the following special macros: 

|**Titl**<br>**e**|**Meaning**|
|---|---|
|$TS|Display title on top status line rather than on title bar of<br>window. Valid only at the start of the TITLE string.|
|$NC|Name of current program or LIT command|
|$ND|Name of current disk device, e.g. "DSK0"|
|$NJ|Name of current job|



A-Shell Reference 

Page 2846 

|**Titl**<br>**e**|**Meaning**|
|---|---|
|$NP|Name of current program (RUN only)|
|$PA|Platform A-Shell compiled for, e.g. "Windows/32"|
|$PN|Current PPN, e.g. "[7,6]"|
|$VA|A-Shell version, e.g. "4.9(942)"|
|$VP|Version of current program|



## **Comments** 

MX_TITLE can also be performed using the SET.LIT TITLE option. Note that if $NC, $ND, $NP, or $PN is specified, the title display will be automatically updated whenever the corresponding information changes. 

A-Shell Reference 

Page 2847 

## **MX_ERRNOMSG** 

## **xcall MIAMEX, MX_ERRNOMSG, errno, message** 

MX_ERRNOSMG (MIAMEX 86) returns the operating system’s text message associated with the specified operating system error code (aka **errno** ). 

## **Parameters** 

_errno_ (Num)  [in] 

is the error number for which you want the message. Note that many MIAMEX functions return operating system errors as negative numbers; these should be converted to absolute value before passing to this function. See History, below. 

_message_ (String)  [out] 

returns the error message. 

## **See Also** 

- ERRMSG for information relating to displaying the text corresponding to ASB error numbers. 

A-Shell Reference 

Page 2848 

## **MX_NOBUF** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_NOBUF, channel** 

## **xcall MIAMEX, MX_FLUSHBUF, channel** 

(Unix only) MX_NOBUF (MIAMEX 87) will disable the normal stream buffering on output streams (i.e. files open for output, and the console itself, aka _stdout_ ). 

MX_FLUSHBUF (MIAMEX 88) flushes (or "unbuffers") the data, which has been buffered but not yet written to the specified file channel. 

## **Parameters** 

_channel_ (Num)  [in] 

is the file channel to disable buffering on. The file must be open for output (or append). For the terminal device, use file channel 0 (which is automatically opened for you at the start of each program). 

## **Comments** 

By default, Unix systems buffer output streams to minimize the amount of system overhead involved in writing to them. For files, the buffer size may be several K. For the terminal or console, the buffering is generally limited to a single line. 

In general this buffering is highly desirable, but there may be cases where it is annoying. One situation occurs when you are treating a physical port as a file, in order to control device connected to that port. In such a case, you may write out a small command to the file/port thinking that the device will see it immediately, but due to the buffering, it would not. A more typical situation involves writing some kind of status information (aka "life signs") to the screen during a lengthy process. Unless each update of the status information ended with a line terminator, it would simply be buffered, with the result that instead of seeing dots or percentage completion indicators steadily appear on the screen, there is a delay, and then it all appears at once. One (but not the only) solution to these problems would be to just disable buffering on the file channel in question. 

An alternate approach is to force the buffer to be flushed on demand. For terminal devices, you can do this with Tab(-1,254), or simply by ending a PRINT statement without a semicolon. For file devices, you can use Function 88. 

A-Shell Reference 

Page 2849 

This buffering issue does not affect data files that are open for random I/O, ISAM, etc. 

A-Shell Reference 

Page 2850 

## **MX_FLSET** 

## **xcall MIAMEX, MX_FLSET, ch, status, recvar'adr {,stavar'adr}** 

MX_FLSET (MIAMEX 89) is used within SBX Subroutines routine to link up with the control variables associated with a random or ISAM file that was opened in the calling program. 

## **Parameters** 

## _ch_ 

is the file channel (opened in the parent program) that you want to access. 

## _status_ (F6) 

returns to a code reflecting the outcome of the operation: 

|**Value **|**Meaning**|
|---|---|
|-1|Parameter error|
|0|File CH was not open|
|1|Success: file was opened for INDEXED access (ISAM 1.0)|
|2|Success: file was opened for INDEXED’EXCLUSIVE|
|3|Success: file was opened for RANDOM access|
|4|Success: file was opened for INPUT|



A-Shell Reference 

Page 2851 

|**Value **|**Meaning**|
|---|---|
|||
|5|Success: file was opened for OUTPUT or APPEND|
|6|Success: file was opened for INDEXED access (ISAM-A)|
|7|Success: file was opened for INDEXED’EXCLUSIVE (ISAM-A)|



## _recvar’adr_ (X,6) 

is an unformatted variable whose origin or location is the same as the F6 variable which you want to use for specifying the record number for this file. We have to resort to this trick of mapping it as an X type so that we can get the true address of the variable, because otherwise floating point arguments to subroutines are pushed on the stack. So, for example, you should map it like this: 

```
MAP1 RECNOX                 ! (specify this to MIAMEX, MX_FLSET)
    MAP2 RECNO,F,6          ! (actual record number control var)
```

or 

```
MAP1 RECNO,F,6              ! (actual record number control variable)
MAP1 RECNOX,X,6,@RECNO      ! (specify this to MIAMEX, MX_FLSET)
```

A-Shell Reference 

Page 2852 

In either case, specify the _recnox_ variable in the MIAMEX call, but use the _recno_ variable to set the record number within the file. 

## _statvar’adr_ (X,6) 

is only used in the case of an ISAM-A file, and is used to specify the ISAM status variable that will return the result of each ISAMA operation. It must be mapped and specified to the subroutine using the same trick as for _recvar’adr_ above. 

## **Comments** 

Once you successfully execute the MX_FLSET operation, you can have full access to the RANDOM, ISAM, or ISAM-A file within the subroutine. 

Refer to SBX Subroutines for more information on this and related MIAMEX functions. 

A-Shell Reference 

Page 2853 

## **MX_BEVEL** 

## **xcall MIAMEX, MX_BEVEL, opcode, bevel, linedraw** 

(Windows only) MX_BEVEL (MIAMEX 90) allows you to query or set the beveling options, which are otherwise available on the Edit menu or via the SET TERM BEVEL command. 

## This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 (mxop_get) to query the current options or 1 (mxop_set) to set them 

_bevel_ (Num)  [in/out] 

indicates the bevel mode: 

|**Value **|**Meaning**|
|---|---|
|0|Beveling off|
|1|Beveling set to automatic|
|2|Beveling set to program control. In this case, to turn beveling on within a<br>program, you can use "?<br>`Tab(-10,BEVEL); str(FLAGS); chr(127)"`<br>where FLAGS are values that control beveling options, with the most useful<br>choices being 0 (off), 255 (on, with no line drawing characters) or 15<br>(beveling, but use line drawing characters also).|



A-Shell Reference 

Page 2854 

## _linedraw_ (Num)  [in] 

should be set to 0 for enabled, or 1 for disabled. The recommendation is to disable line drawing when beveling is active so that lines will be represented entirely by the 3D raised objects. 

## **See Also** 

- AG_BEVEL 

A-Shell Reference 

Page 2855 

## **MX_SYSBCLR** 

## **xcall MIAMEX, MX_SYSBCLR, opcode, sysbclr {,syswinc, systxtc}** 

(Windows and ATE) MX_SYSBCLR (MIAMEX 91) allows you to assign one of the background color numbers (0-15) to reference the default Windows color for dialog box backgrounds (typically gray). 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _opcode_ (Num) 

0 (mxop_get) to query the current system background color number, or 1 (mxop_set) to set it. 

## _sysbclr_ (Num) 

will return the currently defined system background color number (for _opcode_ 0), or establish it (for _opcode_ 1). 

## _syswinc_ (0-7) 

applies to one of the background colors in the color palette 

_systxtc_ (0-7) 

refers to one of the foreground colors. 

You can also set this with SET TERM SYSBCOLOR n. 

## **Comments** 

The idea would then be to use Tab(-3,BGCOLOR) to use that color as your background color. The advantage of tying this color number to the Windows system background color instead of just setting it to a specific color, is that then it will automatically change when the Windows desktop color scheme is changed. For example, if the user switches to a "Valentine’s Day" scheme, the cool gray Window backgrounds will all change to pinkish ones. 

## **See Also** 

A-Shell Reference 

Page 2856 

- AG_SYSBCLR 

A-Shell Reference 

Page 2857 

## **MX_HOTKEY** 

## **xcall MIAMEX, MX_HOTKEY {,enable}** 

## **xcall MIAMEX, MX_HOTKEY, hotkey, swapkey** 

(Unix only) MX_HOTKEY (MIAMEX 92) allows you to temporarily disable the PolyShell hot or swap keys, or reassign them. The typical motivation for temporarily disabling them is in situations where you are allowing an external process to control the screen (for example, an AutoLog communication session). In such a case, swapping jobs with PolyShell may not be advisable. 

## **Parameters** 

_enable_ (Num)  [in] 

Zero to disable the hot and swap keys, or one to re-enable them. The default, if the parameter is omitted, is 0 to disable. 

_hotkey_ (Num)  [in] 

Specifies the ASCII key value of the new PolyShell hot key, or 0 to disable it. 

_swapkey_ (Num)  [in] 

Specifies the ASCII key value of the new PolyShell swap key, or 0 to disable it. 

A-Shell Reference 

Page 2858 

## **MX_ABOUT** 

_Updated February 2017; see History_ 

## **xcall MIAMEX, MX_ABOUT, prdname, version, serial, coname, key, licnodes, phynodes, lognodes, licoptions, expflags, reldate, expdate, inifile {,jobtbl'fspec, jobtbl'inode, jobtbl'cdate, jobtbl'ctime}** 

MX_ABOUT (MIAMEX 93) retrieves several pieces of information relating to the current license and environment. It is mainly used by ABOUT.LIT, but might be useful within in application to check for maintenance expiration, number of licensed users, etc. A quick look at the output of ABOUT.LIT will answer many questions about the parameter output. 

## **Parameters** 

All parameters are [out]. 

|**Parameter**|**Type**|**Description**|
|---|---|---|
|prdname|String|will return the A-Shell platform-specific name, e.g. "A-Shell/Linux" or "A-Shell/Windows/32".|
|version|String|will return the A-Shell version string, e.g. "Ver 6.5(1721)".|
|serial|(Num)|will return the serial number.|
|coname|String|will return the company name that the license was issued to.|
|key|String|will return the license key (aka PIC code).|
|licnodes|(Num)|will return the maximum number of nodes licensed.|



A-Shell Reference 

Page 2859 

|**Parameter**|**Type**|**Description**|
|---|---|---|
|phynodes|(Num)|will return the current number of physical nodes in use.|
|lognodes|(Num)|will return the current number of logical nodes in use. (The logical node count should count each job,<br>whereas the physical count may be less if multiple jobs are identified as being connected with the<br>same session or are running in background.)|
|licoptions|String|will return a string of descriptive tokens identifying license options, such as "COM-XCALL",<br>"PolyShell", etc.|
|expflags|(Num)|Returns indication of the license status combined with a flag indicating whether there is a runtime<br>(vs. maintenance) expiration. See EF_xxx flags in ashell.def, reproduced below.|
|reldate|String|will return the release date of the current executable (dd-mon-yyyy).|
|expdate|String|will return the maintenance or runtime expiration date of the license (dd-mon-yyyy).|
|inifile|String|will return the fully qualified native filespec ofmiame.ini.|
|jobtbl’fspec|String|will return the fully qualified native filespec of thejobtbl.sysfile.|
|jobtbl’inode|(Num)|will return the inode of thejobtbl.sysfile. (Applies to Unix only; will be set to 0 under Windows.)|
|jobtbl’cdate|String|will return the creation date (or last status change date) of thejobtbl.sysfile (dd-mmn-yy) format.|



A-Shell Reference 

Page 2860 

|**Parameter**|**Type**|**Description**|
|---|---|---|
|||Note that under Unix, the "c date" will be updated by any change to the privileges or ownership of<br>the file, so it may not reliably indicate the actual creation time.|
|jobtbl’ctime|String|will return the creation time (or last status change time) of thejobtbl.sysfile (hh:mm) format.|



## **EF_xxx Flags (for** _**expflags**_ **parameter)** 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|EF_NORMAL|0|license good|
|EF_DEMO|1|demo mode|
|EF_BADKEY|2|bad key|
|EF_BADCO|3|bad company|
|EF_BADOS|6|bad os|
|EF_EXPIRED|7|expired runtime|



A-Shell Reference 

Page 2861 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|EF_EXPIRED_EXE|8|expired maint|
|EF_ATSD|10|ATSD not licensed|
|EF_BADMAC|12|MAC address not valid|
|EF_SERIAL|13|serial # out of range|
|EF_BADKEYFMT|14|bad key format|
|EF_BADKEYVER|15|bad key version|
|**The following bit is independent of those above**|||
|EF_RUNTIME|&h020|runtime expiration, else maint|



## **History** 

- 2017 February, A Shell 6.3.1544: Updated expflags. Previously, it returned only 0 (maintenance) or 1 (runtime), plus 16 to indicate expired. 

A-Shell Reference 

Page 2862 

## **MX_GETRC** 

## **xcall MIAMEX, MX_GETRC, row, col** 

MX_GETRC (MIAMEX 94) retrieves the current position of the cursor. _row_ and _col_ (Num) will return the current cursor row and column, respectively. 

A-Shell Reference 

Page 2863 

## **MX_GETOFD** 

_Updated February 2021; see History_ 

## **xcall MIAMEX, MX_GETOFD, path, filter, title, flags {,defext, fname, type}** 

(Windows/ATE only) MX_GETOFD (MIAMEX 95) displays the standard Windows open file or save file dialog. It can only take place on a GUI-enabled client, either ATE or A-Shell/Windows. Note that the routine can be called with just two parameters; see History. 

This function has both a subroutine and a print tab implementation. 

_path_ (String, up to a maximum of 4096 bytes)  [in/out] 

On input, must contain the default filespec or the default directory, fully qualified, in AMOS or Windows notation. See Comments. 

On return, it will contain the full filespec (in Windows notation) of the selected file(s). If more than one file was selected (see OFN_ALLOWMULTISELECT in _flags_ ), the individual filespecs will be separated by chr(10) characters, and all but the first filespec will be stripped down to just the file name and extension, since they will all be in the same directory. 

## _filter_ [in] 

is a set of pairs of strings, concatenated all together using pipes ("|") for delimiters, determining which files will display in the dialog box. The first string in each pair is descriptive, and will display in the "Files of Type" area of the dialog box. The second string in each pair is a wildcard specification for that kind of file. If you have more than one wildcard spec for a particular descriptive name, then separate them with semicolons. For example: 

```
FILTER="Data files|*.DAT|Text files|*.TXT; *.LST"
```

Note that the "Files of Type" control is actually a drop-down box and that "Data files" will show as the initial choice, and "Text Files" will be the next choice in the list. If you want them all appear together, then just specify one pair of strings, such as: 

```
FILTER="Image Files (*.pcx, *.jpg, *.bmp)|*.pcx; *.jpg; *.bmp"
```

Also note: do not include any spaces on either side of the | delimiter characters lest they be confused with the pattern, causing a failure to match any files. 

A-Shell Reference 

Page 2864 

## _title_ (String)  [in] 

may be set to the desired title of the dialog box. The default is "Open". This is the main difference between the File Open and File Save versions of the dialog box. See _type_ parameter. 

## _flags_ (Num)  [in/out] 

May be set to any combination of the options shown below. 

Note that since the parameter may be updated on return from the function (see OFN_EXTENSIONDIFFERENT and OFN_NOREADONLYRETURN), you will have to use an actual variable for the _flags_ parameter if you want to be so advised. Otherwise you can just specify an expression consisting of the literal flags, e.g. OFN_PATHMUSTEXIST+OFN_FILEMUSTEXIST. 

Note also that MX_GETOFD is primarily a wrapper for the Windows API Function GetOpenFileName() which seems to support additional _flags_ with each new version of Windows. Consult the Microsoft documentation for more complete and up-to-date information on available _flags_ . 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|OFN_HIDEREADONLY|&h00000004|Hides the read-only checkbox|
|OFN_NOCHANGEDIR|&h00000008|This function is no longer supported.|
|OFN_FOLDERONLY|&h00000080|Select folder only|
|OFN_NOVALIDATE|&h00000100|Do not force filename entered to contain only valid<br>characters.|
|OFN_ALLOWMULTISELECT|&h00000200|Allow the selection of multiple files. (OFN_EXPLORER<br>flag should be set along with this.) Successive names<br>will appear, null delimited, in the returned PATH|



A-Shell Reference 

Page 2865 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||variable.|
|OFN_EXTENSIONDIFFERENT|&h00000400|Set on return if the extension entered differs from<br>_defext_|
|OFN_PATHMUSTEXIST|&h00000800|Specified directory must exist|
|OFN_FILEMUSTEXIST|&h00001000|Specified file must exist. (Implies that OFN_-<br>PATHMUSTEXIST)|
|OFN_CREATEPROMPT|&h00002000|Prompt for permission to create the file if the file does<br>not already exist|
|OFN_NOREADONLYRETURN|&h00008000|Set on return if file not read-only, directory writeable|
|OFN_NONETWORKBUTTON|&h00020000|Disables the network button|
|OFN_EXPLORER|&h00080000|Forces the dialog box to be in the new Explorer-style.<br>This is the default in most cases, except when<br>OFN_ALLOWMULTISELECT is set.|
|OFN_DONTADDTORECENT|&h02000000|Do not add file to the user’s most recently used<br>document list|



A-Shell Reference 

Page 2866 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|OFN_FORCESHOWHIDDEN|&h10000000|Force showing hidden & system files|
|OFN_FORCEPREVIEWPANEO<br>N|&h40000000|Forces Preview pane on|
|**Definition file: ashell.def**|||



## - Hex Decimal Values 

## _defext_ (String)  [in] 

may specify the default file extension. Do not include the period. If specified and the user types a filename with no extension, this will be appended to the returned _path_ and _fname_ parameters. 

## _fname_ (String)  [out] 

is an optional convenience that will return just the filename and extension, without the rest of the path, saving you from having to parse it out of the _path_ string. Note, however, that it is not guaranteed to be in the directory you initially specified. Parameter is ignored if OFN_ALLOWMULTISELECT is set. Maximum length is approximately 256. 

## _type_ (Num)  [in] 

If specified and set to 1, the main button will say "Save" rather than "Open". This and the title are the main differences between an Open dialog and a Save dialog. 

## **Comments** 

A-Shell Reference 

Page 2867 

Note that if the initial path or directory is in the form of a drive letter and colon with no trailing slash (e.g. "C:"), MX_GETOFD automatically appends "\" to avoid confusion. Such ambiguous specs are otherwise likely to be misinterpreted by A-Shell and/or Windows. 

If there is an error in the format of the parameters, such that the dialog fails to display, A-Shell will open the System Messages window and display a short message with the internal Windows error number; see descriptions in the following table. 

|**Error Num **|**Error Type**|**Description**|
|---|---|---|
|0x0001-<br>0x000C|System errors|These suggest low level problems in Windows (lack of resources, inability<br>to lock memory, etc.|
|0x3001|Subclass failure|Suggests lack of PC memory|
|0x3002|Invalid filename|File spec in path parameter is invalid|
|0x3003|Buffer too small|Selected file name is too long to fit in the provided return buffer|



## **See Also** 

- MX_BROWSEFOLDER 

- MX_GETSHELLPATH 

- Display Open/Save File Dialog 

- AG_GETOFD 

A-Shell Reference 

Page 2868 

## **History** 

- 2021 February A Shell 6.5.1699: Support SBR=GETOFD_NOCOM to revert to old implementation 

- 2021 February, A Shell 6.5.1698: add new flag OFN_FORCEPREVIEWPANEON as part of update to File Open / File Save dialog. The OFN_EXPLORER option is now essentially meaningless—i.e., it is always on. 

- 2016 March, A Shell 6.2.1425:  minimum number of parameters has been reduced from five to two, allowing you to call it with just `xcall MIAMEX, MX_GETOFD, PATH$` 

- 2013 July, A Shell 6.1.1355: filenames containing commas are now quoted; previously they were not, which almost certainly led to incorrect parsing of the response 

A-Shell Reference 

Page 2869 

## **MX_SHELLEX** 

## **xcall MIAMEX, MX_SHELLEX, status, objectspec {,action ,parms ,dir, showflags ,waitflag, clisvr,** 

## **exitstatus}** 

(Windows or ATE only) MX_SHELLEX (MIAMEX 96) provides an interface to "Shell Execute," which is one of the two fundamental mechanisms for launching a new process under Windows. The other method is known as "Execute Windows Command Line" or XS "CreateProcess" or "Win Exec," and is used by HOSTEX and AG_WINEXEC. 

Shell Execute is the method used by Windows itself when you click on a file or shortcut in Explorer, or even type a command line in the Start..Run dialog, and although it supports the ability to form command lines with parameters, it is most commonly used by specifying just an object (e.g. a file, URL, folder, etc.), and letting Windows decide which application is needed to perform the default (or specified) action on the object. Windows does this based on a table of file type associations in the Registry (which you can edit by means of the File Types dialog on the Explorer Tools...Folder Options menu). 

This function has both a subroutine and a print tab implementation. 

Note that all parameters after _objectspec_ are optional. 

## _status_ (F6) 

will return one of the following: 

|**Value **|**Meaning**||**Value **|**Meaning**|
|---|---|---|---|---|
|0|Success||8|Out of memory|
|-1|Out of system resources||11|Bad format|



A-Shell Reference 

Page 2870 

|**Value **|**Meaning**||**Value **|**Meaning**|
|---|---|---|---|---|
|-15|ATE failure to respond||27|File association incomplete|
|2|File not found||32|DLL not found|
|3|Path not found||1155|Sharing violation|
|5|Access denied||1156|DDE failure|
||||1223|User canceled, see_Comments_below|



## _objectspec_ 

is the specification (Windows format) of the file/object to open or act on, or the URL to link to. For example, you might specify a XLS file, such as "C:\Windows\Temp\My Spreadsheet.XLS", in which case the presumed action would be to launch the spreadsheet program (e.g. Excel) to open the spreadsheet. For example, you might specify a URL, such as 

"http://www.microsabio.com" in which case the presumed action would be launch the browser and link to the specified web site or HTML document. 

Embedded environment variables (using the %env% notation, e.g. %temp%\test.doc) are supported. 

You may also specify an executable, such as %systemroot%\system32\mspaint.exe. Use the _parms_ parameter for the remainder of the arguments and switches to be passed to the executable. 

A special macro, "$ASHELL" can also be used to launch another session of A-Shell using the same executable and ini file as the current session. You can combine this with additional switches in the _parms_ parameter to customize the action of the new session. 

A-Shell Reference 

Page 2871 

Note that in the ATE environment, the _objectspec_ will be evaluated by (and relative to) the ATE client, not the server. If the object originates on the server, you will have to first transfer it to the ATE client before using Shell Execute on it. 

## _action_ (String) 

may specify an action: open, edit, print, find, explore or runas. If omitted, the default action for that file association is performed. Typically the default action is "open", which just opens the document. Such actions are defined with the file association in the Explorer Tools...Folder Options...File Types dialog. 

Note that the "runas" action invokes the request for elevation dialog. For GUI commands, this is automatic, but for console commands (e.g. regsvr32), it is not, and this would be the only way to get it to prompt the user for the elevation needed. (Otherwise the operation would just fail.) Unfortunately there is no way to programmatically supply the administrator password. If you need something like that, you may want to check out a Microsoft-sponsored utility called "PsExec". 

## _parms_ (String) 

is an optional list of parameters. Typically _parms_ is used when _objectspec_ contains the name of an executable (e.g. %miame% 

\bin\ashw32.exe), in which combination of _objectspec_ and _parms_ may effectively form a complete command line. _parms_ has a maximum size of 1024 characters. 

## _dir_ (String) 

is an optional starting directory. This can generally be omitted or specified as "". 

## _showflags_ 

is an optional numeric parameter specifying the way to show the window launched by the program associated with the object and action. If omitted, the default window size will be used. Note that if you do specify the parameter, a value of zero means to make the window invisible. The values are the same as for AUI_WINDOW. Note that this is only a suggestion to the target application. There is no way to force it to follow your suggestion if it insists otherwise. 

## _waitflag_ 

A-Shell Reference 

Page 2872 

|**Value **|**Description**|
|---|---|
|0|No wait. Focus will most likely remain on launched app. Default.|
|1|Wait until launched app exits before returning.|
|2|Don't wait, but try to get the focus back.|
|4|Disables the normal 10 second time out waiting for the ShellExecute<br>operation to complete.|



Note that waiting (1) doesn't necessarily wait until the launched app exits. It only waits until the app "signals", which can mean different things for different applications. (It will wait for A-Shell). 

Option 2 will get the focus and keep getting it (if necessary) over a period of 4 seconds, in order to deal with difficult apps (like image viewers) that may take a couple of seconds to launch, after which they set the focus on themselves. 

Ten seconds is normally more than enough time to determine whether the launch was successful or not, but there are some cases, most notably under Vista when the launch requires the user to confirm "elevation", that the server was otherwise timing out while ATE was still waiting for the ShellExecute to return. In such as case, an unreliable error status was often being returned, and then when the command finally did return, the normal response code was ending up in the keyboard buffer, possibly confusing the application. Specifying the +4 flag should not have any effect on older versions of A-Shell or under nonATE situations. 

Note that wait is independent of the existing waitflag option +1, which suspends ATE until the launched application completes. +4 only waits until the program is launched, not until it is closed. 

_clisvr_ (String), 1)  [in] 

A-Shell Reference 

Page 2873 

may be set to "S" (for server), or "L" (for local, which is the same as server in this context); anything else is treated as meaning "client". The option only has significance in the ATSD environment where the possibility exists of performing the function relative to the ATSD server or the client. In all other cases, the parameter is ignored and the operation is performed relative to the client, or returns an empty string if an applicable client is not present. 

Beginning with A-Shell 1373 of January 2014, local mode ( _clisvr_ = "S" or "L") now supports the _waitflag_ options and the _exitstatus_ parameter. Previously, these only worked in the normal/default (client) mode where the operation is forwarded to ATE via the AG_SHLEXEC command. Also, both modes now support shell commands that require COM initialization. 

## _exitstatus_ (Num)[out] 

returns the status of the launched process. As with the _status_ parameter, 0 traditionally indicates success. Other values, if not listed in the table above, are likely to standard Windows error codes, for which a reference can be easily found via an internet search. However, beware that commands that have been ported from UNIX may use non-Windows error codes, in which case consult the documentation for the command in question. 

## **Comments** 

This method is generally preferred over the "Execute Windows Command Line" method (e.g. executing an explicit command line with an explicit location and name for the executable) since it eliminates three of the biggest problems normally associated with launching local applications: knowing the actual name of the executable, the command line syntax, and directory where it is located. All of these are taken care of by the association definition. 

Note that "Shell Execute" will automatically request "elevation" if necessary in order to perform the specified action, whereas "CreateProcesss" will simply fail if the user doesn't have the necessary privileges. 

Aside from a -15 return code for timeout, applications should be aware of return code 1223, which indicates that the user was given some kind of prompt to enable or accept the launch of the program (such as with UAC 'elevation'), and the user chose to cancel rather than allow the launch. 

In addition to an individual parameters length of 1024 bytes, there is an overall limit of 4096 bytes for all of the arguments combined. If the limit is exceeded, the routine will return with status 8 (out of memory). 

## **Example** 

See the discussion "Executing Windows command-prompt commands" on the A-Shell Forum. 

A-Shell Reference 

Page 2874 

## **See Also** 

- AG_SHLEXEC 

A-Shell Reference 

Page 2875 

## **MX_MKDIR** 

## **xcall MIAMEX, MX_MKDIR, dirspec, status {,remoteflag}** 

(Windows only) MX_MKDIR (MIAMEX 97) provides a native Windows equivalent to MX_MKPATH to create a directory. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

|**Paramet**<br>**er**|**Type**|**I/O **|**Description**|
|---|---|---|---|
|dirspec|String|in|the directory name to create. This should be in native file format, but (as of build<br>960) may include embedded environment variables—e.g.%miame%\newdir.|
|status|Num|out|will return 0 for success, else a Windows system error number (183 for already-<br>exists). -15 indicates ATE timeout. SeeMX_ERRNOMSG<br> for translating system<br>error codes to messages.|
|remotefla<br>g|String,1|in|may be optionally specified to clarify, in ATE environments, whether the<br>directory is to be created on the server ("L" for local or "S" for server) or on the<br>ATE client ("R" for remote or "C" for client). Specifying "L" on a Unix machine is<br>an error (returns status = -1) because this MIAMEX function only creates<br>Windows directories.|



**Comments** 

A-Shell Reference 

Page 2876 

MX_MKDIR will be invoked automatically if MX_MKPATH is requested under Windows. But your application still needs to be aware of whether it is running under Windows or Unix because the directory naming syntax is typically different. Note that to create a directory on the ATE client, you must use MX_MKDIR, since MX_MKPATH does not have the _remoteflag_ option. 

There is no harm in attempting to create a directory that already exists; in fact, this may be easier than trying to first determine whether it exists. If the directory already existed, the return value will be 183, which should probably be handled as a non-error. In general this function will not succeed if the parent directory doesn't already exist. 

## **See Also** 

- AG_MKDIR 

A-Shell Reference 

Page 2877 

## **MX_GETREG** 

_Reviwed April 2024_ 

## **xcall MIAMEX, MX_GETREG, key, subkey, name, value** 

(Windows/ATE only) MX_GETREG (MIAMEX 99) allows you to retrieve values from the system Registry. Also see MX_REGISTRY, which offers a more extensive set of registry access capabilities. 

## **Parameters** 

_key_ (Num or B,4)  [in] 

must be one of the following specified values: 

|**Symbol**|**Value**|
|---|---|
|HKEY_CLASSES_ROOT|&h80000000|
|HKEY_CURRENT_USER|&h80000001|
|HKEY_LOCAL_MACHINE|&h80000002|
|HKEY_USERS|&h80000003|
|HKEY_PERFORMANCE_DATA|&h80000004|
|HKEY_DYN_DATA|&h80000005|



A-Shell Reference 

Page 2878 

|**Symbol**|**Value**|
|---|---|
|**Definition file: ashell.def**||



## - Hex Decimal Values 

_subkey_ (String)  [in] 

is the sub key within the specified _key_ section of the Registry. This may have multiple parts, e.g. "Software\Microsoft\MediaPlayer\Player\RecentFileList". 

## _name_ (String)  [in] 

is the name of the particular value to look for within the specified _subkey_ . You may specify a blank string to get the default value. (Many _subkey_ s have only a default value.) For the _subkey_ example given above, the likely names will be "File0", "File1", etc. 

_value_ (type corresponding to registry data type)  [out] 

will return the value of the specified item. The parameter type specified must match the type of the registry item: use B,4 for REG_DWORD items, string for REG_SZ and REG_EXPAND_SZ items, unformatted for other types. Dynamic strings (S,0) are allowed, but the internal maximum size is 1024; data items larger than 1024 bytes will come back as null strings. Environment variables, found in registry items of type REG_EXPAND_SZ, will be expanded. See History for details. 

## **Comments** 

In the case of ATE (with one of the GUI-enabled "G" emulations), the request will be automatically forwarded to the ATE client, even when the server is Windows (i.e. ATSD). To query the server-side registry, use MX_REGISTRY instead. 

A-Shell Reference 

Page 2879 

## **MX_PLAYSOUND** 

## **xcall MIAMEX, MX_PLAYSOUND, fspec {status, flags}** 

(Windows only) MX_PLAYSOUND (MIAMEX 100) allows you to play a WAV (sound) file directly. You could also use MX_SHELLLEX to launch the media player to play a specified sound file, but this method avoids the complication of another application and gives you more control. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_fspec_ (String)  [in] 

must contain the file specification (AMOS or Windows syntax) of the WAV file to play (or the "event label" – see _flags_ value &h00010000 below). 

_status_ (Integer)  [out] 

returns 0 (FALSE) if it failed to play, else non-zero (TRUE) for success. 

_flags_ (Bitmap 32)  [in] 

may be used to specify zero or more flags used by the Windows PlaySound() function: 

|**Value**|**Meaning**|
|---|---|
|&h00000001|Return immediately (while sound still playing). To terminate the playback later, call<br>this function again with_fspec_="".|
|&h00000008|Play sound continuously. Must be used with flag 1 (1+8=9). To terminate the<br>sound later, call with_fspec_="".|



A-Shell Reference 

Page 2880 

|**Value**|**Meaning**|
|---|---|
|&h00000010|Do not stop a currently playing sound. (Otherwise a request to play a sound file<br>will terminate any sound file currently playing; this is why setting_fspec_to null<br>terminates the current sound file.)|
|&h00002000|Do not wait if the sound driver is busy.|
|&h00010000|FSPEC is not interpreted as a file specification but as an "event label" defined in the<br>registry. See HKEY_USERS\.Default \AppEvents\EventLabels. These are the "sound<br>events" that you can associate sound files with using the Control Panel Sound<br>applet (only the registry names may differ from the names displayed in that<br>applet). Typical examples are "SystemAsterisk" and "NmainMouseClick".|



- Hex Decimal Values 

## **See Also** 

- AG_PLAYSOUND 

A-Shell Reference 

Page 2881 

## **MX_GETSW** 

_Reorganized April 2024_ 

## **xcall MIAMEX, MX_GETSW, waitms** 

## **xcall MIAMEX, MX_SETSW, waitms** 

(Unix only) 

MX_GETSW (MIAMEX 101) retrieves the current swap wait time in milliseconds. 

MX_SETSW (MAIMEX 102) allows you to change the swap key wait time for certain terminal drivers, which is normally set by the SWAPWAIT property of miame.ini, or 1000 ms by default. Currently this only affects the Wyse50 driver, and was implemented because the standard wait is a full 1 second, which is apparently necessary on some versions of the terminal but not on terminal emulators. The main downside of the extra wait occurs within PolyShell, where it delayed the repaint of the new screen when swapping sessions. To allow this to remain as flexible as possible, the default value of zero simply causes the terminal driver to use its normal wait time (which in the case of wyse50 is 1000 milliseconds or 1 second). To minimize the wait, set it to 1. 

## **Parameters** 

For MX_GETSW, _waitms_ (Num) will be returned with the current time in milliseconds, or zero to indicate that it is still set to the default or undefined for the current terminal. 

For MX_SETSW, _waitms_ should be set to the desired wait time in milliseconds, or zero to use the default. 

A-Shell Reference 

Page 2882 

## **MX_CLFLAGS** 

_Updated October 2020_ 

## **xcall MIAMEX, MX_CLFLAGS, opcode, clflags1 {,clflags2}** 

MX_CLFLAGS (MIAMEX 103) allows you to determine which command line switches were specified when A-Shell was launched, and to effectively set the flags that are associated with these switches. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 (mxop_get) to query the current command line flags or 1 (mxop_set) to set them. 

_clflags1_ (Num)  [in/out] 

will either return the current command line flags (if _opcode_ is 0 / mxop_get) or supply the new switch settings (if _opcode_ is 1 / mxop_set). The flags and corresponding switches are listed in the following tables. Omitted values have been reserved for internal use and are of no interest to applications. Switches that make no sense to set at runtime (i.e. most of them) are marked "RO" for "read only". Note that there are two sets of flags ( _clflags1_ , _clflags2_ ) because there were too many to fit in one set. 

|**Symbol**|**Value**|**Switch**|**Meaning**|
|---|---|---|---|
|CLF_VER|&h00000001|-v|Display version on A-Shell startup. (RO)|
|CLF_EXIT|&h00000002|-e|Force A-Shell to exit when current command or<br>command file is complete.|
|CLF_DEV|&h00000008|-d|Display A-Shell console device name on startup.<br>(RO)|



A-Shell Reference 

Page 2883 

|**Symbol**|**Value**|**Switch**|**Meaning**|
|---|---|---|---|
|CLF_INI|&h00000010|-i|Specifymiame.ininame.|
|CLF_NOHANG|&h00000100|-h|Ignore hangup signal.|
|CLF_PSHELL|&h00000200|-p|Running under PolyShell. (RO)|
|CLF_HANGDELA<br>Y|&h00000400|-hd|Delay processing of hangup signal.|
|CLF_HANGPARE<br>NT|&h00000800|-hp|Send hangup signal to parent on exit.|
|CLF_QUIET|&h00001000|-q|Quiet mode. (RO)|
|CLF_SUBMIT|&h00002000|-t|Simulate slave task mode. (RO)|
|CLF_SETTINGS|&h00004000|-o|Specific windows settings file specified. (RO)|
|CLF_CHILD|&h00008000|-2|Child session. (RO)|
|CLF_NOPSH|&h00010000|-1|Disallow use of PolyShell job switching. (RO)|
|CLF_HIDE|&h00020000|-z|Hide window. (RO)|



A-Shell Reference 

Page 2884 

|**Symbol**|**Value**|**Switch**|**Meaning**|
|---|---|---|---|
|||||
|CLF_SNAPSHOT<br>S|&h00040000|-ba|Append auto-snaphots to specified buffer. (RO)|
|CLF_MAXFOCUS|&h00080000|-m|Force maximized window. (RO)|
|CLF_NOX|&h00100000|-mx|Remove "X" and system menu. (RO)|
|CLF_CGI|&h00200000|-cgi|CGI mode. (RO)|
|CLF_ATS|&h00800000|-awts|ATS (A-Shell Telnet Server) mode. (RO)|
|CLF_HEI|&h01000000|-hei|Generate error 250 immediately on hangup.|
|CLF_HETCKI|&h02000000|-hetcki|Treat tcki like kbd wait after hangup|
|CLF_LITE|&h04000000|-lite|AshLite mode. (RO)|
|CLF_MIN|&h10000000|-min|Start minimized. (RO)|
|CLF_SYSTRAY|&h20000000|-tray|Like –z but with icon in system tray. (RO)|



A-Shell Reference 

Page 2885 

|**Symbol**|**Value**|**Switch**|**Meaning**|
|---|---|---|---|
|CLF_ATE|&h40000000|-ate or<br>-atecfg|Used internally by TELNET and ATE to signify ATE<br>mode.|
|CLF_NOMENU|&h80000000|-nm|No menus (menu bar hidden).|
|**Definition file: ashell.def**||||



- Hex Decimal Values 

## _clflags2_ (Num)  [in/out] 

## (see notes for _clflags1_ ) 

|**Symbol**|**Value**|**Switch**|**Meaning**|
|---|---|---|---|
|CLF2_PREVIEW|&h00000001||preview mode (RO)|
|CLF2_NOCAPTI<br>ON|&h00000002|-nc|no main window caption (RO)|
|CLF2_NORESIZ<br>E|&h00000004|-nrs|no resizing border (RO)|
|CLF2_CGIP|&h00000008|-cgip|persistent cgi (RO)|



A-Shell Reference 

Page 2886 

|**Symbol**|**Value**|**Switch**|**Meaning**|
|---|---|---|---|
|||||
|CLF2_FASTCGI|&h00000010|-cgifast|(FastCGI) (RO)|
|CLF2_UA|&h00000020|-ua|(unattended) (RO)|
|CLF2_SILO|&h00000040|-silo|(docker container mode) (RO)|
|CLF2_NTTS|&h00000080|-ntts|Force OPTIONS=NTTS on  (RO)|
|CLF2_DPM|&h00000100|-dpm|DPI hi-res awareness mode (RO)|
|CLF2_ZATE|&h00000200|-zate|(ATE) Hide ATE main window after connect  (RO)|
|**Definition file: ashell.def**||||



- Hex Decimal Values 

## **Comments** 

Note that when setting the command line flags, you have to set them all at once. To set just one, first retrieve the current flags and then OR in the flag you want to set, and then use _opcode_ 1 to set the entire collection of flags. Note that when updating the flags ( _opcode_ 1 / mxop_Set), if the _clflags2_ parameter is not specified, those flags are left untouched. 

A-Shell Reference 

Page 2887 

Refer to the documentation on the Command Line Switches for more information about what these switches do. 

## **History** 

- 2020 March, A Shell 6.5.1677  Add -zate switch 

- 2019 September, A Shell 6.5.1666  Add -dpm switch 

- 2018 June, A Shell 6.5.1639  Add -ntts switch 

A-Shell Reference 

Page 2888 

## **MX_GETPID** 

_Reviewed April 2024_ 

## **xcall MIAMEX, MX_GETPID, pid** 

MX_GETPID (MIAMEX 104) retrieves your current process ID number. 

## **Parameters** 

_pid_ (Unsigned Int, 32 bits)  [out] 

returns your process ID. Note that while the maximum _pid_ varies from one operating system to another, to be safe you should allow for a 32 bit integer. 

## **Comments** 

A process ID (aka PID) is a positive integer which uniquely identifies a process. They are assigned by the operating system when the process is created, and recovered (for subsequent reuse) when the process terminates. PIDs are most useful in Unix, where they are the most common way to identify or communicate with another process. They are less useful but still valid in the Windows environment. 

A-Shell Reference 

Page 2889 

## **MX_CLIPBOARD** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_CLIPBOARD, opcode, text {,status {,srow, scol, erow, ecol}}** 

MX_CLIPBOARD (MIAMEX 105) allows you to retrieve or set the text contents of the clipboard. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _opcode_ (Num)  [in] 

|**Value**|**Description**|
|---|---|
|0 (MXOP_GET)|Retrieve clipboard text contents|
|1 (MXOP_SET)|Set clipboard text either from screen coordinates (if non-zero) or<br>from_text_parameter|
|2|Same as 0 but applies to ATE client|
|3|Same as 1 but applies to ATE client|
|5|Mark area specified by coordinates|



A-Shell Reference 

Page 2890 

Note that in non-ATE A-Shell/Unix environments, _opcode_ 0 (MXOP_GET) and 1 (MXOP_sET) will simulate clipboard operations by reading/writing to a file MEM0:<job>.CLP[1,1] if the file exists. If it does not exist, status will be set to -1, the same as if the Windows clipboard could not be opened. 

## _text_ (String)  [in/out] 

will receive the clipboard text contents for _opcode_ 0 and 2. For _opcode_ 1 and 3, if you want to specify a string containing the text to copy to the clipboard, then put it in the text parameter and do not specify the _srow_ , _scol_ , _erow_ , and _ecol_ parameters (or set them to 0). Otherwise, if you want to copy a rectangular area of the current screen to the clipboard, then specify the coordinates in the last four parameters, in which case _text_ will be ignored. The maximum effective size for _text_ is about 3K. 

## _status_ (Signed Int)  [out] 

|**Value**|**Description**|
|---|---|
|0|Success|
|-1|Unable to open clipboard; locked?|
|-2|Clipboard can be opened but not read, or there is no<br>text available in the clipboard|
|-3|Unable to lock memory|
|-4|Invalid coordinates|
|-99|Failure communicating with ATE client|



A-Shell Reference 

Page 2891 

_srow,scol,erow,ecol_ (Num)  [in] 

Optional coordinates used with opcodes 1, 3 to specify the screen area to be copied to the clipboard. (Set them all to 0 in order to load the clipboard from the text parameter instead of the screen.) For opcode 5, they specify the screen area to be marked. Ignored for all other opcodes. 

## **Comments** 

Other than the non-GUI A-Shell/Unix case just mentioned, you can safely used _opcodes_ 2 and 3 in place of 0 and 1 (i.e. add +2) without regard to whether the configuration involves ATE or some other Windows architecture (standalone, peer-to-peer, Terminal Server, etc.). 

In the Windows environment, MX_CLIPBOARD internally uses the AG_CLIPBOARD implementation. 

## **See Also** 

- AG_CLIPBOARD 

A-Shell Reference 

Page 2892 

## **MX_OSVER** 

_Updated September 2023; see History_ 

## **xcall MIAMEX, MX_OSVER, osname {,osver, osrel, asplatform, ate'osname, ate'osver, ate'osrel, ate'platform}** 

MX_OSVER (MIAMEX 106) retrieves information about the current host operating system or ATE, including its name, version, and release, plus the platform for which this copy of A-Shell was compiled. This can be useful in applications which wish to take advantage of features that are only available under certain platforms. 

## This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_osname_ (String, 10+)  [out] 

returns the name of the host operating system. For Windows, the possibilities are: "Win95", "Win98", "WinME", "WinNT 3.51", "WinNT 4.0", "Win2000", and "WinXP".  If the version information is not recognized, it will be reported as "Win X.Y" where X is the major version number and Y is the minor version number. For 64-bit versions, "/64" will be appended to the end. For Unix, OSNAME will return the same as the "uname -s" command, e.g. "Linux," "SCO_SV," "AIX." 

## _osver_ (String, 16+)  [out] 

returns the "version" of the operating system. For Windows, this might contain "OSR2" for Win95, "SE" for Win98, or "Service Pack 6" for NT. For Unix, it will be what "uname -v" returns, e.g. a date string for Linux, or "5.0.5" (SC0), or "4" (AIX 4.3). 

_osrel_ (String, 16+)  [out] 

returns the "release" of the operating system. For Windows, this will be the build number. For Unix, this will be what "uname -r" returns, e.g. "2.4.2-2" (Linux), "3.2" (SCO), "3" (AIX 4.3). 

## _asplatform_ (String, 16+)  [out] 

returns the generic platform that this copy of A-Shell was compiled for. This is the same string that would be returned in the SYSDOS field in GETJTB[XS] . Examples are: "AIX", "SCO Unix", "Linux", "Windows/32". 

A-Shell Reference 

Page 2893 

The parameters _ate'osname_ , _ate'osver_ , _ate'osrel_ , and _ate'platform_ are equivalent to the _osname_ , _osver_ , _osre_ l and _asplatform_ parameters, except they return the information about the ATE client, if applicable. Otherwise they return null strings. 

The sample program MIAMEX.BP in EXLIB:[908,30] illustrates these fields. 

## **Windows Names and Versions** 

The return values of the function are not as easy to to compare to a particular threshold as they might be—but then again, neither are the underlying OS versions themselves. Certain "recognized" versions of Windows will report a "friendly name" (e.g. "Win7") while unrecognized versions will just show "Win x.y" where x.y is the underlying major.minor version reported by Windows itself. Here is a table of those values: 

|**Microsoft Public Name**|**Internal**<br>**Version**|**OSname***|
|---|---|---|
|Windows 11|10.0|Win 11.0***|
|Windows 10|10.0|Win10**|
|Windows 8.1|6.3|**|
|Windows Server 2012 R2|6.3|WinSvr2012R2|
|Windows 8|6.2|Win 6.2|
|Windows Server 2012|6.2|Win 6.2|
|Windows 7|6.1|Win7|



A-Shell Reference 

Page 2894 

|**Microsoft Public Name**|**Internal**<br>**Version**|**OSname***|
|---|---|---|
|Windows Server 2008 R2|6.1|WinSvr2008R2|
|Windows Server 2008|6.0|WinSvr2008|
|Windows Vista|6.0|WinVista|
|Windows Server 2003 R2|5.2|Win 5.2|
|Windows Server 2003|5.2|Win 5.2|
|Windows XP 64-Bit Edition|5.2|Win 5.2|
|Windows XP|5.1|Win 5.1|
|Windows 2000|5.0|Win 5.0|
|Windows ME|4.90|Win 4.90|
|Windows 98|4.10|Win 4.10|
|Windows 95|4.0|Win 4.0|



A-Shell Reference 

Page 2895 

|**Microsoft Public Name**|**Internal**<br>**Version**|**OSname***|
|---|---|---|
|Windows NT|4.0|Win 4.0|
|Windows NT|3.?|Win 3.51|



- /64 is appended for 64-bit OS versions 

- **  Prior to A-Shell 6.2.1420.5, Windows 8.1 and above would report itself as Windows 8. 

*** Windows 11 may report the _osname_ as Win 10.0 or Win 11.0 depending on multiple factors. The most reliable way to tell them apart is by the _osrel_ value; greater than 22000 indicates Windows 11. 

## **See Also** 

- AG_OSVER 

## **History** 

- 2025 December,A Shell 7.0.1781:  (Linux) Refinement to MX_OSVER to use API functions rather than the uname executable to retrieve details about the OS version. 

- 2023 September, A Shell 6.5.1742:  MX_OSVER updated to report more accurate Windows information. Note however, that 

Windows 11 continues to identify itself as Windows 10, apparently due to some Microsoft rationale. You can identify it by a release or build # >= 22000. 

- 2020 July, A Shell 6.5.1687: The _osname_ parameter will now be returned with "/64" appended to the end when running a 64 bit Windows OS. 

A-Shell Reference 

Page 2896 

## **MX_USRMAP** 

## **xcall MIAMEX, MX_USRMAP, idx, name, size {,flags, ver}** 

MX_USRMAP (MIAMEX 107) is analogous to the AMOS SRCH monitor call, allowing you to locate modules in user memory. The maximum number of modules which can be loaded into user memory per job is 96. 

This function is used by the MAP.LIT utility, which would be the normal way to see what modules you have loaded. 

## **Background** 

Although an attempt has been made to provide some of the same user memory functionality as AMOS, the design here is considerably different. The most notable difference is that under AMOS, user memory is one contiguous chunk of physical memory, and the modules are stacked end to end, starting from the lowest available address. The BASIC runtime system then typically takes over the space from the top of the last loaded module to the top of the partition. Deleting a module under AMOS causes all subsequent modules to be shifted down, which might be disastrous to a program that was currently running (and counting on the prior physical location of some memory structures). 

Under A-Shell, the user memory partition (defined by the MEMORY statement in miame.ini, or by the use of MEMORY.LIT or the MX_MEMORY) is mainly used just for the BASIC runtime system’s work area. Any modules, including the RUN program itself, are loaded into dynamically allocated, non-contiguous, memory chunks. Thus the nominal partition size has no real effect on the number or size of the modules which can be loaded, and loading and deleting of individual modules has no effect on any other modules or currently running programs. A-Shell keeps track of the modules which are loaded via an index table, which is analogous to a disk directory, containing the module name, size, location, and other flags. 

## **Parameters** 

_idx_ (Num)  [in/out] 

indicates the starting position in the memory index table to search forward from (0 to start at the beginning). It will be returned with the position of the located module, (0=not found), allowing it to be used in a subsequent call to scan forward from there. 

_name_ (String)  [in/out] 

A-Shell Reference 

Page 2897 

should be set to the name and extension of the module to locate (e.g. "EMAILX.SBX"), or blank to locate the first module after the position specified by _idx_ . It will be returned with the name of the located module. 

_size_ (Num)  [out] 

will return the size of the located module, in bytes. 

_flags_ (Num)  [in]  optional 

will return flags relating to the module status, from the following table: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|USRMEM_INUS<br>E|&h000<br>1|Module currently running. Cannot be deleted under any circumstances.|
|USRMEM_LOCK<br>ED|&h000<br>2|Module is locked in memory. This prevents it from being deleted (with a<br>special switch) and can be set by specifying this flag on the load operation.|
|USRMEM_PERM|&h000<br>4|Module was manually loaded and will be left in memory until manually<br>deleted.|
|USRMEM_CACH<br>E|&h000<br>8|Module was auto-loaded and will be cached in memory for a "reasonable"<br>amount of time.|
|USRMEM_UNLO<br>CK|&h001<br>0|This is a command flag, not a module flag, but is listed here because it is<br>needed with the delete function to delete a module that has the<br>USRMEM_LOCKED flag.|
|USRMEM_NOFI|&h002|Needed in order to load a memory module directly from a variable.|



A-Shell Reference 

Page 2898 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|LE|0||
|**Definition file: ashell.def**|||



_ver_ (String, 13+)  [out]  optional 

will return the version of the module if it is a LIT, SBX, or RUN. 

## **See Also** 

- MX_SETMEMFLAGS 

A-Shell Reference 

Page 2899 

## **MX_USRLOD** 

## **xcall MIAMEX, MX_USRLOD, idx, fspec$ {,flags, var, count}** 

MX_USRLOD (MIAMEX 108) allows you to create and load a memory module from a file or a variable. Unlike under AMOS, this can be done while running a BASIC program. 

## **Parameters** 

_idx_ (Num)  [out] 

will return the index entry number where the module was loaded, or 0 if not loaded. (-1 indicates that the module was already locked into memory.) 

## _fspec$_ [in] 

must be set to the specification of the file to load into memory. (If the USRMEM_NOFILE flag is specified, then _fspec_ just sets the name of the module in memory.) 

_flags_ (Num)  [in] 

may be set to any sensible combination of the memory module flags. Normally this would only be used to set the USRMEM_LOCKED flag to lock the module in memory, or to specify the USRMEM_NOFILE flag (which is required when loading the module from a variable). See MX_USRMAP for a table of applicable flags. 

## _var_ (BLOB)  [in] 

When specified in conjunction with the USRMEM_NOFILE flag, the module is loaded directly from the specified variable. This provides a mechanism similar to COMMON[XS] , which has the advantage of not having any particular limits on the module size or name. 

## _count_ [in] 

This parameter makes it easier to load full or partial arrays into a memory module. 

When _flags_ contains USRMEM_NOFILE (meaning that the module is to be loaded from contents of the variable _var_ , with _fspec$_ indicating the desired name of the memory module), then if _var_ is actually an array element, e.g. VAR(1), then _count_ can be specified to indicate the number of elements to load starting with the specified element. For example: 

A-Shell Reference 

Page 2900 

```
MAP1 ARRAY(70),S,25
```

```
XCALL MIAMEX,MX_USRLOD,MIDX,"MYMOD.SYS",USRMEM_NOFILE,ARRAY(1),70
```

The above would load 70 elements of the array, starting with ARRAY(1) into a memory module named "MYMOD.SYS", whose index number would be returned in MIDX. 

**Warning #1** : It is impossible for the subroutine to know whether the _count_ value you specify is actually valid (i.e. not larger than the array), so the responsibility is yours. 

**Warning #2** : The type of the array must not be F6 or F4. These two types get converted to F8 by the general subroutine handler, causing the address of the array seen by the subroutine to not match that seen by the caller. 

**Note:** _count_ is the number of array elements, not the number of bytes.  In the example above, count is specified as 70, which results in 70 elements of the array, or 70 x 25 = 1750 bytes being loaded.  In contrast, to read/write more than one array element at a time in MX_USRIO, you would need to specify the number of bytes, not elements. This is a likely error when using both MX_USRLOD and MX_USRIO together. 

See the notes under MX_USRMAP for more information on A-Shell’s user memory architecture. 

## **See Also** 

- LOAD.LIT which is the typical way to load a module into memory. 

A-Shell Reference 

Page 2901 

## **MX_USRDEL** 

## **xcall MIAMEX, MX_USRDEL, idx, name {,flags}** 

MX_USRDEL (MIAMEX 109) allows you to delete a module from user memory. 

## **Parameters** 

_idx_ (Num) 

will return the index entry number of the deleted module, if successful, or 0 if not deleted. 

## _name_ 

should be set to the name and extension of the module to delete (e.g. "EMAILX.SBX"). 

_flags_ (Num) 

may be set to USRMEM_UNLOCK to allow deletion of a module that is locked in memory. 

## **See Also** 

- The notes under MX_USRMAP for more information on A-Shell’s user memory architecture. 

- DEL.LIT, which is the typical way to delete a module from memory. 

- MX_SETMEMFLAGS 

A-Shell Reference 

Page 2902 

## **MX_USRSAV** 

## **xcall MIAMEX, MX_USRSAV, status, name** 

XMX_USRSAV (MIAMEX 110) allows you to save a memory module to a disk file. 

## **Parameters** 

## _status_ (F6) 

will return the number of bytes written to disk if successful, 0 if the module was not found in memory, and a negative number to indicate an error. Currently defined error conditions are: -1 if there was a discrepancy in the number of bytes written (perhaps indicating a disk quota or limit was exceeded); -2 if the file could not be opened (perhaps indicating a privilege or write protect problem); and –3 if there was an error in processing the file specification (perhaps indicating that you are not logged into a valid directory). 

## _name_ 

should be set to the name and extension of the module to save (e.g. "EMAILX.SBX"). It will be saved to your current logged in directory. 

## **See Also** 

- The notes under MIAMEX 107 for more information on A-Shell’s user memory architecture. 

- SAVE.LIT, which is the typical way to save a memory module to disk. 

A-Shell Reference 

Page 2903 

## **MX_USRIO** 

_Updated March 2026; see History_ 

## **xcall MIAMEX, MX_USRIO, status, module, opcode, var {,offset, bytes}** 

MX_USRIO (MIAMEX 111) allows you to read and write directly to a memory module. This is a relatively advanced technique that might be useful either to maximize performance in an I/O intensive operation, or to gain the equivalent functionality of a dynamically allocated unformatted variable. (For the latter, it would be necessary to first create a dummy disk file of the desired size, then use MX_USRLOD to load it into memory.) 

## **Parameters** 

_status_ (F6)  [out] 

returns status of the operation, per the following table: 

|**Value**|**Description**|
|---|---|
|-99|Invalid_opcode_|
|-2|_var_parameter is an array with layout insufficient to transfer bytes|
|-1|_module_not found (when module parameter is a string); for numeric<br>_module_, indicates nothing loaded into that slot.|
|0|_module_number out of range (when module parameter is a number)|
|>0|For read/write operations: number of bytes transferred. For search<br>operations: offset to start of match|



A-Shell Reference 

Page 2904 

## _module_ (String or Num)  [in] 

must be set to the name or index number of the module to access. If it is a string, it is interpreted as the name and extension of the module (e.g. "EMAILX.SBX"). If it is a numeric parameter, it is interpreted as the index number of the module. (The index number can be obtained from the module name and extension using MX_USRMAP, and its subsequent use would be more efficient by eliminating the need to scan the memory module list to locate the module by name on each access.) 

_opcode_ (Num)  [in] 

indicates the operation per the following below. 

|**Value**|**Description**|
|---|---|
|0|Read bytes|
|1|Write bytes. See Notes, below.|
|2|Read records. See Notes, below.|
|3|Write records|
|4|Search for string, case insensitive|
|5|Search for string, case sensitive|



var  (BLOB or String)  [in/out] 

A-Shell Reference 

Page 2905 

For opcodes 1 and 3, must contain the data to be written. For opcodes 0 and 2, receives the data read. For opcode 4 and 5, must be set to the string to search for. Note: do not use a dynamic variable in _read_ modes. If _var_ is an array, specify the first element to be referenced, i.e. var(1).  The routine will determine the element size and extent automatically, and the transfer may extend from that element to the end of the array, depending on _bytes_ . 

## _offset_ (Num)  [in] 

specifies the starting offset from the beginning of the memory module. If _opcode_ is 0 or 1, the offset is assumed to be in bytes. If _opcode_ is 2 or 3, it is in records (of size defined by the size of the _var_ parameter, or the value of the _bytes_ parameter, if specified). Note that the first byte or record is at offset 0, not 1.. 

## _bytes_ (Num)  [in] 

indicates the number of bytes to read or write. In record mode ( _opcode_ 2 and 3) it may be omitted, in which case the size of the _var_ parameter will determine this. 

## **Comments** 

_Opcodes_ 2 and 3 are like 0 and 1 except they treat the data as if it were 512-byte-blocked, i.e. organized like disk file records when the SPAN'BLOCKS option is not used. If the record length does not divide evenly into 512, and the data was loaded either from an array or from a file using the SPAN'BLOCKS, then you will need to use _opcodes_ 0 and 1 instead, e.g. to read the Nth record using opcode 0, set offset = sizeof(var) * (N-1). Other differences with the record-oriented _opcodes_ are that the _bytes_ parameter becomes optional (defaulting to the the size of the _var_ parameter), and the _offset_ parameter unit becomes records rather than bytes. 

See the notes under MX_USRMAP for more information on A-Shell’s user memory architecture. 

## **History** 

- 2026 March, A Shell 7.0.1784:  restrict the too-verbose ashlog tracing that occurred when the specified module wasn't found. You now need to set the XCALL TRACE to get even minimal tracing of that event, and add the XDEBUG TRACE to trace all of the modules in memory. 

- 2023 July, A Shell 6.5.1734: _opcode_ 0 was failing to find the specified module by name if it was in the very first position in the module cache. It now logs a detailed trace to ashlog in the case of failure. 

A-Shell Reference 

Page 2906 

## **MX_AMOUSEXLT** 

## **xcall MIAMEX, MX_AMOUSEXLT, opcode, status, flags, s1, t1, ... s10, t10** 

MX_AMOUSEXLT (MIAMEX 112) allows you to define or otherwise control AutoMouse translations within a program. AutoMouse is an A-Shell scheme, which can be activated or deactivated from the Edit menu, which allows the user to double-click on a text "token" anywhere on the screen to transmit those characters to the keyboard. A "token" is a string of characters delimited by any non-alpha, non-numeric characters (i.e. space or punctuation). This MIAMEX function allows you to extend or control this capability by creating translation strings that are not limited to "tokens" (as just defined) and which can transmit arbitrary text (rather than the characters of the string which is double-clicked on). 

## **Parameters** 

## _opcode_ (Num) 

should be set to one of the following: 

|**Value **|**Operation**|
|---|---|
|0|Add (or create new) translation list|
|1|Clear existing translations|
|2|Temporarily disable translations|
|3|Re-enable translations|
|4|Disable intelligent doubleclick|



A-Shell Reference 

Page 2907 

|**Value **|**Operation**|
|---|---|
|5|Restore doubleclick to state it was prior to last_opcode_4 or 6.|
|6|Enable intelligent doubleclick|



## _status_ (F6) 

returns 0 on success, else an error code. Currently defined errors are –1 (cannot allocate memory for translations) and –2 (translations exceed memory limit of 2048 bytes). 

The remaining arguments are only used if _opcode_ =0. 

## _flags_ (Num) 

affect the way the translations work. Currently the only defined flag value is 1, which indicates that the translation is not case sensitive. 

_s1...s10_ 

strings representing the text which may appear on the screen, to be clicked on and translated (to the corresponding _t1...t10_ values). Note that these strings may contain spaces and other non-alphanumeric characters, which would otherwise be considered delimiters. The maximum length of each string is 132 characters. 

## _t1_ through _t10_ 

strings containing the characters to be transmitted to the keyboard when the corresponding string (in _s1_ through _s10_ ) is doubleclicked. They may also be specified as B or F variables, in which case the define the byte value of a single byte to be transmitted. (This may be more convenient than string representation when dealing with control characters, e.g. 1= CTRL+A, 27=ESCAPE, etc.). 

A-Shell Reference 

Page 2908 

You do not have to specify all 10 pairs of _sn_ and _tn_ strings, and even if you do, interpretation will stop at the first null _sn_ string. There is no particular limit to the number of translation pairs you can define (using as many calls to this function as necessary). The total combined limit on the _sn_ and _tn_ strings is 2048 characters. 

_opcode_ 4, 5 and 6 are primarily of interest for eliminating the situation in which double-clicking on an empty part of a form sends a CR, which is treated the same as clicking on the currently focused button. 

A-Shell Reference 

Page 2909 

## **MX_MEMORY** 

## **xcall MIAMEX, MX_MEMORY, newsizk, status** 

MX_MEMORY (MIAMEX 113) allows you to change the size of your user memory partition on the fly, although not within a function or procedure. 

## **Parameters** 

## _newsizk_ 

is the desired new size (in Kilobyte units, e.g. 1024 = 1024K). 

## _status_ (F6) 

|**Value **|**Meaning**|
|---|---|
|0|successful|
|-1|invalid—pathologically small—_newsizk_value.|
|-2|the program is currently executing a function or procedure; this conflicts<br>with the memory resize operation due to inter-dependencies between the<br>partition and the function call stack.|



## **See Also** 

- MEMORY.LIT, which is implemented via the MX_MEMORY function. 

- The MEMORY system parameter. 

A-Shell Reference 

Page 2910 

## **MX_IXCALL** 

## **xcall MIAMEX, MX_IXCALL, sbrnam, xcbadr, status** 

MX_IXCALL (MIAMEX 115) allows you to forward the calling parameter from one SBX subroutine to another, evaluating the new subroutine name on the fly. 

## **Parameters** 

_sbrnam_ (String)  [in] 

is the name of the new subroutine to call. 

_xcbadr_ (F6)  [in] 

is the address of the parameter structure which was passed to the original routine. 

_status_ (F6)  [out] 

will return 0 for success, >0 for subroutine not found or unable to load, else <0 for other system errors. 

## **Comments** 

MX_IXCALL is used in the RXCALL.SBX routine, which allows you to remotely call a routine running on another machine. See the documentation on SBX Subroutines about RXCALL, as well as for information on the subroutine parameter structure. 

A-Shell Reference 

Page 2911 

## **MX_INICLR** 

## **xcall MIAMEX, MX_INICLR, fspec, status** 

MX_INICLR (MIAMEX 116) allows you to process (or reprocess) the specified color initialization file. Normally, this file is called DSK0:INI.CLR[7,0] and is processed automatically when A-Shell is launched. But it may be useful to be able to edit this file and reprocess it, or switch to a different color settings file, without restarting A-Shell. 

_fspec_ must contain the file specification (AMOS or native format) of the color settings file to process. If blank, the default is DSK0:INI.CLR[7,0]. If no extension is specified, the default extension is CLR. 

Refer to Color Configuration for details on the format of the INI.CLR file. 

A-Shell Reference 

Page 2912 

## **MX_MAPI** 

## **xcall MIAMEX, MX_MAPI, status, fspec {,flags, subject, text, xdata, fspec2, fspec3, ...fspecn}** 

(Windows only) MX_MAP (MIAMEX 117) provides a simple way to send the contents of a file via interactive email. It launches the current email client program (e.g. Outlook, Eudora, etc.) and then inserts the contents of the file into the body of the message. The user has only to address the message and optionally type in introductory comments. To send email without user interaction, an A-Shell module called EMAILX is available from MicroSabio. 

Note that this call requires that the Windows "Simple MAPI" interface be installed. This will happen automatically in most cases, as it is included in Outlook Express. But it is not installed by default with the full server version of Exchange Server. In that case, you need to manually install the "simple MAPI" subsystem from your Windows media or Microsoft. 

## _status_ (F6) 

will return a status code indicating the success or failure of the operation, from the following table. Note that the negative error numbers relate to errors within the MIAMEX subroutine, while the positive errors are returned from the MAPI interface itself. 

|**Value **|**Meaning**||**Value **|**Status**|
|---|---|---|---|---|
|0|Success||11|MAPI Attachment not found|
|-1|MAPI interface not available on<br>this computer||12|MAPI Error opening attachment|
|-2|Unable to loadmapi32.dll||13|MAPI Error writing attachment|



A-Shell Reference 

Page 2913 

|**Value **|**Meaning**||**Value **|**Status**|
|---|---|---|---|---|
|-3|Unable to get address of MAPI<br>SendMail function||14|MAPI Unknown recipient|
|-4|Unable to allocate memory||15|MAPI Bad receipt type|
|-5|Unable to open_fspec_||16|MAPI No messages|
|-7|_fspec_not found||17|MAPI Invalid message|
|1|MAPI User abort||18|MAPI Text too large|
|2|MAPI General failure||19|MAPI Invalid session|
|3|MAPI Logon failure||20|MAPI Type not supported|
|4|MAPI Disk full||21|MAPI Ambiguous recipient|
|5|MAPI Insufficient memory||22|MAPI Message in use|
|6|MAPI Access denied||23|MAPI Network failure|
|8|MAPI Too many sessions||24|MAPI Invalid edit fields|



A-Shell Reference 

Page 2914 

|**Value **|**Meaning**||**Value **|**Status**|
|---|---|---|---|---|
|9|MAPI Too many files||25|MAPI Invalid recipients|
|10|MAPI Too many recipients||26|MAPI Not supported|



## _fspec_ 

is the file specification (AMOS or native format) of the file to send via email. 

## _flags_ (Num) 

may contain any combination of the following values: 

|**Value **|**Meaning**|
|---|---|
|1|Receipt requested|
|2|Send file(s) as attachments|
|4|Send using HTML fixed pitch|
|12|Very small fixed type|
|32|Send without user interface; see_Comments_below|



A-Shell Reference 

Page 2915 

_subject_ (String) 

may be set to the desired subject of the message. (Otherwise the user can type a subject in interactively.) 

## _text_ (String) 

may be set to any text which will be inserted in the message prior to the specified file. (This might be useful for introductory comments.) 

_xdata_ (String) 

May contain a single recipient address, using either of these formats: 

```
johndoe@somedomain.com
```

`John Doe` <johndoe@somedomain.com> 

Note that in the second case, the friendly name may or may not actually get picked up by the email client, but the actual email address should be recognized in either case. 

_fspec2...fspecn_ (String) 

specifies additional attachments (if you have more than one). 

## **Comments** 

If flag 32 is used to send the message without user interaction in the email client, you must include a valid recipient address in the _xaddr_ parameter. Even then, because of the security risks of letting programs "commandeer" the email client to send messages in this way, the client may reject the attempt entirely, or it may prompt the user for confirmation. These kinds of responses by the email client are outside of the control of A-Shell. 

To send mail without user interface and with more control, see A-Shell's EMAILX module. For sending email messages from an application after first creating a PDF file, see the PDFX module. 

A-Shell Reference 

Page 2916 

## **MX_FILEPOS** 

_Updated May 2023_ 

## **xcall MIAMEX, MX_FILEPOS, chan, opcode, pos {,filidx}** 

MX_FILEPOS (MIAMEX 118) allows you to get or set the current file position within a sequential file which is open for input or output. 

## **Parameters** 

_chan_ (Num)  [in] 

should be set to the channel number of the open sequential file. 

_opcode_ (Num)  [in] 

0 (mxop_get) to get the current file position or 1 (mxop_set) to set it. 

## _pos_ (Num)   [in/out] 

is the position (offset in bytes from the start of file). For _opcode_ 0 (get), the current position is returned in this parameter. For _opcode_ 1 (set), _pos_ must be set to the desired new file position. Note that to support files larger than 2 GB you must use a variable type capable of it: F6 or I6 or B6. 

_filidx_ (B,4)  [in] 

is an optional handle to a "file index" which can be created and passed back to you by XTREEXS. If _filidx_ is specified and _opcode_ = 1, then rather than setting the file pointer to the byte position specified by _pos_ , it instead interprets pos as the desired line number, and uses the index referenced by _filidx_ to locate that line number directly (without having to scan the file sequentially). 

If there is an error in the operation, _pos_ will be returned as -1. 

## **History** 

- 2023 May, A Shell 6.5.1731.0:  Support extended to files beyond the 32 bit 2GB limit. 

A-Shell Reference 

Page 2917 

## **MX_WINPTR** 

## **xcall MIAMEX, MX_WINPTR, status, printer {port, driver, orientation, length, width, formname, duplex, bin, color, resolution}** 

(Windows/ATE) MX_WINPTR (MIAMEX 120) displays a standard Windows printer selection dialog and returns information about the printer selected. This might be useful for building printer initialization files (see Defining Spoolers) based on the selected printer. Or, you can take it one step farther and just use the full Windows printer name (as returned in the _printer_ parameter) XS directly when sending files to the printer. For more information, see EZSPL and PRINT.LIT. 

This function has both a subroutine and a print tab implementation. 

Note that this operation can only take place on a GUI-enabled client, either ATE or some form of A-Shell/Windows. 

## **Parameters** 

All parameters are [out]. 

|**Paramete**<br>**r**|**Type**|**Description**|
|---|---|---|
|status|Num|0: User cancelled out of the printer selection dialog<br>-1: Feature not supported (requires ATE or A-Shell/Windows)<br>-2: Invalid ATE response (ATE must be build 960+)<br>>0: OK|
|printer|String|the descriptive printer name of the printer selected by the user. This is normally the name which<br>appears under the icon in the printer selection window.|
|port|String|port name. This could be a traditional physical port (like LPT1:), or a logical network port (like<br>NET01: or IP_192.158.200.250).|



A-Shell Reference 

Page 2918 

|**Paramete**<br>**r**|**Type**|**Description**|
|---|---|---|
|driver|String|name of the driver. In most cases with newer versions of Windows, this will be the universal<br>spooler driver "winspool" (which in turn calls the hardware-specific driver).|
|orientation|Num|1=portrait, 2=landscape|
|length|Num|paper length in tenths of millimeters|
|width|Num|paper width in tenths of millimeters|
|formname|String|name of form (e.g. "Letter", "Legal", etc.)|
|duplex|Num|1=simplex, 2=duplex (vert), 3=duplex (horz)|
|bin|Num|bin number|
|color|Num|1=monochrome (B & W), 2=color|
|quality|Num|If greater than zero, indicates the resolution in DPI. Otherwise: -1 = draft, -2 = low, -3 =<br>medium, -4 = high.|



**See Also** 

A-Shell Reference 

Page 2919 

- AG_WINPTR 

A-Shell Reference 

Page 2920 

## **MX_CHAINTO** 

## **xcall MIAMEX, MX_CHAINTO, opcode, progrm** 

MX_CHAINTO (MIAMEX 121) allows you to define a program to chain to automatically if an attempt is made to run a program for which the user does not have sufficient (read) privileges. This is useful if you wish to use the operating system file access privileges for restricting access to sensitive programs (as an alternative, for example, to password protecting them). If no chainto specification is defined, then such an attempt will cause the program to abort, displaying an "access denied" message, probably leaving the user at the dot prompt. By defining a chain-to program, when such an error occurs, the user will automatically be redirected to the specified program (which might be a menu, or perhaps an error recovery program). 

## **Parameters** 

## _opcode_ (Num) 

0 (mxop_get) to retrieve the current chain-to specification into the _progrm_ variable, or 1 (mxop_set) to set the new chain-to specification from the contents of the _progrm_ argument. 

## _progrm_ (String) 

will either return (for _opcode_ 0) or be used to set (for _opcode_ 1) the chain-to specification. It should be a RUN or LIT program in DevPPN format (no CMD or DO files allowed). Examples would be "MAIN.RUN" or "DSK0:MAIN.RUN[100,22]" or "SYS:HOST.LIT." 

## **Comments** 

If the application allows the user to move around to different PPNs, it would be wise to include the complete specification for the desired chain-to program (else it might not be found). Also note that even though the program can be found, the user may no longer be in the expected directory, so a robust program would probably want to log the user to the expected directory automatically (see LOG). 

A-Shell Reference 

Page 2921 

## **MX_SBRFLG** 

_Rewritten May 2013_ 

## **xcall MIAMEX, MX_SBRFLG, opcode, flags1 {flags2}** 

MX_SBRFLG (MIAMEX 123) is used to programmatically retrieve and/or set A-Shell system options that are normally set with the SBR= statement in miame.ini.  See the system parameter SBR for more detailed descriptions of the various flags. An example is provided after the tables. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 (MXOP_GET) to retrieve the current flags, 1 (MXOP_SET) to set them 

_flags1_ (B,4 of F)  [in/out] 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SBRF_BSMID5|&h000000<br>01|Affects sequential serach inSERCH.|
|SBRF_INFLD143|&h000000<br>02|Affects the operation of J justified types inINFLDXS.|
|SBRF_INFLDPS|&h000000<br>04|Impacts the operation of types "P" and "S" inINFLD.|
|SBRF_INFLDB3|&h000000|CausesINFLDto add blank spaces for comma-formatted fields.|



A-Shell Reference 

Page 2922 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||08||
|SBRF_INFLDLDROP|&h000000<br>10|Special handling for type "L" operation inINFLD.|
|SBRF_MXLOCK|&h000000<br>20|ForcesXLOCKto conform exactly to standard documentation.|
|SBRF_MESAGRTN|&h000000<br>40|Changes behavior of MESAG.|
|SBRF_MALLOCSORT|&h000001<br>00|Affects the memory allocation strategy ofBASORT.|
|SBRF_COMMONNDR|&h000002<br>00|Non-destructive read in COMMON.|
|SBRF_PRTCHK1|&h000004<br>00|CausesPRTCHKto return 1 if printer is found, 0 if it is not.|
|SBRF_PRINTNOFF|&h000008<br>00|Eliminates formfeed character in PRINT.|
|SBRF_XPPNOCT|&h000010|Affects how XPPN displays PPN value.|



A-Shell Reference 

Page 2923 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||00||
|SBRF_AMOSJOB1|&h000020<br>00|Causes JOBNAM to return the name of the parent job.|
|SBRF_TRIMCTL|&h000040<br>00|Causes TRIM to remove leading and trailing control characters.|
|SBRF_INFLDR|&h000080<br>00|CausesINFLDto not apply right-justification to the returned field.|
|SBRF_INFLDEDIT|&h000100<br>00|Provide support for a variation of INVUE.|
|SBRF_AXLOCK|&h000200<br>00|Causes A-Shell to exactly duplicate the behavior ofXLOCKunder<br>AMOS.|
|SBRF_LSTLINSTRIP|&h000400<br>00|Strips comments from command line before returning them to<br>LSTLIN.|
|SBRF_PGRW_TTI|&h000800<br>00|Affects howINFLDtype codes<br>**$**and<br>**H**are handled.|
|SBRF_BOX_MINATTR|&h001000|Minimizes the use of attributes (particularly reverse video) used with|



A-Shell Reference 

Page 2924 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||00|certain box drawing operations (particularlyINMEMO).|
|SBRF_INFLD_V1|&h004000<br>00|Eliminates the need to specify the V parameter toINFLD.|
|SBRF_EZPRTX|&h008000<br>00|CausesEZTYPto use EZPRTX.|
|SBRF_FLOCKD|&h010000<br>00|Disables validation of the file channel and record number parameters<br>inFLOCKXS.|
|SBRF_FLOCKL|&h020000<br>00|Backs up FLOCK exclusive record locks with LOKSER locks (provided<br>that LOKSER is enabled). May be useful when different applications<br>(one using FLOCK, the other LOKSER) share files.|
|SBRF_INFLD_KEEPAL<br>IVE|&h040000<br>00|Sends a few bytes every 15 seconds while waiting for input.|
|SBRF_PCKLST_GUI|&h080000<br>00|UseXTREE(GUI) in place ofPCKLST(text)|
|SBRF_INFLDCBRJ|&h100000<br>00|Right-justifies text label.|
|SBRF_SUBMIT2|&h200000|Forces a new process to be the grandchild of the current process.|



A-Shell Reference 

Page 2925 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||00||
|SBRF_NO_MMAP|&h400000<br>00|Disables memory mapping in certain ERS proprietary subroutines.|
|SBRF_XMASCB_OPE<br>N|&h800000<br>00|Optimize file open/close in XCALL xMASCB (ignores redundant open,<br>explicit close; auto-close at program end).|
|**Definition file: ashell.def**|||



## - Hex Decimal Values 

## _flags2_ (B,4 of F)  [in/out] 

Note that for opcode 1, if flags2 not specified, no changes will be made to those flags; in other words, the absence of the _flags2_ parameter is not equivalent to a parameter containing zero. 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SBRF2_GUISELPOS|&h00000001|INFLDGUI caret at start|
|SBRF2_AUTO_TABX|&h00000002|auto add MBF2_TABX to MBF_TAB|



A-Shell Reference 

Page 2926 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SBRF2_PRINT_TIME|&h00000004|add time toPRINTXS hdr|
|SBRF2_PRINT_JOBUSN|&h00000008|add user toPRINTXShdr|
|SBRF2_AUTO_DLGMAX|&h00000010|auto max dlgs > desktop|
|SBRF2_INFLD_PRINTS|&h00000020|INFLD^P : File>Printscreen|
|SBRF2_XTREE_EXPCSV|&h00000040|XTREEadd Export CSV to mnu|
|SBRF2_XTREE_EXPTSV|&h00000080|XTREEadd Export TSV to mnu|
|SBRF2_XTREE_EXPOPEN|&h00000100|XTREEopen after export|
|SBRF2_XTREE_PRINT|&h00000200|XTREEadd print to mnu|
|SBRF2_XTREE_SRCH|&h00000400|XTREEadd search to mnu|
|SBRF2_EFS_CLR_ON_EXI<br>T|&h00000800|Clear EFS key on exit|
|SBRF2_XTREE_EXPCSV2|&h00001000|XTREE add|



A-Shell Reference 

Page 2927 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||||
|SBRF2_XTREE_EXPCSV2X<br>L|&h00002000|XTREE add|
|SBRF2_INFLD_NOPRINTS|&h00004000|Disable INFLD ^P print screen function|
|**Definition file: ashell.def**|||



## **Example** 

To retrieve the current SBR= flags and then set or clear the SUBMIT2 flag: 

```
map1 sbrflags1,b,4
```

```
map1 sbrflags2,b,4
```

```
    xcall MIAMEX, MX_SBRFLG, MXOP_GET, sbrflags1, sbrflags2   ! retrieve
```

```
    sbrflags1 = sbrflags1 or SBRF_SUBMIT2                     ! set SUBMIT2
```

```
or
```

```
    sbrflags1 = sbrflags1 and not SBRF_SUBMIT2                ! clear SUBMIT2
    xcall MIAMEX, MX_SBRFLG, MXOP_SET, sbrflags1, sbrflags2   ! set
```

A-Shell Reference 

Page 2928 

## **Comments** 

MX_SBRFLG normally only operates relative to the server. In the ATE environment, use the AG_SBRFLAGS command to retrieve/set the client flags. 

## **See Also** 

- AG_SBRFLGS 

A-Shell Reference 

Page 2929 

## **MX_ASHLOG** 

## **xcall MIAMEX, MX_ASHLOG, string** 

MX_ASHLOG (MIAMEX 124) outputs the _string_ message to the ashlog.log file. It is useful when you want to log your own messages in the same stream that A-Shell uses for its system messages. 

A-Shell Reference 

Page 2930 

## **MX_MCRS** 

_Rewritten November 2025_ 

## **xcall MIAMEX, MX_MCRS, clickinfo, row, col** 

MX_MCRS (MIAMEX 125) retrieves information about the last mouse click within an INFLD call when mouse cursor reporting has been activated via TCRT 158. Such a mouse click will cause INFLD to return exitcode -47, after which you can use MX_MCRS to retrieve the click type and location. 

## **Parameters** 

## _clickinfo_ (Num)  [out] 

returns a bitmap consisting of one or more of the following: 

|**Value**|**Description**|
|---|---|
|&h01|Left button|
|&h02|Right button|
|&h08|Double click (else single click)|



_row_ (Num)  [out] 

returns the row number where the mouse was clicked 

## _col_ (Num) [out] 

returns the column number where the mouse was clicked 

Note that MX_MCRS only works in conjunction with INFLD (or routines that wrap it, such as SBXINP). 

A-Shell Reference 

Page 2931 

## **Example** 

- `! (assuming mouse cursor reporting previously enabled)` 

```
xcall INFLD, row, col, xmax, xmin, type, entry, inxctl, parentid, opcode, exitcode
```

```
if exitcode = -47 then                         ! mouse cursor reporting exit
```

```
    xcall MIAMEX, MX_MCRS, clickinfo, row, col ! retrieve click details
```

```
    if clickinfo and &h08 then
```

- `? "Double";` 

```
    endif
```

- `? "click at "; row; ","; col` 

## **See Also:** 

- Mouse Cursor Reporting 

A-Shell Reference 

Page 2932 

## **MX_SINK** 

## **xcall MIAMEX, MX_SINK, opcode, srow, scol, erow, ecol, bgc** 

MX_SINK (MIAMEX 126) creates or removes a sunken effect for the specified rectangular area by drawing or removing a border with shading to give it a beveled effect.  This is the same routine used by INFLD (when in text mode) to give the field being edited the appearance of being slightly sunken. You can also get this effect by using the MBF_SUNKEN flag with AUI_CONTROL to create a static text control with that style, but in that case, you cannot freely write on top of the control. With MX_SINK, the effect does not conflict with character-level I/O to that screen area, which is why it works with INFLD in text mode only. 

Note, however, that the effect depends on the beveling feature being enabled; see links below for details. 

## **Parameters** 

## _opcode_ (Num)  [in] 

|**Value**|**Operation**|**Description**|
|---|---|---|
|0|Unsink|Remove the border which gave it the sunken appearance|
|1|Sink|Apply a 3D border to give the rectangle the appearance of being sunken.<br>See example below.|



## _srow,scol,erow,ecol_ (Num)  [in] 

coordinates (integer rows and columns only, no millirows or millicolumns) of the rectangular box to be sunk or unsunk. 

## _bgc_ (Num)  [in] 

The palette index number for the desired background color.  -1 indicates the current background color for that area.  0-7 are normal intensity background colors; 8-15 are reduced intensity. (See menu Settings > Colors for the colors currently associated 

A-Shell Reference 

Page 2933 

with those palette numbers.) Note that in almost all cases, the best choice is to set bgc to match the background of the screen area in question; typically -1 will accomplish that, unless the screen has multiple background colors. 

## **Examples** 

This first image shows the sunken effect in INFLD. Note that the effect is disabled by GUI mode, type **|G** as well as by types **i** , **| _** and **|p** . 

This next example is from the test program MIAMEX in EXLIB:[908,30] which illustrates sinking and unsinking a text area. 

## **See Also** 

- Beveling menu settings 

- Beveling GUI extension 

- MX_BEVEL 

- AG_BEVEL 

## **History** 

- 2023 December, A Shell 1752.2:  Coordinate mismatch corrected. 

A-Shell Reference 

Page 2934 

## **MX_ROUND** 

_Updated June 2020_ 

## **xcall MIAMEX, MX_ROUND, opcode, factor** 

MX_ROUND (MIAMEX 127) allows you to get or set the new variable rounding factor. Note that the setting persists across programs. For an in-depth discussion of the floating point rounding issue, see Rounding of Floating Point Variables. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 (mxop_get) to retrieve the rounding factor, 1 (mxop_set) to set it 

_factor_ (B,4 or F4, F6, and F8)  [in/out] 

sets the level of precision you would like. 1 means round all variables to the nearest integer, .01 would be to the nearest hundredth. A setting of zero disables the feature, which effectively results in rounding to 48 bit precision, i.e. about 11 significant digits, in order to maintain backwards compatibility with original F6 implementation. Values greater than one are disallowed. -1 (see History below) disables the 48 bit rounding, i.e. preserves the full 64 bit IEEE precision. In order to be effective, this also requires disabling the FPROUND option, e.g. SET NOFPROUND, and adding `SIGNIFICANCE 16` to the program. 

## **History** 

- 2020 June, A Shell 6.5.1684:  Several refinements and improvements: 

- F4, F6, and F8 format now accepted for _factor_ . Previously only F6 was recognized. 

- Values for _factor_ greater than one are now rejected, since they would otherwise interfere with certain floating point 

- operations which assume at least integer precision, such as FOR/NEXT loops. Previously it was possible to accidentally set the MX_ROUND value to something crazy and produce seemingly inexplicable downstream errors. 

- An attempt to set the MX_ROUND factor will be rejected if SCALE is in effect. The interaction between SCALE and MX_ROUND 

- would be too complicated for anyone to make sense of; use one or the other, or neither. 

- The SCALE statement now overrides and resets any prior MX_ROUND factor. 

A-Shell Reference 

Page 2935 

- All of the above will result in warnings in the ashlog.log file. 

A-Shell Reference 

Page 2936 

## **MX_GETIP** 

## **xcall MIAMEX, MX_GETIP, ip$** 

MX_GETIP (MIAMEX 128) returns the IP address of client workstation. 

## **Parameters** 

_ip$_ (String)  [out] 

Default IP address returned here, for example "192.168.200.133." 

## **See Also** 

- GETMAC 

- CONDEV 

A-Shell Reference 

Page 2937 

## **MX_ASHFILE** 

_Updated August 2024; see History_ 

## **xcall MIAMEX, MX_ASHFILE, startcmd {,ashfile, ashexe, ashexedir}** 

MX_ASHFILE (MIAMEX 130) returns various parts of the command line with which the current session of A-Shell was launched. 

## **Parameters** 

## _startcmd_ (String)  [out] 

Returns the initial A-Shell command line, i.e. the part of the overall command line by which A-Shell was launched, that was left to process when it first gets to the dot prompt. If A-Shell was launched without specifying a startup command, the default is "astart." 

## _ashfile_ (String)  [out] 

For Windows, returns the name of the settings (.ash) file that was specified on the ashw32 command line (-o parameter). For Unix, returns a null string. 

## _ashexe_ (String)  [out] 

Returns the ashell executable name, as specified in the command line. This may, or may not be fully qualified, depending on what was specified in the launch command line. Under Unix, likely possibilities are "ashell" or "/vm/miame/ashell." Under Windows, a likely possibility is c:\vm\miame\bin\ashw32.exe. 

## _ashexedir_ (String)  [out] 

Facilitate retrieving the A-Shell executable directory. In Windows, the _ashexe_ parameter will usually contain the full A-Shell executable filespec from which you could extract the directory. But in the Linux environment, the _ashexe_ parameter will contain only the first token on the command line, typically just 'ashell' or possibly a partial relative path, leaving the _ashexedir_ parameter as the only reliable way to determine where the executable was launched from. 

## **Examples** 

A-Shell Reference 

Page 2938 

Original command line (Unix): `./ashell -i /vm/miame/miame.ini main.cmd` 

```
startcmd:  "main.cmd"
ashfile: ""
ashexe: "./ashell"
```

Original command line (Windows): `c:\vm\miame\bin\ashw32.exe  -i c:\vm\miame\miame.ini -o c:\vm\miame\custom.ash main.cmd startcmd:  "main.cmd" ashfile: "c:\vm\miame\custom.ash" ashexe: "c:\vm\miame\bin\ashw32.exe"` 

## **History** 

- August 2024, A Shell 7.0.1762:  Add new parameter _ashexedir._ 

A-Shell Reference 

Page 2939 

## **MX_FILESTATS** 

_Updated August 2023; see History_ 

## **xcall MIAMEX, MX_FILESTATS, loc'rem, path, bytes {, mtime, ctime, mode, ver, hash, owner, group, atime}** 

MX_FILESTATS (MIAMEX 131) returns stats for the specified _path_ , either on the local system or the remote PC via ATE. 

This function has both a subroutine and a print tab implementation. 

## _loc'rem_ (String, 1)  [in] 

"L" for local system, "R" for remote PC, "C" for client/cache. See _Comments_ , below, for more info on "C." 

## _path_ (String)  [in] 

specifies a native path or AMOS-style filespec. If native, may include embedded environment variables using the %env% syntax. Note that if _loc'rem_ is "R," and AMOS specification in _path_ will be interpreted relative to the ini file used by ATE on the PC. 

_bytes_ (signed Num)  [out] 

returns the size of the file. If _path_ is not found _bytes_ will be set to -1. -2 indicates that you are attempting to use a remote PATH when you do not have ATE support. 

## _mtime, ctime_ (F or B,6)  [out] 

return the last modification time ( _mtime_ ) or creation time ( _ctime_ ), in seconds since "the epoch" (Midnight Jan 1, 1970). Note that "time" includes date, in this context. This format is very convenient for comparing file times, but be forewarned that comparing file times on different machines (e.g. to decide if a file transfer/update is needed) requires that you synchronize the clocks on the machines in question! If you want to display the file times in a more human-friendly format, use MX_FTFORMAT. See fndatetime.bsi in SOSLIB:[907,10] for some useful and related date/time functions. See History note, below, for A-Shell 6.5.1740. 

_mode_ (F or B2+)  [out] 

A-Shell Reference 

Page 2940 

returns the mode bits indicating the type and other attributes of the file. The most interesting bits are: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|FSTS_PRVPX|&h0001|execute privilege (other)|
|FSTS_PRVPW|&h0002|write privilege (other)|
|FSTS_PRVPR|&h0004|read privilege (other)|
|FSTS_PRVGX|&h0008|execute (group)|
|FSTS_PRVGW|&h0010|write (group)|
|FSTS_PRVGR|&h0020|read (group)|
|FSTS_PRVOX|&h0040|execute (owner)|
|FSTS_PRVOW|&h0080|write (owner)|
|FSTS_PRVOR|&h0100|read (owner)|
|FSTS_SSWT|&h0200|save swapped text after use (sticky)|
|FSTS_SGID|&h0400|set group id on execution|



A-Shell Reference 

Page 2941 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|FSTS_SUID|&h0800|set user id on execution|
|FSTS_PIPE|&h1000|pipe|
|FSTS_SPC|&h2000|chr/special|
|FSTS_DIR|&h4000|directory|
|FSTS_NORM|&h8000|regular file|
|**Definition file: ashell.def**|||



- Hex Decimal Values 

## _ver_ (String)  [out] 

returns the file version information (for RUN, LIT and SBX files only), in the format "a.b.c{.d{.e})" where a=vmajor, b=vminor, c=vsub, d=vedit, e=vpatch. Note that because this format may not be convenient for easily comparing two versions to see which is later, optionally you can retrieve the string in the format "aaaaa.bbbbb.ccccc.ddddd.eeeee" by passing a string mapped as 30 bytes for the ver parameter. 

Files that do not have versions will return empty version strings (rather than either of the formats described above). 

The function does not support retrieving version strings from EXE and DLL files. 

_hash_ (String, 15+)  [out] 

A-Shell Reference 

Page 2942 

returns the file hash code in the format ###-###-###-### 

## _owner, group_ [out] 

may be returned as either integers or strings. If passed as B,4 variables, the numeric value (uid and gid) will be returned. Otherwise, the string names will be returned. Note that their owner and group info applies only to Unix versions of A-Shell, but may be supported under some Windows versions in the future. 

_atime_ (Num)  [out] 

last access time 

## **Comments** 

When MX_FILESTATS is used to query the status of a file on the PC (via ATE), if the filespec is a UNC spec (i.e. starts with "\\"), then the timeout wait is extended from 5 to 15 seconds. This eliminates most problems with ATE timing out before Windows times out, if the UNC spec is not available. The shorter timeout wait was leading to ATE becoming unsynchronized with the server, which in some cases was leading to application confusion. 

The _loc'rem_ parameter value "C", for client/cache, checks for the file on the local client computer, including looking in the cache and other default local directories. In the case of ATE, this is similar to the "R" (remote) option except that if the file is not found in the specified directory, a search will be made of the other directories that ATE normally checks when trying to open files at the behest of the server (%ATECACHE%, %ATEPERMCACHE%, %miame%\icon, and possibly others). In the case of local A-Shell/Windows, this is like the "L" (local) option, except that it also checks the above-mentioned directories. (The cache directory environment variables will typically not be defined for A-Shell/Windows, and thus will be ignored, but the %miame% \icons subdirectory and perhaps others may still be valid and searched.) See Get File Stats if you want to retrieve the actual filespec of the found file. 

## **See Also** 

- MX_HASHFILE 

- AG_FILESTATS 

A-Shell Reference 

Page 2943 

## **History** 

- 2026 April, A Shell 7.0.1785:  Logging refinement: MX_FILESTATS and MX_FINDFIRST no longer output messages to ashlog for file-not-found errors. Any other errors will continue to be logged. Setting the FOPENS TRACE flag will restore the logging of filenot-found errors. 

- 2023 August, A Shell 6.5.1740:  Add support for additional timestamp bits (beyond 32) to resolve the Year 2038 problem. Note that you have to specify a parameter type capable of supporting more than 32 bits, e.g. B6 or F6. 

- 2023 August, A Shell 6.5.1740:  Add support for _atime_ , last access time 

A-Shell Reference 

Page 2944 

## **MX_FTFORMAT** 

## **xcall MIAMEX, MX_FTFORMAT, ftime, strtime {,sdate, stime}** 

MX_FTFORMAT (MIAMEX 132) is used to format a numeric filetime of the type returned by MX_FILESTATS into a more friendly format. 

_ftime_ (Num)  [in] 

File time in the format returned by MX_FILESTATS (seconds since 1970) 

_strtime_ (String, 24+)  [out] 

Formatted time, e.g. "Sun Jul 31 16:02:41 2011" 

_sdate_ (B,4)  [in/out] 

If specified, returns the date corresponding to _ftime._ Can be passed to ODTIM for formatting. 

_stime_ (Num)  [in/out] 

If specified, returns the number of seconds since midnight. Can be passed to ODTIM for formatting. 

## **History** 

- 2023 August, A Shell 6.5.1740:  Add support for additional timestamp bits (beyond 32) to resolve the Year 2038 problem. Note that you have to specify a parameter type capable of supporting more than 32 bits, e.g. B6 or F6. 

A-Shell Reference 

Page 2945 

## **MX_EXPFIL** 

_Updated July 2017_ 

## **xcall MIAMEX, MX_EXPFIL, ch, addrecs, status** 

MX_EXPFIL (MIAMEX 133) expands or contracts random access (aka "contiguous") files in place by adding or removing blocks to/from the end of the file. 

## **Parameters** 

## _ch_ (Num)  [in] 

is the channel number that the file is open (for random exclusive access). If running LOKSER, you should probably open the file for RANDOM (exclusive) before expanding it. If not running LOKSER, you are free to use some other locking scheme. Although the subroutine will not stop you from expanding a file without first gaining exclusive access, you are likely to run into synchronization conflicts with other users who have the file open. For one thing, those users will not be able to access the expanded area (until they close and reopen the file), so if you update a control record they may try to access the new area and get an illegal record number. 

## _addrecs_ (Num)  [in] 

is the number of logical records to add (addrecs > 0) to or subtract (addrecs < 0) from the file, based on the record size passed in the file open statement. It will be converted to the appropriate number of 512 byte blocks to add or subtract. Added blocks will be filled with ]]] characters. 

_status_ (Signed Num)  [out] 

returns the new total number of logical records in the file if the operation is successful. 0 indicates a parameter or other configuration error trapped by the subroutine and is generally accompanied by a displayed message. <0 indicates an operating system error number, which you can retrieve the message for using `MIAMEX,86,STATUS,MSG` . 

## **Comments** 

A-Shell Reference 

Page 2946 

Under AMOS, random access files are truly contiguous, so expanding one required allocating an entirely new (larger) file and copying the contents of the original file to it. Under Windows and Unix, the disk blocks of random access files are not necessarily contiguous, thus making the kind of incremental expansion used by MX_EXPFIL possible. 

Note that it is up to you to update any control records or other internal structures to correspond to the new file size. Remember to release your exclusive access after doing so. 

## **See Also** 

- GOP2_AUTOX_RAN option bit 

A-Shell Reference 

Page 2947 

## **MX_SYNC** 

_Documentation added May 2016_ 

## **xcall MIAMEX, MX_SYNC {,ch, sts, flags}** 

(Unix only) MX_SYNC (MIAMEX 134) invokes one of the operating system "sync" commands to force some or all of the file system cached updates to be flushed to disk. Normally this operation is managed by the operating system in background, but there are times when you may want to be sure that file updates have been written to permanent disk prior to proceeding with then next application step. 

## **Parameters** 

## _ch_ (Num)  [in] 

If specified and non-zero, just updates for the file currently open via that channel are flushed. Internally the operation uses the standard Unix library call fsync() or syncfs() or msync(), depending on the platform and whether the file has been memory mapped. Otherwise, if ch = 0 or not specified, all cached data and metadata updates are flushed using the sync() call. 

_sts_ (Signed Num)  [out] 

If specified, a status value will be returned here... 

|**Group **|**Description**|
|---|---|
|0|success|
|-2|ch not open|
|-3|file type unknown or not applicable (e.g. input only)|
|-4|operation not supported on this platform (e.g. Windows)|



A-Shell Reference 

Page 2948 

|**Group **|**Description**|
|---|---|
|||
|>0|operating system errno value (seeMX_ERRNOMSG)|



## _flags_ (Num)  [in] 

If specified and set to 1, and ch > 0, and the platform supports GNU libraries, then syncfs() is used instead of fsync(). (syncfs flushes all of the data and metadata in the disk partition containing the specified file, whereas fsync only flushes the data and metadata for the specified file.) 

## **Notes** 

**Warning:** Aside from being a relatively costly operation (in terms of performance), it is impossible to be certain that the data is actually written to permanent storage by the time the call returns. This is because even though the operating system may execute a synchronous write operation, there is no way to be sure that the disk driver (RAID, SAN, network, whatever) actually writes the data to the permanent media before returning. (It might have its own cache buffering system.) 

## **History** 

- 2016 January, A Shell 6.3.1502:  Time elapsed in the sync() or fsync() call is now logged in microseconds if the XDEBUG trace flag set. This was motivated by suspicions that the sync() call is taking longer under CentOS/RHEL 6 and 7 than under CentOS/RHEL 5. Such suspicions can now be easily quantified. Also, fsyncing now supported for ISAM-A files—e.g. `xcall` . `miamex, mx_sync, ch {,sts}` 

A-Shell Reference 

Page 2949 

## **MX_REGISTRY** 

## **xcall MIAMEX, MX_REGISTRY, opcode, <params depending on opcode>** 

(Windows only) MX_REGISTRY (MIAMEX 138) provides a range of Registry operations. The symbols and values for _opcode_ are shown in the following table. Parameters, which are dependent on the function being called, are listed and discussed in the topics covering the various functions.  See also MX_GETREG (simplified retrieve with ATE support). 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|REGOP_OPEN|1|Open|
|REGOP_CREATE|2|Create|
|REGOP_SET|3|Set|
|REGOP_READ|4|Read|
|REGOP_ENUMKEYS|5|Enumerate keys|
|REGOP_ENUMVALS|6|Enumerate values|
|REGOP_CLOSE|7|Close|
|REGOP_DELKEY|8|Delete Key|



A-Shell Reference 

Page 2950 

|**Symbol**|**Value**|**Function**|
|---|---|---|
|REGOP_DELVALUE|9|Delete Value|
|REGOP_DELIMS|64|Replace Null Delimiters|
|**Definition file: ashell.def**|||



## **Comments** 

MX_REGISTRY does not recognize ATE. If executed in a non-Windows environment (whether ATE or not), it will be essentially a null operation. If executed in the ATSD environment, it will return information from the server registry, not the client. If you want to retrieve registry information from the ATE client, either use MX_GETREG for simple retrieval, or package your MX_REGISTRY operations in an SBX which can be executed on the client side via AG_XFUNCS or MX_AGWRAPPER. 

Although direct access to the Registry is not available for applications running A-Shell/Unix, Steve Evans of Caliq has developed a pair of routines which allow information to be saved using a similar model but which work on all platforms. See the routines INIX in SOSLIB:[907,26] and SYSREG in SOSLIB:[907,26] for details. 

A-Shell Reference 

Page 2951 

## **OPEN** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_OPEN, hkey, subkey, rights, hkeynew, status** 

This call is needed to open up a branch of the Registry and returns a handle which can be used in subsequent opcodes. 

## **Parameters** 

_hkey_ (B,4)  [in] 

can be a key returned in the _hkeynew_ parameter from a previous open, or more likely, one of the following symbols (from ashell.def) for the main hives in the Registry: 

**Symbol** HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE HKEY_USERS 

## _subkey_ [in] 

is a string combining one or more levels beneath the level referenced by the key _hkey_ , for example: 

```
SUBKEY = "SOFTWARE\MicroSabio\JBCT\ATE"
```

A-Shell Reference 

Page 2952 

Note that _subkey_ is not case sensitive on lookup, but when creating keys, the case specified will be retained. (Same idea as with Windows filenames.) 

## _rights_ [in] 

is a numeric variable combining one or more of the following bits relating to the kind of rights you want to request for this key: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|RGKEY_QUERY_VALUE|&h00000001|Ability to query a value|
|RGKEY_SET_VALUE|&h00000002|Ability to change or set a value|
|RGKEY_CREATE_SUB_KEY|&h00000004|Ability to create a new sub key|
|RGKEY_ENUM_SUB_KEYS|&h00000008|Ability to enumerate sub keys|
|RGKEY_WOW64_32KEY|&h00000200|access key from 32 bit registry view|
|RGKEY_WOW64_64KEY|&h00000100|access key from 64 bit registry view|
|RGKEY_DELETE|&h00010000|ability to delete key|
|**Definition file: ashell.def**|||



- Hex Decimal Values 

A-Shell Reference 

Page 2953 

## _hkeynew_ (B,4)  [out] 

will return the handle to the opened key, and will be needed for subsequent operations. Note that in a non-Windows environment, since the operation will do nothing, it will not update the hkeynew parameter. You should therefore set it to zero initially, so that you can check to make sure that it comes back with a non-zero value. 

_status_ (F6)  [out] 

returns 0 for success, or else an error code. You can convert the error code to a message using: `xcall MIAMEX, MX_ERRNOMSG, status, msg` . Note that status may not be set in the case of the non-Windows environment; see _hkeynew_ comments for error checking advice. 

A-Shell Reference 

Page 2954 

## **CREATE** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_CREATE, hkey, subkey, rights, hkeynew, status** 

This is used to when saving values to the Registry. It will create the specified subkey if it does not exist, or if the subkey already exists, it will open it. 

The parameters are nearly the same as for REGOP_OPEN. The main difference is that the _status_ parameter can return either of the following: 

```
STATUS=1 (Key was created)
```

```
STATUS=2 (Key already existed and was opened)
```

A-Shell Reference 

Page 2955 

## **SET** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_SET, hkey, name, type, value, status** 

This is used to write a new or updated value to the Registry. 

## **Parameters** 

_hkey_ (B,4)  [in] 

must be set to the _hkeynew_ value returned from a previous call to Create or Open a key. 

_name_ (String)  [in] 

is the name of the value to write. (These are the items that appear in the left side of the right hand pane of regedit.exe.) 

_type_ (Num)  [in] 

specifies the type of value you want to write: 

|**Symbol**|**Valu**<br>**e**|**Description**|
|---|---|---|
|REG_NONE|0|No type|
|REG_SZ|1|Null terminated string|
|REG_EXPAND_<br>SZ|2|Same as (1) but signals that string may contain embedded environment<br>variables (e.g.%temp%\xyx.log)|
|REG_BINARY|3|Raw binary data (use X format)|



A-Shell Reference 

Page 2956 

|**Symbol**|**Valu**<br>**e**|**Description**|
|---|---|---|
|REG_DWORD|4|4 byte integer (use B,4 format)|
|REG_MULTI'SZ|7|List of null terminated strings, with a double null terminating the list. See<br>Replace Null Delimiters<br>for an alternative to using null delimiters (with are hard<br>to work with in BASIC).|
|**Definition file: ashell.def**|||



_value_ (String or B,4 depending on _type_ )  [in] 

The data to write to the named item. 

_status_ (F6)  [out] 

0 for success, else error code. 

A-Shell Reference 

Page 2957 

## **READ** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_READ, hkey, name, type, value, status** 

Read is used to read a single value from the Registry. 

## **Parameters** 

_hkey, name_ 

must be set as in opcode 3 (Set) 

_type_ (Num)  [out] 

is ignored on input, and is updated by the call to indicate the data type of the value returned (see table of data types under Set). 

_value_ (String, Raw, or B,4 depending on the type of the data)  [out] 

returns the data. Note that the application is expected to either know the type of data, in which case it can supply an appropriate form of _value_ , or it can use the overlay technique and then extract the data based on the returned _type_ field. Also note that for string data, _value_ must be large enough to include the trailing null. For example, you might map _value_ as: 

```
MAP1 VALUEX,X,512
```

```
MAP1 VALUE$,S,,512,@VALUEX
```

```
MAP1 VALUE,B,4,@VALUEX
```

_status_ (F6)  [out] 

0 for success, else error code. 

A-Shell Reference 

Page 2958 

## **ENUMERATE KEYS** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_ENUMKEYS, hkey, subkey, index, status** 

This is used to list the subkeys of the opened key. 

## **Parameters** 

_hkey_ [in] 

must be set as in opcode 3 (Set) 

_subkey_ (String)  [out] 

will return the subkey name. 

## _index_ (Num)  [in] 

should be set to 0 for the first subkey, and incremented for each subsequent subkey. There is no particular order to the subkeys, so do not put any special significance on _index_ . 

_status_ (F,6)  [out] 

0 for success, else error code. Error 259 indicates that there are no more keys to enumerate. 

A-Shell Reference 

Page 2959 

## **ENUMERATE VALUES** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_ENUMVALS, hkey, name, index, type, value, status** 

This is used to list the named values for the opened key. 

## **Parameters** 

_hkey_ [in] 

must be set as in opcode 3 (Set) 

_index_ (Num)  [in] 

should be set to 0 for the first _value_ , and incremented for each subsequent _value_ . There is no particular order to the _values_ , so do not put any special significance on _index_ . 

_name_ (String)  [out] 

will return the value name corresponding to _index_ . 

_type_ (Num)  [out] 

will return the type of the value (see types under Set). 

_value_ (type depends on _type_ )  [out] 

will return the value of the named item. See Read for notes on how to map it to support multiple types. 

_status_ (F6)  [out] 

0 for success, else error code. Error 259 indicates that there are no more values to enumerate. 

A-Shell Reference 

Page 2960 

## **CLOSE** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_CLOSE, hkey, status** 

This function is used to close a handle previously opened. 

## _hkey_ [in] 

must be set to the handle of the key to close (as returned in HKEY2 by the open or create operations). 

_status_ (F6)  [out] 

- 0 for success, else error. 

A-Shell Reference 

Page 2961 

## **DELETE KEY** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_DELKEY, hkey, subkey, rights, status** 

This function deletes a registry key. 

## _hkey_ (B,4)  [in] 

must specify an open registry handle returned from a previous REGOP_OPEN operation (or may be one of the built-in hive handles, e.g., HKEY_CURRENT_USER, etc.) Note that to delete a key, the the RGKEY_DELETE access right must have been specified in the REGOP_OPEN call. To delete a value, the RGKEY_SET_VALUE access right must have been specified in the open. 

## _subkey_ (String)  [in] 

specifies the key to delete (within HKEY). All values within the key will be deleted, but if there are any nested subkeys, the operation will fail. To delete a multi-level tree, you must start from the lowest level and work up. 

## _rights_ (Num)  [in] 

only applies when running in 64 bit Windows, in which case it can be used to select the registry view: 

```
RGKEY_WOW64_32KEY   &h0200   Delete key from 32 bit registry view
RGKEY_WOW64_64KEY   &h0100   Delete key from 64 bit registry view
```

## _status_ (F6)  [out] 

returns 0 for success, else an error code. 

A-Shell Reference 

Page 2962 

## **DELETE VALUE** 

## **xcall MIAMEX, MX_REGISTRY, REGOP_DELVALUE, hkey, name, status** 

This function deletes the value of a key. 

_hkey_ (B,4)  [in] 

must specify an open registry handle returned from a previous REGOP_OPEN operation (or may be one of the built-in hive handles, e.g., HKEY_CURRENT_USER, etc.) Note that to delete a key, the the RGKEY_DELETE access right must have been specified in the REGOP_OPEN call. To delete a value, the RGKEY_SET_VALUE access right must have been specified in the open. 

_name_ (String)  [in] 

specifies the name of a value to delete. 

_status_ (F6)  [out] 

returns 0 for success, else an error code. 

A-Shell Reference 

Page 2963 

## **REPLACE NULL DELIMITERS** 

This is not a function but an option which can be added to the Set, Read, and Enumerate values functions to simplify the handling of the REG_MULTI_SZ data type. Without this option, in order to parse a list of strings containing embedded null bytes, you need to overlay the string variable on an unformatted variable and then use substring referencing to locate the null bytes and access the substrings between the null bytes. When the REGOP_DELIMS flag is added to, say, REGOP_ENUMVALS, then the embedded nulls are replaced by CHR(128) characters. Such a list of strings can then be parsed with code similar to the following (excerpted from the sample program REGPTR) which lists the individual bin names available for a printer. 

## `! enumerate next value . . .` 

```
xcall MIAMEX, MX_REGISTRY, REGOP_ENUMVALS + REGOP_DELIMS, HKEYNEW, SUBKEY, INDEX, TYPE, V$, STATUS
```

```
! if no error, and value is printBinNames and of REG_MULTI_SZ type, parse it out
```

```
If STATUS=0 and SUBKEY="printBinNames" and TYPE=REG_MULTI_SZ then
```

```
X = 1
```

```
Y = 1
```

```
do while Y > 0
```

```
Y = instr(X,V$,chr(128))
```

```
if Y > 0 THEN
```

```
   BIN$ = V$[X,Y-1]
```

```
   X = Y + 1
```

```
   Print "BIN Name = ";BIN$
```

```
endif
```

```
Loop
```

```
endif
```

A-Shell Reference 

Page 2964 

## **MX_AUTOPARENT** 

_Rewritten June 2025_ 

## **xcall MIAMEX, MX_AUTOPARENT, newctrlid {,oldctrlid}** 

MX_AUTOPARENT (MIAMEX 141) allows you to query and/or set the default AUI parent control, which comes into play in the following circumstances: 

- Controls are created using AUI_CONTROL without explicitly specifying a parent in the parentid parameter. 

- Controls are created using TPRINT/DPRINT/EPRINT (which don't offer such an option) 

- Controls are created by PRINT statements when SET AUTOTPRINT is active 

- TAB(-1,0), TAB(-1,9) or TAB(-1,10) are used (potentially deleting controls from the parent window) 

The main use case is to simplify dialog creation, allowing use of the simpler variations of PRINT statements instead of the more complex AUI_CONTROL calls. 

Note that while Groupbox controls (rather than dialogs) are not normally considered eligible default parents, there in an exception for xPRINT statements.  So for example, after creating a groupbox control and setting it to be the default parent control, you can then display text within the groupbox using PRINT TAB coordinates starting from (1,1). (And if you then change the coordinates of the groupbox, the contents will move with it.) 

To avoid unexpected side effects, clear the auto parent setting when no longer needed by calling the routine with newctrlid set to 0. It will also be cleared automatically at the start of a new RUN program. 

Unless specifically overridden via the parentid parameter passed to AUI_CONTROL when creating GUI objects, the normal default parent will be the current modal dialog (if there is one), else the main window.  to apply to subsequent TPRINT/DPRINT and Tab(-1,9) and Tab(-1,10) commands. 

Although you can accomplish the same result using the AUI_CONTROL functions and specifying the parent control explicitly, the MX_AUTOPARENT function greatly simplifies dialog coding by allowing you to use the much simpler TPRINT, DPRINT, and Tab(-1,9-10) commands. This is particularly true if SET AUTOTPRINT is used to interpret existing PRINT statements as if they were TPRINT statements. 

A-Shell Reference 

Page 2965 

Note that MX_AUTOPARENT will be automatically forwarded to the ATE client via AG_AUTOPARENT. 

## **Parameters** 

_newctrlid_ (String/Num)  [in] 

The alphanumeric control name or numeric ID of the new auto parent.  Must be set to "" if you just want to query the existing auto parent without changing it. 

_oldctrlid_ (Num)  [out] 

If specified, returns the numeric ID of the previous auto parent control. 

## **See Also** 

- A-SHELL ( _pflag_ option related to autoparent) 

## **History** 

- 2014 February, A Shell 6.1.1374: Add support for current and new auto parent. 

A-Shell Reference 

Page 2966 

## **MX_INFDEF** 

## **xcall MIAMEX, MX_INFDEF, opcode, defcodes** 

MX_INFDEF (MIAMEX 143) Retrieves or sets the INFLD default TYPE codes. These may be initially set by the SBR=INFDEF statement in miame.ini, and may also be updated or queried by the SET INFDEF command. 

## **Parameters** 

_opcode_ (Num)  [in] 

- 0 (mxop_get) to retrieve the current SBR=INFDEF: codes into _defcodes_ , and 1 (mxop_set) to make the contents of _defcodes_ be the new default INFLD codes. 

_defcodes_ (String)  [in] 

receives or supplies default INFLD TYPE codes, based on opcode. 

A-Shell Reference 

Page 2967 

## **MX_DEBUG** 

_Updated October 2025_ 

## **xcall MIAMEX, MX_DEBUG, opcode, debuglevel {, traceminlvl, tracetags, traceoutput, traceprefix}.** 

MX_DEBUG (MIAMEX 144) queries or sets the DEBUG control variable, along with several options related to TRACE and DEBUG statements. It is mainly used by SET.LIT. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 (MXOP_GET) to retrieve the current value of the other parameters or 1 (MXOP_SET) to set them. 

_debuglevel_ (Num)  [in/out] 

for _opcode_ 0, returns the current value of the DEBUG control variable.  For _opcode_ 1, supplies the new value you want to set. 

_traceminlvl_ (Num)  [in/out] 

returns or sets the minimum DEBUG value for activating TRACE and DEBUG statements by level.  See Comments below for details. 

## _tracetags_ (String)  [in/out] 

returns or sets the current list (comma-delimited) of tags used to activate TRACE and DEBUG statements.  See Comments for details. 

## _traceoutput_ (String)  [in/out] 

returns or sets the output destination for TRACE and DEBUG statements. See DEBUG Settings for available options ($WIN, $TTY, ...) 

_traceprefix_ (String)  [in/out] 

returns or sets the current list of macros added to those hard-coded in any applicable TRACE and DEBUG statements.  See Comments for details. 

A-Shell Reference 

Page 2968 

## **Comments** 

The DEBUG control variable is useful for embedding debugging code into applications that can be enabled or disabled without modifying the programs. Other ways to modify the variable are via the SET DEBUG command or by compiling with the /DEBUG compile switch. Ways to use the variable within a program include: 

```
IF DEBUG THEN …
```

```
IF DEBUG > N THEN …
```

```
DEBUG.OPEN              ! open System Messages window (if DEBUG variable set)
DEBUG.PRINT msg         ! output msg to debug window (if DEBUG variable set)
DEBUG.PAUSE msg         ! output msg and wait (if DEBUG variable set)
DEBUG.CLOSE             ! close System Messages window (if DEBUG variable set)
```

```
TRACE.PRINT (level, tags) var-or-expr, ...        ! output trace, subject to activation and prefix criteria
```

The general form of the TRACE.PRINT statement shown above includes two activation parameters ( _level_ and _tags_ ) which, along with the options managed by MX_DEBUG, determine whether the particular trace will be enabled at runtime. Specifically, the level value in the TRACE.PRINT statement must be less than or equal to the system DEBUG level (set by _debuglevel_ ) and greater than or equal to _traceminlvl_ AND/OR one of the tracetags must match one of the tags; if tracetags starts with "+", then OR, else AND. If the statement gets enabled, any _traceprefix_ macros (e.g. $#, $T, etc.) will be used to augment any hard-coded into the TRACE.PRINT statement. 

## **See Also** 

- SET.LIT (SET DEBUG xxx) 

- TRACE and DEBUG statements 

- Event Tracing for more information on the System Messages window. 

## **History** 

- 2023 September, A Shell 6.5.1744:  add traceprefix parameter to support querying and setting global tracing prefix. 

A-Shell Reference 

Page 2969 

## **MX_LASTLNO** 

## **xcall MIAMEX, MX_LASTLNO, lineno** 

MX_LASTLNO (MIAMEX 146) allows you to find out the last line number executed in the current program. This is similar to the ERR(1) function in an error trap except it does not require that an error occur. 

A-Shell Reference 

Page 2970 

## **MX_FLINES** 

## **xcall MIAMEX, MX_FLINES, channel, lines {,linelen, slinelen}** 

MX_FLINES (MIAMEX 147) allows you to quickly count the number of lines in a sequential file, and also determine the length of the longest line either with or without trailing spaces. 

## **Parameters** 

_channel_ (Num)  [in] 

must be set to the file channel number of a file open for sequential input. 

_lines_ (Signed Num)  [out] 

returns the number of lines in the file. A negative number indicates an error (-1 means the file channel was invalid, -x indicates that system error x occurred while reading the file.) 

_linelen_ (Num)  [out]  optional 

returns the length of the longest line in the file (including trailing spaces plus one for the trailing terminator). 

_slinelen_ (Num)  [out]  optional 

returns the length of the longest line in the file excluding any trailing unprintable characters (such as spaces, tabs, CR, LF, etc.) 

The file is left open, with the file cursor set to the beginning of the file. 

A-Shell Reference 

Page 2971 

## **MX_GDICALC** 

## **xcall MIAMEX, MX_GDICALC, opcode, handle, status {,params}** 

(Windows/ATE) MX_GDICALC (MIAMEX 148) performs various calculations on the length and/or height of a string as it will appear when printed. In the case of a rectangle, it will also break the string into two parts, the first of which will fit within the rectangle, the remainder of which will be printed in another space or on the next page. 

## **Parameters** 

## _opcode_ (Num)  [in] 

|**Symbol**|**Value **|**Description**|
|---|---|---|
|MXGDI_OPENPTR|1|Open<br>a printer device context|
|MXGDI_SETFONT|2|Choose Font|
|MXGDI_CALCRECT|3|Calculate Rectangular Text Metrics|
|MXGDI_CALCLEN|4|Calculate String Length|
|MXGDI_CLOSEPTR|5|Close printer context. This must be done BEFORE printing to it. Syntax: xcall<br>MIAMEX, MX_GDICALC, MXGDI_CLOSEPTR, handle, status|
|MXGDI_CALCRECTX|6|Calculate Rectangular XTEXT Metrics|
|**Definition file: ashell.def**|||



A-Shell Reference 

Page 2972 

_handle_ (B4)  [in/out] 

The handle variable is returned by the open operation (opcode 1) and must be specified to all the others. 

_status_ (F6)  [out] 

This will be returned from each operation, with 0=success. All others are errors, with the most typical being MX_GDICALC Status Codes. 

See the sample program MMOGDI.BP in EXLIB:[908,37] and the sample text file TSTGDI.TXT in EXLIB:[908,37] for examples of using MX_GDICALC and TEXTRECTANGLE. 

A-Shell Reference 

Page 2973 

## **OPEN** 

## **xcall MIAMEX, MX_GDICALC, MXGDI_OPENPTR, handle, status, printer, mapmode {,length, width}** 

Establishes a printer context, returning a handle to it which must be passed to all the other MX_GDICALC operations. 

|**Paramete**<br>**r**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|handle|B,4|in/<br>out|Name to be used for otherMX_GDICALCoperations.|
|status|F6|out|MX_GDICALC Status Codes<br>.|
|printer|Strin<br>g|in|Any form of printer name allowed bySPOOLXS—e.g. a null string for the A-<br>Shell or Windows default; a printer ini file name, a printer share name, or a<br>printer local driver name.|
|mapmode|Strin<br>g|in|One of the map modes allowed in the GDISETMAPMODEstatement<br>(LOENGLISH, HIENGLISH, LOMETRIC, HIMETRIC, TEXT, TWIPS,<br>DECIPOINTS).|
|length,<br>width|Num|out|If specified, the page length/width (in the specified map mode units) will be<br>returned here.|



A-Shell Reference 

Page 2974 

## **CHOOSE FONT** 

## **xcall MIAMEX, MX_GDICALC, MXGDI_SETFONT, handle, status, pointsz {,face, pitchfam, charset, weight, style, rotation, width}** 

Establishes the font to be used for the various CALCxxx operations to follow. All of the parameters below are the same as those used by the GDI printing directive SETFONT. 

|**Paramet**<br>**er**|**Type**|**I/O **|**Description**|
|---|---|---|---|
|handle|B,4|in|Device context handle (fromMXGDI_OPEN)|
|status|F6|out|MX_GDICALC Status Codes<br>.|
|pointsz|Num|in|Font height in tenths of points.|
|face|Strin<br>g|in|Font face name. If not specified, the Windows default font face for the<br>specified printer will be used.|
|pitchfam|Num|in|Font pitch and family characteristics. If not specified, will be determined by<br>the natural characteristics of the font face.|
|charset|Num|in|Character set indicator. If not specified, the default character set for the font<br>determined by the other parameters will be used.|
|weight|Num|in|Symbolic code for the desired weight of the font. If not specified, the default|



A-Shell Reference 

Page 2975 

|**Paramet**<br>**er**|**Type**|**I/O **|**Description**|
|---|---|---|---|
||||weight is used.|
|style|Num|in|Flags for italic (+1), underline (+2), and strikeout (+4)|
|rotation|Num|in|Rotation in degrees; positive for clockwise.|
|width|Num|in|Font character width specification. Normally the font width is a function of<br>the height and the font style, but you can squeeze or stretch it using this<br>option. Units, if positive, are the same as that for height (tenths of points); if<br>negative, indicates the number of characters that will fit on a line across the<br>page (not the rectangle). Mainly applicable only for fixed pitch fonts.|



A-Shell Reference 

Page 2976 

## **CALCULATE RECTANGULAR TEXT METRICS** 

_Reviewed and revised November 2018_ 

## **Updated axcall MIAMEX, MX_GDICALC, MXGDI_CALCRECT, handle, status, lft, top, rght, btm, memo, height, overflow {,flags}** 

This operation calculates how much text will fit in a specified rectangle, based on the current printer context and font. 

|**Paramet**<br>**er**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|handle|B,4|in|Device context handle (fromMXGDI_OPEN)|
|status|F6|out|MX_GDICALC Status Codes<br>.|
|lft,top,<br>rght,btm|Num|in/<br>out|Coordinates of the rectangle, in the units specified by_mapmode_when the<br>printer device context was established. Coordinates_rght_and_btm_are are<br>updated only when flags parameter contains TRF_CALCRECT option._lft_and<br>_top_are never updated.|
|memo|Strin<br>g|in/<br>out|On input, specifies the text we want to output within the rectangle. On<br>return, it contains the amount of the original text that actually fits in the<br>rectangle.|
|height|Num|out|If_memo_fits entirely within the rectangle,_height_returns the rectangle<br>height actually required (which may be less than the full rectangle height).<br>Otherwise, it will return the input height of the rectangle.|



A-Shell Reference 

Page 2977 

|**Paramet**<br>**er**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|overflow|Strin<br>g|out|Returns the trailing portion of_memo_which does not fit within the rectangle.<br>If it all fits, then a null string is returned here. Note that this operation<br>supports a dynamic string (S,0).|
|Flags|Num|in|Optional flags used when calculating the optimum rectangle based on various<br>formatting options.|



## **Comments** 

The vertical spacing used for the calculation is the natural vertical spacing for the current font and printer device context. To make sure you get the same spacing when actually printing, use the GDI printing directive RESETLPP after SETFONT and before TEXTRECTANGLE. The vertical spacing is not automatically reset by SETFONT. 

If _memo_ must be wrapped to multiple lines to fit within the rectangle, standard word-wrapping logic will be used to avoid breaking lines mid-word. Embedded CRLFs are also respected. 

You can use this operation iteratively (changing the font size incrementally each time) to determine the optimum font size for the specified _memo_ text to fit within the rectangle. 

The test program GDICALC in EXLIB:[908,37] is to illustrate this kind of logic. 

Note that MXGDI_CALCRECT assumes vertical spacing optimum for the font, i.e. as if a RESETLPP command had been executed after SETFONT. If you don't do this in the actual GDI print file, the spacing for the print  operation may not match that used for the calculations. 

A-Shell Reference 

Page 2978 

## **FLAGS** 

_Reviewed and revised November 2018_ 

The optional _flags_ parameter is used to calculate the optimum rectangle size for the specified memo after reformatting it according to various options. 

In this case, the _rght_ and _btm_ parameters are also returned, indicating the adjusted rectangle dimensions required for printing the memo string. For single line memos (TRF_SINGLELINE set, or TRF_WORDBREAK not set and no CRLFs in the line), the width of the rectangle will be adjusted to fit the text. Otherwise, if TRF_WORDBREAK is specified, it will preserve the width of the rectangle, breaking the lines as needed to fit within that width, and adjusting the height of the rectangle. 

Formatting options for _flags_ are chosen from the TRF_xxx flags used by TEXTRECTANGLE (reprinted below), with the mandatory inclusion of the TRF_CALCRECT bit. 

|**Flag**|**Value**|**Meaning**|
|---|---|---|
|TRF_TOP|&h00000000|top justification|
|TRF_LEFT|&h00000000|left justification|
|TRF_HCENTER|&h00000001|horizontal centering|
|TRF_RIGHT|&h00000002|right justification|
|TRF_VCENTER|&h00000004|vertical centering|
|TRF_BOTTOM|&h00000008|bottom justification|



A-Shell Reference 

Page 2979 

|**Flag**|**Value**|**Meaning**|
|---|---|---|
|TRF_WORDBREAK|&h00000010|wrap the text onto multiple lines|
|TRF_SINGLELINE|&h00000020|output text as a single line|
|TRF_EXPANDTABS|&h00000040|expand tabs (8 spaces each)|
|TRF_NOCLIP|&h00000100|no clipping|
|TRF_EXTERNALLEADING|&h00000200|incl. ext. leading in spacing|
|TRF_CALCRECT|&h00000400|calc only (use withMX_GDICALC)|
|TRF_PATH_ELLIPSIS|&h00004000|path ellipsis|
|TRF_END_ELLIPSIS|&h00008000|end ellipsis|
|TRF_WORD_ELLIPSIS|&h00040000|word ellipsis|
|**Definition file: ashell.def**|||



A-Shell Reference 

Page 2980 

## **CALCULATE STRING LENGTH** 

## **xcall MIAMEX, MX_GDICALC, MXGDI_CALCLEN, handle, status, memo, length** 

The MXGDI_CALCLEN operation is similar to MXGDI_CALCRECT, except that it just determines how long the string will be when printed— i.e. does not consider the possibility of wrapping it to multiple lines. 

|**Paramet**<br>**er**|**Type**|**I/**<br>**O**|**Description**|
|---|---|---|---|
|handle|B,4|in|Device context handle (from MXGDI_OPEN)|
|status|F6|out|MX_GDICALC Status Codes.|
|memo|String|in|Text string to consider. Should not contain any CRLF characters.|
|length|Num|out|Returns the length (i.e. width) required to print_memo_text in the current<br>font and device context, in the_mapmode_units specified in the<br>MXGDI_OPENoperation.|



A-Shell Reference 

Page 2981 

## **CALCULATE RECTANGULAR XTEXT METRICS** 

## **xcall MIAMEX, MX_GDICALC, MXGDI_CALCRECTX, handle, status, lft, top, rght, btm, file, height, offset** 

This is used to calculated the XTEXT metrics required for use with the GDI print command //XTEXT, and is essentially the same as the existing MXGDI_CALCRECT except: 

- The _memo_ argument in MXGDI_CALCRECT is replaced here by _file_ , which specifies the filespec of the text file to analyze. 

- The _overflow_ argument in MXGDI_CALCRECT is replaced here by _offset_ , which indicates the offset within the file. On input, it is the 

- starting offset (default 0). On output, it will be 0 if the entire file fits within the specified rectangle. Otherwise, it will be the offset to the first character that did not fit (which can then be passed to a subsequent MX_GDICALC call). 

- Note that unlike MXGDI_CALCRECT, where the font and other spacing factors must be set in advance (via MX_GDICALC _opcode_ 2), 

- with XTEXT printing, the font and other layout parameters are set within the text file (particularly in the case of RTF files). 

The sample program MMOGDI in EXLIB:[908,37] illustrates the use of //XTEXT and MX_GDICALC, MXGDI_CALCRECTX. 

This function also works in ATE. As with XTEXT[XS] , a file resident on the server will be transferred to ATECACHEDIR on PC. Since the use of MXGDI_CALCRECTX implies that this will happen multiple times per file printed, you might want to optimize the operation, if you are doing it on a lot of files, by pre-transferring the files to the ATECACHEDIR and then referencing the filespec as %atecachedir%\xxxxxx.yyy. 

A-Shell Reference 

Page 2982 

## **MX_WINSETTINGS** 

_Reviewed May 2024_ 

Get or set values: 

## **xcall MIAMEX, MX_WINSETTINGS, opcode, id, value** 

Save settings file: 

## **xcall MIAMEX, MX_WINSETTINGS, opcode, file, status** 

Load settings file: 

## **xcall MIAMEX, MX_WINSETTINGS, opcode, file, file2** 

(ATE/Windows) MX_WINSETTINGS (MIAMEX 149) is used to get or set a number of options associated with the Misc Settings and Dialog Sizing dialogs. Set _opcode_ to 0 to retrieve a value or 1 to set it. The ID codes and associated range of values are shown below. Note that the AWS_xxx symbols have been added to ashell.def. 

This function has both a subroutine and a print tab implementation. 

_opcode_ (Unsigned Int)  [in] 

0 (MXOP_GET) to retrieve a value, 1 (MXOP_SET)to set a value (first syntax above); 2 to save the current values to disk (second syntax above); 3 to load a new set of values from disk (third syntax above) 

When used with _id_ 0, returns a comma-delimited string of all the available values. This is much faster than retrieving each value one at a time over ATE, where there could be a several milliseconds latency for each command/response turnaround. Note that the comma-delimited string will have a place for each setting by ID value, from 1 to the maximum ID. 

## _id_ (Unsigned Int)  [in] 

Identifies the item for which the corresponding value will be set or retrieved. The choices for _id_ are listed in the Symbol column in the table below. 

A-Shell Reference 

Page 2983 

## _value_ (Num or String)  [in/out] 

Specifies the value to set (if _opcode_ =1) or returns the value being retrieved (if _opcode_ =0). The data type should correspond to the type of the associated item. Most items are numeric integers, except for the font name values. For items that correspond to on/off options (checkboxes in the Misc. Settings Dialog), 1=on (checked), 0=off (unchecked). 

## _file_ (String)  [in] 

For opcodes 2 and 3, _file_ specifies the full or partial filespec of the settings file to save to or load from. If null, the current default filespec is used. 

## _file2_ (String)  [out] 

For opcode 3, _file2_ returns the fully qualified settings file name (possibly useful if _file_ left blank or partial, or if the file referenced by _file_ was not present and a different settings file from the search order was specified.) See the File > Save dialog for information about the search order for settings files. 

## _status_ (Signed Num)  [out] 

For _opcode_ 2, returns 0 if the save operation was a success, -15 if ATE fails to respond in a reasonable time. 

## **ID Values** 

|**Symbol**|**Valu**<br>**e**|**Type**|**Description**|
|---|---|---|---|
|AWS_LEADING|1|Numeri<br>c|Leading (pixels between rows)|
|AWS_LEADCLR|2|Numeri<br>c|Leading color fill (color number or -1,-2)<br>AWS_LEADCLR_AUTO (-1)<br>AWS_LEADCLR_PASSIVE (-2)|



A-Shell Reference 

Page 2984 

|**Symbol**|**Valu**<br>**e**|**Type**|**Description**|
|---|---|---|---|
|AWS_FONTSCALE|3|Numeri<br>c|Font scale factor|
|AWS_MINMAXMARGI<br>N|4|Numeri<br>c|Minimum margin when maximized|
|AWS_FIXEDPITCHED<br>IT|5|Numeri<br>c|Use fixed pitch in edit boxes (1=on, 0=off)|
|AWS_WININFCLR|6|Numeri<br>c|Use std Windows colors in edit boxes (1=on, 0=off)|
|AWS_EDITLEADING|7|Numeri<br>c|Extend edit boxes into leading area (1=on, 0=off)|
|AWS_CBEDITMATCH|8|Numeri<br>c|Set edit boxes to combo height (1=on, 0=off)|
|AWS_DLGGRIDBASI<br>S|9|Numeri<br>c|Dialog size based on...<br>AWS_DLGGRIDBASIS_FONTSIZE   (0)<br>AWS_DLGGRIDBASIS_WINDOWSIZE (1)<br>AWS_DLGGRIDBASIS_PROGCTL    (2)|



A-Shell Reference 

Page 2985 

|**Symbol**|**Valu**<br>**e**|**Type**|**Description**|
|---|---|---|---|
|AWS_DLGGRIDHEIG<br>HT|10|Numeri<br>c|Dialog grid height (% of font size)|
|AWS_DLGGRIDWIDT<br>H|11|Numeri<br>c|Dialog grid width (% of font size)|
|AWS_BEEPCODE|12|Numeri<br>c|Default beep sound with char(7):<br>AWS_BEEPCODE_DEFAULT   (0)<br>AWS_BEEPCODE_HAND      (16)<br>AWS_BEEPCODE_QUESTION  (32)<br>AWS_BEEPCODE_EXCLAM    (48)<br>AWS_BEEPCODE_ASTERISK  (64)|
|AWS_DLGFONTSCAL<br>E|13|Numeri<br>c|ALTPOS dialog font scale|
|AWS_DLGCAPTINC|14|Numeri<br>c|Include caption in dialog height (1=on, 0=off)|
|AWS_WININFBGC|15|Numeri<br>c|RGB background color for active edits|



A-Shell Reference 

Page 2986 

|**Symbol**|**Valu**<br>**e**|**Type**|**Description**|
|---|---|---|---|
|AWS_FONTFACE|16|String|A-Shell fixed pitch font|
|AWS_GUI_FONTFAC<br>E|17|String|A-Shell GUI font (blank for Windows default)|
|||||
|||||
|AWS_CHARSET|20|Numeri<br>c|Sets and retrieves the current display character set. Valid<br>choices are 0 for ANSI and 255 for OEM. Note that the character<br>set is usually established inmiame.ini(default is OEM) with<br>the FONT=fontname,charset command. Once set, changing<br>fonts doesn't usually change the character set.|
|AWS_XTR_FONTFAC<br>E|21|String|XTREEdefault font|
|**Definition file: ashell.def**||||



## **Examples** 

To change the default beep code to the system "asterisk" sound: 

A-Shell Reference 

Page 2987 

```
xcall MIAMEX, MX_WINSETTINGS, MXOP_GET, AWS_BEEPCODE, AWS_BEEPCODE_ASTERISK
```

To re-load the settings from the current settings file (returning the full filespec of that file in FSPEC2$): 

```
xcall MIAMEX, MX_WINSETTINGS, 3, "", FSPEC2$
```

To save the current (possibly updated) settings to the specified file: 

```
xcall MIAMEX, MX_WINSETTINGS, 2, "%MIAME%\new.ash"", status
```

## **Notes** 

All of the options listed above, other than beepcode, may be set via the dialogs directly. In the case of the beepcode, the command changes the code that is used when a chr(7) is output, but you can still determine what waveform is associated with that code in the Windows Control panel Sounds applet. 

Also note even though the beepcode may not be seen or edited in the dialogs, it is still saved and retrieved along with the other settings (File > Save). 

## **See Also** 

- AG_WINSETTINGS 

A-Shell Reference 

Page 2988 

## **MX_RELEASEKBD** 

_Updated May 2013_ 

## **xcall MIAMEX, MX_RELEASEKBD {,opcode, typeahead}** 

MX_RELEASEKBD (MIAMEX 153) Releases or sets the keyboard hold—i.e. controls whether keyboard characters entered on the client are transmitted to the server. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_opcode_ (Num)  [in] 

|**opcode**|**Description**|
|---|---|
|0 or omitted|causes the keyboard hold to be released, provided it hasn't been locked.|
|1|causes the keyboard hold to be set, and optionally passes the contents of text to ATE to be<br>reprocessed as type-ahead.|
|2|clears the keyboard hold, even if it has been locked.|



## _typeahead_ (String)  [in] 

If specified, the contents will be forced into the keyboard buffer. 

## **See Also** 

- AG_RELEASEKBD 

A-Shell Reference 

Page 2989 

## **History** 

- 2013 May, A Shell 6.1.1352: Opcode 2 added 

A-Shell Reference 

Page 2990 

## **MX_DEFTABXYZ** 

_Reviewed and revised December 2020_ 

## **xcall MIAMEX, MX_DEFTABXYZ, sts, Z {, fgc, bgc, ptype, fontattr, fontscale, fontface, flags}** 

## **xcall MIAMEX, MX_DEFTABXYZ, sts, Z** 

## **xcall MIAMEX, MX_DEFTABXYZ, sts, 0, count** 

MX_DEFTABXYZ (MIAMEX 154) allows you to associate a variety of text attributes with the value Z, so that when you use `PRINT TAB(X,Y,Z);VAR$,` A-Shell will apply the specified attributes to the display of VAR$. 

- The first syntax is used for defining a set of attributes to be associated with the index Z. 

- The second syntax is used for removing the definition for index Z. See Comments, below, for additional info. 

- The third syntax is for expanding the table to allow for _count_ definitions (i.e. for Z = 1 to _count_ ). See Comments, below, for 

- additional info. 

Typically, you would issue several of these subroutine calls when you first log in to your main menu (one per Z value that you actually use in the application). For example: 

- `! Define style 1: normal text, FGC=2, BGC=0` 

```
XCALL MIAMEX,MX_DEFTABXYZ,STS,1,5,0
```

- `! Define style 2: GUI text, standard GUI colors, TPRINT style` 

```
XCALL MIAMEX,MX_DEFTABXYZ,STS,2,-2,-2,"TL"
```

- `! Define style 3: GUI text (Blue=66) in a sunken panel, extra bold` 

```
XCALL MIAMEX,MX_DEFTABXYZ,STS,3,66,-2,"DL",14400
```

A-Shell Reference 

Page 2991 

```
etc.
```

## _sts_ (F6) 

returns >=0 if success, else error. -1 means that the table could not be allocated (out of memory?) and -2 means that the specified Z value is larger than the current maximum table size. 

_Z_ (Integer, 1-19) 

the Z value in TAB(X,Y,Z). 

_fgc, bgc_ (Integer) 

foreground/background color palette values. As with the like-named parameters in AUI_CONTROL, -1 indicates the current color, -2 indicates the standard Windows color. Add +64 to override the Windows Theme color. You may also specify RGB values. 

## _ptype_ (String) 

indicating a combination of style and justification. If null, then only the _fgc, bgc_ values matter and the output will use the normal text (fixed pitch) style of the emulator. Otherwise, the format of the string is: "SJ" where S is replaced by: "T" (TPRINT), "D" (DPRINT), or "E" (EPRINT) and J is the justification code ("L"=left/auto, "C"=center, "R"=right). The TPRINT style is the normal GUI text style. DPRINT style is like that but within a sunken panel (normally used for data as opposed to labels or background text). EPRINT style is the white edit box normally used for INFLD or windows editable text. The left justification code also autojustifies if the first character of the field is blank. In that case, if the last character is also blank, then the field is centered, else it is right justified. (This has to be done automatically because you cannot manually figure out how big the display font will be in order to justify, so A-Shell does it on the fly.) Note that right justify actually leaves one trailing blank, since otherwise it looks too "cramped" when using the DPRINT or EPRINT styles. 

Valid _ptype_ codes include the following: 

A-Shell Reference 

Page 2992 

|**Value **|**Meaning**|
|---|---|
|T[|like TL but shrinks control to just fit the text|
|T]|like T[ but right justified|
|D[|like DL but shrinks control to just fit the text|
|D]|like DR but right justified|



## _fontattr, fontscale, fontface_ 

font attributes, scale factor, and font name, as in the AUI_CONTROL call. 

_flags_ (Num)  [in] 

may specify zero or more of the following options: 

|**Flag**|**Value**|**Description**|
|---|---|---|
|TBZF_AUTONUMK<br>BD|&h000<br>1|TBZF_AUTONUMKBD will automatically assign a click string equal to the numeric<br>value at the start of the string. Requires that the_ptype_be one of the non-null<br>options (starting with "T", "D", or "E").|
|TBZF_AUTOCR|&h000<br>2|TBZF_AUTOCR may be combined with TBZF_AUTONUMKBD to append a chr(13)<br>to the numeric click string.|



A-Shell Reference 

Page 2993 

|**Flag**|**Value**|**Description**|
|---|---|---|
|TBZF_AUTOFKY1<br>00|&h000<br>4|TBZF_AUTOFKY100 is similar to TBZF_AUTONUMKBD except that instead of<br>sending the numeric digits as the click string, it sends the virtual key code<br>sequence VK_xF#  where # is the string of numeric digits. In other words, a<br>label containing "13. Go Directly To Jail" acts like the function key F13 when<br>clicked.|
|TBZF_HIDENUM|&h000<br>8|TBZF_HIDENUM may be added to any of the above to strip off the leading<br>number before displaying the text. For example, when printed, the string "13.<br>Go Directly To Jail", would appear as "Go Directly To Jail", i.e. without the "13."<br>The idea here is that numbered fields are a vestige of traditional text-based<br>applications which had no other way for the user to direct the focus.|
|TBZF_LINKTOLBL|&h001<br>0|Causes the control (created via Tab(x,y,z)) to be assigned the same click string<br>as the control (presumably the label) immediately to the left of the newly<br>created control. As an example, if you used Z=1 for labels (with the<br>TBZF_AUTOFKY100 bit set), and Z=2 for data fields (with the TBZF_LINKTOLBL<br>bit set), the following would result in both labels and data fields sending<br>EXITCODE -1## (## matches the label numeric prefix) on click:<br>? tab(4,10,1);"1. Name";<br>? tab(5,10,1)'"2. Address:";<br>...<br>? tab(4,40,2);NAME$ ? tab(5,10,1);ADDR$ ...|



A-Shell Reference 

Page 2994 

|**Flag**|**Value**|**Description**|
|---|---|---|
|**Definition file: ashell.def**|||



## **Comments** 

If the default maximum 19 text types is not sufficient, you can pre-allocate a larger table using: 

## **xcall MIAMEX,MX_DEFTABXYZ, sts, 0, count** 

Where _count_ is the desired number of text type definitions. _sts_ will be returned with the new maximum (which may be larger than the amount requested.) Allocating a larger table will delete the current table. 

Once the MX_DEFTABXYZ call is used to define a set of attributes for a particular Z value, it remains in effect until you exit A- Shell or undefine it. To undefine a value, just use the form: 

## **xcall MIAMEX, MX_DEFTABXYZ, sts, z** 

At runtime, referencing a Z value that is undefined will cause the TAB(X,Y,Z) to just act like a normal TAB(X,Y). This is also true if GUI not supported by the emulator. 

## **See Also** 

- Three-D Print Tab 

A-Shell Reference 

Page 2995 

## **MX_INSTNUM** 

## **xcall MIAMEX, MX_INSTNUM** 

(Windows) MX_INSTRUM (MIAMEX 156) returns your "instance number." This is the count of how many A-Shell/Windows sessions are running on your PC. 

A-Shell Reference 

Page 2996 

## **MX_FINDWINDOW** 

## **xcall MIAMEX, MX_FINDWINDOW, handle, title {,class}** 

(Windows) MX_FINDWINDOW (MIAMEX 157) is used to search for a window with the specified window title and/or class and/or handle. If both class and title are blank and handle is non-zero, then it searches for the window by its window handle, returning the title and class. If both class and title are blank and handle is zero, then it returns the handle of the A-Shell window (the current modal dialog, if there is one, else the main A-Shell window). 

## **Parameters** 

_handle_ (B,4 or F)  [out] 

returns the window handle if the window is found (or zero if not found). 

## _title_ (String)  [in/out] 

can be loaded with the window title (as shown on the title bar) of the window to search for. 

## _class_ (String)  [in/out] 

can be loaded with the window class to search for. If both _class_ and _title_ are both non-blank, it will only locate a window matching both. 

A-Shell Reference 

Page 2997 

## **MX_GTOCT** 

_Updated December 2017_ 

## **xcall MIAMEX, MX_GTOCT, hexoct, dec** 

MX_GTOCT (MIAMEX 160) converts hex or octal to decimal. 

## _hexoct_ (String)  [in] 

Hex or octal value to convert. Radix must match the current hex/octal mode setting; see MX_GETHEX, MX_SETHEX. In hex mode is set, the hexoct string may optionally contain prefix of "0x", "0X", or "&h". The first two are widely used hex prefixes, while the latter is the hex prefix used in ASB. 

_dec_ (Num)  [out] 

Returns the result of the conversion of hexoct to decimal. See comments. 

## **Comments** 

**Warning:** If _hexoct_ string does not start with a valid hex value, or if it is null, the error return value is -1. If the _dec_ parameter is passed as an unsigned variable type (e.g. B), -1 value will appear as a positive number (e.g. 255 for B,1; 65535 for B2; etc.). While -1 is used for errors, it is also the expected (non-error) result for _hexoct_ = "&hFFFFFFFF". If the hexoct string starts with valid hex characters, the first invalid hex character will be treated as the terminator. So "&h10A" and "&h10AZ" will both be interpreted as 266—the Z marking the effective end of the second string). 

Hex/octal conversions to/from decimal are normally performed using the wrapper functions Fn'Dec2Hex$() and Fn'Hex2Dec() in the SOSLIB:[907,10]. The Fn'Hex2Dec() function implementation may contain additional logic to treat Fn'Hex2Dec("") as 0, which probably seems more natural since VAL("") also equals 0. Consult the function source for details. 

## **See Also** 

- MX_OCVT 

A-Shell Reference 

Page 2998 

## **MX_FILECHINFO** 

_Added August 2015_ 

## **xcall MIAMEX, MX_FILECHINFO, ch, status, fileinfo** 

MX_FILECHINFO (MIAMEX 161) returns information about an open file based on the file channel. It is similar to FILNAM[XS] but provides much more information. 

## **Parameters** 

_ch_ (Num)  [in] 

file channel 

_status_ (Num)  [out] 

returns > 0 if the file channel was located, else 0 

_fileinfo_ (ST_FILE_METADATA)  [out] 

returns info about the file 

ST_FILE_METADAT is defined in ASHINC:ashell.sdf as: 

```
defstruct ST_FILE_METADATA   ! [103] File metadata returned by MX_FILECHINFO
```

```
map2 SPEC,s,160              ! file spec, as specified in OPEN
map2 TYPE,b,1                ! see FILETYPE_xxx
map2 DRIVER,b,1              ! internal implementation code (see FILEDVR_xxx)
map2 MODE,b,2                ! see FILEMODE_xxx
map2 HOOKID,b,4              ! file hook id
map2 HOOKFLAGS,b,4           ! file hook flags
```

A-Shell Reference 

Page 2999 

```
map2 HOOKEVENTS,b,4          ! file hook events
```

- `map2 RANDOM'ISAM             ! fields for random and ISAM files` 

- `map3 RECSIZ,b,4           ! record size (according to open; true size for ISAM)` 

- `map3 BLKFCT,b,2           ! 0=spanblocks map3 RECCNT,b,4           ! # records (does not apply to ISAM-A)` 

- `map3 ISAMA                ! ISAM-A only` 

- `map4 INDEX,b,2         ! selected index # map4 ISFIND,i,2        ! result of last FIND # - see ISFIND_xxx` 

- `map4 ISLOCK,b,4        ! current locked recno` 

- `map4 LASTRECNUM,b,4    ! last rec # map2 SEQ                     ! fields for sequential files` 

- `map3 SPOS,f,8             ! stream pos (0=start, -1=eof)` 

- `map3 ISEQ                 ! input files only` 

- `map4 CSVDELIM,s,2      ! CSV delimiter map3 OSEQ                 ! output files only` 

- `map4 OPOS,b,4          ! output column position map4 LINENO,b,4        ! line # for cur pg - same as .LINENO(ch) map4 PAGENO,B,4        ! page # - same as .PAGENO(ch)` 

```
endstruct
```

A-Shell Reference 

Page 3000 

## **Comments** 

If you call the function in a version of A-Shell less than 6.1.1416, you may not get an error status, but the contents of the structure will be empty. 

## **History** 

- 2015 August, A Shell 6.1.1415:  Function added to A-Shell 

A-Shell Reference 

Page 3001 

## **MX_SETMEMFLAGS** 

## **xcall MIAMEX, MX_SETMEMFLAGS, idx, flags** 

MX_SETMEMFLAGS (MIAMEX 163) is used to change the flags for a memory module. 

## **Parameters** 

_idx_ (Num)  [in] 

should be set to 0 to reference the memory module for the currently running program or subroutine, or else it can specify the module previous located in a call to MX_USRMAP. 

_flags_ (Num)  [in] 

are the new flags (overriding the previous ones). If you just want to turn on or off a particular flag but leave existing flags alone, you should first retrieve the existing flags using the MX_USRMAP call. 

## **Comments** 

If you want to use this call within an SBX to cause the SBX to be deleted from memory on exit (instead of being retained as part of the normal caching scheme), then set FLAGS = USRMEM_INUSE. If you do not have that flag set, the module could be deleted by a subsequent memory operation even while the program is running, which would be bad. 

A-Shell Reference 

Page 3002 

## **MX_CHOOSECOLOR** 

## **xcall MIAMEX, MX_CHOOSECOLOR, rgb, status** 

MX_CHOOSECOLOR  (MIAMEX 164) displays the color selection dialog and returns the selected RGB value. 

## **Parameters** 

_rgb_ (B,4 or F6)  [in/out] 

The RGB color value. On input, it determines the default color selected in the dialog; on output it returns the newly selected color. 

_status_ (F)  [out] 

is 0 for OK, or else indicates an error. Executing this function in a non-GUI environment should return -1. 

A-Shell Reference 

Page 3003 

## **MX_CHOOSEFONT** 

## **xcall MIAMEX, MX_CHOOSEFONT, font$, status** 

MX_CHOOSEFONT (MIAMEX 165) displays the font selection dialog and return the selected font name. 

## **Parameters** 

_font$_ (String, 32+)  [in/out] 

name of font. On input, it determines the default font selected in the dialog; on output it returns the newly selected font. 

_status_ (F)  [out] 

is 0 for OK, or else indicates an error. Executing this function in a non-GUI environment should return -1. 

A-Shell Reference 

Page 3004 

## **MX_VERINODE** 

## **xcall MIAMEX, MX_VERINODE, status, ch1 {,ch2...,chn}** 

(Unix) MX_VERINODE (MIAMEX 167) is used for verifying at runtime that a set of open files matches the directory entries for those files. 

## **Parameters** 

## _status_ 

returns zero if all the specified channels are valid; else it returns less than zero for a system error or else the channel number of the first file in the list that doesn't match its directory entry. 

## **Background** 

Under Unix, it is possible to use the mv command to rename a file even if it is in use. This is because mv is thought of as merely a directory operation, whereas file operations all use the inode rather than the name entry in the directory. Since renaming a file doesn't change its inode, it doesn't affect files that are currently operating on the inode. Once the file is renamed, you can then create or copy a new file whose name matches the original name. That still doesn't affect processes with the file open, since the new file will have a different inode and thus isn't really in conflict with any existing processes using the old file. However, that could cause problems for the application if two sets of users are operating on different copies of the file, thinking that they are the same copy. 

MX_VERINODE can be used to make sure that the open file(s) still match the directory entries for those files. Note that it only works under Unix (Windows doesn't use inodes and this situation wouldn't arise there), and it only currently works for random and ISAM-A (DISAM) files. 

A-Shell Reference 

Page 3005 

## **MX_SETUSRNAM** 

_Reviewed and revised, October 2020_ 

## **xcall MIAMEX, MX_SETUSRNAM, usrnam$** 

MX_SETUSRNAM (MIAMEX 169) sets (overrides) the user name. 

Normally the user name is retrieved from the operating system when needed. In most cases, that is best. However, there are two cases where it might not be: 

• If, for some unfathomable reason you allow all users to login to the operating system with a common user login name, then displaying or retrieving that name in utilities such as SYSTAT (or the ashlog.log) isn't very useful. Usually, the excuse for allowing users to share an operating system login name is that you have a separate login process for the application. If this is the case, then you can now use MX_SETUSRNAM so that the application user name replaces the original operating system login name in SYSTAT and other A-Shell purposes. 

- In the case of ATSD: while the login name is usually set to match the login name of the ATE client, in some cases it may be 

- set to the login name of the ATSD service as set in the Services Manager. 

## **Notes** 

Over-riding the user name does not fool the operating system. It only affects A-Shell routines that would otherwise retrieve or use the login name. 

To reset the user name (back to the original), you can XCALL MX_SETUSRNAM with USRNAM$ argument of "". 

## **History** 

- 2020 October, A Shell 6.5.1690: Loosen the license counting rules slightly to allow for a second session from the same workstation when MX_SETUSRNAM had been used to change the user name of the first session. 

A-Shell Reference 

Page 3006 

## **MX_BROWSEFOLDER** 

## **xcall MIAMEX, MX_BROWSEFOLDER, folder, rootID, title, flags** 

MX_BROWSEFOLDER (MIAMEX 170) displays a standard Windows dialog allowing you to browse for and select a folder or other non-file object (such as a computer or device). This operation can only take place on a GUI-enabled client—either ATE or A- Shell/Windows. 

Note that if the initial path or directory is in the form of a drive letter and colon with no trailing slash (e.g. "C:"), 

MX_BROWSEFOLDER automatically appends "\" to avoid confusion. Such ambiguous specs are otherwise likely to be misinterpreted by A-Shell and/or Windows. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _folder_ (String)  [in/out] 

returns the selected folder (or null if user cancelled). On input specifies the default folder. Note even when the RootID parameter is specified, this default folder specification must be absolute (i.e. not relative to the RootID). But it must specify a folder on or below that RootID folder. 

_rootID_ (Num)  [in] 

specifies a root folder, above which the user would not be able to navigate, using the standard CSIDL_xxx identifiers. 

## _title_ (String)  [in] 

specifies the title message which appears in the dialog box. There is room for 2 or 3 lines of text, which will be auto-wrapped as needed. 

_flags_ (Num) 

A-Shell Reference 

Page 3007 

|**Flag**|**Value**|**Description**|
|---|---|---|
|BIF_RETURNONLYFSDIRS|&h000<br>1|Return only file system folders|
|BIF_DONTGOBELOWDOM<br>AIN|&h000<br>2|Don't include network folders below the domain level|
|BIF_RETURNFSANCESTO<br>RS|&h000<br>8|Only return file system ancestors|
|BIF_EDITBOX|&h001<br>0|Include an edit control in the dialog to allow user to type a path|
|BIF_VALIDATE|&h002<br>0|Don't allow user to type an invalid name in the edit box|
|BIF_NEWDIALOGSTYLE|&h004<br>0|New style of dialog; offers several enhancements over original<br>style (resizing, drag/drop, new folder button, delete, etc.)|
|BIF_USENEWUI|&h005<br>0|Combination of BIF_NEWDIALOGSTYLE and BIF_EDITBOX|
|BIF_BROWSEINCLUDEUR<br>LS|&h008<br>0|Allow display of URLs (requires BIF_USERNEWUI +<br>BIF_BROWSEINCLUDEFILES)|
|BIF_UAHINT|&h010|With BIF_NEWDIALOGSTYLE and not BIF_EDITBOX, displays a|



A-Shell Reference 

Page 3008 

|**Flag**|**Value**|**Description**|
|---|---|---|
||0|standard hint to the user in place of the edit box.|
|BIF_NONEWFOLDERBUTT<br>ON|&h020<br>0|Eliminates the "New Folder" button|
|BIF_KBDLOCKLATETARGE<br>TS|&h040<br>0|Don't traverse target as shortcut|
|BIF_BROWSEFORCOMPUT<br>ER|&h100<br>0|Only allow selection of computers|
|BIF_BROWSEFORPRINTE<br>R|&h200<br>0|Only allow selection of printers. Automatically sets the RootID to<br>CSIDL_PRINTERS unless RootID is already non-zero.|
|BIF_BROWSEINCLUDEFIL<br>ES|&h400<br>0|Dialog displays files as well as folders|
|BIF_SHAREABLE|&h800<br>0|Dialog can display shareable resources on remote systems|
|**Definition file: ashell.def**|||



**See Also** 

A-Shell Reference 

Page 3009 

- AG_BROWSEFOLDER for the equivalent Print Tab command. 

- MX_GETOFD to browse for an select files. 

- The sample program MIAMEX.BP in EXLIB:[908,30] for an example of this function. 

A-Shell Reference 

Page 3010 

## **MX_GETSHELLPATH** 

## **xcall MIAMEX, MX_GETSHELLPATH, csidl, folder {,clisvr}** 

MX_GETSHELLPATH (MIAMEX 171) is used for retrieving the actual directory path for a specified Windows directory ID using the CSIDL_xxx values. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_csidl_ (Num)  [in] 

numeric ID of the logical directory, using its standard CSIDL_xxx identifiers 

. 

_folder_ (String)  [out] 

returns the physical directory path name corresponding to _csidl_ . 

## _clisvr_ (String)  [in] 

may be set to "S" (for server), or "L" (for local, which is the same as server in this context); anything else is treated as meaning "client". The option only has significance in the ATSD environment where the possibility exists of performing the function relative to the ATSD server or the client. In all other cases, the parameter is ignored and the operation is performed relative to the client, or returns an empty string if an applicable client is not present. 

## **See Also** 

- MX_BROWSEFOLDER 

- AG_GETSHELLPATH 

A-Shell Reference 

Page 3011 

## **MX_PWCRYPT** 

_Update May 2014; see History_ 

## **xcall MIAMEX, MX_PWCRYPT, pwin, pwout {,mode, seed, key}** 

MX_PWCRYPT (MIAMEX 172) is used for for password encryption. It is useful for use in GDI files to avoid revealing SMTP passwords. 

## **Modes 1 and 2** 

You specify _pwin_ , the clear text version of password, and it returns _pwout_ , the encrypted version. Note that this is a relatively simplistic password encryption mechanism known to A-Shell and ATE, which is recognized by the fact that the first character will be a chr(2). If you have a need to decrypt them, contact MicroSabio for details. We did not publish the decryption scheme because doing so would compromise what limited security the routine offers. 

The optional _mode_ argument allows you to create the original 7-bit style password encryption used by earlier versions of ATE, in addition to the newer 8-bit style. The two types of encrypted passwords can be distinguished by the first byte: chr(1) indicates type 1 (7 bit), while chr(2) indicates type 2 (8 bit). 

## **Mode 3** 

Encryption mode 3 provides a stronger alternative to modes 1 and 2 for passwords and other short strings up to 44 characters in length. The encrypted strings are a convenient and uniform 68 MIME characters long, plus an ASCII 3 identifying prefix, making them easy to insert into both fixed-length data fields and text files (print files, configuration files, etc.) Based on a blowfish-class, 256-bit, seed-generated key incorporating both randomized "salt" and "pepper", it is strong enough to eliminate the need to hide them from public view. 

In most of the places where A-Shell currently accepts encrypted passwords—e.g. //PDFX files, EMAILX configuration files, FTPDLX[XS] , etc—you can now specify a mode-3 encrypted password. 

## Also note: 

- Due to the randomized salt and pepper, successive encryptions of the same password, using the same seed and key, will still 

- generate entirely different encryption strings. 

A-Shell Reference 

Page 3012 

- To generate a mode 3 encryption string for //PDFX.Email.SMTP.Password, specify the SMTP.Username value as the seed and 

- omit the key parameter. Also make sure that the SMTP.Username always appears in the print file prior to the SMTP.Password. 

- Similarly, for a mode 3 encrypted password compatible with FTP2[XS] , use the FTP user name as the seed. 

- For EMAILX, use the SMTP username as the seed; requires EMAILX[XS] 5.1.128. 

## **Parameters** 

_pwin_ (String)  [in] 

The password to encrypt or decrypt. In the case of encrypt, it should be no more than 44 characters. For decrypt, it should contain the prefix byte indicating the encrypt mode followed by the encrypted string, null terminated. 

## _pwout_ (String)  [out] 

The encrypted or decrypted result. For encryption, the first byte will be chr(1) for mode 1, chr(2) for mode 2, or chr(3) for mode 3. This allows generalized decryption logic to know which scheme to use. For modes 1 and 2, the remainder of the string will equal the length of the PWIN parameter. There may be embedded control characters, but no embedded nulls. 

For mode 3 encryption, the remainder of the string will consist of 68 MIME characters, regardless of the length of the original unencrypted string. Accounting for the prefix and trailing null, you should allow 70 characters for storage. 

## _mode_ (Num)  [in] 

Indicates the operation and encryption mode. For encryption, specify the desired mode (1, 2 or 3). For decryption, specify 0. Note, however, that to protect the security of encrypted strings which may be publicly visible in text files, decryption is not supported in the subroutine, except for mode three when you supply your own key, for which see below. If not specified, encryption method 2 will be used. 

_seed_ (String, 64)  [in] (applies to mode 3 only) 

Affects the way the encryption key is generated. For passwords, you may want to specify the user name as the _seed_ , making it that much more difficult for anyone to reverse engineer the key or otherwise break the encryption. May be blank. 

_key_ (x,32)  [in]  (applies to mode 3 only) 

A-Shell Reference 

Page 3013 

The base key used for the encryption or decryption. Note that it is not the actual encryption key; instead, it is used along with _seed_ and other factors to generate the actual key. It may be omitted or set to all nulls when encrypting in order to use the standard A-Shell encryption key scheme, which can be decrypted internally by A-Shell using internal defaults, allowing it to be used in most places where a password is required; see the notes under Mode 3 above. 

Note however, that while A-Shell internally knows how to construct the key needed for decryption, to protect the security of such encrypted strings, the automatic decryption capability is not exposed in the subroutine interface. If you want to use MX_PWCRYPT for encrypting and decrypting passwords within your application, you will need to use mode 3 and supply your own explicit key for both operations. 

Note also that key is an unformatted 32 byte (256 bit) field, possibly containing nulls. You should use some kind of randomized algorithm to fill the 32 bytes with random values distributed across the bit space, rather than using a simple string like "rosebud". 

## **See Also** 

- CRYPTOXS 

- BLOFSHXS 

## **History** 

- 2014 May, A Shell 6.1.1385: Add mode 3. 

A-Shell Reference 

Page 3014 

## **MX_SHORTCUT** 

_Updated September 2014_ 

## **xcall MIAMEX, MX_SHORTCUT, target, lnkspec {, descr, workdir, icon, iconidx, status}** 

MX_SHORTCUT (MIAMEX 173) creates a shortcut, on the desktop or in any other folder. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

## _target_ (String)  [in] 

should be set to the object or command line that the shortcut links to. Any %ENV% vars will be pre-resolved, i.e. at the time the link is created (rather than when it is clicked on). Examples: 

```
TARGET = """%MIAME%\bin\ashw32.exe"" -i ""%MIAMEFILE% abc"""
```

```
TARGET = "http://www.microsabio.com"
```

```
TARGET = """c:\company shared folders\readme.txt"""
```

Note: as shown above in the first and third example, you must supply literal quotes as needed to enclose any path compoents of the _target_ command line that may contain embedded spaces. (In the first example, we don't know if %MIAME% or %MIAMEFILE% will contain embedded spaces, so we quote them to be safe.) 

## _lnkspec_ (String)  [in] 

should be set the full filespec of the shortcut itself. The default extension is ".lnk"; any other extension may fail to be recognized by the Explorer as a shortcut (or "Shell Link"). _lnkspec_ does not require literal quoting even if contains embedded spaces. Example: 

```
LNKSPEC = "C:\vm\miame\test shortcut.lnk"
```

Note that the filename (minus the .lnk extension and directory) will appear under the icon when in icon view, i.e. "test shortcut" in the above example. 

A-Shell Reference 

Page 3015 

To put the icon on the user's desktop, you can use the %USERPROFILE% environment variable, e.g.: 

```
LNKSPEC = "%USERPROFILE%\Desktop\check this out.lnk"
```

For the common or "all users" desktop, use "%ALLUSERSPROFILE% instead of %USERPROFILE%, but beware that the operation may be blocked by a variety of security restrictions, and will require elevation under Vista. 

See Comments, below. 

_descr_ (String)  [in] 

may specify a description to be embedded within the shortcut properties. 

_workdir_ (String)  [in] 

may specify the starting working directory for the process when the _target_ is launched. It does not require quoting. 

_icon_ (String)  [in] 

may specify a separate file from which the display icon should be taken. It does not require quoting. If not specified, then the first icon of the executable associated with the _target_ will be used. (If you want to user another icon from that executable, you must specify the module name again here.) 

_iconidx_ (Num)  [in] 

may specify the icon index (0,1,2,...) of the icon within the file (default is 0, the first icon). Ignored unless _icon_ is not blank. 

_status_ (F)  [out] 

the return status. 0=ok. Positive numbers are Windows system error codes. (See MX_ERRNOMSG to display text). -1 indicates no GUI support available (requires Windows or ATE), and -15 indicates that ATE did not respond.. 

## **Comments** 

Note that any %ENV% environment variables will be resolved relative to the computer on which this function is invoked. In the case of ATE, that would be the server, whereas you probably want it to be relative to the client desktop. To solve that, you will have to use the AG_GETENV command separately (preferably via MX_AGWRAPPER) to resolve client-specific environment variables, such as %USERPROFILE%, and then pass the resolved value. 

A-Shell Reference 

Page 3016 

## **Example** 

The following would work on either local A-Shell Windows or ATE to create a shortcut on the client desktop, called "test shortcut" which executes the specified ATE launch command. Note for simplicity we are assuming here that the directory c:\ate contains an installation of ATE. To be more general you would need to use additional inquiry commands to determine the environment and the installed location of ATE, if applicable. 

```
program shortcut,1.0(100) ! create shortcut
```

```
++include ashinc:ashell.def
```

```
map1 misc
```

```
map2 cmd$,s,260
```

```
map2 icon$,s,260
```

```
map2 status,f
```

```
map2 lnkspec$,s,260
```

```
icon$ = "ashell1_t.ico"  ! borderless A-Shell icon
```

```
cmd$ = "c:\ate\bin\ashw32.exe -i c:\ate\miame.ini -g "+icon$+" -atecfg ?"
```

```
icon$ = "c:\ate\icons\" + icon$
```

- `! note: for ATE, we have to first resolve any client-side env vars,` 

- `!    in this case, %USERPROFILE%...` 

- `!    (extra step is harmless in local Windows case)` 

A-Shell Reference 

Page 3017 

```
xcall MIAMEX, MX_AGWRAPPER, AG_GETENV, "%USERPROFILE%,1",lnkspec$
```

```
! put the shortcut on the users's desktop
lnkspec$ += "\Desktop\test shortcut.lnk"
```

- `? "Creating shortcut ";lnkspec$` 

```
xcall MIAMEX, MX_SHORTCUT, cmd$, lnkspec$, &
```

```
"Description of shortcut", "c:\ate", icon$, 0, status
```

- `? "Status: ";status` 

```
end
```

## **See Also** 

- AG_SHORTCUT 

## **History** 

2014 September: Added "Comments" and "Example" 

A-Shell Reference 

Page 3018 

## **MX_STRCMP** 

## **xcall MIAMEX, MX_STRCMP, s1, s2, flags, result** 

MX_STRCMP (MIAMEX 174) compares two strings in various ways. 

## **Parameters** 

_s1, s2_ (String)  [in] 

are the strings to compare. Only the first 256 characters are considered. 

_flags_ (Num)  [in] 

may be set to one or more of the following: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|STRCMPF_LDF|&h01|Use LDF collating sequence|
|STRCMPF_NAT|&h02|Use "natural" compare (see "natural sort" above)|
|STRCMPF_FOLD|&h04|Case insensitive comparison|
|**Definition file: ashell.def**|||



_result_ (Signed Num)  [out] 

A-Shell Reference 

Page 3019 

|**Value**|**Meaning**|
|---|---|
|<0|s1 < s2|
|>0|s1 > s2|
|0|s1 = s2|



## **Comments** 

With flags=0, you should get nearly the same results as in the standard BASIC string comparison, except that BASIC string comparison ignores trailing blanks, while MX_STRCMP only ignores them if the "natural" flag is set. 

The standard BASIC string comparison does not take into account the LDF collating sequence, so for example it will treat accented characters as sorting above the non-accented equivalent. 

Unless you modify the LDF accordingly, the standard LDF collating sequences do not change the order of the ASCII characters 1- 127, so even with the LDF option, lower case characters are treated as being greater than upper case. 

You can check the status of the collating sequences in your LDF file by using `DUMP xxxxxx.ldf` ; the lower collating sequence starts at offset CE in the first block, and the upper collating sequence starts at offset CC in the second block. Or, you can use the sample program GTLANG in EXLIB:[908,49]. 

A-Shell Reference 

Page 3020 

## **MX_CHKPCNET** 

## **xcall MIAMEX, MX_CHKPCNET, status, flags {,clisvr}** 

MX_CHKPCNET (MIAMEX 176) checks the network state of the local PC (for A-Shell/Windows) or the ATE client. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_status_ (Signed Num)  [out] 

## returns a value indicating: 

|**Valu**<br>**e**|**Meaning**|
|---|---|
|0|Not connected to internet|
|1|Connected to internet|
|-1|Function not supported: not Windows, ATE not present, or ATE PC version too old|
|-15|ATE did not respond to request|
|-98|Unable to link to required function|
|-99|wininet.dllnot found|



A-Shell Reference 

Page 3021 

Note that since older versions of A-Shell would not have this function supported, you may want to pre-set _status_ to something like -999 so you don't confuse a non-updated _status_ with a real one (or, use MX_GETVER to check the A-Shell version before calling the function). 

Note also for ATE: if A-Shell on the server is 1138.3 or higher, but the ATE PC is not, the function returns STATUS = -1. 

_flags_ (Num)  [out] 

returns flags which can be interpreted as following: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|INTERNET_CONNECTION_CONFIGUR<br>ED|&h004<br>0|local system has a valid connection to the<br>Internet, but it might not be connected.|
|INTERNET_CONNECTION_OFFLINE|&h002<br>0|local system is in offline mode|
|INTERNET_RAS_INSTALLED|&h001<br>0||
|INTERNET_CONNECTION_PROXY|&h000<br>4|local system uses a proxy server|
|INTERNET_CONNECTION_LAN|&h000<br>2|local system uses a LAN to connect|
|INTERNET_CONNECTION_MODEM|&h000|local system uses a modem to connect|



A-Shell Reference 

Page 3022 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||1||



## _clisvr_ (String, 1)  [in] 

may be set to "S" (for server), or "L" (for local, which is the same as server in this context); anything else is treated as meaning "client". The option only has significance in the ATSD environment where the possibility exists of performing the function relative to the ATSD server or the client. In all other cases, the parameter is ignored and the operation is performed relative to the client, or returns an empty string if an applicable client is not present. 

## **See Also** 

- AG_CHKPCNET 

A-Shell Reference 

Page 3023 

## **MX_AGWRAPPER** 

_Reviewed and revised December 2023_ 

## **xcall MIAMEX, MX_AGWRAPPER, agcmd, parms, response {,timeout)** 

MX_AGWRAPPER (MIAMEX 177) serves as a convenient wrapper for "raw" ATE commands that are otherwise invoked via a sequence like: 

```
? TAB(-10,agcmd);parms;chr(127);
```

```
input "",response
```

Aside from simplifying the syntax, MX_AGWRAPPER provides some intelligence to deal with the problem of typeahead that may be "in the pipe" at the time the command was issued and thus get mixed into the response. 

## **Parameters** 

## _agcmd_ (Num)  [in] 

The value of the TAB(-10,x) command to be issued via the wrapper. Normally specified via one of the AG_xxx symbols defined in the ASHINC:ashell.def file (e.g. AG_XFUNCS). 

## _parms_ (String)  [in] 

The list of parameters that would normally follow the AG_xxx function, up to but not including the terminating chr(127). Consult the specifications for the AG_xxx function in question. 

## _response_ (String)  [out] 

Returns the string response which normally would otherwise end up in the keyboard buffer where it would need to be retrieved via an INPUT statement. 

_timeout_ (Num)  [in] 

A-Shell Reference 

Page 3024 

Timeout in milliseconds (0 for infinite), after which the operation will give up waiting for the response and will return with a null response. For commands that are normally quick to respond (e.g. AG_DATETIME), the default timeout is 7500 ms. For certain commands which are known to potentially take a long time to complete (e.g. AG_XFUNC, AG_XFUNCS, AG_FTP, etc.) the default timeout is set to 0 (infinite). You can disable the timeout entirely by setting it to -1 (see _Comments_ , below). 

## **Comments** 

There isn't anything to be gained by using the MX_AGWRAPPER function to issue a command that does not receive a response (e.g. AG_MINTITLE). But if you do, set _timeout_ to -1 to disable the wait for response. Otherwise it will wait for the default timeout (7.5 seconds) to expire. 

Note that many AG_xxx functions already have direct MX_xxx equivalents. The general purpose MX_AGWRAPPER function is mainly of interest when there is no MX_xxx version of the AG_xxx function, or where the MX_xxx version works only on the server side when you really want it to work on the client side. 

## **Example** 

This example illustrates using MX_AGWRAPPER to issue the AG_OPTIONS command (to query the ATE client's option flags). First, the traditional approach: 

```
? tab(-10,AG_OPTIONS);"0";chr(127);
```

```
input "",OPT1,OPT2
```

## And here is the MX_AGWRAPPER version: 

```
xcall MIAMEX, MX_AGWRAPPER, AG_OPTIONS, "0", RESPONSE$
```

```
X = instr(1,RESPONSE$,",")
```

```
OPT1 = RESPONSE$[1,X-1]
OPT2 = RESPONSE$[X+1,-1]
```

A-Shell Reference 

Page 3025 

Or: 

```
dimx OPT(0), s, 0, auto_extend
```

```
xcall MIAMEX, MX_AGWRAPPER, AG_OPTIONS, MXOP_GET, RESPONSE$
OPT() = RESPONSE$       ! OPT(1)=first value, OPT(2)=second
```

Note that in this case, the RESPONSE$ variable would be set to a pair of comma-separated numbers (e.g. "123452,34123"), so we need to extract the values out of the string into individual variables, either by manual parsing (as in the first version), or taking advantage of the direct assignment to an array feature (see Whole Array Assignment).  Either approach may result in more code than in the traditional version, except when when response contains just a single value. But the main benefit of MX_AGWRAPPER is to eliminate the potential complications of the INPUT operation. For example, if the client fails to respond for some reason, or sends just one value instead of two, the INPUT statement will wait forever (possibly displaying a "?"), while the MX_AGWRAPPER call will gracefully timeout. (In the above example, the timeout would default to 7500 ms. We could have specified a shorter timeout, but since it would only matter in the rare case where the client was not responding as expected, it makes more sense to error on the conservative side in order to allow for some unexpected network delay, than to time out prematurely.) 

## **History** 

- 2015 January, A Shell 6.1.1399:  the wrapper routine now handles certain ZTERM legacy commands (AG_FTP, AG_SHLEXEC and AG_WINEXEC) more robustly than before. These commands differ from the standard ATE commands for which MX_AGWRAPPER was designed because they only return a single character, rather than a string with a CR terminator. Previously these worked fine in the case of success, because the successful code of chr(13) matched the response termination character expected by AG_MXWRAPPER. But in the case of failure, the chr(3) response would either abort the program or would be ignored. Now the single character error response (chr(3)) is returned in the MX_AGWRAPPER response parameter, as you would normally expect when using MX_AGWRAPPER. 

A-Shell Reference 

Page 3026 

## **MX_FILEHOOK** 

_Updated September 2017_ 

## **xcall MIAMEX, MX_FILEHOOK, opcode, status, file {,fid, handler, events, flags, enabled}** 

MX_FILEHOOK (MIAMEX 178) allows you to establish file "hooks" on specific files and file events. The "hook" is a means by which you can insert a call to a "handler" (sometimes referred to as a "plug-in") into the midst of what would otherwise be an entirely internal operation, allowing you to monitor, filter, or otherwise customize the operation. Typical uses for file hooks are: 

- audit trails 

- event logs 

- exporting changes 

- enforcing access security rules 

## _opcode_ (Num)  [in] 

may be one of the following (defined in ashinc:hook.def): 

|**Symbol**|**Valu**<br>**e**|**Meaning**|
|---|---|---|
|HOOKOP_DISABL<br>E|0|disable one (or all) hooks|
|HOOKOP_ENABLE|1|re-enable one (or all) hooks|
|HOOKOP_ADD|2|add a new hook|



A-Shell Reference 

Page 3027 

|**Symbol**|**Symbol**|**Valu**<br>**e**|**Meaning**|
|---|---|---|---|
|HOOKOP_DEL||3|delete a hook|
|HOOKOP_APPEVE<br>NT||6|call the hook to process an app-defined event|
|HOOKOP_QRY||7|query a file hook by its fileid or filespec. If found, the status will be >= 0<br>and all of the remaining fields will be returned. See the sample/utility<br>programQRYHOOKS in EXLIB:[908,50]<br> for examples of querying the<br>file hook table.|
|**Definition File:**ashinc:hook.def||||
|ignedNum<br>)  [out]<br>atus code:<br>**Valu**<br>**e**<br>**Meaning**<br>>=0<br>success<br>-1<br>unable to allocate memory for hook table||||
|**Valu**<br>**e**|**Meaning**|||
|>=0|success|||
|-1|unable to allocate memory for hook table|||



## _status_ (Signed Num)  [out] 

## returns status code: 

A-Shell Reference 

Page 3028 

|**Valu**<br>**e**|**Meaning**|
|---|---|
|-2|illegal fspec (must be AMOS-style)|
|-3|invalid handler syntax|
|-4|fspec not found (_opcode_0,1,2,6)|
|-5|fid not found (_opcode_0,1,2,6)|
|-6|opcode not yet implemented|
|-7|illegal opcode|



## _file_ (String)  [in] 

is the specification of the file whose operations are to be hooked. Only AMOS-compatible filespecs are supported. Note that with _opcode_ 0, 1 and 3, _file_ may be "*" to perform the operation on all the hooks in the hook table. Note that in the case of ISAM and ISAM-A files, you must specify the extension, typically IDA or DAT. 

## _fid_ (Num)  [in] 

a unique integer identifier for the file, which will be used in any output files to reference the file (more compact than outputting the file spec each time.) 

_handler_ (String)  [in] 

A-Shell Reference 

Page 3029 

depends on opcode. For opcode 2 (HOOKOP_ADD), it must specify the handler for the hook, using one of the following syntax variations: 

```
SBX:sbxnam
```

```
LOGFIL:fspec
```

In the case of the `SBX:sbxnam` handler, A-Shell will XCALL the specified SBX subroutine (sbxnam) to process the hook, allowing you to add custom logic into the file operation in real time. Note that `sbxnam` is limited to a maximum of six characters, e.g. SBX:AROPEN. In the case of the `LOGFIL:fspec` handler, A-Shell uses its own built-in logic to output information about the event to the specified file, allowing you to process the log file later. Each type of hook is described in greater detail in the sections that follow. 

For _opcode_ 6 (HOOKOP_APPEVENT), the _handler_ parameter may be used to pass an arbitrary string to the handler previously set up by opcode 2. Typically this may be used to send a contextual message to the handler, such as "starting check run" or "posting run complete". 

_events_ (B4)  [in] 

a bit-field of events to hook, from the following (defined in ashinc:hook.def): 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|HFE_PRE_OPEN|&h00000001|prior to open|
|HFE_POST_OPEN|&h00000002|after open|
|HFE_PRE_CLOSE|&h00000004|prior to close|
|HFE_POST_CLOSE|&h00000008|after close|



A-Shell Reference 

Page 3030 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||||
|HFE_PRE_READ|&h00000010|prior to read or get (any)|
|HFE_POST_READ|&h00000020|after read or get (any)|
|HFE_PRE_READL|&h00000040|prior to readl or getl|
|HFE_POST_READL|&h00000080|after readl or getl|
|HFE_PRE_WRITE|&h00000100|prior to write (or update'record)|
|HFE_POST_WRITE|&h00000200|after write (or update'record)|
|HFE_PRE_WRITEL|&h00000400|prior to writel (or create'record)|
|HFE_POST_WRITEL|&h00000800|after writel (or create'record)|
|HFE_PRE_ALLOC|&h00002000|prior to allocate|
|HFE_POST_ALLOC|&h00004000|after allocate|



A-Shell Reference 

Page 3031 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|HFE_PRE_KILL|&h00008000|prior to kill|
|HFE_POST_KILL|&h00010000|after kill|
|HFE_PRE_SORT|&h00020000|prior to sort|
|HFE_POST_SORT|&h00040000|after sort|
|HFE_ISAM_ADD|&h00080000|after ISAM 5 (add); see History|
|HFE_ISAM_DEL|&h00100000|after ISAM 6 (delete); see History|
|HFE_PRE_ISAMA_DEL|&h00200000|ISAM-A pre delete'record|
|HFE_POST_ISAMA_DEL|&h00400000|ISAM-A post delete'record|
|HFE_APP_EVENT1|&h10000000|custom application event|
|**Definition File:**ashinc:hook.def|||



_flags_ (B4)  [in] 

A-Shell Reference 

Page 3032 

a bit-field of flags which are passed to the hook routine (as a clue to how the hook should operate), and/or which are used by A- Shell to modify the operation of the hook (from ashinc:hook.def): 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|HFF_PROG|&h00000001|include program name|
|HFF_SBX|&h00000002|include sbx name|
|HFF_DATA|&h00000004|include copy of data just written (POST_WRITE only)|
|HFF_DATA_WAS|&h00000008|include copy of data as previously read or written, for comparison with data<br>now being written (POST_WRITE only)|
|HFF_RECNO|&h00000010|include recno|
|HFF_TIME|&h00000020|include time|
|HFF_DATE|&h00000040|include date|
|HFF_TIMESTAMP|&h00000060|Include timestamp in log for each event|
|HFF_USER|&h00000080|include user name|
|HFF_PID|&h00000100|include process id|



A-Shell Reference 

Page 3033 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|HFF_AUTO_DEL|&h00001000|auto delete hook on prog exit|
|HFF_SQZ_ENV|&h00080000|'squeeze' env rec (LOGFIL: hooklogs)|
|HFF_DATA_WAS_NA|&h00010000|there is no "was" data available to pass to the hook routine in response to the<br>HFF_DATA_WAS flag|
|HFF_DATA_CHG_ONLY|&h00020000|may be used in conjunction with HFE_POST_WRITE to suppress calling the<br>hook function after the write if the record data hasn't changed.|
|HFF_SQZ_DATA|&h00100000|'squeeze' data recs (LOGFIL: hooklogs)|
|**Definition File:**ashinc:hook.def|||



Note that for the SBX handlers, most of the flags affecting the data that is included in the information passed to handler are ignored. The packet is a fixed size and there is nothing to be gained by blanking out certain fields. The flags which do matter are: HFF_DATA and HFF_DATA_WAS, HFF_DATA_CHG_ONLY, and HFF_AUTO_DEL. 

_enabled_ (Num)  [out] 

returns zero or one to indicate if the hook is disabled or enabled. 

**Comments** 

A-Shell Reference 

Page 3034 

Hook definitions are not directly affected by file open and close operations. Nor are they affected by termination of the program unless the HFF_AUTO_DEL flag is specified when the hook is established. They are automatically removed by termination of the A-Shell session. So you can add/delete all your file hooks in a common application startup/shutdown program, without making any modifications to the individual programs which operate on the files. 

MX_FILEHOOK works with random, ISAM, and ISAM-A files. In the case of ISAM and ISAM-A files, only the data file is hooked. 

## Use the following pattern to establish a file hook... 

```
    ++include'once ashinc:ashell.def
```

```
    ++include'once ashinc:hook.def
```

```
    define FID_CUST    = 1001            ! file ID for customer file
```

```
map1 hook'vars
```

```
    map2 hook'status,f
    map2 hook'file$,s,40
    map2 hook'fid,b,4
    map2 hook'handler$,s,16
    map2 hook'events,b,4
    map2 hook'flags,b,4
```

```
hook'file$    = "DSK2:CUST.DAT[100,50]"
hook'fid      = FID_CUST
```

A-Shell Reference 

Page 3035 

```
hook'handler$ = "SBX:MYHOOK"
```

```
hook'events   = HFE_POST_OPEN or HFE_POST_WRITE or HFE_POST_WRITEL or HFE_POST_CLOSE or HFE_PRE_ALLOC
```

```
hook'flags    = HFF_PROG or HFF_SBX or HFF_RECNO or HFF_TIME or HFF_DATE  &
```

```
xcall MIAMEX, MX_FILEHOOK, HOOKOP_ADD, hook'status, hook'file$, hook'fid, hook'handler$, hook'events,
hook'flags
```

```
if hook'status < 0 then ? "Error setting hook: ";hook'status
```

After the above code is executed the hook handler (MYHOOK.SBX) will be called after every open, write, writel and close operation on the file DSK2:CUST.DAT[100,50], and also every allocate operation on the file. See the following topic Hook SBX Specification. 

The above example could be changed to use the LOGFIL: handler instead, by changing the `hook'handler$` assignment to something like: 

```
hook'handler$ = "LOGFIL:APPLOG:FILEIO.LOG
```

or 

```
hook'handler$ = "LOGFIL:dsk0:audit.log[1,2]
```

- - See the following topics, File Based File Hook Handler and MX_FILEHOOK Support for ISAM A, for more details. 

- - 2018 July, A Shell 6.5.1642: Added _handler_ LOGFIL: and File Based File Hook Handler to A-Shell 

- 2015 February, A Shell 5.1.1402: Added events HFE_ISAM_ADD and HFE_ISAM_DEL. Note that unlike most of the other file hooks, these don't come in PRE- and POST-flavors. For the ADD hook, the record data supplied to the hook routine ( _rec_ parameter) will 

A-Shell Reference 

Page 3036 

contain the key rather than the record data. Since ISAM adds are followed by a WRITE statement, you can hook that to get the contents of the record itself. For the DEL hook, the record data of the record being deleted is supplied to the hook routine in the _pre'rec_ parameter. The _rec_ parameter should be ignored. The sample hook program FHOOKTST3.BP and hook subroutine FHOOK1.SBX in EXLIB:[908,50] have been updated to illustrate both hooks. 

A-Shell Reference 

Page 3037 

## **HOOK SBX SPECIFICATION** 

_Updated November 2016_ 

The SBX you specify to handle the hook will be called automatically by A-Shell for the specified events, as follows: 

## **xcall <NAME>, sts, envelope, rec, pre'rec** 

## **Parameters** 

## _sts_ (Num)  [in] 

returns 0 for ok. Any odd value returned from a HFE_PRE_xxx event will cause A-Shell to skip the event. This allows you to completely replace the file operation originally programmed, with one of your own. 

## _envelope_ (ST_HOOK_ENV structure)  [in] 

a structure containing the following information (defined in ashinc:hook.def): 

|**Field**|**Type **|**Meaning**|
|---|---|---|
|event|b,4|event code (see HFE_xxxx flags)|
|flags|b,4|event processing flags (see HFF_xxx)|
|fileid|b,4|unique file id #|
|recno|f,8|rec #. Note that this will always be zero-based, regardless of the<br>actualFILEBASEsetting in either the hook SBX or in the main<br>program.|
|pid|b,4|process id|



A-Shell Reference 

Page 3038 

|**Field**|**Type **|**Meaning**|
|---|---|---|
||||
|recsiz|b,4|record size|
|mode|b,4|mode (depends on event)|
|prog|s,16|program name|
|sbx|s,16|sbx name (if appl)|
|user|s,24|user name|
|chan|b,4|actual file channel; might not match fileid|
|locatio<br>n|b,4|location counter|
|lineno|b,2|last line number|



## _rec_ (String or x)  [in] 

contains data relative to the event. For the HFE_POST_READx and HFE_xxxx_WRITEx events, it will contain the record data which was just read or which is to be (or was just) written. For the OPEN, ALLOC and KILL events, it will contain the filespec (in 

A-Shell Reference 

Page 3039 

native format). For the APPEVENT event, it will contain the contents of the HANDLER$ parameter passed to the MX_FILEHOOK call. For other events, it may be undefined. 

## _pre'rec_ (X)  [in] 

used only with the HFE_POST_WRITE event, when the HFF_DATA_WAS flag is set, in which case it will contain the previous contents of the record (at the time of the last read or write operation on the file). **Warning:** this mechanism only works when no other records in the same file were accessed since the last read or write of this record. If other accesses have occurred, the contents of pre'rec will be empty. 

## **Comments** 

The sample hook FHOOK1 and sample program FHOOKTST1 can be found in EXLIB:[908,50]. 

## **Comments** 

- 2016 November, A Shell 6.3.1538:  Add _envelope_ fields channel, location and line number. These are mostly motivated by the desired to use the hook mechanism for application forensics that for more traditional purposes (export, data audit), i.e. they allow the hook return to more information context in which the file operation occurred. The new fields do not break compatibility with existing hook routines, nor do hook routines using the expanded structure lose their backwards compatibility; the new fields just won't be available. See ASHINC:HOOK.DEF for the updated structure and related symbol defintions. 

A-Shell Reference 

Page 3040 

## **- FILE BASED FILE HOOK HANDLER** 

_Added July 2018_ 

Beginning with A-Shell 6.5.1642 of August 2018, a file-based file hook handler option may be specified by setting the MX_FILEHOOK handler parameter to LOGFIL:fspec where fspec is the AMOS- or native-style file spec for the hook log file. Intead of calling an SBX for each hooked event, it writes an event record to the log file. 

The potential advantages of the LOGFIL: handler over the original SBX: handler are: 

- It separates and optimizes the part of the operation that is time sensitive—the event handling itself—from the part which isn't 

- —the final or back-end processing of the event records, whether for auditing, replication to remote databases, or simply archival. The time sensitive part event handling part is considerably faster than the SBX event handlers, creating less drag on the application. 

- It is easier to implement, since the handler itself requires no programming or debugging. You still need to write some code to 

- process the log file created by the handler, but there is typically little time sensitivity for that. 

- It allows for multiple hook processes per file without any additional impact on the application's real-time performance, since 

- the logs can be processed multiple times by multiple processes any time later. 

- The log files can be processed on remote machines, either by writing the log files to a network-mounted directory, or 

- transferring them to another machine for final processing. 

Three new flags have been added to the ASHINC:HOOK.DEF to support new  options associated with the new handler: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|HFF_TIMESTA<br>MP|&h000000<br>60|Include timestamp in log for each event|
|HFF_SQZ_ENV|&h000800<br>00|'squeeze' env rec (LOGFIL: hooklogs)|
|HFF_SQZ_DA|&h001000|'squeeze' data recs (LOGFIL: hooklogs)|



A-Shell Reference 

Page 3041 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|TA|00||



## The timestamp uses the following structure (HOOK.DEF) : 

```
defstruct ST_HOOK_TIMESTAMP
```

```
    map2 date,b,4           ! separated date format
    map2 msecs,b,4          ! milliseconds since midnight
```

```
endstruct
```

Each event record in the hook log file consists of the following fields, most of which are equivalent to the parameters passed to the SBX version of the hook, and each of which is preceded by a prefix byte—represented below as [hex value]—to help ensure correct/synchronized/adaptable interpretation of the log. Note that some of the fields come in raw or 'squeezed' versions, depending on HFF_xxx flags passed to MX_FILEHOOK. This is described in further detail below. 

|**Symbol**|**Description**|
|---|---|
|[&h80]<version>|start event prefix followed by version, currently 1|
|[&h82]<timestamp>|(optional) timestamp, ST_HOOK_TIMESTAMP|
|[&h83]<env>|uncompressed hook env, ST_HOOK_ENV|



A-Shell Reference 

Page 3042 

|**Symbol**|**Description**|
|---|---|
|[&h84]<squeezed env>|'squeezed' version of hook env|
|[&h85]<prerec>|raw prerec (rec deleted or prior to update)|
|[&h86]<squeezed<br>prerec>|'squeezed' version of prerec|
|[&h87]<rec>|raw rec (updated record)|
|[&h88]<squeezed rec>|'squeezed' version of rec|
|[&h8A]<app msg>|msg from app with HOOKOP_APPEVENT; max 256<br>chars|
|[&h8F]|event record terminator|



- The timestamp field is included if the HFF_TIMESTAMP—HFF_TIME or HFF_DATE—flag is set in the MX_FILEHOOK call. 

• The env (environment) field—ST_HOOK_ENV, identical to the environment passed to the SBX handler—is always included; either in raw format (default) or, in 'squeezed' format if the HFF_SQZ_ENV flag was passed to MX_FILEHOOK. 

A-Shell Reference 

Page 3043 

- The prerec and rec fields are included under the same conditions that they would be passed to the SBX form of the hook. By 

- default they are in raw (binary) format but may be 'squeezed' if the HFF_SQZ_DATA flag was passed to MX_FILEHOOK when the hook was established. 

- The app msg field is only present if MX_FILEHOOK is called to send an app-defined message to the hook. 

• The 'Squeezed' format is an A-Shell-specific lightweight data compression scheme designed explicitly for typical data records. These are typically too small for other compression algorithms, 32 bytes to maybe 4K, and because the most common data storage formats used in fixed length records are likely to have consecutive runs of nulls, spaces, zeroes, and/or brackets ("]"). The 'squeezed' format reduces all such consecutive runs of 3-63 bytes to 2 bytes. The penalty is that individual bytes of value &hDD (221) are also encoded into 2 bytes. So the worst case scenario would be a record where every other byte is &hDD, which would be 50% larger in the 'squeezed' format than the raw. But that is an exceedingly minute likelihood; in the vast majority of cases, the 'squeeze' will result in a significant reduction in the log file size. 

The module FNFHOOKLOG.BSI in SOSLIB[907,10] provides a convenient function, Fn'Hooklog'Read'Event(), which is able to split out an event record from the log, whether squeezed or not, into the various fields. 

The test/demo program FHOOKTST4.BP in EXLIB:[908,50] illustrates both initializing a LOGFIL: hook handler but also reading from the log created, producing a CSV file representation. 

## **History** 

- 2018 July, A Shell 6.5.1642: Function added to A-Shell 

A-Shell Reference 

Page 3044 

## **- MX_FILEHOOK SUPPORT FOR ISAM A** 

The following table summarizes the event flags to use for hooking the various ISAM-A operations. 

|**Symbol**|**ISAM-A File Operation**|
|---|---|
|HFE_xxx_WRITE|UPDATE'RECORD|
|HFE_xxx_WRITE|UPDATE'RECORD|
|HFE_xxx_WRITEL|CREATE'RECORD|
|HFE_xxx_ISAMA_D<br>EL|DELETE'RECORD|
|HFE_xxx_READ|GET, GET'NEXT, GET'PREV (optional<br>'READ'ONLY)|
|HFE_xxx_READL|GET'LOCKED, GET'NEXT'LOCKED,<br>GET'PREV'LOCKED|
|HFE_xxx_ALLOC|ALLOCATE'INDEXED|



## The DELETE'RECORD hook is enabled by one of the two event flags in HOOK.DEF in ASHINC: 

```
define HFE_PRE_ISAMA_DEL=  &h00200000  ! ISAM-A pre delete'record
```

A-Shell Reference 

Page 3045 

```
define HFE_POST_ISAMA_DEL= &h00400000  ! ISAM-A post delete'record
```

GET'LOCKED and GET'NEXT'LOCKED are hooked like READL, while GET and GET'NEXT (without locking) are hooked like READ. Use the HFE_xxx_READL and/or HFE_xxx_READ flags to enable. 

ALLOCATE'INDEXED is hooked like ALLOCATE (HFE_xxx_ALLOCATE flags). 

A sample program, ISPTSTH.BP in EXLIB:[908,50] is available to demonstrate and test the ISAM-A hooks. Also see fnhooklog.bsi in SOSLIB[907,10] for the applicable hook event flags. 

## **History** 

- 2019 March, A Shell 6.5.1658:  Function added to A-Shell 

A-Shell Reference 

Page 3046 

## **MX_AGINTERPROC** 

## **xcall MIAMEX, MX_AGINTERPROC, hwnd, agcmd, msg, status** 

MX_AGINTERPROC (MIAMEX 179) provides for sending AG commands between instances of A-Shell/Windows. 

## **Parameters** 

_hwnd_ (B4)  [in] 

is the target window handle (use MX_FINDWINDOW to get it) 

_agcmd_ (Num)  [in] 

is a value in the range of 1 to 99 corresponding to the AG_xxx functions. 

_msg_ (String)  [in] 

is the text string normally following the AG_xxx function (must be terminated with chr(127)!!! _status_ (Signed Num)  [out] 

returns a status code indicating the success of the operation: 

|**Statu**<br>**s**|**Meaning**|
|---|---|
|1|OK (target received and processed msg)|
|0|No response from target|
|-1|Target received msg but rejected it as invalid|



A-Shell Reference 

Page 3047 

|**Statu**<br>**s**|**Meaning**|
|---|---|
|-2|Missing trailing chr(127) on message|
|-3|Target HWND not found|



A-Shell Reference 

Page 3048 

## **MX_IATIMEOUT** 

_Modifed June 2017 (added second paragraph to Comments)_ 

## **xcall MIAMEX, MX_IATIMEOUT, opcode, timesecs** 

MX_IATIMEOUT (MIAMEX 180) allows querying / setting the inactivity timeout. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 (mxop_get) to retrieve, 1 (mxop_set) to set 

_timesecs_ (Num)  [in, out] 

Timeout value in seconds. If _opcode_ =0, the current timeout setting (or zero if disabled) is returned here. Otherwise the value passed in _timesecs_ is used to reconfigure the current inactivity timer. 

## **Comments** 

Note that unlike the case in miame.ini IATIMEOUT property, which uses units of minutes, the MX_IATIMEOUT function uses units of seconds. 

In ATE GUI environments, chances are that an inactivity timeout will occur while the ATE client is waiting on input within a local client context, in which case it will not detect that the server-side process received a timeout signal, or even that the connection has been terminated from the server side. To avoid that, set the inactivity timeout on the client (using AG_IATIMEOUT) rather than on the server side. Such a timeout will cause ATE to initiate a disconnect, which will generate a SIGHUP signal sent to the application process on the server, resulting in error 250. 

## **See Also** 

- AG_IATIMEOUT 

- IATIMEOUTSP 

A-Shell Reference 

Page 3049 

- Trapping Timeouts and Closed Windows 

A-Shell Reference 

Page 3050 

## **MX_CSVDELIM** 

## **xcall MIAMEX, MX_CSVDELIM, opcode, delim** 

MX_CSVDELIM (MIAMEX 181) allows the CSV delimiter to be set or retrieved. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 (mxop_get) to retrieve, 1 to (mxop_set) set 

_delim_ (String, 1)  [in/out] 

the delimiter retrieved (opcode 0) or to be set (opcode 1) 

## **Comments** 

When set, the specified delimiter overrides the one normally used by the WRITECD and INPUT CSV statements. 

The setting persists for the remainder of the session, or until changed explicitly by another call to MX_CSVDELIM. 

To restore the default behavior, in which the delimiter is determined by the most prevalent of the four typical delimiter characters—comma, semicolon, colon, and tab—in the first line of the file, set the delim to "" (null). 

## **Example** 

```
XCALL MIAMEX, MX_CSVDELIM, 0, OLD'DELIMITER$        ! retrieve original
```

```
XCALL MIAMEX, MX_CSVDELIM, 1, NEW'DELIMITER$        ! set new
```

```
OPEN #CH, FILE$, INPUT
```

```
XCALL MIAMEX, MX_CSVDELIM, 1, OLD'DELIMITER$        ! reset to original delimiter (won't affect this file)
```

A-Shell Reference 

Page 3051 

```
INPUT CSV #CH, VAR1, VAR2, ...                      ! (uses NEW'DELIMITER$)
```

A-Shell Reference 

Page 3052 

## **MX_SETERR** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_SETERR, errnum {,chan}** 

MX_SETERR (MIAMEX 182) triggers an ASB error. It may be useful for testing/debugging error handling routines, as well as for using the error trapping mechanism as a way of passing coded signals (i.e. virtual error codes) from within an arbitrarily nested function/procedure up to the main error trap. 

## **Parameters** 

_errnum_ (Num)  [in] 

the ASB error to trigger; sets ERR(0) 

_chan_ (Num)  [in] 

channel number; sets ERR(2) 

## **Comments** 

MX_BASERR is an alias for MX_SETERR, meaning that calls to MX_BASERR invoke MX_SETERR. 

## **See Also** 

- ERR() 

- Error Trapping 

A-Shell Reference 

Page 3053 

## **MX_ATEFILEXFR** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_ATEFILEXFR , hostfile, pcfile, status** 

MX_ATEFILEXFR (MIAMEX 183) provides file client-to-server transfer capability for the ATE/ATSD environment, where such transfers are otherwise inconvenient due to the typical lack of an FTP service. It uses the keyboard channel to send the raw data from the client to the server, independent of routers, firewalls, etc. A-Shell 6.1.1357 or later is required on both the server and the ATE client. 

## **Parameters** 

## _hostfile_ (String)  [in] 

filespec of target file on the server. If it exists and matches the source, no action is taken , otherwise it will be overwritten. 

_pcfile_ (String)  [in] 

filespec of the source file on the client. 

## _status_ (Signed Int)  [out] 

returns the number of bytes output to _hostfile_ . Negative numbers constitute system error codes, or one of these: 

|**Code**|**Description**|
|---|---|
|###|BASIC error ###|
|-99|platform error (only supported on ATSD/ATE)|
|-98|invalid options|



A-Shell Reference 

Page 3054 

|**Code**|**Description**|
|---|---|
|-97|unable to allocate memory|
|-96|timeout while waiting for data|
|-95|ATE client or A-Shell/Windows version too old|
|-94|File transferred but hash doesn't match original|
|-1|pcfile not found|
|0|No transfer because hostfile already matches pcfile|



## **See Also** 

- ATEAPX in SOSLIB:[907,33] for server-to-client file transfers. 

- ATEAPX in SOSLIB:[907,33] which acts as a wrapper to MX_ATEFILEXFR and extends the capability to ATE/Unix 

- environments. 

## **History** 

- 2013 July, A Shell 6.1.1357: Routine added to A-Shell 

A-Shell Reference 

Page 3055 

## **MX_CLRINBUF** 

_Added January 2015_ 

## **xcall MIAMEX, MX_CLRINBUF {,flags, buffer}** 

MX_CLRINBUF (MIAMEX 184) provides a simple way to eliminate all type-ahead from both the server and client input buffers. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_flags_ (Num)  [in] 

Specifies the sum of: 

- +1) leave kbd locked 

+2) set ATE master kbd hold. Same as `TAB(-10,AG_HOLDKBD);"2";chr(127)` . 

_buffer_ (String)  [out] 

string buffer which will return the characters that were cleared from the local input buffer. 

## **Comments** 

In a standalone Windows or text environment, this just provides another alternative to existing techniques for clearing the input buffer, including TINKEY, GETKEY(0), and INFLD (type "0"). But in an ATE/GUI environment, it provides the additional feature of clearing any input characters which are currently buffered on the ATE client. Those can sometimes create problems when they accumulate silently on the client and then get released to the host unexpectedly. 

Note that to minimize the chance of missing input characters currently in transit from the client to the server, it sends an AG_ACK request (with a five second time limit). 

Compatibility: requires 6.0.1400.0+ on the server; works with any ATE version. However, for earlier ATE versions, some of the advanced features are unavailable and thus it may not work much better than the existing alternatives mentioned above. 

## **See Also** 

A-Shell Reference 

Page 3056 

- AG_CLRINBUF 

## **History** 

- 2015 January, A Shell 6.1.1400:  Routine added to A-Shell 

A-Shell Reference 

Page 3057 

## **MX_MALLOCLIMIT** 

_Reviewed April 2024_ 

## **xcall MIAMEX, MX_MALLOCLIMIT, op, limit** 

MX_MALLOCLIMIT (MIAMEX 185) provides a programmatic way to query and/or set the MALLOCLIMIT set in miame.ini, which see for more details. 

## **Parameters** 

_op_ (Num)  [in] 

0 to get the limit and 1 to set it 

_limit_ (Unsigned Int)  [out] 

returns the current limit (op=0) or supplies the new limit (op=1). Units are bytes—not kilo-, mega-, or giga-bytes. Maximum practical limit is 2GB-1 (2147483647). 

## **History** 

- 2016 February, A Shell 6.2.1424: Routine added to A-Shell 

A-Shell Reference 

Page 3058 

## **MX_LASTPRTFIL** 

_Updated February 2022; see History_ 

## **xcall MIAMEX, MX_LASTPRTFIL, fspec** 

MX_LASTPRTFIL (MIAMEX 186) returns the file spec of the last file written by the PDFX printer driver. 

## **Parameters** 

_fspec_ (String)  [out] 

## return the filespec 

Currently this only works for PDFX5+, where it solves the problem of finding out the actual name of the PDF file which otherwise may be unknowable due to auto-numbering strategies in the driver, or due to the operator using the Save As dialog to rename the file. The feature may be expanded in the future to support other similar printing situations. 

## **History** 

- 2022 February, A Shell 6.5.1711: MX_LASTPTRFIL previously worked properly only if the WAIT option was used in the prior SPOOL request. It now returns the last filespec written by the PDF-XChange Standard driver (for the current session) regardless of the switches. But since the file writing operation is asynchronous, the WAIT option is still required to be sure that the filespec returned is from the last print request and not from a prior one if the application has gotten ahead of the printer driver. 

- 2016 February, A Shell 6.3.1509: Routine added to A-Shell 

A-Shell Reference 

Page 3059 

## **MX_FILESOCK** 

_Added October 2016_ 

## **xcall MIAMEX, MX_FILESOCK, ch, socket, status** 

MX_FILESOCK (MIAMEX 187) binds a TCP socket to a sequential file channel so that PRINT #CH and/or INPUT #CH transfers data over the socket rather than to/from the file. 

## **Parameters** 

_ch_ (Num)  [in] 

must be a file channel (> 0) open for sequential input or output. Typically you would open the file using the .NULL filespec as described in .NULL Files. 

_socket_ (Num)  [in] 

must be a valid socket opened via TCPX[XS] . 

_status_ (Signed Num) [out] 

returns 0 for success, else error. 

If _ch_ was open for output, then after the successful completion of the MX_FILESOCK call, PRINT #CH statements will output to the socket instead of the file. Similarly, if _ch_ was open for input, then INPUT # _ch_ statements will read from the socket. 

Note that while sockets are bidirectional, sequential file channels are not, so if you want to both input and output to the socket this way, you will need to open two file channels and bind them both to the same socket with two separate MX_FILESOCK calls. 

Once the file channel is bound to the socket, closing the file channel will also close the socket. 

To simplify the operation of opening the file and socket and binding the two together, a pair of functions has been added to the SOSFUNC: library: 

```
Fn'FileSock'Out(ch, socket, server$)
```

```
Fn'FileSock'In(ch, socket, server$)
```

A-Shell Reference 

Page 3060 

See fnfilesock.bsi in SOSLIB:[907,10] for details. 

## **History** 

- 2016 September, A Shell 6.3.1524:  Routine added to A-Shell 

A-Shell Reference 

Page 3061 

## **MX_WEBCACHE** 

_Added October 2016_ 

## **xcall MIAMEX, MX_WEBCACHE, 0, status** 

## **xcall MIAMEX, MX_WEBCACHE, 1, status** 

## **xcall MIAMEX, MX_WEBCACHE, 2, status, url** 

## **xcall MIAMEX, MX_WEBCACHE, 3, status, url** 

## **xcall MIAMEX, MX_WEBCACHE, 4, status, url, localfile** 

## **xcall MIAMEX, MX_WEBCACHE, 5, status {,wildspec}** 

MX_WEBCACHE (MIAMEX 188) provides operations related to A-Shell's web cache feature. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_opcode_ (Num)  [in] 

Determines operation as described below. 

_status_ (Signed Num)  [in/out] 

Sets or returns options, or returns status codes shown under option 4 below. 

_url$_ (String)  [in] 

Specifies a web directory for ocodes 2 and 3, and a fully qualified file URL for opcode 4. Currently the only URL schemes supported are http:// and https://. An optional :port may be appended to the end. Examples: 

```
http://www.mysite.com/webrepo
```

A-Shell Reference 

Page 3062 

```
http://www.mysite.com/webrepo/myfile.run:10080
```

```
https://www.mysite.com/my web repository
```

## **Opcodes** 

## Opcode 0 retrieves the current webcache options in status. Status flags (defined in ASHINC:HOOK.DEF) : 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|WCDF_ENABL<br>ED|&h000000<br>01|web cache enabled (else disabled)|
|WCDF_PROG|&h000000<br>02|download/cache programs (RUN,LIT,SBX)|
|WCDF_OPENI|&h000000<br>04|download/cache files on open for input|
|WCDF_LOOKU<br>P|&h000000<br>08|download/cache any file on LOOKUP or SIZEXS|
|WCDF_DLL|&h000000<br>10|download DLLs to bin or webcache|
|WCFG_ALL|&h000000F<br>E|all flags except WCDF_ENABLE|



A-Shell Reference 

Page 3063 

Opcode 1 sets the webcache options to the value status. 

Opcode 2 and 3 retrieve and set webcache url (web directory), respectively. Status will return 0 for success. 

Opcode 4 performs a manual download from the specified _url$_ to the specified _localfile$_ . If the _url$_ is just a file.ext and the webcache url directory has been previously set, then the two are combined to form the complete source url. If _localfile$_ is "", the source file.ext is used. If _localfile$_ does not contain a directory, then the local webcache directory (%miame%\webcache) is used. Returned Status will equal the # of bytes downloaded if successful, else an error code: 

|**Statu**<br>**s**|**Meaning**|
|---|---|
|-1|Unsupported URL scheme (e.g. not http:// or https://)|
|-2|Specified URL does not contain filename (Opcode 2)|
|-3|URL too long|
|-4|Unable to connect to host web server|
|-5|Error sending HTTP GET command to server|
|-6|Error in local webcache directory\file spec|
|-7|Response from web server missing header terminator|



A-Shell Reference 

Page 3064 

|**Statu**<br>**s**|**Meaning**|
|---|---|
|-8|Response from web server not recognizable|
|-9|Transmission problem receiving header|
|-###|HTTP response error code (converted to negative)|



Opcode 5 clears the local webcache directory. If the wildspec$ parameter is specified and non-blank, only those files matching the wildspec$ will be cleared; otherwise all of the files in the cache will be cleared. Returned status will equal the number of files removed from the cache. 

## **See Also** 

- AG_WEBCACHE 

## **History** 

- 2016 October, A Shell 6.3.1529 and 1531: WEBCACHE function added to A-Shell. 

A-Shell Reference 

Page 3065 

## **MX_CALLSTACK** 

_Added November 2016_ 

## **xcall MIAMEX, MX_CALLSTACK, maxdepth, csarray(1), mainprog}** 

MX_CALLSTACK (MIAMEX 189) returns information about the call stack. The motivation here is to allow application routines to identify the context in which they were called. For example, the file hook subroutine, or an error trapping routine, might want to identify not just the location where the file operation or error occurred, but if that location was within a callable routine, the routine(s) that called it. 

## **Parameters** 

## _maxdepth_ (Num)  [in/out] 

should be set to the number of elements in the _csarray()_ , i.e. the maximum number of stack levels—working backwards from the current stack frame context—to retrieve. On return, it will be set to the number of levels in the current stack. If greater than the number you originally specified, it indicates that not all of the levels were returned. 

_csarray(1)_ (array of ST_CALLSTACK)  [out] 

## the first element of an array of structures defined in ASHINC:CALLSTACK.DEF as follows: 

## `defstruct ST_CALLSTACK` 

```
    map2 calltype,b,2    ! type of call (see CSTF_xxx)
```

```
    map2 src'lno,b,2     ! line # at or prior to call
    map2 src'loc,b,4     ! location counter at call
    map2 dst'loc,b,4     ! target location (for call, fn, proc)
    map2 dst'name,s,52   ! name of sbx or AMOS command line
```

```
endstruct
```

A-Shell Reference 

Page 3066 

Typically _csarray()_ would be defined via: 

```
dimx callstack(MAX_CALLSTACK), ST_CALLSTACK
```

MAX_CALLSTACK should be set to the maximum number of levels you want to retrieve. 

_mainprog_ (String)  [out] 

returns the main program at the top of the call stack. 

## **Example** 

```
++include ashinc:ashell.def
++include ashinc:callstack.bsi
```

```
define MAX_CALLSTACK = 10
```

```
map1 misc
    map2 program$,s,10
    map2 stackdepth,i,2
```

```
dimx callstack(MAX_CALLSTACK), ST_CALLSTACK
stackdepth = MAX_CALLSTACK   ! max # levels we can handle
xcall MIAMEX, MX_CALLSTACK, stackdepth, callstack(1), program$
```

```
for i = 1 to stackdepth min MAX_CALLSTACK
```

A-Shell Reference 

Page 3067 

```
    ? Fn'Call'Stack'Descr$(callstack(i))
```

```
next i
```

The Fn'Call'Stack'Descr$() function referenced above is in the SOSLIB module SOSFUNC:callstack.bsi. It creates a one line description of a call (GOSUB, procedure, function, subroutine, amos statement, etc.) from one location/context to another. An example showing a context six levels deep looks like this: 

```
from loc 3B7 call proc() @3DF
```

```
from loc 38C fn'() @393
```

```
from loc 32B call proc() @331
```

```
from loc 4F1 xcall callstack1
```

```
from loc 47C fn'() @483
from loc 323 call proc() @41A
```

## **Notes** 

- In the above example, the program had no line numbers, so they weren't listed in the output. 

- To match up the location counter values to source code lines, see the LSX file created by the compiler /L switch. 

- The entry in the array (shown at the top) describes the level that called the code that executed the MX_CALLSTACK function. 

- So in the above case, the current code is within a procedure that starts at location 3DF (hex) and was called from location 3B7. Location 3B7 is within a function that starts at location 393, which in turn was called from location 38C, etc. 

## **History** 

## - 2016 November, A Shell 6.3.1538:  Function added to A-Shell. 

A-Shell Reference 

Page 3068 

## **MX_LANGUAGE** 

_Added February 2017_ 

## **xcall MIAMEX, MX_LANGUAGE, opcode, lang {,status}** 

MX_LANGUAGE (MIAMEX 190) retrieves or sets the current language. 

## **Parameters** 

_opcode_ (Num)  [in] 

- 0 (mxop_get) to retrieve, 1 (mxop_set) to set 

_lang_ (String)  [in/out] 

For the get operation, returns the current language name. Note that this is the name defined within the LDF file, not the name OF the LDF file. For example, the englsh.ldf file contains the name "ENGLISH." 

For the set operation, must specify the name of the LDF file to load. This can be either an unadorned name, like "ENGLSH" (in which case it will look for dsk0:name.ldf[1,6]), or a complete filespec. Note that although the status parameter will indicate if the file was found, the only way to really evaluate the success of the operation is to use GTLANG to retrieve all the attributes of the new language. 

_status_ (Signed Num)  [out] 

If specified, returns 0 for success, else -1 if the specified LDF is not found. 

## **History** 

- 2017 February, A Shell 6.4.1543: Function added to A-Shell. 

A-Shell Reference 

Page 3069 

## **MX_SRCHPATH** 

_Added June 2018_ 

## **xcall MIAMEX, MX_SRCHPATH, file, foundpath** 

MX_SRCHPATH (MIAMEX 191) searchs for a file in the system path. 

## **Parameters** 

_file_ (String)  [in] 

filename to search for. Wilcards and directory names disallowed. 

_foundpath_ (String)  [out] 

returns "" if not found, else the full path. 

## **Comments** 

The search path is system dependent, but normally includes the current directory, the directory from which the A-Shell executable was loaded, plus all the directories included in the PATH environment variable. 

One use of this function would be to check whether a particular external command exists before attempting to launch it via HOSTEX[XS] . 

## **History** 

- 2018 June, A Shell 6.5.1638:  Function added to A-Shell. 

A-Shell Reference 

Page 3070 

## **MX_DYNSTRUCT** 

_Reviewed April 2025_ 

MX_DYNSTRUCT (MIAMEX 192) implements A-Shell's dynamic structures. Note that there is a lengthy discussion of Dynamic Structures in "Development Topics." 

## **xcall MIAMEX, MX_DYNSTRUCT, DYNOP_DEF, status, src$, fields, stsize, dsname$ {,errmsg$,workareak}** 

## **xcall MIAMEX, MX_DYNSTRUCT, DYNOP_BIND, status, dsname$, ds** 

## **xcall MIAMEX, MX_DYNSTRUCT, DYNOP_INFO, status, ds, fields, flddefs(1)** 

## **xcall MIAMEX, MX_DYNSTRUCT, DYNOP_INFO, status, dsname$, fields, flddefs(1)** 

## **xcall MIAMEX, MX_DYNSTRUCT, DYNOP_COPY, status, dssrc, dsdst** 

This MIAMEX subfunction provides various utilities related to dynamic structure operations, according to the specified opcode: 

|**Opcode from**<br>ashinc:<br>dynstruct.def|**Description**|**Wrapper Function from**<br>sosfunc:fndynst.bsi|
|---|---|---|
|DYNOP_DEF (1)|Define (aka compile) a<br>dynstruct. See_History_below.|Fn'Dynst'Define()|
|DYNOP_BIND (2)|Bind a defined dynstruct to a<br>dynstruct variable|Fn'Dynst'Bind()|



A-Shell Reference 

Page 3071 

|**Opcode from**<br>ashinc:<br>dynstruct.def|**Description**|**Wrapper Function from**<br>sosfunc:fndynst.bsi|
|---|---|---|
|DYNOP_INFO (3)|Retrieve layout info for a<br>dynstruct definition or for a<br>bound dynstruct variable|Fn'Dynst'Get'Def'By'Name(<br>)<br>Fn'Dynst'Get'Def'By'Instan<br>ce()|
|DYNOP_COPY|Copy a bound dynstruct variable<br>to a previously un-bound<br>dynstruct variable.|Fn'Dynst'Copy()|



Note the existence of the wrapper functions in the SOSFUNC library module. In general these are preferred over the direct MX_DYNSTRUCT calls because they provide a degree of isolation between the internals of the implementation (which may be subject to change) and the application. In some cases the wrapper functions also provide additional convenience by taking care of details. 

_status_ (Signed Num)  [in] 

Returns status of the operation, according to the following table: 

|**Value **|**Description**|
|---|---|
|0|Success|



A-Shell Reference 

Page 3072 

|**Value **|**Description**|
|---|---|
|-1|Illegal opcode (DYNOP_xxx)|
|-2|No results to process|
|-3|Out of memory|
|-4|Too few parameters|
|-6|Fields value, i.e. flddefs() array extent, too small to hold all results|
|-7|Bad flddefs() array parameter|
|-8|Dynstruct definition corrupt|
|-9|Unable to locate named structure definition|
|-10|Parameter not a dynstruct|
|-11|Dynstruct uninitialized|
|-12|Compilation error|



A-Shell Reference 

Page 3073 

## _fields_ (Num)  [in/out] 

For DYNOP_DEF, returns the number of fields in the defined structure. Note that this includes a field for the overall structure itself. For DYNOP_INFO, caller must set _fields_ to the extent of the _flddefs()_ array. On return, it will contain the number of fields in the structure, which may be more than the size of the _flddefs()_ array, in which case _status_ will be -6, but the array will be filled to the size set by the original value of _fields_ . 

_stsize_ (Num)  [out] 

Returns the overall size of the defined structure. 

_src$_ (String)  [out] 

A string or file containing or referencing the target DEFSTRUCT (per _dsname$_ ), along with all the DEFINEs, DEFTYPEs, and other DEFSTRUCTs on which the target depends. There are three sub-cases: 

- _src$_ contains the source code as one large string variable, with each line terminated by a chr(10). This allows building the 

- source DEFSTRUCT dynamically at runtime. 

- _src$_ is a filespec (of the file containing the source code containing the target DEFSTRUCT). To distinguish this case from the 

- prior one, precede the filespec with "@", e.g. `src$ = "@devlib:recmaps.def"` 

- if _src$_ = "", the DEFSTRUCT is assumed to be embedded into the current RUN file. See History below and Structure Definition 

- Embedding for details. 

Note that for the first two cases, any other source code not part of or prerequisite to the target DEFSTRUCT will be ignored. So it can be used to extract DEFSTRUCT definitions from any source code (including nested ++includes) that can otherwise be compiled. 

_dsname$_ (String)  [in] 

Name of the dynamic structure, which is the same as the name of the DEFSTRUCT used to define it, not to be confused with the name of the dynstruct variable to which it will eventually be bound. Determines which DEFSTRUCT within the source ( _src$)_ contains the actual dynamic structure definition. For DYNOP_BIND, it contains the name of a previously defined structure to bind to the specified dynstruct variable. 

A-Shell Reference 

Page 3074 

_errmsg$_ (String)  [out] 

Returns the text of any error that occurs during the process of compiling the definition. 

## _ds, dssrc, dsdst_ (DYNSTRUCT)  [in/out] 

For DYNOP_BIND, this is the variable to be bound to the definition. For DYNOP_INFO, this is a previously bound dynstruct variable from which the routine will retrieve the definition. For DYNOP_COPY, these are the source and destination dynstruct variables. The source ( _dssrc_ ) must have been previously bound to a definition.  The destination ( _dsdst_ ) will be bound by the function to the same definition, and the content of _dssrc_ will be copied to _dsdst_ . 

## _flddefs_ (ST_FLDDEF)  [out] 

The DYNOP_INFO call returns an array describing each field of the specified structure. Unless you want only the first field, you must specify the first element of the array in the parameter list, i.e. _flddefs(1)_ . 

Note that subroutine is not able to auto_extend the array; it is up to the caller to dimension it appropriately and to then specify the actual extent in the _fields_ parameter. The routine will fill out the array up to the smaller of the actual number of fields in the structure definition, or the number of elements passed from the app in the _fields_ parameter. If the return information is truncated due to _fields_ being too small, _status_ will be set to -6, but _fields_ will be returned with the total # of fields in the structure, allowing the application to redimension the array and call the function again if desired. 

Note that the first entry in the returned array describes the entire structure, rather than being a traditional structure member. 

To retrieve just the name of the structure definition to which a dynstruct variable is bound, you can pass the _flddefs_ parameter as a scalar, or a single-element array.  The structure definition name will be returned in both the _name_ and _deftyp_ members of the first element. 

## _workareak_ (Num)  [in] 

Requested work area size, in kilobytes. The default size of 2048—i.e. 2M total bytes—should be sufficient for all but the most complex cases; if insufficient, status -3 will be returned. See _History_ below for details. 

## **See Also** 

- Dynamic Structures 

A-Shell Reference 

Page 3075 

## **History** 

2022 February, A-Shell 6.5.1711: MX_DYNSTRUCT enhancement: the DYNOP_DEF call now supports the ability to retrieve the structure definition directly from the RUN file, provided it has been embedded. To indicate that you want to retrieve the definition from the current RUN file, set the src$ parameter to "", for example: `xcall MIAMEX, MX_DYNSTRUCT, DYNOP_DEF, status, "", fields, stsize, dsname$` 

2021 October, A-Shell 6.5.1707, compiler edit 952:  Several changes: The default amount of work area memory allocated when defining (compiling) a dynamic structure has been increased from 128K to 2M. A new optional parameter, _workareak_ , has been added to allow the caller to specify more than the default amount of memory when defining a dynamic structure. The routine now properly returns status -3 for the out-of-memory condition, allowing the caller to try again with an explicitly larger workarea. 

- 2019 April, A Shell 6.5.1659,compiler edit 898: Compiler refinement, edit 898: MX_DYNSTRUCT now allows DEFTYPE aliases for implicitly sized X variables. There were previously allowed, but the DEFTYPE name was lost during the runtime compilation. 

- 2018 August, A Shell 6.5.1645:  Function added to A-Shell. 

A-Shell Reference 

Page 3076 

## **ST_FLDDEF** 

_Added October 2018_ 

## The layout of ST_FLDDEF, defined in ASHINC:DYNSTRUCT.DEF, is: 

```
define MAX_ARY_DIMS = 4            ! max # array dimensions
deftype T_DYN_NAME  = S,64         ! type,size for DYNSTRUCT struct and field names
deftype T_DEFTYP    = S,64         ! type used to store name a DEFTYPE name
```

```
defstruct ST_FLDDEF                !
    map2 name,T_DYN_NAME           ! name of struct or field
    map2 vartyp,b,2                ! see VARTYP_xxx
    map2 varsiz,b,4                ! size of field (or element in array)
    map2 pos,b,4                   ! offset from base of structure, base 0
    map2 subs,b,2                  ! # subscripts (0 for scalar)
    map2 subext(MAX_ARY_DIMS),b,4  ! # of elements in up to 4 dimensions
    map2 deftyp,T_DEFTYP           ! name of deftype (if applic.)
```

```
endstruct
```

The `deftyp` member will contain the name of the DEFTYPE used to define the member type and size, if it didn’t use a built-in type. The idea behind including it is to allow DEFTYPEs to be used as data dictionary data types, allowing you to write generic code to handle the special formatting or other semantic attributes of members that aren’t otherwise knowable from the simple types. 

A-Shell Reference 

Page 3077 

## **MX_DYNFUNC** 

_Added October 2018_ 

## **xcall MIAMEX, MX_DYNFUNC, op, funcname, status, type, size** 

MX_DYNFUNC (MIAMEX 193) is used for DYNFUNC-related utilities. 

## **Parameters** 

_opcode_ (Num)  [in] 

Only one opcode, 1, is supported. It returns existence, type, and size info for the specified dynamic function. 

_funcname_ (String)  [in] 

Name of the function to inquire about. Case sensitive. Must be tagged with the Dynamic keyword for it to be visible. _status_ (Signed Num)  [out] 

Returns 1 if found, 0 if not found, <0 for errors 

_type_ (String)  [out] 

Returns the type of the function, which could be an internal type—e.g. "B", "S", "X", "F", or "I"—or a DEFSTRUCT type. 

_size_ (Num)  [out] 

Returns the length in bytes of the function's return value. 

## **Also See** 

- Dynamic Functions 

## **History** 

- 2018 September, A Shell 6.5.1647:  Function added to A-Shell. 

A-Shell Reference 

Page 3078 

## **MX_GETWINFILEVERS** 

_Added May 2019_ 

## **xcall MIAMEX, MX_GETWINFILEVERS, file, vmajor, vminor, vbuild, vpatch, {,status}** 

MX_GETWINFILEVER (MIAMEX 194) retrieves version of a Windows DLL or executable. 

## _file_ (String)  [in] 

Specifies the executable or DLL to retrieve the version info from. If no explicit path given, the search path is the same as it would be for loading that kind of file. 

## _vmajor, vminor, vbuild, vpatch_ (Num)  [out] 

These will be updated with the parts of the version information from the specified file. All but _vmajor_ are optional. 

_status_ (Signed Num)  [out]  (optional) 

Returns operation status: 

|**Value**|**Meaning**|
|---|---|
|0|success|
|-1|unable to locate file|
|-2|unable to read version resource|
|-3|memory allocation failure|



A-Shell Reference 

Page 3079 

|**Value**|**Meaning**|
|---|---|
|-4|premature end of version string (must contain at least three parts - vmajor, vminor,<br>vbuild)|



## **History** 

- 2019 May, A Shell 6.5.1661: Function added to A-Shell. 

A-Shell Reference 

Page 3080 

## **MX_FILEVAR** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_FILEVAR, op, ch, sts, recno {,stat}** 

MX_FILEVAR (MIAMEX 195) gets or sets the value of the file record number variable, and, in the case of ISAM-A, the stats variable. 

## **Parameters** 

_op_ (Num)  [in] 

specifies 0 for get, and 1 for set 

_ch_ (Num)  [in] 

is the file channel 

_sts_ (Signed Num))  [out] 

returns 0 for success, -1 if file ch not open, or -2 for unsupported file type 

_recno_ (Num)  [in/out] 

the value of the record number variable—associated with the file in its OPEN statement—to be retrieved or set. 

_stat_ (Num)  [in/out] 

the value of the stat variable—associated with the file in its OPEN statement—to be retrieve or set. 

## **Parameters** 

The need for this function arises from the fact that the various file OPEN statements create an internal ink between the file channel and the record number / status variables, which must have global scope. But that complicates the ability to create user defined functions that perform file operations based on the channel number as an argtument.  Either you have to declare those control variable as ++EXTERN inside or any such function, or you can use MX_FILEVAR to access those control variables. Another approach would be to use the "X" versions of the file i/o statement, which take the control variables as explicit arguments. 

A-Shell Reference 

Page 3081 

## **See Also** 

- File I/O Statements 

- XREAD, XWRITE, XUNLOKR 

- ++EXTERN 

- MX_FLSET 

## **History** 

- 2019 July, A Shell 6.5.1664: Function added to A-Shell. 

A-Shell Reference 

Page 3082 

## **MX_FILETIMES** 

_Updated August 2023_ 

## **xcall MIAMEX, MX_FILETIMES, fspec, opcode {,status, mtime, ctime , atime, loc'rem}** 

MX_FILETIMES (MIAMEX 196) provides a way to set a file's last modification time ( _mtime_ ), creation time ( _ctime_ ), and/or last access time ( _atime_ ). Setting the mtime of a file is equivalent in the Unix world to using the touch command on the file. For convenience, the function can also retrieve the file times, overlapping functionality already provided by MX_FILESTATS. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_fspec_ (String)  [in] 

native or AMOS-style file specification of file 

_opcode_ (Num)  [in] 

0 (mxop_get) to get the current times, 1 (mxop_set) to set them 

_status_ (Signed Num)  [out] 

returns 0 for success, else an error code (file not found, etc.) 

_mtime, ctime, atime_ (T_FILETIME or B,6)  [in/out depending on _opcode_ ] 

Unix-style file times, i.e. seconds since "the epoch" (midnight Jan 1, 1970). This is the same format as is used for MX_FILESTATS. When op = 1 (set), any time parameters either omitted or set to 0 will result in no change to the corresponding time attribute; -1 (or &hffffffff) may be used as a shortcut for the current time. See History note, below, for A-Shell 6.5.1740. _atime_ (Num)  [in/out] 

last access time (B6, I6 or F6 needed for 2038+) 

_loc'rec_ (String)  [in] 

A-Shell Reference 

Page 3083 

R=redirect to ATE; C=redirect to ATE, include cache search; L=local (default) 

## **Notes** 

- T_FILETIME and T_FILETIME48 are defined in ASHINC:TYPES.DEF as B,4 and B,6 respectively. 

- You can use the MX_FTFORMAT function to convert these time values to other formats. 

- To convert other time formats to the T_FILETIME format, you can use the SOSLIB function Fn'Date'Time'tO'FILETIME() 

## function (fndatetime.bsi). 

- The operating system may impose limits and/or perform cleanup on your attempts to set file times. For example, in the Unix 

- world, the ctime value isn't really the "creation" time but the time that the file's metadata was last changed, and there is no direct way to change it. However, changing either the mtime or atime will indirectly set the ctime to match. 

- Note that redirecting the operation to ATE requires ATE 6.5.1740.0+ 

## **Examples** 

Set the modification time of the file fspec$ to the current time. Note that the literal -1 will be auto-converted to the T_FILETIME (B,4) format: 

```
xcall MIAMEX, MX_FILETIMES, fspec$, MXOP_SET, status, -1
```

## Get the mtime and ctime and display the mtime in human readable form: 

```
xcall MIAMEX, MX_FILETIMES, fspec$, MXOP_GET, status, mtime, ctime
```

```
xcall MIAMEX, MX_FTFORMAT, mtime, strtime$
```

- `? "Last mod time of ";fspec$;" was: ";strtime$` 

## **History** 

- 2023 August, A Shell 6.5.1740:  Add support for additional timestamp bits (beyond 32) to resolve the Year 2038 problem. Note that you have to specify a parameter type capable of supporting more than 32 bits, e.g. B,6 or F6. 

A-Shell Reference 

Page 3084 

- 2023 August, A Shell 6.5.1740:  Add support for last accessed time and ability to redirect operation to ATE 

- 2019 November, A Shell 6.5.1671:  Function added to A-Shell. 

A-Shell Reference 

Page 3085 

## **MX_GETDPI** 

_Added October 2020_ 

## **xcall MIAMEX, MX_GETDPI, sysdpi {,ctlid, ctldpi}** 

MX_GETDPI (MIAMEX 197) returns information about the effective or simulated resolution of the workstation monitor(s) in DPI (dots per inch). Applies only to A-Shell/Windows and ATE. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_sysdpi_ (Num)  [out] 

system DPI (primary monitor). 

_ctlid_ (String / (Num)  [in] 

optional control ID (name or number) of control for which to return the control's DPI. This will only differ from _sysdpi_ in a multimonitor system where the control is on one of the secondary monitors. 

_ctldpi_ (Num)  [out] 

DPI of the monitor on which the control specified by _ctlid_ is located. 

## **Comments** 

If you don't specify the -dpm command line switch when launching A-Shell/Windows or ATE, the return value will probably be a value simulated by Windows (typically 96) rather than the real resolution of the monitor. The -dpm switch disables the Windows standard resolution simulation, giving access to the actual monitor resolution. See the documentation on the command line switch DPI Per Monitor Awareness for more details. 

## **See Also** 

- AG_GETDPI 

## **History** 

A-Shell Reference 

Page 3086 

- 2020 October, A Shell 6.5.1692: Function added to A-Shell. 

A-Shell Reference 

Page 3087 

## **MX_GETUPTIME** 

_Added January 2021_ 

## **XCALL MIAMEX, MX_GETUPTIME, systime {,jobtime, ashtime}** 

MX_GETUPTIME (MIAMEX 198) retrieves information about the amount of time that the system has been up and the job has been logged in: 

## **Parameters** 

_systime_ (Num)  [in] 

Number of seconds since the operating system booted. 

_jobtime_ (Num)  [in] 

Number of seconds since the current job logged in. 

_ashtime_ (Num)  [in] 

Number of seconds since the Job Table (jobtbl.sys) last created. This is likely to be the same as the _jobtime_ under Linux, since the jobtbl.sys creation time comes from the directory _ctime_ which may be updated for reasons other then creation. 

## **History** 

- 2021 January, A Shell 6.5.1694:  Function added to A-Shell. 

A-Shell Reference 

Page 3088 

## **MX_DRAGDROP** 

_Added July 2021_ 

## **xcall MIAMEX, MX_DRAGDROP, opcode, status, ctlid {,fidx ,fspec}** 

MX_DRAGDROP (MIAMEX 199) provides support for accepting files dragged and dropped from Windows File Explorer—or another Windows Shell object—onto a control created with AUI_CONTROL. 

## This function has both a subroutine and a print tab implementation. 

To enable the feature, specify the WS_EX_ACCEPTFILES (&h0010) flag in the _winstylex_ parameter of the AUI_CONTROL call when creating the target control. Typically this would be a static control, perhaps with a colored background and some explanatory text (e.g. “"Drop files here"), but in theory it could be nearly any control type—including dialogs—that are created with AUI_CONTROL. 

Two modes are supported: destructive and non-destructive. In the destructive mode, each drop event replaces the existing contents of the drop buffer with the newly dragged file specs, as with a clipboard Copy. In the non-destructive mode, each drop event adds to the existing contents of the drop buffer. Destructive mode is the default. Non-destructive mode is established via MX_DRAGDROP _opcode_ 3 after creating the drop target control. 

In both modes, the drop event triggers exitcode -75,notifying the application so that it can respond by querying and/or retrieving the filespecs using the MX_DRAGDROP function. 

## **Parameters** 

_opcode_ (Num)  [in] 

|**Value**|**Description**|
|---|---|
|0|query drop buffer, set_status_parameter to the number of files in the drop target<br>(_ctlid_)|



A-Shell Reference 

Page 3089 

|**Value**|**Description**|
|---|---|
|1|retrieve_fspec_corresponding to_fidx_from the specified drop target (_ctlid_)|
|2|clear the contents of the drop target buffer|
|3|set non-destructive (previous "asynchronous") mode|



_status_ (Signed Num)  [out] 

<=0: failure, or no files available in opcode 0; >0: success, which is the number of files for _opcode_ 0, or the number of bytes in _fspec_ for _opcode_ 1 

_ctlid_ (String )  [in] 

control id of the target control 

_fidx_ (Num)  [in] 

for _opcode_ 1, must be set to the number of the _fspec_ to retrieve (starting with 1) 

_fspec_ (String ) [out] 

file specification returned for _opcode_ 1 

## **Comments** 

Note that it isn’t actually the files themselves that are being dragged and dropped; it is just their file specifications. 

Although the implementation is primarily on the Windows side, accessing the new MX_DRAGDROP feature from an ATE session will require that the server instance of A-Shell also be at least at version 6.5.1705. 

A-Shell Reference 

Page 3090 

There is nothing stopping you from defining more than one drop target control within a given UI context. But since all drop events trigger the same exitcode -75, you would need to query each of the possible drop target controls in order to identify which control received the drop event. 

## **Examples** 

Create a drop target control—in this case, a static text control. The critical element here is the WS_EX_ACCEPTFILES value for the _winstylex_ parameter.… 

```
! create the drop target (must be MBF_STATIC with WS_EX_ACCEPTFILES)
```

```
DROPCTLID$ = “txtDropTarget”
```

```
xcall AUI, AUI_CONTROL, CTLOP_ADD, DROPCTLID$, &
```

```
    "Drop File(s) Here" + chr(13) + "Click to query", MBST_ENABLE, &
    MBF_STATIC+MBF_CENTER+MBF_KBD, "VK_xF100", NUL_FUNC$, NUL_CSTATUS, &
```

```
    srow,scol,erow,ecol, NUL_FGC, &hddccbb, &
```

```
    NUL_FONTATTR, NUL_FONTSCALE, NUL_FONTFACE$, NUL_TOOLTIP$, &
```

```
    DLGID$, NUL_WINCLASS$, NUL_WINSTYLE, WS_EX_ACCEPTFILES, &
```

```
    NUL_CTYPE2
```

## Set asynchronous mode: 

```
opcode  = 3
```

```
ctlid = DROPCTLID$
```

```
xcall MIAMEX, MX_DRAGDROP, opcode , status, ctlid
```

## Query drop target to see how many files are available: 

A-Shell Reference 

Page 3091 

```
opcode  = 0
```

```
ctlid = DROPCTLID$
```

```
xcall MIAMEX, MX_DRAGDROP, opcode , status, ctlid
```

```
count = status   ! # of files in target
```

## Retrieve file specifications from the drop target: 

```
opcode  = 1
ctlid = DROPCTLID$
```

```
for fidx = 1 to count   ! count retrieved from opcode 0
```

```
    xcall MIAMEX, MX_DRAGDROP, opcode, status, ctlid, fidx, fspec$
```

- `? “File #”;fidx;” : “;fspec$` 

```
next fidx
```

## **Also See** 

- The sample program FILEDROP1.BP in EXLIB:[908,90] illustrating a simple drag-drop user interface. 

## **History** 

- 2021 July, A Shell 6.5.1705: Function added to A-Shell. 

A-Shell Reference 

Page 3092 

## **MX_AS3264** 

_Added October 2021_ 

## **xcall MIAMEX, MX_AS3264, bits** 

MX_AS3264 (MIAMEX 200) returns the architecture of the A-Shell executable, 32 or 64 bit. 

## **Parameters** 

_bits_ (Num)  [out] 

## 32 or 64 

Note that for prior A-Shell versions, calling this function will generate a pop-up invalid opcode error message. So if you are coding to be 32/64 bit aware, you should first check the A-Shell version, perhaps using the function Fn'MinAshVer() found in fnminasver.bsi SOSLIB:[907,10].  It's safe to assume that any A-Shell version below 1708 is 32 bit or less. 

## **History** 

- 2021 October, A Shell 6.5.1708: Function added to A-Shell. 

A-Shell Reference 

Page 3093 

## **MX_TRANSCOPY** 

_Added June 2023_ 

## **xcall MIAMEX, MX_TRANSCOPY, op, srcfile, dstfile, tcffile, section, status{, flags, maxlen, errmsg}** 

MX_TRANSCOPY (MIAMEX 202) copies and translates a file, applying a series of regular expression replacement operations such that the destination file is a variant of the source. The new term "transcopy"—translate or transform plus copy—was coined to describe this operation. 

## **Parameters** 

_op_ (Num)  [in] 

must be set to 1 

_srcfile_ (String)  [in] 

source filespec 

_dstfile_ (String)  [in] 

destination filespec; replaced if already exists 

_tcffile_ (String)  [in] 

configuration filespec; see TCF specification 

_section_ (String)  [in] 

optional section name within the TCF 

_status_ (Signed Int)  [out] 

on success, number of modified lines; see table below for errors 

_flags_ (Int)  [in] 

optional REGEXXS flags combined with any that are set in the TCF 

A-Shell Reference 

Page 3094 

_maxlen_ (Int)  [in] 

optional max length of source lines to support; default 16K 

_errmsg_ (String)  [out] 

set only if status < 0) 

## **Comments** 

This function (Op 1) is essentially equivalent to the compiler _transclude_ mechanism (++include with integrated transcopy) and may be used to debug your ++include TCF files. But it is also useful for general purpose file translations. 

## **Errors (status parameter)** 

|**Value**|**Description**|
|---|---|
|-2 to -25|matching errors (same asREGEX<br>XS)|
|-101 to -199|pattern compiliation errors (same as REGEXXS)|
|-93 to -99|misc errors (same as REGEXXS)|
|-92|unable to allocate sufficient memory|
|-91|input file error|
|-90|output file error|



A-Shell Reference 

Page 3095 

|**Value**|**Description**|
|---|---|
|-89|invalid item or syntax error in TCF|
|-88|too many s#/r# pairs in TCF|
|-87|TCF maximum line length exceeded|
|-86|unable to open TCF|
|-85|TCF section not found|
|-84|Unable to load REGEX library (PCRE)|



## **History** 

- 2023 June, A Shell 6.5.1732:  Function added to A-Shell. 

A-Shell Reference 

Page 3096 

## **TCF SPECIFICATION** 

_Added June 2023_ 

The Transcopy Configuration File contains the search and replace patterns and other options to apply to the transcopy operation. The structure is based on standard INI files, with Item=Value elements grouped beneath [Section] headers. Optionally the top section of the file may contain global items (without a [Section] header). The section names are entirely arbitrary, intended for your convenience in grouping related sets of translations within a single TCF file. 

The defined item=value pairs (not case sensitive) are: 

s{#}=value 

Search pattern {optional # in 1-127 range}. Value is a regex pattern. See limitations below. 

r{#}=value 

Replacement pattern associated with the prior search pattern. If a number is specified, it must match the prior search pattern number. References to submatches in the search pattern must use \# syntax, where the # is the submatch number—not to be confused with the overall search pattern number. 

flags=value 

XS Optional REGEX flags. Same as for REGEX . 

Blank lines, and those beginning with !, ;, or # are treated as comments. 

For example, this TCF file... 

```
[cust]
```

```
; set PCRE_UNGREEDY...
```

```
flags=&h0200
```

```
s=([^\w])(orderNo|custName)([^\w])
```

```
r=\1wo.\2\3
```

A-Shell Reference 

Page 3097 

... contains a single section, setting the Regex flags to &0200 (PCRE_UNGREEDY), and defining a single pair of search/replace patterns (with three submatch expressions). This would translate all word-delimited occurrences of "orderNo" to "wo.OrderNo" and "custName" to "wo.custName". 

## **Limitations** 

• Maximum number of s#/r# pairs per section: 127. If you need more, split them into separate sections and execute the operation multiple times, once per section. 

• If the optional pattern numbers are used, they must be consecutive, and the search and corresponding replacement lines must use the same number. Whether this helps you organize your patterns, or just gets in the way, remains to be seen. 

- Maximum number of sub-match replacements in a single s# pattern: 99 

A-Shell Reference 

Page 3098 

## **MX_RUNPROF** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_RUNPROF, opsts {,fspec}** 

MX_RUNPROF (MIAMEX 203) generates a run profile log to be analyzed for an overview of the program call structure and performance. 

## **Parameters** 

## _opsts_ (Signed Int)  [in/out] 

## specifies the opcode and return status: 

|**Opcode**|**Opcode**|**Returned Status**|**Returned Status**|
|---|---|---|---|
|**Value**|**Function**|**Value**|**Function**|
|0|Check profiling status|0|disabled|
|||1|enabled (+flags)|
|1|Enable profiling and<br>output to_fspec_|2|enabled|
|||-2|already enabled|
|||-3|cannot open file|



A-Shell Reference 

Page 3099 

|**Opcode**|**Opcode**|**Returned Status**|**Returned Status**|
|---|---|---|---|
|2|Disable profilling|3|now disabled|
|||0|was disabled|



## _fspec_ (String)  [in] 

destination filespec; replaced if already exists; default is <pid>.rpl 

## **See Also** 

- RUNPROF.LIT 

## **History** 

- 2023 July, A Shell 6.5.1735: Function added to A-Shell. 

A-Shell Reference 

Page 3100 

## **MX_DIRCLEAN** 

_Reviewed and revised April 2024_ 

## **xcall MIAMEX, MX_DIRCLEAN, dirspec, loc'rem, status {,wildspec, flags, timelimit, bytes}** 

MX_DIRCLEAN (204) scans a specified directory, counting and/or deleting files based on various filter attributes. 

This function has both a subroutine and a print tab implementation. 

## **Parameters** 

_dirspec_ (String)  [in] 

target directory, in any reasonable format; may include %env% variables 

_loc'rem_ (String)  [in] 

L)ocal interprets _dirspec_ as local to application server; R)emote or C)lient interprets _direspec_ as an ATE remote spec 

_status_ (Signed Int)  [out] 

returns the number of files matched or deleted; negative values indicate errors 

_wildspec_ (String)  [in] 

optional wildcard spec (default is *.*) 

_flags_ (Bitmap 8)  [in] 

zero or more of the following bit flags: 

|**Value**|**Meaning / Effect**|
|---|---|
|&h0001|only files with mtime < timelimit|



A-Shell Reference 

Page 3101 

|ence||
|---|---|
|&h0002|only files with timestamp < timelimit|
|&h0004|only files > bytelimit|
|&h0008|only files < bytelimit|
|&h0010|no action (just count matching files, bytes; else delete)|



## _timelimit_ (T_FILETIME or B6)  [in] 

time threshold (seconds since the 'epoch') if flags &h0001 or &h0002 are specified. Note that B4 will work up to 2038, but beyond that the value will overflow 32 bits. 

## _bytes_ (Num)  [in/out] 

on input, sets file size threshhold (if flags &h0004 or &h0008); on output returns number of bytes in the matching files 

## **See Also** 

- AG_DIRCLEAN 

## **History** 

- 2023 August, A Shell 6.5.1740:  Function added to A-Shell 

A-Shell Reference 

Page 3102 

## **MX_LOCALE** 

_Added May 2024_ 

## **xcall MIAMEX, MX_LOCALE, op, attrid, value, status** 

MX_LOCALE (205) provides a convenient way to query the native OS locale information, in contrast to the A-Shell locale which is 

set via the LANGUAGE parameter in  miame.ini and queried via GTLANG[XS] . This routine is intended to be helpful when debugging the confusing situation that can occur when either A-Shell or the native OS is using the period as a thousands separator and/or the comma as the decimal point. 

## **Parameters** 

_op_ (Integer)  [in] 

operation: 0=get; no other options are currently supported 

_attrid_ (String)  [in] 

attribute to get:  "dec" = decimal point character, "tsp" - thousands separator character 

_value_ (String)  [in/out] 

value of attribute 

_status_ (Signed Int)  [out] 

returns 0 for ok, else error # 

## **History** 

- 2024 May, A Shell 7.0.1759: Function added to A-Shell. 

A-Shell Reference 

Page 3103 

## **MX_LOGDIR** 

_Written September 2025_ 

## **xcall MIAMEX, MX_LOGDIR, opcode, dirspec** 

MX_LOGDIR (207) provides a means to relocate the ashlog.log file directory. 

## **Parameters** 

_opcode_ (Num)  [in] 

0 for get, 1 for set 

_dirspec_ (String)  [in/out] 

ashlog.log location 

Although it is probably uncommon to change the ashlog location during a session, it comes in handy during debugging on a system with many users, in conjunction with verbose traces like XCALL and FUNCS. Rather than fill the common ashlog.log file with your traces, you can relocate the ashlog location for just your session to a local directory (or '.' for your current directory). You can then use `VIEWASHLOG/LOCAL` to view the traces in your local copy of the ashlog. 

SP The ashlog.log file directory can also be changed via the LOGDIR directive and the system command SET LOGDIR. 

## **History** 

- 2025 August, A Shell 7.0.1778: MX_LOGDIR and SET LOGDIR added to A-Shell. 

A-Shell Reference 

Page 3104 

## **MX_SYSLOG** 

_Written October 2025_ 

**xcall MIAMEX, MX_SYSLOG, -1, ident, option, facility   ! open/init** 

**xcall MIAMEX, MX_SYSLOG, -2                                      ! close** 

**xcall MIAMEX, MX_SYSLOG, -3, mask                            ! set log mask** 

**xcall MIAMEX, MX_SYSLOG, level, msg                         ! output message** 

**xcall MIAMEX, MX_SYSLOG, msg                                   ! output message** 

(Linux only) MX_SYSLOG (207) outputs text to the Linux syslog facility. 

## **Parameters:** 

_ident_ (String)  [in] 

identifier to include with each message (defaults to 'ashell'). 

## _option_ (Integer)  [in] 

options that may be set on the open call that then carry through to the subsequent outputs. One or more of the following (OR'd together): 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SYSLOG_PID|&h01|include the pid with each message|
|SYSLOG_CONS|&h02|log on console if errors in sending|



A-Shell Reference 

Page 3105 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SYSLOG_ODELAY|&h04|delay open until first output (default)|
|SYSLOG_NODELAY|&h08|don't delay open|
|SYSLOG_PERROR|&h20|log to_stderr_as well|



## _facility_ (Integer)  [in] 

## indicator of category of message: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|SYSLOG_USER|&h1000|user-level messages (default)|



Consult syslog(3) documentation for other options, although none of them seem sensible in this context, which is why they aren't documented here. 

## _mask_ (Integer)  [in/out] 

mask bits allowing outputs to be enabled/disabled by the level of severity. (Parameter returns the original value of the mask; passing 0 preserves the original mask value, i.e. query only.) 

|**Symbol**|**Value**|**Meaning: Log message to...**|
|---|---|---|
|SYSLOG_UPTO_EMERG|&h0001|SYSLOG_EMERG|



A-Shell Reference 

Page 3106 

|**Symbol**|**Value**|**Meaning: Log message to...**|
|---|---|---|
|SYSLOG_UPTO_ALERT|&h0003|SYSLOG_ALERT|
|SYSLOG_UPTO_CRIT|&h0007|SYSLOG_CRIT|
|SYSLOG_UPTO_ERR|&h000F|SYSLOG_ERR|
|SYSLOG_UPTO_WARNING|&h001F|SYSLOG_WARNING|
|SYSLOG_UPTO_NOTICE|&h003F|SYSLOG_NOTICE|
|SYSLOG_UPTO_INFO|&h007F|SYSLOG_INFO|
|SYSLOG_UPTO_DEBUG|&h00FF|SYSLOG_DEBUG|



## _level_ (Integer)  [in] 

## importance of the message; one of the following: 

|**Symbol**|**Value**|**Meaning...**|
|---|---|---|
|SYSLOG_EMERG|0|system is unusable|
|SYSLOG_ALERT|1|action must be taken immediately|



A-Shell Reference 

Page 3107 

|**Symbol**|**Value**|**Meaning...**|
|---|---|---|
|SYSLOG_CRIT|2|critical conditions|
|SYSLOG_ERR|3|error conditions|
|SYSLOG_WARNING|4|warning conditions|
|SYSLOG_NOTICE|5|normal but significant condition|
|SYSLOG_INFO|6|informational default|
|SYSLOG_DEBUG|7|debug-level messages|



_msg_ (String)  [in] 

message to output 

## **Comments** 

The open, close, and mask operations are all optional. 

MX_SYSLOG is comparable to MX_ASHLOG, except that instead of writing to the A-Shell log file along with several automatic prefix fields, it uses the Linux system() function to send the specified message to the operating system logging (syslog) service. How the service handles the message is entirely dependent on the service configuration options (which in a modern Linux platform are quite extensive). 

A-Shell Reference 

Page 3108 

Note that in order to get a plain text log file (e.g. /var/log/syslog), you may need to install the rsyslog service and make configuration changes to /etc/rsyslog.conf, sysctl.conf and/or journald.conf or their equivalents so that the the messages get forwarded to rsyslog and written to a file. 

Note that the out-of-the-box configuration is likely to echo all the messages to the console of all connected terminals, which is probably not what you want. 

A-Shell Reference 

Page 3109 

## **MX_SETERSATZ** 

_Added February 2026_ 

## **xcall MIAMEX, MX_SETERSATZ, erzdef {, status}** 

MX_SETERSATZ (208) allows for adding or updating ERSATZ device definitions without relaunching session. This may be useful in applications where the specific location of certain system-wide ersatz devices (e.g. REPORTS:) may need to change based on the user, menu selection, etc. 

## **Parameters** 

## _erzdef_ (String)  [in] 

either a filespec containing ERSATZ definitions, or a single ersatz definition in the format: erznam:=device:{[p,pn]} 

_status_ (Num)  [out] 

optionally returns status of operation: 

|**Value**|**Meaning**|
|---|---|
|0|single definition replaced|
|1|definition(s) added|
|-1|invalid format|
|-2|exceeded max # of allowed ERSATZ definitions|
|-3|file not found|



A-Shell Reference 

Page 3110 

## **See Also** 

- ERSATZ.LIT 

## **History** 

- 2026 February, A Shell 7.0.1783: MX_SETERSATZ added to A-Shell. 

A-Shell Reference 

Page 3111 

## **MSBOXX** 

_Revised December 2023; see History_ 

## **xcall MSBOXX, strow, stcol, endrow, endcol, boxcod {, boxsts, boxclr}** 

MSBOXX performs text-based box drawing operations, including the ability to save and restore the area underneath the box. 

## _strow, stcol, endrow, endcol_ 

specify the coordinates of the upper left and lower right corner of the box to be drawn. It is important to note that if a border is applicable, it is drawn OUTSIDE of the coordinates specified for the box. Thus the interior, or usable part of the box is the same size whether or not the border option is specified. 

## _boxcod_ 

specifies one or more options (added together). These are generally referenced symbolically via the msboxx.bsi include file. 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|BOX_ERA|&h00000001|Clear interior of the box|
|BOX_BDR|&h00000002|Draw border around the box|
|BOX_SVA|&h00000004|Save area used by box (to be restored later)|
|BOX_RSA|&h00000008|Restore area (previously saved)|
|BOX_COF|&h00000010|Leave cursor off on exit|



A-Shell Reference 

Page 3112 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|BOX_REV|&h00000020|(Not supported under A-Shell)|
|BOX_FAO|&h00000040|Field attributes on/off (at edge of box)|
|BOX_CHK|&h00000080|Return BOXSTS=0 if save/restore supported|
|BOX_PSA|&h00000100|Pop saved area without displaying it|
|BOX_MAP|&h00000400|(Not supported under A-Shell)|
|BOX_PRT|&h00000800|(Not supported under A-Shell)|
|BOX_ATR|&h00001000|Save/restore screen context|
|BOX_HLI|&h00002000|Draw horizontal line (set_strow_=_endrow_)|
|BOX_VLI|&h00004000|Draw vertical line (set_stcol_=_endcol_)|
|BOX_DBL|&h00008000|Draw double line border around box|
|BOX_SBU|&h00010000|Scroll box up one line|



A-Shell Reference 

Page 3113 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|BOX_SBD|&h00020000|Scroll box down one line|
|BOX_SRF|&h00040000|Draw line with serifs|
|BOX_WIN|&h00080000|Display pop-up window; see_Comments_below|
|BOX_PAR|&h00100000|See note in_History_, below|
|**Definition File:**ashinc:msboxx.def|||



- Hex Decimal Values 

## _boxsts_ 

optionally returns a code indicating if the operation succeeded. 0 indicates success. 

_boxclr_ 

optionally defines the set of colors to use for the parts of the box: 

```
MAP1 BOXCLR
```

```
   MAP2 BRDR'FG,B,1    ! Border foreground
   MAP2 BRDR'BG,B,1    ! Border background
   MAP2 IBOX'FG,B,1    ! Interior foreground
```

A-Shell Reference 

Page 3114 

```
   MAP2 IBOX'BG,B,1    ! Interior background
```

The A-Shell implementation of MSBOXX is nearly equivalent to the original version included with TRACKER. Note that it simplifies box drawing operations, you can perform all of the same operations directly in ASB code using Print Tab Functions. 

## **See Also** 

- ABOXXS: An alternate box-drawing routine 

- MSGBOX: Windows-style message box 

- INMEMO: Free-form and menu text inside a box 

## **History** 

- 2023 November, A Shell 7.0.1751.4:  Hot spots created with Tab(-1,162) are now saved and restored in ATE environments as well as pure Windows.  Note however that in the ATE environment, the application needs to send a Tab() command with an explicit termination following the Tab(-1,162) in order to get a clean save/restore. Tab(-1,254); (flush) is the simplest way to satisfy the requirement. 

- 2011 April, A Shell 5.1.1210:  New flag BOX_PAR may be used with BOX_WIN and BOX_SVA/BOX_RSA to automatically make the pop-up panel act as the parent to any controls (including TPRINT statements) created until the box is removed (with BOX_RSA+BOX_WIN+BOX_PAR). You could have done this yourself using MX_AUTOPARENT except that MSBOXX does not return an identifier for the panel; the BOX_PAR option overcomes that issue and automatically issues the necessary MX_AUTOPARENT calls. 

Note that with BOX_WIN, the box/panel is a GUI control, and thus you cannot output plain text on top of it; use TPRINT, DPRINT, AUI_CONTROL, and other GUI control generation statements instead of PRINT. Furthermore, with BOX_PAR, since the panel acts like a parent, the cursor position of controls and text to be placed on it must be adjusted to be relative to the box/panel rather than the screen. (The overall effect is similar to using a regular dialog box.) 

2011 April, 5.1.1210: BOX_SVA with the BOX_WIN option now saves underlying controls, as well as text, and BOX_RSA+BOX_WIN will restore them. This allows BOX_WIN panels to effectively overlay areas containing either plain text or GUI controls, or both.♥B 

A-Shell Reference 

Page 3115 

## **MSGBOX** 

_Updated January 2021; see History_ 

## **xcall MSGBOX, msg, title, btnflag, iconflag {, miscflags, rtncde** 

## **{, mxflags, timeout, timein, url, iconspec, btn1, btn2, btn3, btn4, btn5,** 

## **tip1, tip2, tip3, tip4, tip5,** 

## **fontface, fontscale, fgc, bgc}}** 

Note that in the syntax shown above, spaces and line breaks have no meaning—i.e., they do not and should not exist in the actual program. They are used here strictly as visual aides to illustate the structure of the commands. 

MSGBOX displays a message in a popup dialog, with a variety of standard or customized response button options. Depending on the environment and parameter options, one of four implementations may be used: 

- Standard Windows Message Box. Used in GUI environments prior to A-Shell 6.3.1543 or when no extended options are 

- requested. 

- Enhanced A-Shell Message Box using a dialog built with the AUI_CONTROL API. Used in A-Shell 6.3.1543 and later GUI 

- environments when the _mxflags_ parameter is specified. 

- INMEMO free-form menu. This is used in plain text environments or when forced with the MBX_FRCTXT flag. 

- HTML. In CGI mode, the message is simply sent to the browser in HTML format as the CGI response. 

## **Parameters** 

_msg_ (String)  [in] 

Specifies the message to display. The width of the message box will be adjusted (within certain reasonable limits) to the size of the message, which will them be wrapped as needed. You can also force your own line breaks and blank lines by inserting 

A-Shell Reference 

Page 3116 

CHR$(13) characters. 

_title_ (String)  [in] 

Specifies the title that will appear in the title bar of the message box. 

_btnflag_ (Num)  [in] 

Select one of the following values to specify the set of response buttons that will appear in the message box. Note that you can change the button text via the _btn1-btn5_ parameters. When using custom buttons, you can set the _btnflag_ to 0, which is equivalent to a single "OK" button in the standard case; if custom buttons are defined, will be interpreted accordingly. See Comments below for more details on defining custom buttons. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBTN_OK|0|OK button only, or customized buttons; see comments.|
|MBTN_OK_CANCEL|1|OK and CANCEL buttons|
|MBTN_ABORT_RETRY_IGNORE|2|ABORT, RETRY, and IGNORE buttons|
|MBTN_YES_NO_CANCEL|3|YES, NO, and CANCEL buttons|
|MBTN_YES_NO|4|YES and NO buttons|
|MBTN_RETRY_CANCEL|5|RETRY and CANCEL buttons|
|MBTN_CANCEL_TRY_CONTINUE|6|See note in_History_, below|



A-Shell Reference 

Page 3117 

||||
|---|---|---|
|MBTN_HELP|&h4000|Add a HELP button. Combine with any other MBTN_xxx option.|
|**Definition File: ashell.def**|||



## - Hex Decimal Values 

## _iconflag_ (Num)  [in] 

Select one of the following to specify the standard Windows icon that appears in the message box (in a GUI environment). 0 specifies no icon. See _iconspec_ to specify a custom icon. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBICON_STOP|&h0010|Stop (Red X)|
|MBICON_QUESTION|&h0020|Question (?)|
|MBICON_EXCLAMATION|&h0030|Exclamation (!)|
|MBICON_ICON|&h0040|Information (i)|
|**Definition File: ashell.def**|||



A-Shell Reference 

Page 3118 

- Hex Decimal Values 

## _miscflags_ (Num)  [in] 

Combine zero or more of the following to specify misc options: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBMISC_DFLT2|&h0100|Make the second button be the default. (Normally the first button will be the default button.)|
|MBMISC_DFLT3|&h0200|Make the third button be the default.|
|MBMISC_DFLT4|&h0300|Make the fourth button be the default|
|MBMISC_DFLT5|&h0400|Make the fifth button be the default|
|MBMISC_SYSMODAL|&h1000|System modal. Suspends all Windows applications until the dialog box is responded to. (Windows<br>only)|
|MBMISC_TASKMODA<br>L|&h2000|Task modal. Suspends the A-Shell session until the dialog box is responded to. (Windows only)|
|MBMISC_TOPMOST|&h8000|Force message dialog to remain on top until closed. This prevents a problem where it can get<br>hidden by other windows, even though it has the focus, making the other windows appear to be<br>dead.|



A-Shell Reference 

Page 3119 

**Definition File: ashell.def** 

- Hex Decimal Values 

## _rtncde_ (Num)  [out] 

Returns a code indicating what button was pushed to respond to the message, from the list below: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBRC_OK|1|OK button|
|MBRC_CANCEL|2|CANCEL button|
|MBRC_ABORT|3|ABORT button|
|MBRC_RETRY|4|RETRY button|
|MBRC_IGNORE|5|IGNORE button|
|MBRC_YES|6|YES button|
|MBRC_NO|7|NO button|
|MBRC_CLOSE|8|Dialog closed; see notes below|



A-Shell Reference 

Page 3120 

|ence|||
|---|---|---|
||||
|MBRC_HELP|9|HELP button|
|MBRC_TRYAGAIN|10|TRY AGAIN button|
|MBRC_CONTINUE|11|CONTINUE button|
|MBRC_CTRLC|12|Control-C; see notes below|
|<no symbol>|101|First custom button; see mxflags MBX_RCBTNO|
||102|Second     "     "     "     "|
||103|Third        "     "     "     "|
||104|Fourth      "     "     "     "|
||105|Fifth        "     "     "     "|
|**Definition File: ashell.def**|||



A return code of 8 indicates that the message box was closed without clicking on one of the button choices (either the X button in the corner of the dialog under Windows/ATE or the ESCAPE key under Unix/text mode). Note, however, that at least under 

A-Shell Reference 

Page 3121 

Windows, the internal message box logic may try to translate the close option to one of the existing buttons if it makes logical sense. For example, closing an OK/CANCEL dialog may return as if CANCEL clicked. 

The MBRC_xxx values are associated with standard buttons sets as specified by the MBTN_xxx values in btnflag while the values 101105 are used for custom button sets; see mxflags MBX_RCBTNO flag and Comments below. Note that Control-C will set the ControlC flag (triggering ASB error 1) if Control-C is enabled; otherwise it will return MBRC_CTRLC. Also note that for the standard Windows Message Box, Control-C while the box is displayed may be ignored (acting instead as the Windows Copy command); but if the Control and C keys are down when the message box is created or destroyed, it will be detected and processed, providing a way out of situations where an error message box is being displayed in an endless loop. Hold down the Control and C buttons with one hand and dismiss the message box using the mouse with the other hand. 

_mxflags_ (Num)  [in] 

flags related to extended options: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBX_RCBTNO|&h10000000|return 101-105 for buttons 1-5|
|MBX_FRCTXT|&h20000000|force plain text version|
|MBX_TI1|&h00100000|time-in delay on button 1|
|MBX_TI2|&h00200000|time-in delay on button 2|
|MBX_TI3|&h00400000|time-in delay on button 3|
|MBX_TI4|&h00800000|time-in delay on button 4|



A-Shell Reference 

Page 3122 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|MBX_TI5|&h01000000|time-in delay on button 5|



## - Hex Decimal Values 

## _timeout_ (Num)  [in] 

if not zero, sets the timeout (in seconds) on the default button, at which point the button is auto-clicked. Except in the case of icon buttons, the button will show the countdown progress. 

## _timein_ (Num)  [in] 

used in conjunction with the MBX_TIx flags (see mxflags) to specify a time (in seconds) before which one or more buttons are unable to be clicked (i.e. disabled). This is useful when you want to make sure the message box stays on the screen for at least a certain number of seconds, either so that the user can read the message, or perhaps to prevent the possibility of accidentally clicking a button before understanding the consequences. Note that if _timeout_ is not zero, it overrides the _timein_ for the default button. 

## _url_ (String)  [in] 

optionally specifies a clickable hyperlink that appears beneath the message text and above the buttons. The visible text may be the same as the target url, or you may use HTML format to display something other than the actual link, e.g. 

```
http://www.microsabio.com
```

```
<a href=http://www.microsabio.com>MicroSabio Home Page</a>
```

```
<a href="http://www.microsabio.com">MicroSabio Home Page</a>
```

The third example shows the proper HTML format—i.e., with the url field quoted. Note that to embed quotes within a quoted 

A-Shell Reference 

Page 3123 

string in BASIC you have to use double quotes (""). The second example, without the extra quotes is supported for convenience. See History note of May 2017. 

## _iconspec_ (String)  [in] 

optionally specifies an icon (native Windows filespec or iconname::icondll, e.g. "warning::ashico1") to be used instead of the standard one based on the iconflag value, which will be ignored if _iconspec_ is non-null. If neither an _iconflag_ nor an _iconspec_ is specified, the message box will have no icon. Note the standard icons specified via the _iconflag_ parameter do not change size with _fontscale_ , but custom icons (specified via _iconspec_ ) do scale. 

_btn1 - btn5_ (String, 32)  [in] 

optional text or icon to display for up to 5 buttons—assuming you want to override the default button text corresponding to the _btnflag_ parameter. Although you can mix text buttons and icon buttons, it probably works (or looks) best if you stick to one or the other. For icons, you can use the native Windows filespec of the .ico file or the iconname::icondll format for an icon within an icon library (like ashico1.dll). Note the 32 byte limit on the length of each field; for ico filespecs, to fit within 32 characters you may need to drop the directory from the path and either put the icon in the current directory or in the default A-Shell icon search path—e.g. the cache, permcache, or icons subdirectories. 

_tip1 - tip5_ (String)  [in] 

optional tool tips for up to 5 buttons. 

_fontface_ (String)  [in] 

optional font to use 

_fontscale_ (Num)  [in] 

optional font scale adjustment in percent. 0 is treated the same as 100 percent. In modern high-res environments, you may find that increasing the font size makes for a more readable message. Note that the font scale does not affect the title bar, but it does affect nearly everything else in the message box. See note under _iconspec_ . 

_fgc_ (Num)  [in] 

A-Shell Reference 

Page 3124 

optional RGB value to use for the message text. 

## _bgc_ (Num)  [in] 

optional RGB value to use for the background of the message. 

## **Examples** 

## Standard Abort/Retry/Ignore message box in both GUI and plain text versions: 

```
xcall MSGBOX, "Best man tried on ring, can't get it off!", "Wedding Crisis", 2, &h0030, 0, rtncde
```

## Enhanced version with custom buttons, hyperlink colors... 

```
msg$ = "Obamacare repealed - how do you want to pay? (Click link below to complain)"
```

```
title$ = "Emergency Room Cashier Encounter"
```

```
link$ = "<a href="http://www.whitehouse.gov">White House</a>"
```

```
icon$ = "first_aid::ashico1"
```

```
btn1$ = "Cash" : btn2$ = "Medicare" : btn3$ = "Private Ins"  : btn4$ = "" : btn5$ = ""
```

```
tip1$ = "If you got it"  : tip2$ = "Ages 65+ only" : tip3$ = "If you can afford it"
```

```
font$ = ""
```

```
fontscale = 150
```

```
bgc = &hddddff    ! pink background
```

```
xcall MSGBOX, msg$, title$, 0, 0, 0, rtncde, 0, 0, 0, link$, icon$, btn1$, btn2$, btn3$, btn4$, btn5$, tip1$,
```

A-Shell Reference 

Page 3125 

```
tip2$, tip3$, tip4$, tip5$, font$, fontscale, fgc, bgc
```

## Enhanced version with icon buttons... 

```
title$ = "Music Player"
```

```
msg$  = "Current selection: "+chr(13)+chr(13) "I've been working on the A-Shell..."
```

```
icon$ = "music::ashico1"
```

```
link$ = ""
```

```
btn1$ = "media_beginning::ashico1" : btn2$ = "media_rewind::ashico1" : btn3$ = "media_play::ashico1"
```

```
btn4$ = "media_fast_forward::ashico1" : btn5$ = "media_end::ashico1"
```

```
tip1$ = "beginning" : tip2$ = "rewind" : tip3$ = "play" : tip4$ = "fast forward" : tip5$ = "end"
```

```
font$ = "Comic Sans MS"
```

```
fontscale = 200
```

```
xcall MSGBOX, msg$, title$, 0, 0, 0, rtncde, 0, 0, 0, link$, icon$, btn1$, btn2$, btn3$, btn4$, btn5$, tip1$,
tip2$, tip3$, tip4$, tip5$, font$, fontscale
```

## **Comments** 

**Standard vs custom buttons:** the original version of the message box offered several standard sets of buttons (OK, YES/NO, etc) as specified by the _btnflag_ parameter, and returned a code unique to each button's meaning, rather than its position. So MBRC_CANCEL means the same regardless of whether the CANCEL button was in the 2nd or 3rd position. The enhanced version allows you to specify an arbitrary set of up to 5 buttons, and gives you the choice of treating those as substitutes for the standard button labels, still using the MBRC_xxx rtncde values, or as totally arbitrary buttons (identified by button position in rtncde values 101-105), based on the mxflag MBX_RCBTNO flag. For example, if you set btnflag to MBTN_YES_NO, but specify btn1="Good" and btn2="Bad", unless you set the MBX_RCBTNO flag, the "Good" button will act as the YES button (returning MBRC_YES) and the 

A-Shell Reference 

Page 3126 

"Bad" button will act as NO (returning MBRC_NO). This might make sense in some cases, but in general it will probably be best to explicitly set the MBX_RCBTNO flag to return the button number (101 thru 105) when using customized labels. There are two cases where the MBX_RCBTNO flag will be implicitly set. The first occurs when the number of custom buttons defined is more than the number in the standard set as specified by btnflag. In that case, the additional buttons will always return the position code (101105). The second occurs when btnflag is set to zero and more than one custom button label is defined (i.e. when btn2 is non empty). Although btnflag value zero is equivalent to MBTN_OK, it seems clear that if two or more custom buttons are defined, the intended meaning of btnflag zero is not MBTN_OK but "custom buttons only". This allows you to leave both btnflag and mxflag at zero with a set of custom buttons while avoiding the confusion of the first button returning MBRC_OK while the other buttons return values 102 thru 105. 

Aside from the features documented above, an advantage of the enhanced message box is that although it forces you to respond to the message box before returning to the application (i.e. it is task modal), it allows you to access the A-Shell menu bar, for example, to use the Print Screen utility. 

## **See Also** 

- Display Standard Message Dialog 

## u **History** 

- 2021 January, A Shell 6.5.1697:  The _timein_ parameter now applies selectively to each of the buttons (based on the xflags MBX_TIx bits), and is independent of the _timeout_ value, except that the _timeout_ value overrides the _timein_ value for the default button. Previously the _timein_ needed to be applied to all buttons for it to work at all, and there was no visual indication of the _timein_ countdown. 

- 2019 September, A Shell 6.5.1667:  Calls using MBICON_QUESTION are no longer logged to the ashlog. Only MBICON_STOP or MBICON_EXCLAMATION trigger the logging. 

- 2017 May, A Shell 6.4.1550: All parameters after _mxflags_ are now optional.Previously, if _mxflags_ was specified, but _url_ and _iconspec_ were not also specified, the routine was likely to crash. 

- 2017 January, A Shell 6.3.1543:  Major enhancements and internal rewriting. Add support for up to five buttons, customizeable button labels or icons, tool tips, time delay, time out, optional hyperlink field, colors, fonts, etc. 

- 2011 August, A Shell 5.1.1231:  Right-click on the box now reveals a context menu option to print the screen (if the 

A-Shell Reference 

Page 3127 

## bas:aprntscrn.cfg is configured for print screen). 

- 2011 April, A Shell 5.1.1210: MBTN_CANCEL_TRY_CONTINUE produces the buttons "Cancel", "Try Again", and "Continue", and returns two new status values MBRC_TRYAGAIN and MBRC_CONTINUE. This is actually just an alternate style to the older ABORT/RETRY/IGNORE message box (with ABORT being replaced by CANCEL, RETRY being replaced by TRY AGAIN, and IGNORE being replaced by CONTINUE). The new variation has been used in Windows since W2000, in preference to the older style. 

Actually, no change to MSGBOX was necessary to support this new style - it was just a matter of defining symbols for the new codes in ashell.def. The only internal change is that if you specify the new style but are not running in GUI mode, it continues to display in the old style, while behaving compatibly with the new style. 

- 2011 April, A Shell 5.1.1210: MSGBOX now checks if the CTRL and C keys are down, both on entrance and exit. If so, and CTRLC is enabled for the job, error 1 is triggered. Otherwise, it returns the new return status code 12 (MBRC_CTRLC). This should help alleviate a frustrating situation where a program was putting up error message boxes too fast to allow the CTRL+C keyboard status to be detected between the MSGBOX calls (and Ctrl+C is not recognized as an abort by the standard Windows message box itself). 

- 2009 November, A Shell 5.1.1164: MBMISC_DEFLT2 and MBMISC_DEFLT3 flags (to select the default button) are now supported in text mode. (Previously text mode always selected the first button.) Also, the Windows version now uses the LDF to get the button labels (the Unix version has done this for a long time). 

- 2006 March, A Shell 4.9.953:  The text version of MSGBOX now gets button text from LDF. 

- 2006 Jan, A Shell 4.9.950: MSGBOX is now implemented as an internal subroutine (effectively replacing MSGBOX.SBX). There should be no other change in the behavior. If, for some reason, you want to keep using the MSGBOX.SBX, then rename it to something else (e.g. MSGBXX.SBX) and then create an ALIAS[SP] : 

## `ALIAS=MSGBOX:MSGBXX` 

That way, when your application does call MSGBOX, the ALIAS[SP] will convert this to MSGBXX, which will find the SBX. 

A-Shell Reference 

Page 3128 

## **NFIND** 

## **xcall NFIND, string, stpos, endpos, char, pos** 

NFIND is similar to the INSTR() function, except with more sophistication. 

## **Parameters** 

_string_ (String)  [in] 

string to be searched 

_stpos_ (Num)  [in] 

starting position (first byte is number 1) 

_endpos_ (Num)  [in] 

ending position to search in the string. Must be greater than or equal to _stpos_ or the result will always be zero. If larger than the length of the string, it will be treated as equal to the length. 

## _char_ (String, 1)  [in] 

the character to search for, with two special wildcards: "%" matches any non-space in the substring, and "/" matches nonnumeric, non-alphabetic character. 

## _pos_ (Num)  [out] 

Returns the position of the matched character, or zero if there is no match within the specified substring. 

## **See Also** 

- INSTR() 

- .INSTRR() 

A-Shell Reference 

Page 3129 

## **NOECHO** 

_Reviewed and revised April 2024_ 

## **xcall ECHO {,channel}** 

## **xcall NOECHO {,channel}** 

ECHO is used to turn terminal echo on. It may also be used to return a serial port under UNIX to its normal settings. NOECHO is used to disable terminal echo. 

## **Parameters** 

_channel_ (Unsigned Int)  [in] 

Optional file channel associated with a serial point under UNIX. A value of zero, or omitted, refers to the terminal. 

Calling ECHO with no arguments is equivalent to executing the ECHO statement. 

## **Comments** 

NOECHO is usually used in conjunction with GET or some other subroutine for terminal input, such as INFLD, in order to (a) allow character input, and (b) disable echo. NOECHO does not affect the true state of the terminal, but merely changes the internal operation of A-Shell itself. So, for example, if HOSTEX is used to execute a host command, that command will function in the same way whether or not the NOECHO subroutine had been used. 

Under Unix, a serial port may be opened for input, and then NOECHO called with that channel specified, for example: 

```
open #1,"/dev/tty1",input
```

```
xcall NOECHO,1
```

In this case, the true _host_ mode of the port will be changed. Echo will be disabled, cooked mode processing will be disabled and so on, enabling all characters to be received unaltered from the port with the GET routine. This is particularly useful for communicating with external equipment such as modems, time record devices and so on. 

A-Shell Reference 

Page 3130 

If a port’s mode is changed in this way, then it should be reset with NOECHO before closing the channel. Failure to do this will leave the port in its altered state even when A-Shell is exited. 

## **Also See** 

- GETXS for more details on inputting from a serial port 

- ECHOSC 

A-Shell Reference 

Page 3131 

## **NUMCHK** 

## **xcall NUMCHK, string {,len, rc}** 

NUMCHK checks a string to see if it contains valid numeric characters only, and possibly that it is of a certain length. 

## **Parameters** 

_string_ (String)  [in/out] 

string to be searched. _string_ is stripped of leading and trailing spaces and tabs and returned that way, regardless of whether valid. 

_len_ (Num)  [in] 

if specified, stripped _string_ length must match. 

- _rc_ (F6)  [out] 

optional return value specifying okay (0), or that _string_ contains invalid characters or is not of _len_ length (-1). Note that NUMCHK may be passed to the XFUNC function, in which case rc is not really relevant since the function itself returns the same value. 

A-Shell Reference 

Page 3132 

## **OAUTH2** 

_Updated May 2024; see History_ 

## **xcall OAUTH2, opcode, status, clientid$, clientsecret$, option, auth'endpoint$, token'endpoint$, challenge$, scope$, refresh'token$, response$, handle, stsmsg$ {,file {,add'param}}** 

OAUTH2 implements the industry-standard OAUTH2 protocol for authorization. It provides a means of obtaining an OAUTH2 access token needed for some modern web services, such as Gmail when "less secure applications" is not enabled. See the following topics, OAUTH2 Setup and Refresh'token$, for additional details. 

## **Parameters** 

|**Name**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|opcode|Num|in|1: Request the auth url<br>2: Request the token after signing in on web<br>3: Request a refresh token for previously authorized service|
|status|Signed Int|out|Return status: 0=ok, elseASHNET Status Codes|
|clientid$|String|in|Client id previously assigned by service provider|
|clientsecret$|String|in|Client secret previously assigned (or negotiated) by service provider|
|option||in|For opcode 1, port; for opcode 2, timeout (in secs)|



A-Shell Reference 

Page 3133 

|**Name**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|auth'endpoint$|String|in|URL determined by service provider. For example, Google uses<br>"https://accounts.google.com/o/oauth2/v2/auth"|
|token'endpoint$|String|in|URL determined by service provider. For example, Google's API uses<br>"https://www.googleapis.com/oauth2/v4/token"|
|challenge$|String|in|Optional challenge string|
|scope$|String|in|Scope of the request, typically a URL, e.g. "https://mail.google.com"|
|refresh'token$|String|in|Usage depends on_opcode_.|
|response$|String|out|Response (typically a JSON document). Argument does not auto-expand, so make<br>sure it is sufficiently large.|
|handle|X8|in/out|Value returned by op 1 and passed to op 2|
|stsmsg$|String|out|Status message. If S,0, must be pre-initialized to desired maximum length.|
|file$|String|in|For op 1, if specified, the response tokens are written directly to the specified file.<br>For op 3, if specified and the refresh_token$ parameter is "", then the<br>refresh_token string is retrieved from the file, and the file is updated with the new<br>access_token. In either case, the response is also returned in the response$ parameter.|



A-Shell Reference 

Page 3134 

|**Name**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|add'param|String|in|Should be in the form of a comma-delimited list of name=value pairs, e.g.<br>"token_access_type=offline,foo=bar"|



## **See Also** 

## • Sample program OAUTH2 in EXLIB:[908,77] 

- XOAUTH2XS 

- Google Cloud Access Token 

## **History** 

- 2024 May, A Shell 7.0.1759: New optional parameter _add'param_ allows specification of additional authorization or token query parameters, which are required by some services. This requires ashnet 1.14.195 or higher. 

- 2018 October, A Shell 6.5.1648: Routine added to A-Shell. Requires ASHNET library 1.12.163+. See comments for more details. 

A-Shell Reference 

Page 3135 

## **OAUTH2 SETUP** 

As a preliminary to OAUTH2 authentication, you'll need to establish an account with a service provider (e.g. Google API, Microsoft Azure, etc.), typically through an online portal; this is independent of A-Shell. The provider will issue you a client ID and secret, and probably some other attribute values (e.g. authorization endpoint, scope, etc.) which you'll need to save locally (typically in JSON format) in order to provide them as part of the opcode 1 request. As an example, here is a typical set of client attributes for Gmail: 

```
{
```

```
"client_id":"123456789012-abc123xyz456jkl789pqr321ack.apps.googleusercontent.com",
```

```
"project_id":"emailx-123456",
```

```
"auth_uri":"https://accounts.google.com/o/oauth2/auth",
```

```
"token_uri":"https://oauth2.googleapis.com/token",
```

```
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
```

```
"client_secret":"XXXXXX-aBcDeFgHiJkLm123456789",
```

```
"redirect_uris":["http://localhost"],
```

```
"scope":"https://mail.google.com/"
```

```
}
```

For the initial opcode 1, you'll need to match up the necessary attribute values with the corresponding OAUTH2 parameters. Using the example, above, _clientid$_ is "client_id" ("123456..."), _clientsecret$_ is "client_secret" ("XXXXX..."), _auth'endpoint$_ is "auth_uri," _token'endpoint$_ is "token_uri," etc. 

The _response$_ from a successful opcode 1 will be a URL which you'll then need to launch a browser to, in order for the user to interactively acknowledge the desire to access the service. This is the big difference between the OAUTH2 protocol and most other authentication schemes, i.e. that it requires a level of user interactivity. However, this interaction step is normally only 

A-Shell Reference 

Page 3136 

required for the first access after which the application will be able to re-use and even refresh the access token for a substantial period or time or number of requests without further interaction. 

To launch the browser to the specified URL for the initial authorization step, under local A-Shell/Windows you can use MX_SHELLEXXS.In the telnet/ssh environment, it won't be possible to use MX_SHELLEX directly from the server/application side, so you'll need another way to arrange for the user to browse to the specified URL. If the client workstation is running ATE, you XS XS could use AG_SHLEXEC , although the easiest approach is probably to use XOAUTH2 in place of OAUTH2. XOAUTH2 is an SBX that offers the identical application interface as OAUTH2, but in the case of ATE executes the operation on the ATE client, eliminating the need for additional logic in the application code to handle the two scenarios. 

Once the browser has been launched, the application can proceed to _opcode_ 2, which waits (up to the specified time out) for the user to complete the interactive authorization via the browser, after which it will either succeed (returning the _status_ 0, with the access token and related details in response$) or fail with a non-zero _status_ value. 

In code, the sequence of requesting a new access token may be summarized as ... 

```
xcall OAUTH2, 1, status, clientid$, clientsecret$, option, auth'endpoint$, token'endpoint$, challenge$,
scope$, refresh'token$, response$, handle, stsmsg$
```

```
if status = 0 then    ! on success, launch the browser to the response URL...
```

```
    xcall MIAMEX, MX_SHELLEX, status, response$, "", "", "", SW_SHOWNORMAL, 0
```

- `! after launching the browser, proceed to opcode 2 (waiting for the user to complete` 

- `! the authorization and for the web service to accept and issue the token)...` 

```
    xcall OAUTH2, op, status, clientid$, clientsecret$, wait, auth'endpoint$, token'endpoint$, challenge$,
scope$, refresh'token$, response$, handle, stsmsg$
```

```
...
```

A-Shell Reference 

Page 3137 

The successful _response$_ is also typically in JSON form, for example... 

```
{
```

```
    "access_token": "xy12.x1Bux_KpEC0z...",
```

```
    "expires_in": 3599,
```

```
    "refresh_token": "9//23-42ZxTgy8I6...",
    "scope": "https://mail.google.com/",
    "token_type": "Bearer",
    "refresh_token_expires_in": 604798
```

```
}
```

The access token may then be used to access the desired service. In most cases that will involve an HTTPXS operation with the access code included in the request header. Or, In the case of EMAILXXS, the access code is used in place of the password. 

Access tokens typically last for a certain period of time (one hour in the example above), after which you'll need to use _opcode_ 3, (passing the refresh token in the _refresh'token$_ parameter) to get a new access token. Once the refresh token expires, the request for a refresh will fail and you'll need to start over with _opcode_ 1. 

A-Shell Reference 

Page 3138 

## **REFRESH'TOKEN$** 

_Written November 2020_ 

For _opcode_ 3, request a refresh token for previously authorized service, the _refresh'token$_ parameter should contain the value of the "refresh'token" (typically in the form of a name-value pair within a JSON document) in the _response$_ parameter returned by a prior _opcode_ 1 or 2. For example, a typical _response$_ JSON document might look something like this... 

```
{
```

```
  "access_token": "zb29.E0RfWH6SMC2upzYbvBoy31p3Cmtuqr8T...",
```

```
  "expires_in": 3599,
```

```
  "refresh_token": "1//0fbpxFnYPChkpGgXIARAAGA8SNwF-L9Ir4eQLxI3KyuoZWRMz9y...",
```

```
  "scope": "https://www.googleapis.com/auth/analytics",
```

```
  "token_type": "Bearer"
```

```
}
```

In this case, you would set _refresh'token$_ to "1//0fbpxFnYPChkpGgXIARAAGA8SNwF-L9Ir4eQL..." 

For _opcode_ 1, request authorization URL, you may optionally set this parameter to specify the HTML redirect code that the authorization process will send to the browser upon success and/or failure. The default displays a generic page designed more for developers than users. The format of the parameter must be: 

```
chr(1) + <html-if-allowed> + chr(2) + <html-if-denied> + chr(3) + <app-callback-url>
```

For example: 

```
chr(1) + "<html><body>Thank you for allowing access.</body></html>" + chr(2) + "<html><body>Access denied -
try support.</body></html>"
```

The <app-callback-url> clause is mainly used with certain OAuth2 services which do not allow for the http://localhost:port callback, and thus can typically be omitted. 

A-Shell Reference 

Page 3139 

Each of the three clauses (consisting of the control character followed by the HTML or URL string) is optional, but must be supplied (even if the string is null) if any of the subsequent clauses are specified. 

Typically the HTML string would use the meta clause to specify a URL to redirect to, after displaying a brief message, e.g. 

```
refresh'token$ = chr(1) &
```

- `+ "<html><head><meta http-equiv='refresh' content='0;url=https://www.yourwebsite.com/access-allowed/'>" &` 

- `+ "</head><body>Thank you for allowing access.</body></html>" &` 

- `+ chr(2) &` 

- `+ "<html><head><meta http-equiv='refresh' content='0;url=https://www.yourwebsite.com/access-denied/'>" &` 

- `+ "</head><body>Sorry, access denied.</body></html>"` 

The URLs should of course reference actual pages you have created or know to exist. 

The <app-callback-url> is mainly used with certain OAuth2 services which to not allow for the http://localhost:port callback. 

A-Shell Reference 

Page 3140 

## **ODTIM** 

_Updated November 2018; see History_ 

## **xcall ODTIM, stringfmt, odate, otime, flags** 

ODTIM performs the reverse function of IDTIM, i.e. it converts an internal format date and/or time to a string format. Its formatting options are much more extensive, however, than the formats allowed by IDTIM. 

## **Parameters** 

_stringfmt_ (String)  [out] 

the formated date/time string is returned here. 

## _odate_ (Num)  [in] 

should contain the internal (aka "separated" – see IDTIM for details) date to be formatted. 0 is taken to mean the current date. 

_otime_ (Num)  [in] 

should contain the internal time—seconds since midnight—to be displayed, with 0 indicating either the current time (if _odate_ is also 0), or midnight (if _odate_ <> 0). As there are 86400 seconds in 24 hours, values greater than or equal to 86400 may produced undefined results; see Comments below. 

## _flags_ (Num)  [in] 

must specify a sum of desired formatting options from the following table: 

|**Value**|**Meaning**|
|---|---|
|&h00000001|Omit date from output (ignore all other date related flags)|
|&h00000002|Output the day of the week|



A-Shell Reference 

Page 3141 

|**Value**|**Meaning**|
|---|---|
|&h00000004|Use the full name of the day of the week; else use the first three characters|
|&h00000008|Output the month as a number (1-12) and ignore flag &h0010.|
|&h00000010|Output the full name of the month; else use the first character abbreviation|
|&h00000020|Output four digit year; else two digit year|
|&h00000040|Output the month first, then the day; else the day first, then the month|
|&h00000080|If &h0100 not specified, use spaces to separate the parts of the date, as in 17 Jul 2013. If &h0100<br>is also specified (i.e. &h0080 + &h0100) then use separator character defined in the language<br>definition file (LDF).|
|&h00000100|If &h0080 not specified, use slashes to separate the parts of the date, as in 7/17/03. If &h0080 is<br>also specified, use LDF separator character (see above).|
|&h00000200|Omit time from output (ignore all other time related flags)|
|&h00000400|Omit seconds from the time output|
|&h00000800|Use 12 hour time format with AM/PM; else use 24 hour format|



A-Shell Reference 

Page 3142 

|**Value**|**Meaning**|
|---|---|
|&h00001000|Do not output a separator between the hours and minutes (also see &h0020000)|
|&h00002000|Use colon as the time separator; else use the character defined in the LDF|
|&h00004000|Suppress leading zeroes from numeric portion of date.|
|&h00020000|Do not output a separator between the minutes and the seconds|
|&h00200000|Do not output date punctuation|
|&h00800000|Do not output the day|
|&h01000000|Do not output the month|
|&h02000000|Do not output the year|



- Hex Decimal Values 

## **Comments** 

Two special flags values, which override the bit settings in the table above, are also recognized: 

- flags = 0 produces output of the form: 17-Jul-03 13:15:58. 

A-Shell Reference 

Page 3143 

- flags = -1 (&hffffffff) produces output of the form: Monday, July 17, 2013 01:15:58 PM 

In both of the above special cases, the LDF settings will be applied as appropriate. 

As of 6.5.1650.1 (see History), _otime_ values >= 86400 are handled as follows: 

- If the date output is omitted (flags bit &h0001 set) and 24 hour format is requested (flags bit &h0800 not set), then otime is 

- treated as a cumulative value with  no particular upper limit, e.g. otime = 455571 results in 126:32:51, which might represent an elapsed time for some 

activity. 

- If the date is to be included in the output (flags bit &h0001 not set), then the odate value specified will be increased by one 

- day for each multiple of 86400 in otime, with otime reduced accordingly.  For example, if odate = 0 and otime = 86401, it will display tomorrow's date and 00:00:01 as the time. 

- If the date output is omitted and 12 hour format requested (flags bits &h0801) the result is undefined. 

## **See Also** 

The system function ODTIM() provides a somewhat simpler syntax for the same operation. 

## **History** 

- 2018 October, A Shell 6.5.1650: special handling of _otime_ >=86400; see Comments. 

A-Shell Reference 

Page 3144 

## **PCKLST** 

## **xcall PCKLST, row, col, answer, array, maxcnt, prompt, exitcode {,strow, endrow, flags, file, mmoclr}** 

PCKLST displays a list of items in a box (aka a "pick list"), optionally waiting for the user to select one. Besides simplifying this common user interface element, it can operate in either text or GUI modes, making the decision at runtime based on external factors, and with a good deal of compatibility between them. 

In GUI mode, PCKLST acts as an alias for a simple selection XTREE,  while in text mode it acts as a wrapper for the vertical menu mode of INMEMO. 

Developers committed to the GUI environment should consider PCKLST deprecated and just use XTREE directly, while those interested in both text and GUI (or text only) should use PCKLST. For information on the differences between PCKLST and XTREE, and how PCKLST/XTREE handles text versus GUI issues, see the note on those subjects in XTREE. 

## _row, col_ (Num) 

If XTF_XYXY is not specified in _flags,_ these are the locations where the ordinary field input would have taken place. The pick list box is drawn around the position where the field was or would have been (to give it the flavor of a drop-down box). If XTF_XYXY flag is specified, these are interpreted as the top left character position of the box (i.e. starting row, starting col). 

_answer_ (Num) 

On exit, _answer_ is set to the Row number of the selection (first row is numbered 1). On input, _answer_ specifies the default position of the selection bar. Range is limited to 0-65535. 

_array_ (String array or BLOB) 

is an array of strings containing the choices for the pick list. The end of the array is marked by the first null entry or _maxcnt_ . Note that the array element size must be large enough to accommodate at least one trailing null on each element. Any text in an array element following a backslash will be treated as "hidden text", meaning that it will not be displayed (nor used in determining the box display width). See note in _History_ , below. 

A-Shell Reference 

Page 3145 

_maxcnt_ (Num) 

is the maximum number of elements in the array. 

## _prompt_ (String) 

If XTF_COLDFX is not specified in _flags_ , contains the string to display in the top border of the box as a title or prompt. If the string contains an embedded CHR$(13), the remainder of the string will go on the bottom border of the box. See the documentation on XTF_COLDFX for details on the interpretation of this parameter when XTF_COLDFX is specified. 

_exitcode_ (Signed Num) 

will return a code indicating how the pick list was exited, with 0 indicating the normal exit via the ENTER key, and 1 indicating ESCAPE. See the _flags_ parameter below for enabling other exit keys. 

## _strow, endrow_ (Num) 

if specified, determine the top and bottom display position of the box. Otherwise the box is likely to extend both above and below the row specified by the _row_ parameter, according to some kind of primitive internal heuristics. (Set to 0 as a placeholder if needed for subsequent parameters.) 

If the XTF_XYXY bit is set in the _flags_ parameter, _strow_ and _endrow_ are reinterpreted as the ending row and ending column (bottom right corner) of the box, whose top left corner will be set by _row_ and _col_ . This is the more traditional method for specifying the coordinates of a box, as used by XTREE. 

_flags_ (Num, two-element array of B,4) 

may be used to specify zero or more options from the tables below. See XTREE XTREE Flags for details on mapping this parameter. Note that while this parameter is generally compatible between PCKLST and XTREE, many of the XTREE flags are ignored by PCKLST. To simplify, the tables below list only the flags that are recognized by PCKLST, or for which the interpretation differs between PCKLST and XTREE. The XTF_xxx symbols are def!ined in ashinc:xtree.def. 

A-Shell Reference 

Page 3146 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTF_FKEY|&h0000000<br>1|Allow F1-F16 (returning Exitcodes -1 through –16)|
|XTF_LEFT|&h0000000<br>2|Enable Left arrow (Exitcode -40)|
|XTF_RIGHT|&h0000000<br>4|Enable Right arrow (Exitcode –41)|
|XTF_UP|&h0000000<br>8|EnableCTRL+UP-ARROWon first row (Exitcode -42)|
|XTF_TAB|&h0000002<br>0|EnableTAB(Exitcode -44), andSHIFT+TAB(Exitcode -35)|
|XTF_HOME|&h0000004<br>0|EnableHOMEkey (Exitcode –45)|
|XTF_END|&h0000008<br>0|EnableENDkey (Exitcode –46)|
|XTF_NOAS|&h0000010<br>0|Disable auto-shrink of box height to match amount of data. (This flag is ignored byXTREEsince it<br>does not support auto-shrink.)|
|TXF_MODELE|&h0000020|Leave list box on the screen after exit from the subroutine.|



A-Shell Reference 

Page 3147 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|SS|0||
|XTF_TIMOUT|&h0000040<br>0|For thePCKLST(text mode) only, sets a 200 second timeout—i.e., acts as if user had hitESCAPE. For<br>XTREE, ignored; use XTR.TIMEOUT instead.|
|XTF_FST|&h0000080<br>0|Fast selection mode. InPCKLST, this means menu items can be selected by entering the minimum<br>number of characters to uniquely identify the item. (Without the XTF_FST flag,ENTERwould be<br>required to complete the selection.) ForXTREE, this means that a single click (completes the<br>selection operation, rather than requiring a double-click or a click followed byENTER).|
|XTF_XYXY|&h0000200<br>0|Interpret the 1st and 2nd parameters (_row, col_) as starting row, starting col, and the 8th and 9th<br>parameters (_strow, endrow_) as ending row, ending col. Mandatory forXTREE, optional forPCKLST.|
|XTF_COLDFX|&h0004000<br>0|Indicates that the_prompt_parameter is actually anXTREEadvancedColdef<br>syntax specification,<br>rather than simply a title string.|
|XTF_NOSEL|&h0010000<br>0|Exit immediately, rather than waiting for the user to make a selection. (This only makes sense in<br>conjunction with XTF_MODELESS; also see_xtrctl_ `XTR.opcode`)|
|XTF_DEL|&h0040000<br>0|EnableDELexit (Exitcode –47)|
|XTF_CTRLC|&h0100000<br>0|CausesCTRL+Cto set Exitcode 10 (as inINFLD) instead of 1.|



A-Shell Reference 

Page 3148 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTF2_PGUPDN|&h00000040|EnablePAGE-UP/PAGE-DOWN(exitcodes 4, 6).|
|XTF2_DOWN|&h00000080|EnableCTRL+DOWN-ARROWon last row (exitcode -43).|
|XTF2_SAVRES|&h00008000|CausesPCKLSTto save the screen area.|



## - Hex Decimal Values 

## _file_ (String) 

specifies a sequential file to be used instead of the Array parameter. When non-null, the interpretation of Array, Maxcnt, and Answer parameters changes as follows. Array becomes an ordinary string which is used to pass in the default selection (text) and to get back the item chosen by the user. Answer and Maxcnt are then ignored (with the actual contents of the file being examined to determine Maxcnt and the maximum width). 

## _mmoclr_ 

may be used to specify a set of colors for the various parts of the pick list display. It is equivalent to the INMEMO parameter of the same name, which is not surprising, since PCKLST is actually just a front-end to the vertical menu mode of INMEMO. The format of MMOCLR is: 

## `MAP1 MMOCLR` 

```
   MAP2 BFCLR,B,1,-1          ! Border Foreground
   MAP2 BBCLR,B,1,-1          ! Border Background
```

A-Shell Reference 

Page 3149 

```
   MAP2 TFCLR,B,1,-1          ! Text Foreground
   MAP2 TBCLR,B,1,-1          ! Text Background
   MAP2 AFCLR,B,1,-1          ! Arrow Foreground
   MAP2 ABCLR,B,1,-1          ! Arrow Background
   MAP2 PFCLR,B,1,-1          ! Prompt Foreground
   MAP2 PBCLR,B,1,-1          ! Prompt Background
   MAP2 WFCLR,B,1,-1          ! Warnings & messages Foreground
   MAP2 WBCLR,B,1,-1          ! Warnings & messages Background
   MAP2 SFCLR,B,1,-1          ! Orig. Status line Foreground
   MAP2 SBCLR,B,1,-1          ! Orig. Status line Background
   MAP2 RFCLR,B,1,-1          ! Inactive selection bar - see Comments
   MAP2 RBCLR,B,1,-1          ! Inactive selection bar - see Comments
```

The individual fields within MMOCLR are shown above initialized to -1, which is what you must do to get default colors, since color 0 is black. (Specifying MMOCLR with all the fields un-initialized will result in a not-very-interesting black on black display.) 

If XTF_XYXY not specified, the width of the box will be determined by considering the maximum length of the top and bottom prompts and the data items (not counting any hidden text). If XTF_XYXY is specified, then the coordinates of the box are explicitly determined by the _row_ , _col_ (upper left) and _strow_ , _endrow_ (interpreted as lower right row/col) parameters. 

Rather than setting colors in individual calls to PCKLST, it would be easier to set them globally in the LIB:INI:CLR file. See Configuration for more details. 

A-Shell Reference 

Page 3150 

When the XTF_COLDFX flag is specified, the prompt parameter is assumed to be in the format of an XTREE advanced Coldef syntax definition with a single column. From this string, the _ctitle_ field is extracted and used for the top title. ( _cpos_ is ignored and assumed to be 1; _cwidth_ must be greater than or equal to the actual width of the elements of _array_ ; _cformat_ is ignored.) The main advantage of using this alternate form is to make it easier for a program that operates in both text and GUI modes to take advantage of the features of XTREE without breaking PCKLST compatibility. PCKLST will ignore all of the Advanced Coldef Options that it doesn't understand, but there is one that it does: SelChgExit=###. For example: 

## `prompt = "1~20~Selections~S~SelChgExit=155~~"` 

The above example would set the title to "Selections", and tell PCKLST to exit with exitcode -155 whenever the selection changes. 

Inactive selection bar colors: Normally, when you exit from PCKLST, the bar indicating the selected item remains displayed, exactly as when the menu was active. This is typically desirable, or doesn't matter, but there are some situations where it is useful to provide some visual indication that the list (and selection process) are no longer active. XTREE handles this by changing the standard selection bar (dark blue) to light gray. PCKLST provides you an option to redisplay the selection bar in a different color scheme, by setting the RFCLR and RBCLR fields of the _mmoclr_ structure to the desired colors. If left at the default values of -1, the selection bar is left as is. 

See the sample program PCKMNU in EXLIB:[908,21] for an example of a two-level menu program using PCKLST which operates in either text or GUI mode. 

PCKLST supports a maximum of 32K rows. 

The following screens are from a single menu implementation, using two side-by-side PCKLST controls, as it appears in text and GUI modes. See PCKMNU in EXLIB:[908,21] for the actual program. 

A-Shell Reference 

Page 3151 

Originally, PCKLST was created to provide a simplified way of accessing INMEMO's menu mode with the idea of upgrading a functionally equivalent INFLD operation to be more user friendly. In other words, rather than call INFLD to have the user type one of the allowed options, the program could call PCKLST to perform the same function—input a field—but in a way that allows the user to easily see the choices and select one without actually typing it. For example: 

Screen save/restore was built in to PCKLST, so there was no need to worry about the parts of the screen that would be temporarily covered by the pick list (making it easier to upgrade a screen designed to allow only a single line for the input field). 

With the advent of GUI capabilities in A-Shell, a more powerful Windows list/selection control (XTREE) was implemented, but with the same parameter interface. This allows A-Shell to redirect calls to PCKLST to the XTREE if the environment supports GUI and the feature is enabled in miame.ini (via SBR=PCKLST_GUI). Over time, XTREE grew to support so many extended capabilities unrelated to PCKLST that it is now difficult to recognize the parts of XTREE that are compatible with, or even related to PCKLST. So we've tried to keep it simple for PCKLST developers by keeping separate documentation, while trying to note the areas of particular similarity or difference between the two routines. 

- 2011 June, A Shell 5.1.1221 and 1220: 

- XTF2_SAVRES causes PCKLST to save the screen area. 

- XTROP_DELETE operation to clear the screen area used by the list is now supported. 

- XTREE-style title justification codes ("| ","< ","> ") are now supported for the top title. 

- The XTF_NOSEL flag bit is now supported. 

- The SelChgExit=### advanced coldef option is now supported. 

A-Shell Reference 

Page 3152 

- RFCLR, RBCLR now affect inactive selection bar. 

- The _prompt_ parameter can now use the XTREE advanced Coldef syntax. 

A-Shell Reference 

Page 3153 

## **PEEK, POKE** 

## **xcall PEEK, packet** 

## **xcall POKE, packet** 

PEEK and POKE are simplified wrappers for COMMON, reading and writing a single packet named "PEPOKE". See COMMON for details on configuring the number and size of packets and other behavior. 

## **Parameters** 

_packet_ (BLOB)  [in/out] 

Buffer containing data to read (PEEK) or to write (POKE) 

## **History** 

2025 February: These subroutines have existed in A-Shell for many years, but were only documented at this time. 

A-Shell Reference 

Page 3154 

## **PLYJOB** 

## **xcall PLYJOB, jobno, job'stats** 

PLYJOB is similar to GETJTB in that it returns most of the information related to your job in a single operation. The main reason it is included in addition to GETJTB[XS] is for PolyTRACK programmers who may already be using the routine, and for anyone who may be using the MicroSabio routine JOBPAR[XS] (which is basically the same thing and can be aliased to PLYJOB using the alias facility in miame.ini). PLYJOB[XS] does have one feature that GETJTB[XS] does not: the ability to retrieve information about a job other than the current one. The amount of information that can be retrieved in this way is limited to job name, program name, ppn, and username, but that is still very useful in situations where you want to match a job number up with a job name. 

## **Parameters** 

_jobno_ (2-byte binary)  [in/out] 

If zero, information is returned about the current job, otherwise about the job whose number is specified. 

_job'stats_ 

## mapped as follows: 

```
MAP1 JOB'TABLE               ! 87 byte area
```

```
MAP2 LOG'DEV,s,3          ! Device name
```

```
MAP2 LOG'LUN,s,3          ! Logical unit
MAP2 PROJECT,s,3          ! Project number (p,pn)
MAP2 PROGRMR,s,3          ! Programmer number
MAP2 PARTITION,s,6        ! Job name
MAP2 PROG'ID,s,6          ! Program name
MAP2 TERM'NAME,s,6        ! Trmdef name
MAP2 TERM'DRVR,s,6        ! Terminal driver
```

A-Shell Reference 

Page 3155 

```
MAP2 INTERFACE,s,6        ! IDV name
MAP2 JOB'NBR,s,3          ! Job number
MAP2 JOB'TYPE,b,2         ! Job type flags
MAP2 CMDFIL,b,2           ! Nonzero=command file
MAP2 JOBPPN,b,2           ! P,PN as binary
MAP2 JOBEXP,b,1           ! Job experience
MAP2 JOBLVL,b,1           ! Job level
MAP2 JOBUID,s,3           ! Numeric portion of username
MAP2 JOBUSN,s,20          ! Job user name
MAP2 JOBCPU,b,4           ! CPU time
MAP2 JOBDSR,b,4           ! Disk reads
MAP2 JOBDSW,b,4           ! Disk writes
MAP2 JOBATT,s,6           ! Parent job name
MAP2 JOBSTS,b,2           ! Job status
MAP2 TRKVER,s,3           ! Tracker version [22C]
```

Several of the fields above are only applicable under the AMOS version of PLYJOB, including JOBCPU, JOBDSR, JOBDSW, JOBATT, JOBEXP, and JOBLVL. 

A-Shell Reference 

Page 3156 

## **PRTCHK** 

## **xcall PRTCHK, printer, rtncde** 

Under AMOS, PRTCHK may be used both to check for the existence of a printer, and to check whether a particular file is being printed. The A-Shell implementation contains only the first function, due to the limitations of either the spooling systems, or the interfaces to those spooling systems, of the operating systems on which it runs. 

## **Parameters** 

_printer_ (String)  [in] 

A-Shell spooler name to check 

_rtncde_ (F or String)  [in/out] 

For type F, returns zero if the printer is found, else one. For type S, returns "F" if the printer is found. To be certain of the result, you should preset the variable to some other value first. Note that "found" means only confirmation of the logical existence of the spooler—i.e. the routine tests whether a corresponding printer ini file (dsk0:printer.ini[1,4] or dsk0:printer.pqi[1,7]) exists. 

Apparently some versions of PRTCHK work the opposite way, returning 1 if the printer is found and 0 if it is not. To get this behavior, add SBR=PRTCHK1 to miame.ini. This option only applies when _rtncde_ is a floating point variable. 

A-Shell Reference 

Page 3157 

## **PUTBYT** 

## **xcall PUTBYT, channel, buffer, bytes** 

PUTBYT writes raw bytes to a sequential output file. 

## **Parameters** 

_channel_ (Num)  [in] 

is the channel number of the file, which must be open for output or append. 

_buffer_ (BLOB)  [in] 

supplies the data to be written. 

_bytes_ (Num)  [in] 

specifies the number of bytes to write (which must be less than or equal to the size of _buffer_ ). 

## **Comments** 

```
xcall PUTBYT, channel, buffer, bytes
```

is equivalent to 

```
PRINT #channel, buffer[1,bytes];
```

PUTBYT supports channel 0 to output to the terminal device. This can be useful (mainly under Unix) if you need to output raw binary data to the terminal and want to be sure there is no filtering and do not want it to corrupt the screen map. Otherwise, typically you get Tab expansion (unless OPTIONS=RAWTABS), and CR is always prepended to line LF characters. 

## **See Also** 

- GETBYT 

A-Shell Reference 

Page 3158 

## **REGEX** 

_Updated June 2023; see History_ 

Pre-compiling only: 

## **xcall REGEX, pattern, patno {,flags}** 

General use: 

**xcall REGEX, pattern, status, subject {,flags, stpos, match { ,subcnt, submatch1, ... submatchn}} xcall REGEX, pattern, status, subject ,flags, stpos, match ,subcnt, submatch(n)** 

REGEX provides a detailed XCALL interface to A-Shell's regular expression processor. Other interfaces to the same processor are provided in the INSTR() function and INFLD. 

The first general syntax shown above is the traditional form, which uses individual submatch variables to receive the submatch results. The second uses an array to receive the submatch results. 

If three parameters are specified, the type of the third parameter determines whether the operation is pre-compilation or general use:  numeric ( _flags_ ) for the former, string ( _subject_ ) for the latter. 

## _pattern_ (String)  [in] 

Regular expression, without the Perl-style leading/trailing slash. To specify a pre-compiled pattern, set _pattern_ = CHR$(1) thru CHR$(128) for the 128 precompiled patterns. Note that when using the same pattern string consecutively, explicit pre-compiling is superfluous; all pattern strings get internally pre-compiled, and whenever the current pattern string is the same as the previous one, the previously pre-compiled pattern is used automatically. Explicit pre-compilation only makes sense when you are repetitively using more than one pattern string in alternation. 

_status_ (F or I)  [out] 

A-Shell Reference 

Page 3159 

|**Value**|**Meaning**|
|---|---|
|>0|Matching success (starting position of match)|
|-101 to -199|Pattern Complilation Errors|
|-99|Too few parameters|
|-98|Unable to load PCRE library (pcre3.dllunder Windows)|
|-97|Unable to allocate memory for library|
|-96|Unable to link to pcre_compil2 or pcre_exit function in lib|
|-95|Invalid pre-compiled pattern number (1-128)|
|-94|No such precompiled pattern (not previously compiled)|
|-93|Error outputting to dynamic variable (out of memory?)|
|-2 to -25|Matching Errors|



_patno_ (F or I)  [in/out] 

A-Shell Reference 

Page 3160 

For precompiling, on input must be set to an integer 1-128 (for the 128 numbered precompiled patterns). On output, will still be set to the same value for success, or <=0 on error; see _status_ codes above. See note under _pattern_ regarding pre-compilation. 

_subject_ (String)  [in] 

Subject string to test against the pattern. 

_flags_ (F or B,4)  [in] 

A bitmap of option flags whose symbols are defined in ASHINC:REGEX.DEF. See Options Flags. Note that you can use Perl-style internal option settings within a pattern to change options that would otherwise require using the _flags_ parameter. 

_stpos_ (Num)  [in] 

Optional starting position in _subject_ , base 1. If not specified or zero, treated same as 1 (i.e. start at beginning of _subject_ ). 

_match_ (String)  [out] 

Returns the string within the _subject_ that was matched. On errors, it may return the text of the error description. 

_subcnt_ (Num)  [in/out] 

For the array syntax (where the subexpression matches are returned into an array instead of individual parameters), you must set _subcnt_ to the number of elements in the array, starting from the element supplied in the parameter. In other words, if you pass submatch(1), then set _subcnt_ to the total number of elements in the submatch() array; if you pass submatch(2), set _subcnt_ to one less than the total. 

For the non-array syntax, _subcnt_ is ignored on input; the maximum number of possible matches is limited instead by the number of _submatch1 .. submatchn_ parameters passed. 

For either syntax, on return, _subcnt_ will be set to the number of sub-expression matches in the _subject,_ even if it exceeds the number of _submatch_ parameters passed or the specified size of the _submatch(n)_ array. Therefore, when processing the returned sub-expression matches, care must be taken that you don't get fooled by the return value of _subcnt_ into trying to access more _submatch_ parameters than were available to the routine or especially more array elements than exist. For example: 

```
subcnt = .extent(submatch())                       ! limit matches to extent of array
```

```
xcall REGEX, pattern, status, subject, flags, match, subcnt, submatch(1)
```

A-Shell Reference 

Page 3161 

```
if status > 0 then                                 ! on success...
```

```
    for i = 1 to (subcnt min .extent(submatch()))  ! process sub-matches (up to limit)
        ...
```

_submatch1 ... submatchn_ (String)  [out] 

These return subexpression matches (up to the number specified by _subcnt,_ up to a maximum number of 100. Note that null matches are quite possible; that is, _subcnt_ may return N, but of those N, some of them, and not necessarily only the ones at the end, may be empty. 

_submatch(n)_ (String array)  [out] 

A single starting element in a string array, e.g. **submatch(1)** , may be used in place of several individual _submatchn_ parameters. The array must have a fixed number of elements, but its elements can be dynamic strings (e.g. **map1 submatch(50),s,0** ). This is particularly useful where you are dealing with many expressions and thus don't know at the time of writing the code how many or how large they might be. 

Note: Since the xcall interface does not pass information about the entire array, in order to use the array syntax, you must set _subcnt_ to the number of elements in the array (see _subcnt_ above), AND you must also set the PCREX_SUBMATCH_ARRAY (&h40000000) flag in the _flags_ parameter. If the flag is not set, REGEX will treat your _submatch(1)_ parameter as a single variable (as in the first syntax). 

## **See Also** 

- REGEX2XS 

## **History** 

- 2023 June, A Shell 6.5.1721:  add support for pre-compilation options using the _flags_ parameter. In order to distinguish this from the three-parameter general use, _flags_ must be a numeric type. 

- 2023 June, A Shell 6.5.1721:  increase maximum number of pre-compiled patterns from 20 to 128. 

- 2017 March, A Shell 6.4.1546:  remove 1024 byte limit on _subject_ string length. 

## **Subtopics** 

A-Shell Reference 

Page 3162 

- Pattern Complilation Errors 

- Matching Errors 

- Options Flags 

- Background and General Information 

- License Notes 

A-Shell Reference 

Page 3163 

## **PATTERN COMPLILATION ERRORS** 

|**Value **|**Description**|
|---|---|
|-101|\ at end of pattern|
|-102|\c at end of pattern|
|-103|unrecognized character follows \|
|-104|numbers out of order in {} quantifier|
|-105|number too big in {} quantifier|
|-106|missing terminating ] for character class|
|-107|invalid escape sequence in character class|
|-108|range out of order in character class|
|-109|nothing to repeat|
|-110|[this code is not in use]|
|-111|internal error: unexpected repeat|



A-Shell Reference 

Page 3164 

|**Value **|**Description**|
|---|---|
|-112|unrecognized character after (?|
|-113|POSIX named classes are supported only within a class|
|-114|missing )|
|-115|reference to non-existent subpattern|
|-116|erroffset passed as NULL|
|-117|unknown option bit(s) set|
|-118|missing ) after comment|
|-119|[this code is not in use]|
|-120|regular expression too large|
|-121|failed to get memory|
|-122|unmatched parentheses|



A-Shell Reference 

Page 3165 

|**Value **|**Description**|
|---|---|
|-123|internal error: code overflow|
|-124|unrecognized character after (?<|
|-125|lookbehind assertion is not fixed length|
|-126|malformed number or name after (?(|
|-127|conditional group contains more than two branches|
|-128|assertion expected after (?(|
|-129|(?R or (?[+-]digits must be followed by )|
|-130|unknown POSIX class name|
|-131|POSIX collating elements are not supported|
|-132|this version of PCRE is not compiled with PCRE_UTF8 support|
|-133|[this code is not in use]|



A-Shell Reference 

Page 3166 

|**Value **|**Description**|
|---|---|
|-134|character value in \x{...} sequence is too large|
|-135|invalid condition (?(0)|
|-136|\C not allowed in lookbehind assertion|
|-137|PCRE does not support \L, \l, \N, \U, or \u|
|-138|number after (?C is > 255|
|-139|closing ) for (?C expected|
|-140|recursive call could loop indefinitely|
|-141|unrecognized character after (?P|
|-142|syntax error in subpattern name (missing terminator)|
|-143|two named subpatterns have the same name|
|-144|invalid UTF-8 string|



A-Shell Reference 

Page 3167 

|**Value **|**Description**|
|---|---|
|-145|support for \P, \p, and \X has not been compiled|
|-146|malformed \P or \p sequence|
|-147|unknown property name after \P or \p|
|-148|subpattern name is too long (maximum 32 characters)|
|-149|too many named subpatterns (maximum 10,000)|
|-150|[this code is not in use]|
|-151|octal value is greater than \377 (not in UTF-8 mode)|
|-152|internal error: overran compiling workspace|
|-153|internal error: previously-checked referenced subpattern not found|
|-154|DEFINE group contains more than one branch|
|-155|repeating a DEFINE group is not allowed|



A-Shell Reference 

Page 3168 

|**Value **|**Description**|
|---|---|
|-156|inconsistent NEWLINE options|
|-157|\g is not followed by a braced name or an optionally braced non-zero number|
|-158|(?+ or (?- or (?(+ or (?(- must be followed by a non-zero number|



A-Shell Reference 

Page 3169 

## **MATCHING ERRORS** 

|**Value **|**Description**|
|---|---|
|-2|(Internal error) ovector was NULL and ovecsize was not zero.|
|-3|An unrecognized bit was set in the options argument.|
|-4|PCRE stores a 4-byte "magic number" at the start of the compiled code, to catch the case when it is passed a junk<br>pointer and to detect when a pattern that was compiled in an environment of one endianness is run in an<br>environment with the other endianness. This is the error that PCRE gives when the magic number is not present.|
|-5|While running the pattern match, an unknown item was encountered in the compiled pattern. This error could be<br>caused by a bug in PCRE or by overwriting of the compiled pattern.|
|-6|If a pattern contains back references, but the ovector that is passed to pcre_exec() is not big enough to remember<br>the referenced substrings, PCRE gets a block of memory at the start of matching to use for this purpose. If the call<br>via pcre_malloc() fails, this error is given. The memory is automatically freed at the end of matching.|
|-7|This error is used by the pcre_copy_substring(), pcre_get_substring(), and pcre_get_substring_list() functions. It is<br>never returned by pcre_exec().|
|-8|The backtracking limit, as specified by the match_limit field in a pcre_extra structure (or defaulted) was reached.<br>See the description above.|
|-9|This error is never generated by pcre_exec() itself. It is provided for use by callout functions that want to yield a|



A-Shell Reference 

Page 3170 

|**Value **|**Description**|
|---|---|
||distinctive error code. See the pcrecallout documentation for details.|
|-10|A string that contains an invalid UTF-8 byte sequence was passed as a subject.|
|-11|The UTF-8 byte sequence that was passed as a subject was valid, but the value of startoffset did not point to the<br>beginning of a UTF-8 character.|
|-12|The subject string did not match, but it did match partially. See the pcrepartial documentation for details of partial<br>matching.|
|-13|The PCRE_PARTIAL option was used with a compiled pattern containing items that are not supported for partial<br>matching. See the pcrepartial documentation for details of partial matching.|
|-14|An unexpected internal error has occurred. This error could be caused by a bug in PCRE or by overwriting of the<br>compiled pattern.|
|-15|This error is given if the value of the ovecsize argument is negative.|
|-21|The internal recursion depth limit has been exceeded. This has been set internally to 2500 for Windows and 10000<br>for Unix, which in theory is about as much as we could expect to handle before running the risk of a stack overflow<br>and segmentation fault. If you are hitting this limit, either your pattern/subject combination is enormously<br>complex, or, more likely, your pattern is inefficiently designed to cause more recursion that is necessary.|
|-23|An invalid combination of PCRE_NEWLINE_xxx options was given.|



A-Shell Reference 

Page 3171 

A-Shell Reference 

Page 3172 

## **OPTIONS FLAGS** 

_Updated December 2023; see History_ 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|PCRE_CASELESS|&h00000001|If this bit is set, letters in the pattern match both upper and lower case<br>letters. It is equivalent to Perl's /i option, and it can be changed within a<br>pattern by a (?i) option setting. In UTF-8 mode, PCRE always understands<br>the concept of case for characters whose values are less than 128, so<br>caseless matching is always possible. For characters with higher values,<br>the concept of case is supported if PCRE is compiled with Unicode<br>property support, but not otherwise. If you want to use caseless matching<br>for characters 128 and above, you must ensure that PCRE is compiled<br>with Unicode property support as well as with UTF-8 support.|
|PCRE_MULTILINE|&h00000002|By default, PCRE treats the subject string as consisting of a single line of<br>characters (even if it actually contains newlines). The "start of line"<br>metacharacter (^) matches only at the start of the string, while the "end<br>of line" metacharacter ($) matches only at the end of the string, or before<br>a terminating newline (unless PCRE_DOLLAR_ENDONLY is set). This is the<br>same as Perl.|
|PCRE_DOTALL|&h00000004|If this bit is set, a dot metacharater in the pattern matches all characters,<br>including those that indicate newline. Without it, a dot does not match<br>when the current position is at a newline. This option is equivalent to<br>Perl's /s option, and it can be changed within a pattern by a (?s) option<br>setting. A negative class such as [^a] always matches newline characters,<br>independent of the setting of this option.|
|PCRE_EXTENDED|&h00000008|If this bit is set, whitespace data characters in the pattern are totally<br>ignored except when escaped or inside a character class. Whitespace does|



A-Shell Reference 

Page 3173 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||not include the VT character (code 11). In addition, characters between<br>an unescaped # outside a character class and the next newline, inclusive,<br>are also ignored. This is equivalent to Perl's /x option, and it can be<br>changed within a pattern by a (?x) option setting. This option makes it<br>possible to include comments inside complicated patterns. Note, however,<br>that this applies only to data characters. Whitespace characters may<br>never appear within special character sequences in a pattern, for example<br>within the sequence (?( which introduces a conditional subpattern.|
|PCRE_ANCHORED|&h00000010|If this bit is set, the pattern is forced to be "anchored", that is, it is<br>constrained to match only at the first matching point in the string that is<br>being searched (the "subject string"). This effect can also be achieved by<br>appropriate constructs in the pattern itself, which is the only way to do it<br>in Perl.|
|PCRE_DOLLAR_ENDONLY|&h00000020|If this bit is set, a dollar metacharacter in the pattern matches only at the<br>end of the subject string. Without this option, a dollar also matches<br>immediately before a newline at the end of the string (but not before any<br>other newlines). The PCRE_DOLLAR_ENDONLY option is ignored if<br>PCRE_MULTILINE is set. There is no equivalent to this option in Perl, and<br>no way to set it within a pattern.|
|PCRE_UNGREEDY|&h00000200|This option inverts the "greediness" of the quantifiers so that they are not<br>greedy by default, but become greedy if followed by "?". It is not<br>compatible with Perl. It can also be set by a (?U) option setting within the<br>pattern.|
|PCREX_REPLACE_CASE|&h04000001|When used with REGEX2 causes the replacement operation to attempt to<br>match the case of the original string (UPPER, lower, or Capitalized) based|



A-Shell Reference 

Page 3174 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||its first two letters. Includes the PCRE_CASELESS (&h01) flag since this<br>only makes sense with caseless matches.  For example, if used with<br>_spattern_"irs" and_rpattern_"aaa", would convert the subject string from:<br>"Mr. Irsy, first head of the IRS"<br>to:<br>"Mr. Aaay, faaast head of the AAA"|
|PCREX_NOT_PRECOMPILED|&h08000000|Eliminates the ambiguity when passing a single-byte pattern toINSTR()or<br>REGEXXSas to whether it represents a normal pattern or a previously<br>precompiled pattern number.|
|PCREX_VERBOSE|&h10000000|With ++include transcopy, more verbose error messages.|
|PCREX_ASB_SOURCE|&h20000000|(For TRCOPY/transclude only) Treat subject as ASB source, merging<br>continuation lines into one.|
|PCREX_ASB_SOURCE|&h20000000|Treat_srcfile_as A-Shell Basic, merging continuation lines into one. This<br>may affect the pattern matching which is otherwise limited to one source<br>line at a time.|
|PCREX_SUBMATCH_ARRAY|&h400000000|This is not a standard PCRE flag (hence the prefix PCREX_). It is used to<br>indicate that you are passing a single element of an array of_subcnt_<br>elements to receive the subexpression matches, rather than just a single<br>variable (which could receive only one sub-match).|



A-Shell Reference 

Page 3175 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|PCREX_PRECOMPILE|&h80000000|Another non-standard flag. It is used with theINSTR()function to indicate<br>that you only want to precompile the pattern; seeINSTR()<br> for more<br>details.|



## **Definition File:** regex.def 

## **History** 

- 2025 November, A Shell 7.0.1781:  Added PCREX_REPLACE_CASE 

- 2023 December, A Shell 7.0.1752:  Added PCREX_NOT_PRECOMPILED 

A-Shell Reference 

Page 3176 

## **BACKGROUND AND GENERAL INFORMATION** 

There are various implementations and flavors of "regular expressions", including POSIX and Perl. We've chosen to go with the Perl flavor, because it is generally considered better—more features, more predictable, faster—and seems to be more popular— with Java, Python and .NET for example using similar or derived implementations. The specific implementation we are using is called PCRE (Perl-Compatible Regular Expression); see the website for more details. 

A-Shell versions prior to 7.0.1777 used the original version of PCRE; beyond that, depending on the OS platform, it may use the newer version 2 (aka PCRE2). Under Windows, the original library is housed in pcre3.dll (think of it as version 1.3); beyond that, it is housed in pcre2-8.dll. In either case, the appropriate version is included with the standard A-Shell distribution and loaded dynamically the first time you access a regular expression function. For A-Shell/Linux, it is installed via the package pcre or pcredevel (version 1) and pcre2 / pcre2-devel (version 2). You can determine which version is required by using the command 'ldd ashell' to list the dependencies. 

For details on the syntax of regular expressions, see the Perl Regular Expression documentation or any number of web sites which offer tutorials and examples. 

The two most common uses of regular expressions are to extend the power and flexibility of string searches, and to check for valid syntax in a string. Another possible use is for parsing and extracting specific portions of strings, using the capture group mechanism to return the subexpression matches of interest. 

The main downside of regular expressions is that they are rather cryptic and can become so complex as to consume massive computing resources (although that is generally not an issue for common usage). As an example, a simple (incomplete) regular expression to match a valid email address word-delimited within a larger string, is: 

```
"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b"
```

A more complete expression for validating email addresses (based on RFC 2822) is: 

`"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|""(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-` " - - - - - * - - - - - - - * - `\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*"` )@(?:(?:[a z0 9](?:[a z0 9 ] [a z0 9])?\.)+[a z0 9](?:[a z0 9 ] [a - - - - - - - - - - - - - - * - - z0 9])?|\[(?:(?:25[0 5]|2[0 4][0 9]|[01]?[0 9][0 9]?)\.){3}(?:25[0 5]|2[0 4][0 9]|[01]?[0 9][0 9]?|[a z0 9 ] [a z0 9]:(?: - - - - - - " [\x01 \x08\x0b\x0c\x0e \x1f\x21 \x5a\x53 \x7f]|\\[\x01 \x09\x0b\x0c\x0e \x7f])+)\]) 

A-Shell Reference 

Page 3177 

While it may be doubtful that many users would be able to conjure up such an expression during an ad-hoc search, application developers may build up a collection of useful regular expressions (often you can just copy them from helpful websites devoted to the subject) that can be used for common search or validation purposes. 

Regular expression processing internally consists of two separate operations: 

- compiling the expression (checking for syntax errors) 

- using the expression to match against subject string(s). 

Because the operation of compiling the expression can be as CPU intensive as matching it against subject strings, both REGEX and INSTR() support means of reusing previously compiled expressions. In the default case, if the current pattern matches the previously used one, then the previous compilation will be used automatically. This strategy works well when applying a single expression repetitively against many subject strings (as when searching for a pattern in a text file). But it doesn't work so well if you are searching through a file or database and comparing each line/record against more than one regular expression. To maximize efficiency in such cases, as well as for cases where you have a collection of common patterns used throughout your application, you can precompile and store up to 20 patterns, which can then be used on demand without having to re-compile them. 

Note: the original implementation of REGEX in A-Shell 5.1.1100 treated a null pattern string as referring to the previously compiled pattern. This mechanism has been dropped, since it is somewhat confusing to implement at the application level, and also introduces the problem of having to specifically check for null patterns. The new implementation just compares the current pattern to the last one (for non-precompiled patterns) to determine when recompilation can be avoided). Null patterns return 0 (failed match) in all cases. 

See the sample programs in EXLIB:[908,46]. 

" - - " See the thread Substring search right to left on the A-Shell Forum for an example of using REGEX to split a path spec into the directory and filename. 

A-Shell Reference 

Page 3178 

## **LICENSE NOTES** 

REGEX uses the Open Source Perl-Compatible Regular Expression (PCRE) library—originally PCRE version 1, but starting with A- Shell 7.0.1777 and certain newer OS platforms, PCRE2.  For A-Shell/Windows prior to 7.0.1777, it requires pcre3.dll; for A-Shell 7.0.1777 and later, it requires pcre2-8.dll; both of these are included with the full A-Shell/Windows distribution. For Linux, it requires the package pcre or pcre-devel (version 1, libpcre.so.x), or pcre2 / pcre2-devel (version 2, libprec2-8.so.x). In either case, it could also be acquired from http://www.pcre.org/. For details on the syntax of regular expressions, see the Perl Regular Expression documentation. 

PCRE is covered under the BSD license, which requires the following notes be included in the documentation included with A- Shell: 

Written by: Philip Hazel 

Email local part: ph10 

Email domain: cam.ac.uk 

University of Cambridge Computing Service, Cambridge, England. 

Copyright (c) 1997-2020 University of Cambridge 

All rights reserved. 

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. 

A-Shell Reference 

Page 3179 

## **REGEX2** 

## **xcall REGEX2, spattern, status, subject, flags, rpattern, outstr** 

REGEX2 supports a replacement operation, similar to that of MX_TRANSCOPY, except that it acts on a single string subject, pattern and replacement specification rather than a file-based set of them. 

## **Parameters** 

_spattern_ (String)  [in] 

search pattern, equivalent to the _pattern_ parameter in REGEXXS subroutine. 

## _status, subject_ 

same as for REGEX. 

## _flags_ 

## Same as for REGEX except for the option flag PCREX_REPLACE_CASE, which only applies to REGEX2. 

_rpattern_ (String)  [in] 

replacement pattern, optionally including \# clauses referring to numbered capture sub-matches in the search pattern. 

_outstr_ (String)  [out] 

the string resulting from the replacement operation. If there were no matches ( _status_ < 1), then it will equal subject . 

Consistent with the regular expression standard, parentheses in the search pattern mark sub-pattern capture groups which can then be referenced in the replacement pattern. These and any other special characters in the search pattern must be escaped by a leading backslash to treat them as literal.  However, in the replacement pattern, the only special character is the backslash, used with a number to reference a captured sub-pattern (e.g. "\1"). 

As with MX_TRANSCOPYXS, the search and replace operation repeats until there are no more matches. 

## **Example** 

To replace all occurrences of "[#]" with "(#)" (where # is an integer of any size), you could use the following: 

A-Shell Reference 

Page 3180 

```
spattern = \[(\d+?)\]  ! series of digits within [brackets]
```

```
rpattern = (\1)        ! the matched digits, now with (parens)
```

This combination would replace "Funkhouser[13], Tavares[172], Griffin[9x]" with "Funkhouser(13), Tavares(172), Griffin[9x]". (The third bracketed expression doesn't match the search pattern because of the "x".) 

## **See Also** 

- REGEXXS 

- MX_TRANSCOPYXS 

## **History** 

- 2025 December, A Shell 7.0.1781:  PCREX_REPLACE_CASE flag added. 

- 2023 September, A Shell 6.5.1743:  Function added to A-Shell. 

A-Shell Reference 

Page 3181 

## **RENAME** 

_Reviewed May 2026_ 

## **xcall RENAME, oldname, newname, status** 

RENAME (aka RENAM) provides the means to programmatically rename files. It will fail if _oldname_ does not exist, or if _newname_ does. Both _oldname_ and _newname_ support either DevPPN or native operating system filenames, and also support the use of embedded environment variables (e.g. %MIAME%). 

## **Parameters** 

_oldname_ (String)  [in] 

current file name 

_newname_ (String)  [in] 

name to which the file is being changed 

_status_ (F,6)  [out] 

0 if successful, other if not 

Errors are  logged to the ashlog.log file. In addition, if the SYSERR TRACE is active, they will be displayed on the screen. This is helpful in  recognizing and tracking down mysterious Windows rename errors. 

## **History** 

- 2015 July, A Shell 6.1.1414: Under Windows, XCALL RENAME will now overwrite an existing destination file. It was never documented what it should do here, but this matches the way it has always worked under Unix. 

The motivation for the change now is that it has been determined that Windows file sharing networks can sometimes yield false positives—i.e. they report that the destination file exists when it doesn't—causing applications to fail unexpectedly and returning an error in the STATUS parameter of XCALL RENAME. 

A-Shell Reference 

Page 3182 

Note that this does not affect RENAME.LIT, nor does it affect the MX_COPYFILE function, which can also be used to rename a file, but which offers an explicit option of whether to replace an existing file. 

- 2007 November, A Shell 5.0.997: 

A-Shell Reference 

Page 3183 

## **RXPCHK** 

## **xcall RXPCHK, string {,rc}** 

RXPCHK checks a string to determine if it contains unprintable chararacters, which are defined as those whose ASCII values are less than 32 or are between 127 and 160 inclusive. 

## **Parameters** 

_string_ (String)  [in] 

string to check. _string_ is stripped of leading and trailing spaces and tabs and returned that way, regardless of whether valid. 

- _rc_ (F,6)  [out] 

optional return value specifying okay (0) or the position of the first unprintable character in _string._ Note that RXPCHK may be passed to the XFUNC function, in which case rc is not really relevant since the function itself returns the same value. 

A-Shell Reference 

Page 3184 

## **SBXINP** 

## **xcall SBXINP, label, opcode, row, col, xmax, entry, inftype, setdef, maxchars, clickcode, tooltip, parentid, exitcode, defpt, timer, cmdflg, maxpt, infldid, labelid, changeflag** 

SBXINP.SBX is a wrapper for INFLD. Its biggest single advantage over INFLD is that allows you to associate (and align) a label with an INFLD control, rather than having to handle the label and the edit control in separate operations. This routine was originally developed by Firmaware and is now included as part of the standard subroutine collection. 

or, as an xfunc$ function: 

```
map1 inp'result
```

```
   map2 result'exitcode,s,4
```

```
   map2 result'values,s,5000
   map2 result'id,s,4
```

```
   map2 result'changed,s,1
```

```
inp'result = xfunc$("sbxinp",label,opcode,…)
```

Source, samples and related functions can be found in SOSLIB:[907,37]. 

_label_ (String)  [in] 

Controls many of the extended capabilities of SBXINP (relative to INFLD). See the subtopic Label for full information. 

_opcode_ (Num)  [in] 

A-Shell Reference 

Page 3185 

Determines the operation (edit, display, etc.) according to the following table: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|SXI_EDT|1|Preload field contents and edit the field. (Ignores_label_)|
|SXI_DSP|2|Display only (create the label; create the edit control to display the data but do not put the<br>focus on it).|
|SXI_DSPEDT|3|Display and edit. Combination of SXI_EDT and SXI_DSP.|
|SXI_DISABLE|20|Add this to disable the field.|
|SXI_STATIC|30|Add this to display field as a static text control.|



## _row_ (Num)  [in] 

Row where the field is displayed and edited. (In the case of multi-line fields, this is the top row.) 

_col_ (Num)  [in] 

Starting column of the field (not the label). 

_xmax_ (Num)  [in] 

Determines the width (in current grid units) of the control used to display and edit the field. (Same as INFLD _xmax_ parameter.) If _maxchars_ not specified, then _xmax_ also determines the maximum number of characters that may be entered into the field. _entry_ (Any type)  [in/out] 

A-Shell Reference 

Page 3186 

Field contents. For _opcode_ values except 0, the initial value of _entry_ is preloaded into the field, for display and to establish the initial or default value. On exit, returns the updated field contents. Note that unlike INFLD which requires _entry_ to be a string, SBXINP allows you to pass a numeric data type for fields containing numeric data. 

## _inftype_ (String)  [in] 

Same as INFLD _type_ parameter, except that unless _inftype_ starts with a "+", whatever you specify will be added to the following default codes: A]134569kWhsg|G|E 

If _inftype_ starts with a "+", then there is no default. The "+" is discarded and _inftype_ is used for the INFLD _type_ string. 

There are two special cases: "D>" specifies a Date Picker, and "t" specifies a Time Picker. 

_setdef_ (String)  [in] 

Same as INFLD _setdef_ parameter, except with the following extensions: 

To specify a minimum number of allowed characters, append ">#" to the end of _setdef_ , where # is the number. 

Set _setdef_ to "@" to cause the field to be validated (by VALIDA.SBX) for valid email format. 

## _maxchars_ (Num)  [in] 

Same as INFLD _maxchars_ parameter. If not specified or 0, the maximum number of allowed characters will be equal to the value of the _xmax_ parameter. Setting maxchars larger than _xmax_ allows the field to scroll horizontally (accepting more characters than can be displayed at once). Setting _maxchars_ less than _xmax_ just means that the field will "look" bigger than necessary for the number of allowed characters. Note that the units of _xmax_ are grid units, whereas the units of _maxchars_ are characters. Since characters may requires more or less space than the current grid unit, even when _maxchars_ = _xmax_ , you might have either horizontal scrolling or hit the _maxchars_ limit before filling the display space of the field. 

## _clickcode_ (Floating point or Signed Int)  [in] 

Specifies the _exitcode_ value to be generated by clicking on this field when the field is not active. Note that this number should be positive even though click exitcodes are generally negative. (Setting _clickcode_ to 400 will cause the field to generate _exitcode_ -400 when clicked.) 

_tooltip_ (String)  [in] 

A-Shell Reference 

Page 3187 

Text of the tooltip to associate with the field. 

## _parentid_ (String) or Num) [in] 

ID of the parent control (tab, groupbox, dialog). If 0, it is assumed to be the current dialog. If it is a non-empty, non-numeric string, it identifies the parent control by its ID name, rather than its number. Also see _infldid_ parameter (which gets combined with this to create the full INFLD parentid parameter). 

## _exitcode_ (Floating point or Signed Int)  [in/out] 

Same as INFLD _exitcode_ parameter, except that it has significance on input as well as output. If the incoming _exitcode_ matches _clickcode_ , then the routine assumes that you must have activated the field by clicking on it (which may cause different initial or default field behavior than otherwise.) 

Special exitcode values: ?? 

_defpt_ (Num)  [in] 

Number of display lines for multi-line fields, or the default decimal point position for numeric fields. (Same as INFLD _defpt_ ). 

_timer_ (Num)  [in/out] 

Same as INFLD _timer_ . 

_cmdflg_ (Num)  [in] 

Same as INFLD _cmdflg_ . 

_maxpt_ (Num)  [in] 

Same as INFLD _maxpt_ . 

_infldid_ (String or Num)  [in/out] 

Optional ID to assign to, or to retrieve from the INFLD control. (This is combined with the _parentid_ parameter above before being passed to INFLD as its parentid parameter.) If the parameter is specified but is empty, or numeric, then it will return the numeric control ID which is auto-assigned to the INFLD control. 

A-Shell Reference 

Page 3188 

_labelid_ (String or Num)  [in/out] 

Optional ID to assign to, or retrieve from, the label control associated with the INFLD control. If a non-empty string name passed, then that is the name that will be assigned to the label control. If an empty string or a numeric parameter is passed, the auto-assigned numeric ID of the control will be returned here. 

_changeflag_ (String)  [out] 

Set to "1" if the field contents are changed. 

A-Shell Reference 

Page 3189 

## **LABEL** 

If _label_ is a simple text string, a static (but clickable) text label is created two columns on the left of the start of the INFLD field (i.e. the right edge of the button is two columns less than _col_ ). The left edge of the button is determined by the length of the _label_ string contents. 

You may fine tune the size of the label control by using the format "<###<text" or "<###>text". In the former case, the label will be left aligned starting at column ###. In the latter case, the text within the button will still be right aligned, but the left column of the label control will be ###. 

To display the label above the field, use the format "^text". This will left align the label with the left edge of the field (as determined by col), with the top of the label 700 millirows above the top of the edit field. To override the standard 700 millirow spacing, use the format "^<####>text" where #### is the number of millirows desired. 

You can also adjust the default font size used for the label by adding %###% to specify ###% scaling, i.e. "%120%Name:" will scale the label "Name" at 120% of normal. (If any of the column previous adjustment parameters are included, the %###% must be first. 

Inserting a pipe character in front of the text string (e.g. "|text") causes the label to become a button rather than a static text control. 

In the case of checkboxes, the first two positions of label are used to specify the alignment options: 

|**Valu**<br>**e**|**Alignment**|
|---|---|
||||Text on the left, left aligned.|
||>|Text on the right, left aligned.|
|>||Text on the left, right aligned.|



A-Shell Reference 

Page 3190 

|**Valu**<br>**e**|**Alignment**|
|---|---|
|>>|Text on the right, right aligned.|



A-Shell Reference 

Page 3191 

## **SCRSTS** 

## **xcall SCRSTS, opcode {params}** 

The parameter syntax varies with the _opcode_ : . 

**xcall SCRSTS, SCROP_INIT, srow, scol, erow, ecol{, parentid, sflags, title, closecmd, coldef, xt'kbdstr, xt'flags, ctlid}** 

## **xcall SCRSTS, SCROP_ADD, msgfmt, arg1, ... argN** 

## **xcall SCRSTS, SCROP_TMADD, msgfmt, arg1, ... argN** 

## **xcall SCRSTS,SCROP_SCROLL {,msg, exitcode}** 

## **xcall SCRSTS,SCROP_CLR** 

## **xcall SCRSTS,SCROP_DEL** 

SCRSTS.SBX outputs a status message to a window, scrolling previous messages up. Three variations are supported, depending on flags and environment: 

- Text mode using INMEMO 

- GUI mode using multi-line INFLD control 

- GUI mode using XTREE 

Some examples using SCRSTS are provided below. Source, additional samples and related functions can be found in SOSLIB: [907,20]. 

_opcode_ (Num)  [in] 

A-Shell Reference 

Page 3192 

specifies the operation using one of the options from the following table: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|SCROP_INIT|0|Initialize (create) the control.|
|SCROP_ADD|1|Add a message.|
|SCROP_CLR|2|Clear all the messages.|
|SCROP_DEL|3|Delete the control.|
|SCROP_SCROLL|4|Explicitly scroll the control contents; needed only in text mode.|
|SCROP_TMADD|5|Add a message with an automatic timestamp.|
|**Definition file:**ashinc:scrsts.def|||



## _srow,scol,erow,ecol_ (Num)  [in] 

specify coordinates of the rectangle in normal or milli-units 

## _sflags_ 

takes MBF_xxxxx flags (from ashell.bsi); the only ones of interest so far are MBF_DIALOG and MBF_MODELESS, which, together cause the scrolling status control to be placed inside its own modeless dialog window (ignored in text mode). Also, MBF_LISTBOX causes GUI version to use XTREE instead of INFLD, eliminating the scrolling limit 

A-Shell Reference 

Page 3193 

## _title_ 

title string to display in the dialog; ignored unless _sflags_ contains the MBF_DIALOG option. 

## _closecmd_ 

if MBF_KBD and MBF_SYSMENU flags included in _sflags_ , then _closecmd_ determines what happens when X clicked (if "", then dialog is closed internally; else string is sent in place of the normal ESC) (Virtual click codes supported) 

## _coldef_ 

can be a legal XTREE advanced column definition, if MBF_LISTBOX (The default is "1~512~ ~S~~") **Warning** : if you define any columns, it is up to you to pass subsequent MSG strings formatted to be compatible with the definition). Also note that if the header fields are all blank, the header row will be removed entirely. 

## _xt'kbdstr_ 

if MBF_KBD and MBF_LISTBOX defined, clicking on the control will send this string (which applications would typically responsd to by calling SCROP_SCROLL). 

## _xt'flags_ 

optional XTREE flags (if MBF_LISTBOX) 

## _xt'ctlno_ 

## B,2 optionally returns XTREE control ID (XTR.CTLNO) or INFLD AUI ID 

When the XTREE option is requested (see Using XTREE with SCRSTS), three additional optional parameters can be passed to the SCROP_INIT call: 

## _xt'kbdstr_ (String,10) 

sets the `XTR.KBDSTR` member of the _xtrctl_ structure, so that clicking on the status control sends the specified string. This can be useful if you want to allow the user to manipulate the status window, such as to sort, select, etc. This probably only makes sense in conjunction with a _coldef_ that defines relevant features such as columns, popup menus, etc. The application would normally call the SCROP_SCROLL opcode to in response to receiving the XT'KBDSTR. 

A-Shell Reference 

Page 3194 

## _xt'flags_ 

may be used to specify additional XTREE flags, such as perhaps XTF_MSEL, etc. 

## _ctlid_ 

will return the XTREE control number (XTR.CTLNO), or in the case of INFLD, the AUI control id. This would only be of interest in sophisticated situations where you wanted to bypass SCRSTS.SBX and operate on the control directly using XTREE or INFLD. 

These parameters apply only to the SCROP_ADD and SCROP_TMADD: 

## _msgfmt_ (String)  [in] 

The message to output. May contain zero or more of the following special field markers, some of which are supplied by the next parameter in sequence (see _arg1,...argN_ and Examples below): 

|%d|decimal value|(from arg1,...argN)|
|---|---|---|
|%s|string value|(from arg1,...argN)|
|%x|hex value|(from arg1,...argN)|
|%u|user name||
|%m|machine name||
|%p|program name||



A-Shell Reference 

Page 3195 

%v program version 

_arg1,...argN_ (various types)  [in] 

These arguments are plugged into the %d, %s, and %x field markers from _msgfmt_ 

These parameters apply only to the SCROP_ADD and SCROP_TMADD: 

## _msg_ (String)  [in] 

A string message to add to the bottom of the list. For text mode, the list is scrolled up one line to first to make room. For GUI mode, the scroll operation is automatic and thus this opcode is typically not used, although when it is used, it has the effect of suspending the application and putting the focus on the list control (allowing the operator to perform any operations supported internally by the control itself). To exit back to the application the user must issue some kind of _exitcode_ (such as ESC); see _exitcode_ . 

_exitcode_ (Signed Num)  [out] 

When specified in GUI mode, the standard XTREE exitcode value will be returned here, indicating how the user exited from the state of having the focus on the message list. 

## Display/add a message to the window: 

```
xcall SCRSTS, SCROP_ADD, msgfmt {,arg1,...argN}
```

Clear the message window: 

```
xcall SCRSTS, SCROP_CLR
```

Delete the message window (restore area in text mode) 

A-Shell Reference 

Page 3196 

```
xcall SCRSTS, SCROP_DEL
```

(If message window created inside its own dialog, dialog will be automatically deleted) 

Allow user to scroll/activate the window. 

```
xcall SCRSTS, SCROP_SCROLL {,msg{,exitcode}
```

## **Extended Example** 

The following example, from the actual AshLPD utility, illustrates the variation of SCRSTS based on XTREE, and includes the relatively advanced feature of using XTREE foreground row colors to code the various types of messages. 

## The initialization code for this image is: 

```
! Columns 1-8 are the hh:mm:ss; 10 is the color code
```

```
COLDEF = "0~0~ ~H~RGBfg=200,200,220,D~"     ! D = Debug
```

```
COLDEF = COLDEF + "RGBfg=250,100,0,E~"      ! E = Error (Red Orange)
```

```
COLDEF = COLDEF + "RGBfg=255,0,0,F~"        ! F = Fatal (Red)
```

```
COLDEF = COLDEF + "RGBfg=0,0,204,I~"        ! I = Info (Blue)
```

```
COLDEF = COLDEF + "RGBfg=100,100,180,L~"    ! L = Low level info (gray)
```

```
COLDEF = COLDEF + "RGBfg=0,0,0,P~"          ! P = Printing msg (black)
```

```
COLDEF = COLDEF + "RGBfg=210,0,210,W~~"     ! W = Warning (yellow)
```

```
COLDEF = COLDEF + "1~8~ ~S~~10~1~ ~Hc~~11~120~ ~S~~"  ! column layout of msgs
```

```
xcall
```

```
SCRSTS,SCROP_INIT,3,5,20,75,0,SFLAGS,"","",COLDEF
```

A-Shell Reference 

Page 3197 

Messages are added with calls such as the following one. (Note that the color code letter, "I" in this case, indicating Info (Blue), is just sandwiched at the start of the message (matching the _coldef_ layout set up above). 

```
xcall SCRSTS,SCROP_TMADD,"IPerforming housekeeping..."
```

```
xcall SCRSTS, SCROP_TMADD, "I Archive for %d day(s), age cutoff = %d seconds", CFG'ARCHIVE, cutoff
```

The name (SCROLL) is slightly misleading because in GUI mode, you could scroll without this, but it is necessary in text mode, and in XTREE mode it activates the control allowing other features (such as sorting, selecting, etc. to take place). If _exitcode_ is specified, returns _exitcode_ , if any. 

Stores data between calls using memory module SCRSTS.MEM (meaning that currently there can be only one of them active per A-Shell instance.) 

Note that in text mode, if the height is >= 3, we use a border (which occupies 2 of the allowed rows). Otherwise no border. Also, on _opcode_ 0, we save the area, and restore it on _opcode_ 3. 

The SCROP_SCROLL operation now supports the return of an exitcode: 

## **xcall SCRSTS, SCROP_SCROLL, msg, exitcode** 

Since the SCROP_SCROLL opcode actually puts the focus on the status control, the _exitcode_ will be that which you would have gotten from XTREE, INFLD, or INMEMO, depending on the environment. This would probably be most useful if you defined a PopupMenu, which returned interesting exitcodes. 

The sample program REGPTR in EXLIB:[908,29] illustrates some of the capabilities of SCRSTS. 

## **Using XTREE with SCRSTS** 

SCRSTS.SBX 1.3(108), A-Shell’s scrolling status window handler, supports an option to use XTREE rather than INFLD to display the scrolling status window. To specify XTREE, you must set the MBF_LISTBOX bit in the _sflags_ parameter when creating the scrolling status window. An optional new parameter allows you to specify an XTREE column definition string: 

A-Shell Reference 

Page 3198 

## **xcall SCRSTS, SCROP_INIT, srow, scol, erow, ecol {,parentid, sflags, title, closecmd, coldef}** 

The rest of the SCRSTS opcode formats are unchanged. 

Although the XTREE version actually has more overhead (XTREE is a vastly more complex control than the multi-line edit control used by INFLD), here are some of the reasons why you might prefer it: 

- It eliminates the 1600 char limit on the amount of text that can be left in the window. With XTREE, there is essentially no 

- limit. 

- You can access many of the advanced XTREE features, such as colors, popup menus, columns, even multiple levels. Note, 

- however, that it is up to you to supply a text string (in the SCROP_ADD or SCROP_TMADD calls) that is formatted to match the _coldef_ specified with the SCROP_INIT. 

Also note that if any of the column header fields in _coldef_ are not blank, then the normal column header bar will be displayed. Otherwise it will not (making it more like a typical scrolling status window). 

The sample program TSTSCR.BP in SOSLIB:[907,20] sample program has been updated to allow easy experimentation with the new version. 

A-Shell Reference 

Page 3199 

## **SEND** 

## **xcall SEND, job, string {,options, status}** 

SEND provides the same functionality at the programmer level that SEND.LIT does at the command prompt level. 

## **Parameters** 

_job_ [in] 

may be specified as B,1 in which case it is interpreted as the target job number, or S,6 in which case it is the target job name. 

If mapped as B,1 or B,2 (i.e., to specify the target via its job number), then you can set it to -1 to indicate all jobs. 

If mapped as a string (i.e. to specify the target via its job name), then you can set it to "ALL" to indicate all jobs. 

_string_ (String)  [in] 

is the text message (one line) to send. 

## _options_ [in] 

may be set to 0 (normal, i.e. display the message wherever the cursor happens to be on the target terminal), 1 (top status line), or 2 (bottom status line). 

## _status_ 

if specified, will return 0 if the message was successfully sent. 

When sending to all jobs, the return value of STATUS takes on a new meaning. With one job, a return STATUS of 0 means success. But when sending to all jobs, STATUS returns the number of jobs to which the message was sent. 

## **Comments** 

Under Unix, there are security limitations on who can send messages. See the discussion on File Ownership and Privileges and ITC for more details. 

A-Shell Reference 

Page 3200 

Under Windows, there are no privilege issues but there may be a delay of several seconds before the message is delivered. See the IJCFREQ system parameter. 

A-Shell Reference 

Page 3201 

## **SERCH** 

_Reviewed July 2025_ 

## **xcall SERCH, ch, rec, key, stpos1, enpos1, bsend, bsmid, srcctl, srcopt, rcnost, rcnoen, stpos2, enpos2, stpos3, enpos3** 

SERCH is used for searching index files that consist of a sorted area and an unsorted "overflow" area. The sorted area is searched using a binary search routine, while the overflow area is searched sequentially. At best, binary searching is nowhere near as efficient as ISAM index lookups, and this discrepancy gets rapidly worse as the size of the overflow area increases, so it is not a highly recommended indexing technique. Nevertheless it is quite common, due to its use in the old AlphaAccounting programs and concerns in the early days about the reliability of ISAM. 

## _ch_ (Num) 

is the file channel of the file being searched, opened for random access; any of the optional attributes are permitted, including span'blocks. 

_rec_ (BLOB, 2048 bytes maximum) 

is an unformatted area for the located index record to be returned in. 

## _key_ (String) 

is the string key to search for. This can consist of up to 3 parts (corresponding to the _stpos1_ , _enpos1_ , _stpos2_ , _enpos2_ , _stpos3_ and _enpos3_ locations in the index record), all of which must be concatenated together. 

_stpos1, enpos1, stpos2, enpos2, stpos3, enpos3_ (Num) 

specify the starting and ending position of up to 3 segments of the index record which make up the key to search for. 

_bsend_ (Num) 

is the number of records in the sorted portion of the file (which must begin at the first record in the file). 

_bsmid_ (F,6) 

A-Shell Reference 

Page 3202 

will return the record number of the located index record. 

_srcctl_ (F,6) 

returns a completion code (0=found, 1=not found) 

## _srcopt_ (Num) 

## specifies the type of search to perform: 

|**Valu**<br>**e**|**Search Type**|
|---|---|
|1|Display "Please Wait" on line 12 of the screen, perform a binary/sequential search, clear the message, and<br>return.|
|2|Perform a binary/sequential search, clear line 12 of the screen, and return|
|3|Display the wait message, perform a binary/sequential search, and return|
|4|Perform a binary/sequential search and return (without any display)|
|5|Perform a sequential search only, starting with the record number specified by_bsmid_.|
|6|Perform a binary/sequential search which guarantees the locating of the first of a series of identical keys.<br>(The other binary search options do not guarantee this.)|



A-Shell Reference 

Page 3203 

By "binary/sequential" in the table above, we mean that it first performs a binary search on the sorted portion of the index file, and if the record is not found, it then performs a sequential search on the overflow area. 

## _rcnost, rcnoen_ 

mark the starting and ending positions within the record that are used to indicate a deleted record. This area must be at least 2 bytes long, and each of the bytes must contain binary zero. (You can create such a binary field by setting a variable of type F or B to zero, in which case all of the bytes of the variable will contain 0, or by setting a string variable to "".) 

## **Comments** 

Traditionally, due to performance or memory limitations, it is common for applications to create an index file, separate from the main data file, containing just the keys and corresponding pointers to the main data file. Looking up a record consists then of using SERCH on the index file and then using the index record's pointer (record number) to read the main data record. However, there is nothing preventing you from eliminating the separate index file and using SERCH directly on the main file, assuming that it's practical to keep it reasonably sorted, or you don't mind the performance of linear searching. 

The speed of SERCH can be increased dramatically by using one of the techniques described in the discussion of XCALL ASFLAG. It also goes without saying that you should sort the file as needed to keep the overflow area from growing very large. 

SERCH works with flat (random) index files, with or without the span'blocks option, including record sizes up to 2048. 

A-Shell Reference 

Page 3204 

## **SETJTB** 

## **xcall SETJTB, job-table-variable** 

SETJTB is the converse of GETJTB and operates on the same format structured variable. It writes back each field into the job control block (with the exception of the job number, which cannot be changed), and thus may be used to change PPNs and devices, or to change the job name. 

## **Comments** 

Care must be taken when using SETJTB, as it does not perform any checking on the values within the job table variable, and it is possible to store invalid information in your job control block. 

Note that the PPN is represented both in its binary and string forms in _job-table-variable_ . The current PPN will be set to the string values only if both binary fields contain zero. (Using the string fields is preferable, since they support the full range of 000999, while the single byte binary versions are limited to octal values 0-377.) 

A-Shell Reference 

Page 3205 

## **SIZE** 

_Reviewed May 2026_ 

## **xcall SIZE, fspec, count {,flags}** 

SIZE returns the size of the specified file in bytes. 

## **Parameters** 

_fspec_ (String)  [in] 

is specification of the file (in DevPPN or native format). 

_count_ (Signed Num)  [out] 

returns the number of bytes. If the file does not exist, -1 is returned. A return value of 0 indicates that the file exists but contains no data. 

_flags_ (Num)  [in] 

specifies what to return in the _count_ parameter: 

|**Value**|**Data Returned**|
|---|---|
|0 (default)|Number of bytes in file|
|1|Number of lines in (text) file|
|2|Number of non-blank lines in (text) file|



A-Shell Reference 

Page 3206 

## **History** 

- 2015 December, A Shell 6.3.1501:  Add _flags_ . Prior to this update, the routine only returned the number of bytes in the file, as if _flags_ =0. 

- 2015 January, A Shell 6.1.1400:  Routine now supports files larger than 2GB when the returned parameter is any F type. Previously, it only avoided the 2GB limit for F,6. 

A-Shell Reference 

Page 3207 

## **SLEEP** 

_Added November 2025_ 

## **xcall SLEEP, seconds** 

SLEEP puts the job to sleep for the specified amount of time. Seconds may be fractional, down to a theoretical precision of .0001 seconds. There is no maximum. 

## **Parameters** 

_seconds_ (Num)  [in] 

Number of seconds to sleep. 

## **See Also** 

- SLEEP ASB statement 

- Xcall WAKNO to wake up a sleeping job. 

- SLEEPR.LIT to sleep until a specified time. 

A-Shell Reference 

Page 3208 

## **SORTIT** 

_Reviewed May 2025_ 

**xcall SORTIT, array, reccnt, recsiz, k1siz, k1pos, k1ord {,** 

**k2siz, k2pos, k2ord, k3siz, k3pos, k3ord, k1typ, k2typ, k3typ,** 

**k4siz, k4pos, k4ord,** 

**k5siz, k5pos, k5ord, k6siz, k6pos, k6ord,** 

## **k4typ, k5typ, k6typ}** 

Note that in the syntax shown above, line breaks have been added strictly for readability. In an actual program you would need to use the ampersand continuation symbol for any mid-statement line breaks. See ASB Program Symbols. 

SORTIT sorts an array in memory. The parameters are all analogous to those of BASORT, subject to the comments below. 

_array_ [in/out] 

Since A-Shell/BASIC does not have a natural syntax for referring to the entirety of an array, you can either specify an unformatted variable which occupies the same space as the array, or you can specify the first element of the array. For example: 

```
MAP1 XARY
```

```
    MAP2 ARY(100)
```

```
        MAP3 FLD1,S,10
```

```
        etc.
```

A-Shell Reference 

Page 3209 

Assuming the above layout, you could either specify the XARY variable, or ARY(1). The first choice has the advantage of allowing A-Shell to make sure that you don't accidentally specify more rows than exist. The downside is that the technique cannot be used with DIMX arrays. For example: 

```
DIMX ARRAY(COUNT),S,WIDTH
```

```
XCALL SORTIT, ARRAY(1), COUNT, WIDTH, K1SIZ, ...
```

In the above case, you have no choice but to use the second method, specifying ARRAY(1) for the array parameter. Note that it may not be possible for SORTIT to verify the size of the array in this case, so IT IS CRITICAL that the passed subscript is actually (1) and that the reccnt parameter is less than or equal to the total extent of the array lest you corrupt memory and suffer all manner of humiliation and suffering. Note that you can use the .EXTENT() function to determine the physical extent of an array at runtime. 

_reccnt_ (Num)  [in] 

Number of elements in the array to sort. See warning under array about making sure reccnt doesn't exceed the size of the array. _recsiz_ (Num)  [in] 

Size of each element in the array. 

_k?siz_ (Num)  [in] 

Size of the key (? = 1,2,3,4,5,6). For unused keys, specify 0. Note that for binary and integer keys, only 2 and 4 byte sizes are supported. For F keys, size may be 4, 6, or 8. 

_k?pos_ (Num)  [in] 

Position of the key within each array element (starting with 1). 

_k?ord_ (Num)  [in] 

Sort order: 0=ascending, 1=descending 

A-Shell Reference 

Page 3210 

## _k?typ_ (Num)  [in] 

|**Valu**<br>**e**|**Search Type**|
|---|---|
|0|String|
|1|Floating point: 4, 6 or 8 byte|
|2|Binary: 2, 3, 4, 5 bytes|
|3|Integer: 2 or 4 bytes|
|4|Natural Sort|
|5|Case insensitive natural sort|



The default value is 0 (String). Also see History note 1136 below. 

## **History** 

- 2013 January, A Shell 6.1.1332:  The routine now checks for certain parameter errors that might otherwise have caused erroneous results (at best) or corrupted memory (at worst). These would include specifying more rows to be sorted than exist in the array, or attempting to sort an array made up of dynamic string elements (which are not contiguous and thus cannot be 

A-Shell Reference 

Page 3211 

sorted by SORTIT in its current state of development). Note that we are unable to check for the case where the array parameter is specified as an individual element other than the first one, which could lead to memory overflow even if the specified row count is within the bounds of the extent of the array. 

For example, if the physical size of the array is 100, and you specify 100 rows to sort, but instead of specifying array(1) as the initial element you accidentally specify array(10), then it could end up referencing non-existent rows 101-110. 

- 2009 January, A Shell 5.1.1136: SORTIT now support the 3 new sort types (see BASORT), plus F4 and F8. Note, however, that SORTIT does not support B1 or I1 keys, and ignores the LDF collating sequence. 

A-Shell Reference 

Page 3212 

## **SQUEEZ** 

_Written March 2021_ 

## **xcall SQUEEZ, outbuf, cbout, inbuf{, cbin}** 

SQUEEZ implements the data "squeeze" algorithm used by the MX_FILEHOOK File-Based File Hook Handler. 

## **Parameters** 

_outbuf_ (X)  [out] 

Receives the squeezed version of the data in _inbuf_ . Note that it should either be dynamic (X,0) or a fixed size greater than or equal to two times the size of _inbuf_ . Although in most cases the squeezed data will be much smaller than the original, the worst case could be twice as large. 

_cbout_ (Signed Num)  [out] 

Receives the number of bytes written to _outbuf_ . A negative value indicates an error, most likely that the _outbuf_ wasn't large enough. Note that you should use this value rather than the size of _outbuf_ to determine how much of its contents to process. 

_inbuf_ (X)  [in] 

The raw data to be squeezed. 

cbin  (Num)  [in] 

If specified, this determines the number of bytes in _inbuf_ to process. If omitted, the entire contents of _inbuf_ is processed. 

## **Comments** 

You can use the Fn'Hooklog'Read'Squeezed() function in fnfhooklog.bsi in SOSLIB:[907,10] to unsqueeze the data. Note that unlike the actual file hook routine, SQUEEZ doesn't automatically include any envelope with the data. You should probably include your own envelope, or at least a designated packet start byte make sure that your unsqueeze operation is in sync with the data. 

- See File Based File Hook Handler for details on the squeeze algorithm. 

## **History** 

A-Shell Reference 

Page 3213 

- 2021 March, A Shell 6.5.1699:  Add function to A-Shell. 

A-Shell Reference 

Page 3214 

## **SQL** 

## **xcall SQL, opcode, cmdhdr {,parm1,…,parmN}** 

SQL provides direct access (query/read/write/update) to SQL databases, in particular MySQL and any database supported by an OBDC driver. The name of the routine is SQL as shown here, but the name of the option/module in A-Shell is "ASQL." Information on ASQL is in its own document, for which see the documentation page on the A-Shell web site. 

Note that ASQL is a licensed A-Shell option. If you try to use XCALL SQL without having licensed ASQL, you will get an error message and a usage restriction. That restriction—A-Shell going into demo mode—can be reset by closing and then restarting the session. 

A-Shell Reference 

Page 3215 

## **STRIP** 

## **xcall STRIP, strvar** 

STRIP removes trailing blanks and tabs from the specified string. 

## **See Also** 

- TRIMXS, which trims leading spaces, trailing spaces and tabs, and has an option to remove control characters as well. 

- XSTRIPXS, which provides more sophisticated removal of specific characters from string. 

- STRIP$(), a function version of the same logic. 

- RTRIM$(), same as STRIP$() but removes spaces only 

- EDIT$(), similar function with expanded capabilities. 

A-Shell Reference 

Page 3216 

## **STRTOK** 

_Reviewed  May 2025_ 

## **xcall STRTOK, opcode, subject, fdelim, fld1 {, rdelim, fld2, ...fldn}** 

STRTOK parses the _subject_ variable according to the delimiters specified, and returns one or more fields in the _fld1...fldn_ variables. You can call it once for each field (and change the field delimiter characters as you go), or have it return several parsed fields in one call, ending either when it hits a delimiter in the _rdelim_ field or runs out of _subject_ or of _fldx_ parameters. 

STRTOK is both convenient and very efficient (compared to the equivalent logic in BASIC) for parsing string data, but may take a little practice to get used to. For a couple of real examples using it, see Almost Comma Delimited and Large Packets, Multiple Delimiters. 

## _opcode_ (Num)  [in/out] 

should be set to 0 for the initial call, and 1 for subsequent calls using the original _subject_ . It will be updated automatically from 0 to 1 to make this easy. In addition, you may specify one or more of the following values for variations of the behavior: 

|**Value**|**Search Type**|
|---|---|
|&h0002|Ignore delimiters in_subject _if they are inside pairs of quotes ("). Quotes surrounding a field are<br>removed.|
|&h0004|Ignore quotes in the middle of fields in_subject_. For example, in a CSV list (comma delimited) containing<br>{ 6" wrench, 2" screw, "foo,bar", ... }, the quotes in the first two items would be treated as normal<br>characters.|



_subject_ (String)  [in/out] 

A-Shell Reference 

Page 3217 

is the string to be parsed. Must be null terminated! _subject_ will be modified by the routine, which will replace the delimiter characters with null bytes. 

_fdelim_ (String)  [in] 

is a list of one or more field delimiter characters. 

_rdelim_ (String)  [in/out] 

is a list of one or more "record" delimiter characters. 

(The subroutine will terminate when it hits one of these, whereas it will keep going after each field delimiter until all the FLDx parameters are used up.) Parameter is irrelevant if you just want to get one field. Even in the case of multiple fields, you can set it to "". Note, however, that if specified, it will be returned updated with the actual last delimiter character processed (i.e. the one that terminated the subroutine). This can be very useful when there are more than one possible delimiter, or when you want to determine whether you got a complete record or just ran out of FLDx parameters. If you do not care about record delimiters, then specify it as a literal "" (in which case it cannot be updated) or remember to clear it prior to each `XCALL STRTOK` . Otherwise, it will get updated to match the field delimiter. The subroutine should be smart enough to ignore record delimiters that are also field delimiters, but it could nonetheless lead to confusion. 

Note that prior to Build 905.3, _rdelim_ was assumed to be 2 or more bytes and the second byte was getting cleared, which would have clobbered the next variable if rdelim only mapped as one byte. 

_fld1...fldn_ (String)  [out] 

will return the parsed fields or tokens from _subject_ , according to the specified delimiters. 

## **Subtopics** 

- Almost Comma Delimited 

- Large Packets, Multiple Delimiters 

A-Shell Reference 

Page 3218 

## **ALMOST COMMA DELIMITED** 

Ordinary comma delimited data is easy to parse with INPUT CSV, but what do you do when the comma delimited file contains commented lines? A good example is the A-Shell INI.CLR file, which looks something like this: 

- `; Color Definitions (for a primarily blue background)` 

- `; Color legend: 0=blk, 1=wht, 2=blu, 3=mag, 4=red, 5=yel, 6=grn, 7=cyn` 

- `; VUECLR=override?,edit fg,edit bg, command fg, command bg, help fg, help bg, status/info fg,bg` 

- `; Use the following for a reasonable scheme using blue background.` 

```
VUECLR=Y, 1,2, 5,2, 7,2, 6,2
```

- `; Use the following to disable VUE colors, i.e. use current colors only.` 

- `;VUECLR=Y,-1,-1,-1,-1,-1,-1,-1,-1` 

- `; EZCLR=override?,text fg,bg, border fg,bg, cmd fg,bg, sts fg,bg, help fg,bg, highlight fg,bg, menu fg,bg, brief menu fg,bg` 

```
EZCLR=Y, 1,2, 1,2, 5,2, 0,9, 1,3, 1,4, 5,2, 7,2
```

- `; INFCLR=override?,display fg,bg, edit fg,bg, negative fg,bg, update fg,bg, message fg,bg, original msg line fg,bg, forms fg,bg` 

```
INFCLR=Y, 5,2, 1,10, 4,2, 7,2, 7,2, 1,2, 0,2
```

- `; MMOCLR=Y,border fg,bg, text fg,bg, arrows fg,bg, prompt fg,bg, status line fg,bg, protected fg,bg` 

- `MMOCLR=Y, 6,2, 5,10, 6,2, 7,2, 1,2, 7,2` 

- `; SCNCLR=override?,screen text (fg), screen background` 

- `; The following sets up white on blue` 

```
SCNCLR=Y,1,2
```

A-Shell Reference 

Page 3219 

This seems like a simple enough format, but the unpredictable presence of the commented lines (marked by a semicolon), and the equal sign make it difficult or impossible to use INPUT CSV. STRTOK comes in handy here because it can be used on a string, allowing you to first input the entire line to check for commented out lines, then pass it to STRTOK. Also, it eliminates the need to deal with special tests for prematurely terminated lines, lines with comments in them, uneven spacing, etc. The following code parses the input, putting into the MAP structures: 

```
MAP1 VUECLR'OVR,S,1
MAP1 VUECLR(4,2),S,1   ! 4 pairs
MAP1 EZCLR'OVR,S,1
```

```
MAP1 EZCLR(8,2),S,1    ! 8 pairs
MAP1 INFCLR'OVR,S,1
MAP1 INFCLR(7,2),S,1   ! 7 pairs
```

```
MAP1 MMOCLR'OVR,S,1
MAP1 MMOCLR(6,2),S,1   ! 6 pairs
MAP1 SCNCLR'OVR,S,1
MAP1 SCNCLR(2),S,1     ! 1 pair
MAP1 PLINE,S,100
MAP1 STATE,F,6,1       ! 1)VUECLR, 2)EZCLR, etc.
MAP1 RDELIM,S,2
```

```
MAP1 FDELIM,S,3,"=,"
MAP1 OPCODE,B,1,0
```

```
OPEN #1, "LIB:INI.CLR", INPUT
```

A-Shell Reference 

Page 3220 

```
LOOP:
```

```
INPUT LINE #1, PLINE
IF EOF(1)=1 AND PLINE="" GOTO PREMATURE'END
xcall TRIM,PLINE,1
IF PLINE="" OR PLINE[1,1]=";" GOTO LOOP
```

```
OPCODE = 0
```

```
ON STATE CALL PVUE,PEZ,PINF,PMMO,PSCN
IF STATE < 5 GOTO LOOP
```

```
PREMATURE'END:
```

```
PRINT "PREMATURE END OF FILE"
```

```
DONE:
```

```
CLOSE #1
```

```
END
```

```
PVUE:    ! parse VUECLR line
RDELIM = ";" + CHR(10)
```

```
xcall STRTOK,OPCODE,PLINE,FDELIM,VUECLR'OVR,RDELIM, &
```

A-Shell Reference 

Page 3221 

```
VUECLR(1,1),VUECLR(1,2),VUECLR(2,1),VUECLR(2,2), &
VUECLR(3,1),VUECLR(3,2),VUECLR(4,1),VUECLR(4,2)
```

```
STATE = STATE + 1
```

```
RETURN
```

```
PEZ:    ! parse EZCLR line
```

```
RDELIM = ";" + CHR(10)
```

```
xcall STRTOK,OPCODE,PLINE,FDELIM,EZCLR'OVR,RDELIM, &
```

```
EZCLR(1,1),EZCLR(1,2),EZCLR(2,1),EZCLR(2,2), &
EZCLR(3,1),EZCLR(3,2),EZCLR(4,1),EZCLR(4,2), &
EZCLR(5,1),EZCLR(5,2),EZCLR(6,1),EZCLR(6,2), &
EZCLR(7,1),EZCLR(7,2),EZCLR(8,1),EZCLR(8,2)
```

```
STATE = STATE + 1
```

```
RETURN
```

```
PINF:    ! parse INFCLR line
RDELIM = ";" + CHR(10)
```

```
xcall STRTOK,OPCODE,PLINE,FDELIM,INFCLR'OVR,RDELIM, &
```

```
INFCLR(1,1),INFCLR(1,2),INFCLR(2,1),INFCLR(2,2), &
INFCLR(3,1),INFCLR(3,2),INFCLR(4,1),INFCLR(4,2), &
INFCLR(5,1),INFCLR(5,2),INFCLR(6,1),INFCLR(6,2), &
```

A-Shell Reference 

Page 3222 

```
INFCLR(7,1),INFCLR(7,2)
```

```
STATE = STATE + 1
```

```
RETURN
```

```
PMMO:    ! parse MMOCLR line
RDELIM = ";" + CHR(10)
```

```
xcall STRTOK,OPCODE,PLINE,FDELIM,MMOCLR'OVR,RDELIM, &
```

```
MMOCLR(1,1),MMOCLR(1,2),MMOCLR(2,1),MMOCLR(2,2), &
MMOCLR(3,1),MMOCLR(3,2),MMOCLR(4,1),MMOCLR(4,2), &
MMOCLR(5,1),MMOCLR(5,2),MMOCLR(6,1),MMOCLR(6,2), &
MMOCLR(7,1),MMOCLR(7,2)
STATE = STATE + 1
```

```
RETURN
```

```
PSCN:    ! parse SCNCLR line
RDELIM = ";" + CHR(10)
```

```
xcall STRTOK,OPCODE,PLINE,FDELIM,SCNCLR'OVR,RDELIM, &
```

```
SCNCLR(1),SCNCLR(2)
```

```
STATE = STATE + 1
```

```
RETURN
```

A-Shell Reference 

Page 3223 

The example above was complicated by the fact that every line of the file contained a different format and needed to be put into different variables. So we needed a lot of individual STRTOK commands. But we did not need any complicated substring processing–it was all very straightforward. 

A-Shell Reference 

Page 3224 

## **LARGE PACKETS, MULTIPLE DELIMITERS** 

The next example is perhaps more typical, taken from a real-world data stream arriving over a TCP socket. The data represents the answer to an auto parts query, and is made up of a list of auto makes. Within each make is a list of models. And within each model is a list of years. The model records are terminated with a "|", the make records are terminated with ~, and the individual fields are terminated with semicolons. So a block of data may look something like this: 

```
Ford; Mustang; 1975-79; 1985-88; 1999-2004|Pinto; 1968,1971,1980-85,1992|Explorer; 1992,1994-96; 1998-2004|
Expedition; 2001; 2003~Chevrolet; Impala; 1957-61; 1965-70; 1976,1979|Camaro; 1962; 1964; 1966; 1968;
1975~Mazda; RX7; 1985-91; 1994|Miata; 2004~
```

Our program to parse the data looks like this: 

```
MAP1 PARAMS
```

```
MAP2 MAKES(20)              ! Up to 20 makes
```

```
MAP3 MKNAME,S,10            ! name of make
```

```
MAP3 MODELS(20)             ! up to 20 models per make
```

```
MAP4 MODNAME,S,10       ! model name
```

```
MAP4 YEARS(30),S,10     ! up to 30 years per model
```

```
MAP1 PARAMS$,S,124200,@PARAMS   ! for easy init of all
```

```
MAP1 INFO,S,10000           ! block of data
```

```
MAP1 RDELIM,S,2,""
```

```
MAP1 FDELIM,S,1,";"         ! field delimiter
```

```
MAP1 OPCODE,B,1
```

```
MAP1 MKX,F,6                ! index to MAKES()
```

```
MAP1 MDX,F,6                ! index to MODELS()
```

A-Shell Reference 

Page 3225 

```
MAP1 YX,F,6                 ! index to YEARS()
```

```
!   <receive data from socket into INFO>
```

```
INFO = "Ford;Mustang;1975-79;1985-88;1999-2004|" &
```

- `+ "Pinto;1968;1971;1980-85;1992|Explorer;1992;" &` 

- `+ "1994-96;1998-2004|Expedition;"2001;2003~Chevrolet;"` 

- `+ "Impala;1957-61;1965-70;1976,1979|Camaro;"` 

- `+ "1962;1964;1966; 1968;1975;1976; 1977;1978;"` 

- `+ "1980;1982;1984;1986; 1988;1990;1992;" &` 

- `+ "1994;1996;1998;1999;2000;2002;2004~" &` 

- `+ "Mazda;RX7;1985-91;1994|Miata;2004~"` 

```
PARAMS$ = ""   ! Clear entire param array
```

```
MAKE'LOOP:      ! input one 'make' record per loop
```

```
MKX = MKX + 1
```

```
RDELIM = ""
```

```
MAKE$ = ""   ! clear entire MAKES(MKX)
```

```
xcall STRTOK,OPCODE,INFO,FDELIM,MKNAME(MKX)
```

```
IF MKNAME(MKX)="" GOTO DONE
```

```
MDX = 0
```

A-Shell Reference 

Page 3226 

```
MODEL'LOOP:     ! input models, one per loop
```

```
MDX = MDX + 1
RDELIM = "~|"   ! could end on either delimiter
```

```
xcall STRTOK,OPCODE,INFO,FDELIM,MODNAME(MKX,MDX),RDELIM, &
YEARS(MKX,MDX,1),YEARS(MKX,MDX,2),YEARS(MKX,MDX,3), &
YEARS(MKX,MDX,4),YEARS(MKX,MDX,5),YEARS(MKX,MDX,6), &
YEARS(MKX,MDX,7),YEARS(MKX,MDX,8),YEARS(MKX,MDX,9), &
YEARS(MKX,MDX,10),YEARS(MKX,MDX,11),YEARS(MKX,MDX,12), &
YEARS(MKX,MDX,13),YEARS(MKX,MDX,14),YEARS(MKX,MDX,15)
```

- `! check what delimiter we ended with...` 

```
IF RDELIM="~" GOTO MAKE'LOOP   ! get next make
IF RDELIM="|" GOTO MODEL'LOOP  ! get next model
IF RDELIM<>";" GOTO ERROR      ! unexpected delimiter
```

- `! if last delimiter ; get more fields – note we have` 

```
! a limit of 30 params so we could not do them all in
```

- `! one xcall` 

```
RDELIM = "~|"   ! could end on either delimiter
```

A-Shell Reference 

Page 3227 

```
xcall STRTOK,OPCODE,INFO,FDELIM,YEARS(MKX,MDX,16),RDELIM, &
```

```
YEARS(MKX,MDX,17),YEARS(MKX,MDX,18),YEARS(MKX,MDX,19), &
YEARS(MKX,MDX,20),YEARS(MKX,MDX,21),YEARS(MKX,MDX,22), &
YEARS(MKX,MDX,23),YEARS(MKX,MDX,24),YEARS(MKX,MDX,25), &
```

```
YEARS(MKX,MDX,26),YEARS(MKX,MDX,27),YEARS(MKX,MDX,28), &
```

```
YEARS(MKX,MDX,29),YEARS(MKX,MDX,30)GOTO MAKE'LOOP
```

```
GOTO MAKE'LOOP
```

Note that STRTOK does not clear the unused fields, so it is up to the program to reset them in advance. In the program above, although this is not a problem since we only use the arrays once, we use a string overlay to clear the entire 3 level array in one step just to illustrate the general case. 

A-Shell Reference 

Page 3228 

## **SUBMIT** 

_Revised/reviewed June 2020_ 

## **xcall SUBMIT, pid, stdin, stdout, stderr, executable, {arg1, arg2, ...argn}** 

(Unix only) SUBMIT allows you to execute an arbitrary command (executable and arguments) as a child process of the current A- Shell process. It is similar to HOSTEX, but implemented using the lower level fork() / exec() sequence, rather than the higher level system() call used by HOSTEX. The lower level implementation provides some additional flexibility, which is mainly of use to SUBMIT.LIT, and thus is primarily of interest as an internal routine. 

## **Parameters** 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|pid|Num|out|Returns the process id number (pid) of the child process created to run the command. (Note<br>that such pids can be larger than 64K in most modern Unix implementation, thus B,2 is not a<br>good choice.)|
|stdin|String|in|Must specify the filespec (AMOS-style or native) of a file containing the input to be forced to the<br>process (aka the "control file"). This is typically similar to a CMD file, but may contain raw<br>keyboard characters as well as commands, and should start with a LOG command.|
|stdout,<br>stderr|String|in|Must specify the filespecs of files to which the standard and error output of the process will be<br>sent. To mimic the AMOS log file behavior, set them both to the same name (typically with an<br>extension of LOG and a base name either matching the control file or the job name).|
|executable|String||Filespec of an executable which the child process will be forced to run. (In the case of<br>SUBMIT.LIT<br>,this is always "ashell", but could in theory be anything.) Normal operating system<br>search path rules apply if the filespec doesn't specify a path.|



A-Shell Reference 

Page 3229 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|arg1,<br>arg2,<br>...<br>argn|String|in|Optional arguments to the command specified in the executable parameter, not to be confused<br>with theSUBMIT.LIT<br> switches. Note that switches consisting of two parts, such as "-j JOBABC"<br>must be specified as two separate arguments (i.e. "-j" and "JOBABC"). If a single switch part<br>contains embedded spaces, it must be enclosed in quotes, i.e. "-i", """c:\vm test\miame.ini""".<br>See the example below, andCommand Line Switches<br> for A-Shell switches.|



## **Example** 

```
xcall SUBMIT, PID, "CMD:TEST.CTL", "TEST.LOG", "TEST.LOG", "ashell", "-i", "/vm/miame/miame.ini", "-j",
"TSTJOB"
```

## **Comments** 

SUBMIT is used by SUBMIT.LIT, but only in the Unix environment, and only for certain combinations of switches. For example, the /NEXT and /AFTER switches do not result in SUBMIT calls, and those switches would be invalid arguments to XCALL SUBMIT. Similarly, the SUBMIT.LIT switches used for queries or displays are handled independently within SUBMIT.LIT. To examine the relationship between SUBMIT.LIT and SUBMIT, you can set the TRACE Option to log the subroutine operations within SUBMIT.LIT to the ASHLOG file. 

Child processes launched via SUBMIT are generally dependent on the parent process to continue running for the duration of the child process. To launch a child/background process independent of the current process, use SUBMIT.LIT with the /NEXT: or /AFTER: switch, or set the SUBMIT2 system parameter. 

## **See Also** 

- The system parameter SBR option SUBMIT2 for related information. 

- SUBMIT.LIT 

A-Shell Reference 

Page 3230 

## **SWPSBR** 

_Updated December 2023; see History_ 

## **xcall SWPSBR, function {,parameters dependent on function}** 

SWPSBR performs various functions related to the Swap multi-session and screen-tracking system available as a third-party addon in the AMOS world. A-Shell does not support Swap per se, since it has its own screen tracking system (TRACKER) and multisession system (either PolyShell or using multiple Windows instances), but it does support most of the SWPSBR functions, which are listed below. Note that unless you already have a lot of code using these functions, you would be better off to use MSBOXX, which can do all of these things and which is both more powerful and better supported. 

## **xcall SWPSBR, 0, active$** 

Function 0 tests whether the Swap system is active. A-Shell returns "Y" in the _active$_ parameter. 

## **xcall SWPSBR, 1, screen** 

## **xcall SWPSBR, 1, srow, scol, erow, ecol, screen** 

Function 1 restores the previously saved window or entire screen. With Swap, the screen parameter was a buffer to hold the screen contents, but it is ignored with A-Shell, which has an internal storage scheme. (You can map it as X,1 to save space.) However, A-Shell's scheme acts like a stack, so you must save and restore in LIFO order (i.e. last item saved will be the first item restored.) The first format above restores the entire screen. The second format restores a previously saved partial screen. 

You can also restore an entire screen with Tab(-1,203), assuming it has previously been saved with Tab(-1,202) or an equivalent. You can also save and restore partial screens using MSBOXX 

## **xcall SWPSBR, 3, screen** 

## **xcall SWPSBR, 3, srow, scol, erow, ecol, screen** 

Function 3 saves an entire screen (first format) or partial screen (second format). See Function 1 above for the restore operation. 

A-Shell Reference 

Page 3231 

## **xcall SWPSBR, 7, srow, scol, erow, ecol, siz** 

Function 7 was used to establish the size needed to store the specified screen area. The call is simply ignored by A-Shell, since you do not need to provide any storage space for the save and restore operations. 

## **xcall SWPSBR, 8, srow, scol, erow, ecol** 

Function 8 was used to restore attributes on the right side of the box. It is not implemented by A-Shell. You do not need this capability with mode emulations (such as Windows, VT100, etc.) and if you really need it, you can get it by using MSBOXX and the BOX_FAO option, or via Function 128. 

## **xcall SWPSBR, 9, srow, scol, erow, ecol** 

Function 9 clears the specified box. It is equivalent to the MSBOXX option BOX_ERA. 

## **xcall SWPSBR, 128, srow, scol, erow, ecol, flags** 

Function 128 draws a box, with various options determined by the contents of the _flags_ parameter. The options are listed in the following table, and may be strung together using commas. For example, "T,C,B,O=2,I=3." 

|**Flags**|**Description**|
|---|---|
|B|Draw a border around the box. Equivalent toMSBOXX<br>option BOX_BDR.|
|C|Clear interior of box. Equivalent toMSBOXX<br>option BOX_ERA.|
|T|Seal up field attributes. Equivalent toMSBOXX<br>option BOX_FAO.|
|I=<text fg>|Sets the text (interior) foreground color. For example, I=1 would set it to white. Equivalent to the IBOX'FG parameter in<br>MSBOXX<br>.|



A-Shell Reference 

Page 3232 

|**Flags**|**Description**|
|---|---|
|O=<border<br>fg>|Sets the border (outside) foreground color. For example, O=2 would set it to color 2 (blue). Equivalent to the BRDR'FG<br>parameter inMSBOXX<br>.|



## **xcall SWPSBR, 129, screen, fspec$** 

Function 129 saves the current screen, VUEs the specified file, then restores the screen. As with the other functions involving the Screen parameter, Screen is ignored by A-Shell, which instead uses EZTYP to save the screen, display the file, and restore the screen on exit. 

## **History** 

- 2023 November, A Shell 7.0.1751.4:  Hot spots created with Tab(-1,162) are now saved and restored in ATE environments as well as pure Windows.  Note however that in the ATE environment, the application needs to send a Tab() command with an explicit termination following the Tab(-1,162) in order to get a clean save/restore. Tab(-1,254); (flush) is the simplest way to satisfy the requirement. 

A-Shell Reference 

Page 3233 

## **TCPX** 

## **xcall TCPX, opcode, status, buffer, sockport, flags {,timer, hostname}** 

## **xcall TCPX, opcode, status, buffer, sockidx, flags, timer, hostname, sockary(1)** 

TCPX provides an interface for applications to communicate with other processes via TCP sockets. It supports both client and server operations, and is theoretically compatible with just about any TCP socket-based client or service, whether implemented via A-Shell on the local machine, or some entirely different language and operating system on a remote machine across the Internet. 

For managing an array of sockets with the _sockary()_ parameter and the second syntax shown above, refer to the subtopic of that name below. 

_opcode_ (Num)  [in] 

indicates operation, per the TCPX Opcodes table. 

_status_ (F,6)  [in/out] 

Returns status of operation. <0 = -errno. >0 indicates number of bytes read or written. For other operations, 0 generally indicates success. See the Status table, which shows details by _opcode_ . 

_buffer_ (String, Raw, or array)  [in/out] 

Packet of data to read or write. Note that there is no hard coded limit on the packet size; however the OS may impose its own limits. 8K should work nicely in all environments. **Warning:** _buffer_ takes on special meaning with TCPOP_ACCEPT (non-TLS) and TCPOP_CONNECT (with TCPXFLG_TLS). In the TCPOP_ACCEPT case, if buffer is not "", then the first 32 bytes will be transmitted to the client automatically upon accepting the connection. This may be a convenience in some cases, but can cause all kinds of problems if the client is not expecting it. For the TCPOP_CONNECT case (with TCPXFLG_TLS set in the flags parameter), if not "", it is interpreted as a list of algorithm/authentication/security priorities to override the default. See the topic TLS/SSL for more details. 

A-Shell Reference 

Page 3234 

Also note that the TCPOP_ACCEPT call will send the first 32 bytes of _buffer_ (if not empty), unsolicited to the client. This can cause all kinds of confusion if the client is not expecting it, so in general you will want to make sure that _buffer_ = """ prior to accepting a connection. 

## _sockport_ (Num)  [in/out] 

On connect or accept ( _opcodes_ TCPOP_ACCEPT, TCPOP_CONNECT, TCPOP_CONNECT_OLD) must supply the port number to listen on or connect to; returns the connected socket number, which must be supplied to all other calls (except _opcode_ TCPOP_ERRMSG). See Advanced Server Connection Options for special case involving TCPXFLG_LISTEN. Also note that for some kinds of errors, TCPX may automatically close the socket, in which case it will return _sockport_ set to -1, eliminating the need for your application to explicitly close it. 

_flags_ (Num)  [in] 

Usage varies with _opcode_ as noted in the tables TCPX Flags1 and TCPX Flags2. 

## _timer_ (Num)  [in]  optional 

Number of milliseconds to wait before returning if operation cannot be completed. The value returned in _status_ after a time out depends on the _opcode_ . For _opcode_ TCPOP_CHECK, _status_ will return 0 on time out. For _opcode_ TCPOP_WRITE and TCPOP_READ, _status_ will return the number of bytes transferred before the timer expired. Under Windows only, _timer_ also affects _opcode_ TCPOP_ACCEPT (server wait for connection), causing it to return with _status_ set to a negative value if no connection was accepted before the timer expired. Under Unix, _timer_ has no affect on _opcode_ TCPOP_ACCEPT, which will wait until either a connection is accepted or the process is aborted by an external event. 

The _timer_ parameter works to set a limit on the amount of time waiting in the TCPOP_CONNECT operation. Although in theory, the TCPOP_CONNECT operation should succeed or fail without delay, in practice, DNS delays and some firewalls can cause the operation to hang for several seconds, particularly on failed attempts. In earlier versions of A-Shell, the _timer_ parameter had no effect on that. 

## _hostname_ (String)  [in] 

For TCPOP_CONNECT, must specify the host name or IPV4 address (###.###.###.###) of the host server to connect to. If specifying a name, do not include any protocol prefixes; just include the DNS name (e.g. myservice.mydomain.com, www.yourdomain.net, etc.). For TCPOP_ACCEPT, if specified, it will return the hostname or IP of the client. Ignored for all other opcodes. 

A-Shell Reference 

Page 3235 

Note that as a convenience for backwards compatibility with TCPCLI/TCPSRV, _hostname_ can be the fifth parameter (if six parameters are specified and the sixth is numeric), or the last parameter (if five, six, or seven parameters are specified). 

- Socket Programming for a more detailed discussion of sockets in general. 

- Sample programs TCPxxx in EXLIB:[908,25]. 

- Subtopics listed below. 

- On the A-Shell forum, search for "TCPX" and see the thread "AIX / TCPX issue: async connects." 

- TLS/SSL 

- If you get tired of waiting for an asynchronous connection to complete, you can cancel the connection attempt by using 

- TCPOP_CLOSE, just like you would for an established connection. 

- The interpretation of the STATUS value returned from TCPOP_CONNECT depends on whether it is a normal or asynchronous 

- (TCPXFLG_ASYNC) connection request. In the normal case, STATUS>=0 indicates success. In the asynchronous case, STATUS=0 means the connection is still pending, while STATUS=1 means success. If still pending, you need to use TCPOP_CHECK to determine the outcome. It will return STATUS=0 for still pending, STATUS=1 for success, or STATUS<0 for connection failed. 

• If TCPOP_CONNECT (with the TCPXFLG_ASYNC flag) returns with STATUS=1 and SOCKPORT > 0, then the socket SOCKPORT is open (or "half open"), even though the connection is still pending. So you would be responsible for closing it if you don't follow through with the TCPOP_CHECK procedure to check for the result. On the other hand, if you get STATUS<0 on the TCPOP_CHECK (with TCPXFLG_ASYNC) operation, the socket will be automatically closed. 

- If an asynchronous connection attempt returns the pending status, the socket will be in non-blocking mode, regardless of 

- whether you initially specified the TCPXFLG_BLOCK flag. To get it back into blocking mode once the connection is established, you need to specify TCPXFLG_BLOCK along with TCPXFLG_ASYNC on the TCPOP_CHECK call(s).+ 

A-Shell Reference 

Page 3236 

- As a convenience for backwards compatibility with TCPCLI on the TCPOP_CONNECT _opcode_ , _flags_ can be the sixth 

- parameter if the fifth parameter is a string— i.e. TCPX is called with the TCPCLI syntax: 

## **xcall TCPX, opcode, status, buffer, sockport, hostname, flags** 

## - 2017 April, A Shell 6.5.1618:  Add _sockary_ parameter, which see below. 

## **Subtopics** 

- Advanced Server Connection Options 

- Asynchronous Client Connections 

- Closing 

- TCPX Opcodes 

- TCPX Flags1 

- TCPX Flags2 

- Status (TCPX) 

- TCPCLI 

- TCPSRV 

- Sockary 

A-Shell Reference 

Page 3237 

## **ADVANCED SERVER CONNECTION OPTIONS** 

Normally the TCPOP_ACCEPT operation will open a listening socket on the port specified by _sockport_ , and then wait for a connection to be accepted. At that point, it closes the listening socket and returns the connection socket in _sockport_ to the caller. 

There are two shortcomings to this protocol. One is that while waiting for a connection to be accepted, the server application is suspended; if no client ever connects, the server would be suspended indefinitely, unless it was aborted by CTRL+C or some other signal. The other is that any attempt by a client to connect to the server while the server is servicing a connection will be rejected. To get around either or both of these shortcomings, you can use the _flags_ TCPXFLG_LISTEN, TCPXFLG_ASYNC, and TCPXFLG_KEEPLISTEN in conjunction with the TCPOP_ACCEPT operation. 

If the TCPXFLG_LISTEN flag is specified, then the TCPOP_ACCEPT operation returns immediately, with _sockport_ set to the listening socket rather than the connection socket. The application should then save this returned _sockport_ value in a separate variable, perhaps called LISTENSOCK, as it may be needed later after _sockport_ has been again updated. 

Since opening the listening socket is fast (does not require waiting for a client to make a connection request), this eliminates the possibility of the server getting stuck for an indefinite time waiting for a client connection. It can subsequently use the TCPOP_CHECK operation to check if a connection is ready, although it should do so frequently, since the clients do not like to wait very long. Once a connection is ready to accept, or if you decide you do not mind waiting, you can use the TCPOP_ACCEPT _opcode_ again, this time with TCPXFLG_ASYNC (and optionally, TCPXFLG_KEEPLISTEN) to accept a connection on the listening socket specified in _sockport_ . The accepted connection socket is returned in _sockport_ . This would overwrite the saved listening socket number, so if you plan to accept further connections on this same listening socket, you must save the listening socket in another variable. 

If the server wants to "stay open for business" while processing the current connection, it should use the TCPXFLG_KEEPLISTEN flag so that the listening socket previously opened—and hopefully saved in a separate variable, i.e. LISTENSOCK—can be left open and reused for the next connection. 

As long as the listening socket is left open, any connection requests will queue up, either until the queue fills, or the client gets tired of waiting and cancels the request. The length of the queue is 64, which should be more than adequate for most situations. 

Note that if you use TCPXFLG_LISTEN, and then do not accept a connection or accept one with the TCPXFLG_KEEPLISTEN flag set, the listening socket remains open, and must be manually closed (in addition to any connection socket) when your program ends. Use the normal TCPOP_CLOSE operation and specify the listening socket, which you hopefully saved in a variable separate from _sockport_ .) 

A-Shell Reference 

Page 3238 

## **ASYNCHRONOUS CLIENT CONNECTIONS** 

Attempts to establish client connections (TCPOP_CONNECT) are generally quick to succeed or fail, unlike listening for connections from the server side, which might involve an indefinite wait. Still, in some cases such as slow DNS servers, sneaky firewalls, many hops, routing problems, etc., it can take several seconds to determine whether the connection can be made, during which your application is effectively hung. You can put a limit on the wait by specifying a _timer_ value, but that only gives you the ability to abort the connection if the attempt takes too long. If you're willing to allow the connection attempt to take several seconds, but don't want to be stuck while waiting, you can make an asynchronous client connection request, with the following procedure. (This capability added in edit 996.3). 

Start by calling TCPX with the TCPOP_CONNECT _opcode_ , but also specify the TCPXFLG_ASYNC option in _flags_ . TCPXFLG_BLOCK is optional. You can set _timer_ > 0 if you're willing to wait a short time to allow a successful connection to be fully established, but don't want to abort the connection if it takes longer than the limit. Otherwise, with _timer_ = 0, the call will always return immediately. The only point of setting _timer_ to, say 1 second, would be to possibly eliminate the need for the following TCPOP_CHECK calls if the connection succeeds quickly. 

If the connection succeeds immediately, or within the limit set by _timer_ , it will return _status_ = 1, and the connected socket in _sockport_ . This case is identical to the normal, synchronous, connection, except that the return _status_ is 1 instead of 0, and from this point forward, it can be handled just like a normal connected socket. 

Similarly, if the connection fails immediately or within the limit set by _timer_ , it will return _status_ < 0. 

Otherwise, it will return status = 0 (indicating "pending") and yet it will return the open (or "half open") socket in _sockport_ . In this case, you are free to do other things while waiting for the connection attempt to finally succeed or fail. To check on the progress of the operation, you must use TCPOP_CHECK with the half open _sockport_ , also specifying TCPXFLG_ASYNC, and optionally, TCPXFLG_BLOCK. This will return _status_ =0 to indicate that the connection attempt is still pending, 1 to indicate a successful completed connection, or <0 to indicate a failed connection, in which case the socket will be closed for you. If and when the connection succeeds, you can the treat it like a normal client socket. 

## Notes: 

• If you want a blocking connection, you need to specify TCPXFLG_BLOCK both in the TCPOP_CONNECT call and in the TCPOP_CHECK call(s), since the blocking status cannot be set until after the connection is finally complete. 

A-Shell Reference 

Page 3239 

• If you get tired of waiting for the connection to complete, you can call TCPOP_CLOSE at any time to terminate it. This might be useful, for example, if you were to display a dialog box saying "Attempting connection…" which gave the user a CANCEL button option. 

• You can do other work while waiting for a connection to succeed or fail by specifying the TCPXFLG_ASYNC flag with the TCPOP_CONNECT operation. In that case, if the connection cannot be established within the time limit specified by TIMER (or immediately, if TIMER=0), then the subroutine returns with STATUS=0 and SOCKPORT (>0) set to the socket whose connection attempt is still in progress. (You can consider this socket "half opened", meaning it is open on your end, but the other end still hasn't responded.) You must then use TCPOP_CHECK (continuing to specify the TCPXFLG_ASYNC flag and the half-opened socket in SOCKPORT) to check whether the connection attempt is complete. STATUS=1 indicates success, STATUS<0 indicates an error, STATUS=0 indicates that the connection attempt is still pending. 

A-Shell Reference 

Page 3240 

## **CLOSING** 

The TCPOP_CLOSE operation used to (in TCPCLI/TCPSRV) issue both a bi-directional shutdown and a close. In TCPX, it only closes the socket. The distinction between close and shutdown is as follows: 

• Shutdown sends a signal to the remote end indicating that the sender is shutting down its end of the socket. Since sockets are full duplex, it is possible to shutdown just the sending side, or the receiving side or both. Two new flags, TCPXFLG_SHUTRD and TCPXFLG_SHUTWR have been added to allow the application to take advantage of this capability. If both, or neither, are specified, the socket is shut down in both directions. Shutdown does not substitute for close though, and therefore should be followed (eventually) by a normal close. 

• Close will generally have the same effect as a shutdown in both directions, except in the case where a socket is being shared by a parent and child process. The parent may have accepted the connection, then used XCALL SUBMIT to fork a child, which inherits the connection. Normally the parent would then close its connection socket. In the case, the close will not have any effect on the other end, since the child still has the socket open. Shutdown, on the other hand, would cause the other end to get an error if tried to read or write to the socket. When the child closes the socket, since it is the last one at its end to have it open, it will really be closed. 

If the remote side attempts to read from the socket (or is in a blocking read) when the local socket is closed, it will return an error, although the precise error number may vary between operating systems and how the remote side performed the close/shutdown. 

A-Shell Reference 

Page 3241 

## **TCPX OPCODES** 

This table contains a brief explanation of the operation of each opcode. Note that in nearly all cases, you will need to check the return value of the Status parameter to determine the outcome of the operation. 

|**Symbol**|**Value**|**Operation**|
|---|---|---|
|TCPOP_ACCEPT|1|Create listening socket on port specified by_sockport_, and wait for a client to connect. Be<br>careful to make sure that the_buffer_parameter is empty, or else the first 32 bytes of it<br>will be sent, unsolicited, to the client immediately after accepting the connection, which<br>is likely to cause confusion unless the client was specifically expecting it.) On successful<br>return,_sockport_is set to the connected socket, and must be specified to all the other<br>calls for this socket.|
|TCPOP_WRITE|2|Write_buffer_to socket.|
|TCPOP_READ|4|Read_buffer_from socket.|
|TCPOP_SHUTDOWN|5|Informs the other end that we are shutting down prior to the close. This is mainly useful<br>when shutting down only one direction. See_flags_.|
|TCPOP_CLOSE|6|Close socket. You must do this explicitly when done, since BASIC will not close sockets<br>for you at the end of the program, like it does for files. Note thatTCPXwill automatically<br>close the socket after certain errors, in which case it will set_sockport_to -1. In other<br>words, if_sockport_= -1, don't bother to close it; doing so redundantly is harmless but<br>will return you the error_status_= -1.|
|TCPOP_CHECK|7|Check if data available to read; returns_status_=1 if so, 0 if not, and <0 if the socket has<br>been closed at the other end. Also used withAsynchronous Client Connections<br>and|



A-Shell Reference 

Page 3242 

|ell Reference|||
|---|---|---|
|||Advanced Server Connection Options<br> to check if the connection is complete or ready to<br>accept.|
|TCPOP_CHKQTY|8|Check how much data avail to read; return number of bytes in_status_, <0 indicates<br>socket closed or dropped at other end.|
|TCPOP_CONNECT|9|(client) Connect to generic server. If_timer_> 0 and the connection is not established<br>within the specified time, the connection is aborted. SeeAsynchronous Client<br>Connections<br>.|
|TCPOP_CONNECT_OLD|10|(client) Equivalent to old TCPCLI_opcode_1; now considered archaic|
|TCPOP_ERRMSG|11|Return system error message corresponding to_status_.|
|TCPOP_STARTTLS|12|TCPXopcode to initiateSTARTTLS<br>.|
|TCPOP_WRITE_UD`P`|18|UDP version of WRITE.|
|TCPOP_READ_UDP|20|UDP version of READ.|



A-Shell Reference 

Page 3243 

## **TCPX FLAGS1** 

## This first table describes the defined _flags_ bits along with the _opcodes_ that they go with: 

|**Symbol**|**Value**|**Opcode**|**Meaning**|
|---|---|---|---|
|TCPXFLG_BLOCK|&h00000001|TCPOP_ACCEPT,<br>TCPOP_CONNECT|Establish connection being accepted as blocking.|
|TCPXFLG_LISTEN|&h00000004|TCPOP_ACCEPT|CausesTCPXto return with the listening socket in<br>_sockport_instead of the connection socket, without<br>waiting to accept a connection.|
|TCPXFLG_ASYNC|&h00000008|TCPOP_ACCEPT|Accept connection on previously opened listening<br>socket._sockport_must be the listening socket.|
|TCPXFLG_ASYNC|&h00000008|TCPOP_CONNECT|Attempt to connect asynchronously. SeeAsynchronous<br>Client Connections<br>.|
|TCPXFLG_KEEPLISTEN|&h00000010|TCPOP_ACCEPT|Combined with TCPXFLG_ASYNC to keep the listening<br>socket open after accepting the connection.|
|TCPXFLG_SHUTRD|&h00000020|TCPOP_SHUTDOWN|Shut receiving side only.|
|TCPXFLG_SHUTWR|&h00000040|TCPOP_SHUTDOWN|Shut sending side only.|
|TCPXFLG_NODELAY|&h00000080|TCPOP_ACCEPT,|Disable the Nagle delay.|



A-Shell Reference 

Page 3244 

|**Symbol**|**Value**|**Opcode**|**Meaning**|
|---|---|---|---|
|||TCPOP_CONNECT||
|TCPXFLG_LINGER|&h00000100|TCPOP_ACCEPT,<br>TCPOP_CONNECT|Set the standard TCP option SO_LINGER to "on". See<br>Setting The SO_LINGER Option<br>.|
|TCXPXFLG_TLS|&h00100000||Support forTLS/SSL<br>.|
|TCPXFLG_STARTTLS|&h00200000|TCPOP_CONNECT|Support forSTARTTLS<br>.|
|TCPXFLG_UDP|&h00400000||UDP mode (with TCPOP_ACCEPT, TCPOP_READ)|



- Hex Decimal Values 

A-Shell Reference 

Page 3245 

## **SETTING THE SO_LINGER OPTION** 

You may set the SO_LINGER socket option to "on" by passing the flag TCPXFLG_LINGER and then putting the desired linger time (in seconds) into the 4th (high byte of B,4) byte of FLAGS during a TCPOP_CONNECT or TCPOP_ACCEPT call. For example: 

```
TCPOP = TCPOP_CONNECT               ! (or TCPOP_ACCEPT)
```

```
FLAGS = FLAGS or TCPXFLG_LINGER    ! activate SO_LINGER option
```

```
FLAGS = FLAGS + (5 * (2 ** 24))     ! set timer to 5 seconds
```

The SO_LINGER option affects the behavior of the TCPOP_CLOSE operation, relative to data that has been sent but may not yet have been delivered. There are three possibilities: 

By default, the SO_LINGER option is turned off, which means that the close operation returns immediately, but if there is any data still remaining in the socket send buffer, the system will try to deliver it to the remote end. 

If SO_LINGER is turned on, and the timer value is 0, then the connection will be aborted when TCPOP_CLOSE is called. Any data still remaining in the socket send buffer will be discarded, and a reset packet (RST) will be sent to the remote end, rather than the normal termination sequence. 

If SO_LINGER is turned on, and the timer value is non-zero, then the kernel will "linger" when the socket is closed either all of the data in the send buffer has been sent and acknowledged by the remote end, or the timer expires. If the socket is blocking, TCPOP_CLOSE will not return until one of those conditions is met. (If non-blocking, it will return, possibly with STATUS set to EWOULDBLOCK, but the kernel will still linger as just described.) 

Note that the SO_LINGER timer should not be confused with the TCPX TIMER parameter, which relates to the time until the connection is made or accepted. 

A-Shell Reference 

Page 3246 

## **TLS/SSL** 

_Updated October 2017_ 

Encrypted sockets using TLS/SSL protocol can be enabled with the TCPXFLG_TLS flag, subject to the following notes and caveats: 

- You must pass the TCPXFLG_TLS flag with every call to TCPX. This will probably necessitate that the flags parameter be mapped 

- as B,4. Note that the flag is above the range normally used for the transfer size for TCPOP_READ and TCPOP_WRITE (where flags may be used to specify the number of bytes to transfer). 

- The multitude of variations and parameters relating to secure connections (ciphers, protocols, certificate types, algorithms, 

- etc.) are currently all defaulted to a "standard set". You can override the default by specifying a valid list of GnuTLS "priorities" in the buffer parameter. Search the Internet for "gnutls_priority_init" for the latest documentation on this rather cryptic string. 

- Passing the TCPXFLG_TLS option to TCPX will cause the LIBASHTLS library modules to be dynamically loaded. For Windows, this 

- consists of the libashtls.dll module along with several other DLLs from GnuTLS package. As a convenience we may package the GnuTLS-related DLLs in a zip, available from our download site in the other/gnutls directory. For Linux, the library consists of libashtls.so.x.x.x which must be linked to libashtls.so.1, plus any libraries required by GnuTLS, which must be installed separated; see gnutls.org for details.) 

- See the sample program SOAP1.BP for an example of using the TLS feature to submit a SOAP request to a secure web server. 

- See the sample programs SOAP1.BP and GNUGET.BP in EXLIB:[908,025], as well as the function FNHTTPGET.BSI in SOSLIB: 

- [907,10] for examples. 

- As of A-Shell 6.5.1618, only client mode is supported. 

A-Shell Reference 

Page 3247 

## **STARTTLS** 

The STARTTLS protocol is supported via a an opcode and flag (in ashell.def). 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|TCPOP_STARTTLS|12|TCPXopcode to initiate STARTTLS|
|TCPXFLG_STARTTLS|&h00200000|Use with TCPOP_CONNECT|



Limitations: As with TLS connections (introduced in 1179.0), currently only client connections (TCPOP_CONNECT) are supported. Also, the TIMER option seems to interfere with the TLS handshaking. If having problems, turn that off and just use blocking mode, in conjunction with TCPOP_CHECK to check for data. 

To initiate a STARTTLS connection, use the TCPOP_CONNECT opcode, along with the TCPXFLG_TLS and TCPXFLG_STARTTLS flags to initiate the unencrypted connection. When you want to start the TLS negotiation, use whatever unencrypted means are required to inform the server that you are about to start negotiating TLS, and then call TCPX with opcode TCPOP_STARTTLS. After the successful return (STATUS=0), you will be in encrypted mode, and the TCPXFLG_STARTTLS flag will no longer be needed. (However, as mentioned in the 1179 notes, TCPXFLG_TLS is required with EVERY call to TCPX if you are using TLS or STARTTLS protocol, including those calls prior to using TCPOP_STARTTLS.) 

Note: EMAILX 5.1(121) uses this new feature to support the STARTTLS protocol extension to SMTP, permitting, for example, the use of the GMAIL SMTP server. 

Unix installation requirements: 

- Standard installation of the GnuTLS package, preferably version 2.8.6 (from www.gnu.org). 

- Copy the latest libashtls.so.1.0.xxx (xxx currently at 204) into the $MIAME/bin directory (where the ashell executable is). 

- Create /usr/lib/libashtls.so.1 as a symbolic link to the libashtls library in the $MIAME/bin directory, e.g.: 

A-Shell Reference 

Page 3248 

- `# ln -s $MIAME/bin/libashtls.so.1.0.204 /usr/lib/libashtls.so.1` 

## Windows installation requirements: 

- Download http://www.microsabio.net/dist/other/gnutls/gnutls-2.8.6.zip and unzip the contents into the bin directory (where 

- ashw32.exe is located). 

- Download http://www.microsabio.net/dist/51dev/bin-win/libashtls-204.zip and unzip the contents (libashtls.zip) into that 

- same bin directory. 

Debugging notes: Use the "SOCKS" trace option (SET TRACE SOCKS ON) to record many details about the operation of the TLS library. For even more detail (particularparticularly about the handshaking process), also set the XDEBUG trace option. 

A-Shell Reference 

Page 3249 

## **TCPX FLAGS2** 

This table lists all of the _opcodes_ and describes the interpretation of the _flags_ parameter for each. Note that in several cases, such as with the read, write and check operations, the value of _flags_ relates to a number of data bytes, rather than to bit values as in the Flags1 table.. 

|**Opcode**|**Interpretation of**_Flags_**Parameter**|
|---|---|
|TCPOP_ACCEPT|TCPXFLG_BLOCK sets blocking mode, which means that read and write calls wait until they can<br>be completed or the timer expires; in non-blocking mode, if_timer_=0 and the read/write<br>operation cannot be immediately completed, an error status is returned.|
|TCPOP_WRITE|Specifies the number of bytes to write. Must be less than or equal to the size of_buffer_, unless<br>_buffer_is subscripted, in which case we just trust the_flags_value. If_flags_=0 (or not specified),<br>writes the entire_buffer_block. If_flags_non-zero, the specified number of bytes are written. In<br>order to minimize partial packet writes, we set the send buffer low water mark to match the<br>number of bytes to write, so that we do not start the operation unless the socket buffer has<br>sufficient space. If_timer_> 0, it waits until the timer expires or the packet is fully written. If<br>_timer_= 0 and the connection is non-blocking, it returns an error ("EWOULDBLOCK") if the<br>packet cannot be written immediately. Otherwise it waits indefinitely, for the packet to be<br>entirely written or the socket is closed at the other end. This is one case where you might have a<br>problem if you use a packet size larger than the OS supports.|
|TCPOP_READ|Specifies the number of bytes to read. 0 means read whatever is available, from 1 byte to size of<br>buffer. Otherwise, if timer > 0, routine will wait until the required number of bytes is read up to<br>the time limit. If timer = 0 and flags > 0, for non-blocking connections, the flags value is only an<br>upper limit; the routine will return as soon as the interface indicates there is data available even<br>if not the requested number of bytes. For blocking connections, with timer = 0 and flags > 0, the<br>subroutine will wait until the # of bytes is received, or the socket is closed at the other end.<br>If both flags = 0 and timer = 0, for blocking connections it should wait until any data or an error<br>condition is available. For non-blocking connections, the behavior may be platform dependent.|



A-Shell Reference 

Page 3250 

|**Opcode**|**Interpretation of**_Flags_**Parameter**|
|---|---|
||Under Unix and Windows, it should return immediately, either with data or with Unix error -11<br>(resource temporarily unavailable) or Windows error -10035 (a non-blocking socket operation<br>could not be completed immediately). Under some versions of AIX, it has been reported to act<br>the same as for a blocking connection—i.e. waiting until data or some other error is available. If<br>this is a critical concern for your application, you should test it under the platform you will be<br>using. See the test programTCPTST in EXLIB:[908,25]<br> to simplify your testing.|
|TCPOP_SHUTDOWN|0 indicates a shutdown in both directions. Otherwise, you can shut down just one direction by<br>specifying either TCPXFLG_SHUTRD (32) or TXPXFLG_SHUTWR (64).|
|TCPOP_CLOSE|_flags_not used.|
|TCPOP_CHECK|If_timer_specified,_flags_is ignored and_timer_is used. If_timer_not specified,_flags_specifies how<br>long to wait before returning_status_0 if no data avail. If_flags_is F,6 then it is interpreted as<br>fractional seconds; otherwise it is interpreted as milliseconds. (You should specify_timer_in all<br>new programs; the option to exclude it is only supported for backward compatibility with TCPCLI<br>and TCPSRV, and is deprecated.) SeeAsynchronous Client Connections<br>for special considerations<br>involving_flags_and TCPOP_CHECK.|
|TCPOP_CHKQTY|_flags_not used.|
|TCPOP_CONNECT|TCPXFLG_BLOCK sets blocking connection (see TCPOP_ACCEPT)<br>TCPXFLG_ASYNC sets asynchronous mode (seeAsynchronous Client Connections<br>).|
|TCPOP_CONNECT_OLD|TCPXFLG_BLOCK sets blocking connection (see TCPOP_ACCEPT)|



A-Shell Reference 

Page 3251 

|**Opcode**|**Interpretation of**_Flags_**Parameter**|
|---|---|
|TCPOP_ERRMSG|_flags_not used.|
|TCPOP_STARTTLS|STARTTLS (engage TLS mode)|
|TCPOP_WRITE_UDP|UDP version of WRITE|
|TCPOP_READ_UDP|UDP version of READ|



A-Shell Reference 

Page 3252 

## **STATUS (TCPX)** 

This table lists details relating to the interpretation of the _status_ parameter, based on the _opcode_ . 

|**Symbol**|**Interpretation of Status Returned**|
|---|---|
|TCPOP_ACCEPT|_Status_>= 0 indicates success. Any value > 0 implies that you had data in the_buffer_parameter,<br>which was sent unsolicited to the client - up to 32 bytes. That is an unusual protocol though, and<br>likely to confuse the client.|
|TCPOP_WRITE|_Status_returns the number of bytes written. <0 indicates an error. Note that for non-blocking<br>connections, a special error value (EWOULDBLOCK, which is -10035 for Windows and typically -11<br>for Unix) is returned if the socket cannot accept the data immediately. All other errors would<br>suggest a permanent problem requiring the socket to be closed.|
|TCPOP_READ|_Status_returns the number of bytes read. <0 indicates an error. See note above for TCPOP_WRITE<br>about the special EWOULDBLOCK error.|
|TCPOP_SHUTDOWN|Returns 0 for success, <0 for error.|
|TCPOP_CLOSE|Returns 0 for success, <0 for error.|
|TCPOP_CHECK|Returns 0 to indicate that the socket is not ready—that is, there is no data to read, or, in the case<br>ofAsynchronous Client Connections<br>, the socket is not yet connected. <0 indicates an error;<br>probably the socket has been closed at the other end, or the asynchronous connection attempt<br>failed. 1 indicates that the socket has data to read, or the asynchronous connection has<br>successfully completed.|
|TCPOP_CHKQTY|Returns the number of bytes available to read, or <0 for an error.|



A-Shell Reference 

Page 3253 

|ell Reference||
|---|---|
|||
|TCPOP_CONNECT|Returns 0 for a successful normal connection, else <0 for error. In the case ofAsynchronous Client<br>Connections<br>, 0 indicates that the connection attempt is in progress, while 1 indicates that it<br>connected successfully.|
|TCPOP_ERRMSG|_Status_should be set to the error code (probably returned from the previous operation) in order to<br>get the error description. This is the one case where_status_is used for input to the subroutine<br>rather than output from it.|



A-Shell Reference 

Page 3254 

## **TCPCLI** 

This subroutine has been superseded by TCPX; it is supported and documented for historical reasons only. Unless you are running an ancient (and no longer supported) version of A-Shell, you should be using TCPX. 

## **xcall TCPCLI, code, status, buffer, sockport, hostname {,flags}** 

TCPCLI provides a way for a client process to communicate with a server process over TCP/IP sockets. It is specifically designed to interface easily with another A-Shell server process which is running TCPSRV, but it is flexible enough to be used with a wide variety of server processes. 

## **Parameters** 

_code_ (Num)  [in] 

## Specifies operation, from choices below: 

|**Value **|**Description**|
|---|---|
|1|Connect to TCPSRV server (same as 9 but waits for a response)|
|2|Write contents of BUFFER to socket.|
|4|Read data from socket into BUFFER|
|6|Close socket|
|7|Check if socket has data to be read (returns STATUS=1 if so)|
|8|(Unix only) Same as 7 but returns STATUS= number of bytes available to read|



A-Shell Reference 

Page 3255 

|**Value **|**Description**|
|---|---|
|||
|9|Connect to server; same as 1 but does not wait for a response (works for any server,<br>including TCPSRV)|



## _status_ 

Return status. <0 for errors (-errno), >0 indicates number of characters written or read. 

_buffer_ (String or BLOB) 

Read/write buffer (maximum 4096 bytes) 

_sockport_ (F,6) 

For connect, caller must supply port number to connect to. On return, this will contain the connected socket number, which must then be passed to all the other calls for this session. If the connect operation returns <0, this indicates an error (with the number indicating which of the several internal steps failed). 

## _hostname_ 

On connect, must contain the host name or IP address of the server. 

_flags_ (F,6)  optional 

On the connect calls (1 & 9), set to 1 for a blocking connection, or 0 for a non-blocking connection. (Default is blocking.) On the check operation, set to number of seconds to wait before returning if no bytes are available. (Fractional seconds are ok; default is 0 if parameter not specified.) On the read call specifies (if non-zero) the maximum number of bytes to read (default is the size of BUFFER). On the write call, specifies (if non-zero) the number of bytes to write. 

A-Shell Reference 

Page 3256 

## **Comments** 

Sockets are not automatically closed when a BASIC program terminates, so it is important that you add a socket close command to your error trap. Otherwise you may not be able to reconnect to the socket. 

You can translate the system error codes returned as negative numbers in the STATUS parameter by using `XCALL MIAMEX,` MX_ERRNOMSG `,` ABS `(STATUS), MESSAGE$` 

The client connect calls will fail if the server is not already waiting for a connection. (In contrast, the server side the corresponding "accept connection" (Code 1) call using TCPSRV, will wait indefinitely for a client to make a connection.) 

The number of bytes to read or write (as specified by FLAGS) will be trimmed to the smaller of the size of BUFFER and 4096 bytes. The one exception is that if the BUFFER variable is subscripted, then FLAGS may be as large as 4096. (This overcomes the obstacle when using an array caused by the fact that the subroutine calling mechanism reports the size of just one element, rather than the size of the entire array.) 

Opcode 9 is recommended in place of Opcode 1, even when you know the server is running TCPSRV. The only difference is that Opcode 1 does an automatic read after connecting. It is more standard and flexible to issue a separate read to retrieve the server’s ACK message (if any). 

A-Shell Reference 

Page 3257 

## **TCPSRV** 

This subroutine has been superseded by TCPX; it is supported and documented for historical reasons only. Unless you are running an ancient (and no longer supported) version of A-Shell, you should be using TCPX. 

## **xcall TCPSRV, code, status, buffer, sockport {,flags}** 

TCPSRV provides a way to create server processes that support client requests via a socket interface. Similar to TCPCLI, and in fact designed specifically to integrate easily with it, TCPSRV is nevertheless flexible enough that it can be used to communicate with a wide variety of client processes over TCP/IP sockets. For example, you could use it to create a server that responded to web queries submitted from a CGI process. 

## **Parameters** 

## _code_ (Num)  [in] 

## Specifies operation, from choices below: 

|**Valu**<br>**e**|**Description**|
|---|---|
|1|Create listening socket on port specified by SOCKPORT, and wait for a client to connect. If BUFFER<br>parameter is non-null, then after the connection is accepted, the first 32 bytes of the BUFFERDATA<br>parameter will be sent to the client as an acknowledgment message. On successful return, SOCKPORT is<br>set to the connected socket, which must be specified to all the other calls for this socket.|
|2|Write contents of BUFFER to socket.|
|4|Read data from socket into BUFFER|



A-Shell Reference 

Page 3258 

|**Valu**<br>**e**|**Description**|
|---|---|
|5||
|6|Close socket|
|7|Check if socket has data to be read (returns FLAGS=1 if so)|
|8|(Unix only) Like CODE 7 except returns the number of bytes available to read.|



_status_ (F,6) 

Return status. <0 for errors (-errno), >0 indicates number of characters written or read. 

_buffer_ (String or BLOB) 

Read/write buffer (maximum 4096 bytes) 

_sockport_ (String or BLOB) 

For connect, caller must supply port number to connect to. On return, this will contain the connected socket number, which must then be passed to all the other calls for this session. If the connect operation returns <0, this indicates an error (with the number indicating which of the several internal steps failed). 

_flags_ (F,6)  optional 

On the connect operation, may contain 1 for a blocking connection, or 0 for a non-blocking connection. (Default is blocking.) On the check operation, contains the number of seconds to wait before returning if no characters are available. (Fractional seconds are ok; default is 0 if parameter not specified.) For the write operation, it specifies the number of characters to write. (Default is 

A-Shell Reference 

Page 3259 

size of the BUFFER parameter if FLAGS not specified.) For the read operation, if non-zero, specifies the maximum number of bytes to read. 

## **Comments** 

Note that only one server process can wait for connections on a particular port number for a single machine. So it is important that the server do its job and close the socket quickly if there is a possibility of multiple clients making frequent requests. Typically, this kind of single-threaded server works best for quick and simple lookup operations, such as price lookups or inventory status checks. 

See the sample program TCPTST.BP in EXLIB:[908,25] for a working example. 

A-Shell Reference 

Page 3260 

## **SOCKARY** 

_Added November 2017_ 

## **xcall TCPX, opcode, status, buffer, sockidx, flags, timer, hostname, sockary(1)** 

The optional parameter _sockary_ is used to manage an array of sockets. When it is used, argument 4 (normally _sockport_ ) is now interpreted as the index into the sockary, rather than the socket itself. As in the normal case, the TCPOP_ACCEPT calls expects the 4th argument to be the port to listen on. 

The sockary() parameter should be an array of up to 1025 ST_SOCKARY structures, defined by fntcpxary.bsi in SOSLIB[907,10] as: 

```
defstruct ST_SOCKARY
```

```
    map2 socket,b,3    ! socket value
    map2 ready,b,1     ! TCPOP_CHECK sets this to 255 if ready
endstruct
```

The last element of this array must be zero; this is how TCPX identifies the end of the array. In most cases an application would have no need to access this array directly. If you do want to access it directly, you should. Instead, use the utility functions in use the utility functions in fntcpxary.bsi in SOSLIB[907,10] to provide isolation from possible changes in the structure. 

The main advantage of using the sockary method is that it by setting the _sockidx_ parameter to 0, TCPX will perform certain operations (mainly TCPOP_CHECK and TCPOP_CLOSE) on the entire set of open sockets in the array, rather than just one socket at a time. 

For TCPOP_CHECK, if _sockidx_ is zero, TCPX will wait on all of open sockets until one of them is ready to read from, subject to the time limit set by the _timer_ parameter. If there is a socket ready, it will return _sockidx_ set to the index into the array for that socket, so that a subsequent TCPOP_READ will read from that socket. If multiple sockets are ready to read from, TCPX will use a round-robin scheme so as to not unduly favor those sockets near the start of the array. It will also return the _status_ parameter set to the number of sockets that are ready, allowing the application (optionally) to read from them all by scanning _sockary()_ for 

A-Shell Reference 

Page 3261 

those with the ready flag set. This may or may not be preferable to just calling TCPOP_CHECK again and relying on it to return the _sockidx_ of the next ready socket. 

For TCPOP_CLOSE, if _sockidx_ is zero, TCPX will close all of the open sockets, and return _status_ set to the number that were closed. 

For TCPOP_READ, if _sockidx_ is zero, it will read from whichever socket is available, although this is probably not useful except in very particular cases. 

A-Shell Reference 

Page 3262 

## **TIMES** 

_Reviewed June 2020_ 

## **xcall TIMES, opcode, elapsed** 

TIMES returns high-precision time information. 

## **Parameters** 

_opcode_ (Num)  [in] 

determines operation; see table 

_elapsed_ (Num)  [out] 

returns the elapsed time in the units and according to the logic described in the following table 

|**Valu**<br>**e**|**Units**|**Description**|
|---|---|---|
|1|secs|Returns the number of seconds since midnight. This is equivalent to the system variable TIME,<br>except that if the_elapsed_parameter is a floating point variable, then the returned value may<br>return fractional seconds.|
|2|msecs|Returns the number of milliseconds since midnight. As with_opcode_1, if_elapsed_is a floating point<br>variable, a fractional number of milliseconds may be returned.|
|3|usecs|Returns the number of microseconds elapsed since the previous_opcode_3. Note that this is only<br>practical for timing operations lasting only seconds or perhaps minutes, but not hours or days. The<br>first time this routine is called, the return value will be essentially random garbage.|



A-Shell Reference 

Page 3263 

|**Valu**<br>**e**|**Units**|**Description**|
|---|---|---|
|4|secs|Returns seconds since "the epoch". Needed to support 2FA / TOTP.|



## **See Also** 

- FNTOTP.BSI in SOSLIB:[907,10] for an example of 2FA / TOTP authentication. 

A-Shell Reference 

Page 3264 

## **TINKEY** 

_Reviewed June 2020_ 

## **xcall TINKEY, char** 

TINKEY allows you to input a keyboard character if one is available, without waiting if one is not available. 

## **Parameters** 

_char_ (String or B,1)  [in] 

The input character—or a null byte if no input available—will be placed into the first byte of this parameter with no conversions or termination. A dynamic string (S,0) may also be used, although it doesn't make much sense. 

## **Comments** 

If the session has received the hangup signal and is running in background pending an input operation to terminate, by default, XCALL TINKEY will not be counted as an input operation. If you want it to be counted as an input operation, and thus terminate the session, specify  Hangup Error on Tcki when launching A-Shell. 

## **See Also** 

- ACCEPT, ACCEPNXS 

- GETXS  (keyboard or file input) 

- GETKEYXS 

- GETXXS 

A-Shell Reference 

Page 3265 

## **TMENU, TMEN2** 

_Added June 2020_ 

## **xcall TMENU, title, select** 

## **xcall TMEN2, title, select** 

TMENU and TMEN2 display a standard menu of transaction operations as shown below. The text for the numbered elements is taken from SYS:SBRMSG.lan 007,001 thru 007,007 which can be adjusted for different languages or otherwise changed to your liking. This routine was part of the original AlphaACCOUNTING subroutine set. 

## **Parameters** 

_title_ (String)  [in] 

screen title to display in the upper left corner. 

_select_ (Num)  [out] 

returns the numerical option selected, or zero if ESCAPE or BACK-ARROW is entered. 

## **Example** 

The output of TMENU is as shown below. The output of TMEN2 is identical but includes only the first four items. 

TMENU TITLE PLEASE SELECT APPLICATION  _ 1. ENTER (ADD) NEW TRX 

A-Shell Reference 

Page 3266 

2. CHANGE EXISTING TRX 

3. DELETE EXISTING TRX 

4. PRINT TRX EDIT LIST 

5. POST TRX TO MAIN FILE 

6. CREATE BACKUP WORK FILE 

7. RESTORE BACKUP WORK FILE 

A-Shell Reference 

Page 3267 

## **TRIM** 

_Reviewed June 2020_ 

## **xcall TRIM, strvar {,flag}** 

TRIM removes leading spaces, trailing spaces and tabs from the specified string. In addition, it can optionally remove other control characters. 

## **Parameters** 

## _strvar_ (String)  [in/out] 

is the string variable from which you want to trim the leading spaces, trailing spaces, or tabs. It does not need a trailing null byte. 

## _flag_ (Num)  [in] 

may be specified as any non-zero value to cause TRIM to treat any characters with ASCII values less than 32 (space) the same as space—i.e. remove them. Like spaces, they must still be prior to the first printable character or after the last one, and prior to the first null, to be removed. Any spaces or other control characters that are embedded between printable characters are left alone. 

## **See Also** 

- The EDIT$() function which supports the ability to remove certain types of characters within (rather than just at the beginning 

- or end of) the string. 

- The SBR=TRIMCTL setting in the system parameters file, which forces TRIM to act as if a nonzero flag value had been passed. 

- XSTRIP, which provides more sophisticated removal of specific characters from string. 

- String function TRIM(a$) 

A-Shell Reference 

Page 3268 

## **TRMCHR** 

## **xcall TRMCHR, status, trmchr'map** 

TRMCHR provides a means to determine various characteristics of the terminal running your program. The current number of rows and columns, foreground and background colors, and other information is available. The A-Shell implementation is a compatible super-set of the AMOS version. 

## **Parameters** 

_status_ (F)  [out] 

Returns 0 for success. (Actually it does nothing under A-Shell, since there is no way for it to fail.) 

## _trmchr'map_ 

A structure which must be mapped as specified. Typically you would access the standard copy via ++ `include ashinc:trmchr.map` ). All fields are output only, except for TRMCHR'WINROW. See the following topic TRMCHR'MAP for full details. 

## **Comments** 

Under A-Shell/Windows GUI mode, if there is a standard modal dialog box open at the time of the subroutine TRMCHR, WINROW and WINCOL will be set to the usable number of rows and columns in the dialog box. 

A-Shell/Server/ATE Extension: Under A-Shell/Unix (or A-Shell/Windows on a telnet server with ATSD), if the client is ATE, then there is a possible ambiguity in TRMCHR over whether the information returned should be from the server or the client side. In most cases, these will agree, except for the case of WINROW and WINCOL, since dialog box information may only be known to the client. (The server application would have given the command to create the dialog box, but that information, and especially the knowledge of whether the dialog box is still open on the client, is not necessarily available to TRMCHR.) 

To resolve the ambiguity, if you want the WINROW / WINCOL information to return information about a dialog box displayed on the ATE client, you must set WINROW to -1 prior to the subroutine. In that case, TRMCHR will query the client for all of the information. Otherwise, it will just use the server's view of the terminal status, which, as of build 915, will mean that the WINROW and WINCOL fields will come back 0. To clarify, the main reason why you would want to set WINROW to -1 before 

A-Shell Reference 

Page 3269 

XCALL TRMCHR is if you are interested in knowing the size of the current dialog box on the client display, if any. (It makes no difference under A-Shell/Windows what you set WINROW to, since it always returns the client information in that case.) 

See the sample program TRMCHR.BAS in EXLIB:[908,28], and the trmchr.bsi and trmchr.map include files in ASHINC. 

A-Shell Reference 

Page 3270 

## **TRMCHR'MAP** 

```
MAP1 TRMCHR’MAP
```

```
   MAP2 TRMCHR’FLAGS,F,6
   MAP2 TRMCHR’ROWS,F,6
   MAP2 TRMCHR’COLS,F,6
   MAP2 TRMCHR’COLORS,F,6
   MAP2 TRMCHR’FORE,F,6
   MAP2 TRMCHR’BACK,F,6
   MAP2 TRMCHR’WINROW,F,6
   MAP2 TRMCHR’WINCOL,F,6
   MAP2 TRMCHR’TSLSIZ,F,6   ! (optional)
   MAP2 TRMCHR’BSLSIZ,F,6   ! (optional)
   MAP2 TRMCHR’BSSSIZ,F,6   ! (optional)
```

The individual fields are described in the following table. 

|**Symbol**|**Description**|
|---|---|
|TRMCHR’FLAGS|Returns the sum of flags from the following table.|
|TRMCHR’ROWS|The number of rows currently displayed.|



A-Shell Reference 

Page 3271 

|**Symbol**|**Description**|
|---|---|
|TRMCHR’COLS|The number of columns currently displayed.|
|TRMCHR’COLORS|The number of colors the terminal supports. Monochrome terminals will report 0.|
|TRMCHR’FORE|The current foreground color. Monochrome terminals will report 0. The color values are: 0 Black, 1<br>White, 2 Blue, 3 Magenta, 4 Red, 5 Yellow, 6 Green, 7 Cyan|
|TRMCHR’BACK|The number of the current background color (same color values as TRMCHR’FORE).|
|TRMCHR’WINROW|The number of rows in the current dialog. If initially set to -1 and the terminal is ATE, the operation is<br>performed on the ATE workstation instead of within the server job.|
|TRMCHR’WINCOL|The number of columns in the current dialog.|
|TRMCHR'TSLSIZ|(optional A-Shell extension) Length of top status line|
|TRMCHR'BSLSIZ|(optional A-Shell extension) Length of bottom status line|
|TRMCHR'BSSSIZ|(optional A-Shell extension) Length of bottom shifted status line|



The following table defines the TRMCHR'FLAGS bits. 

A-Shell Reference 

Page 3272 

|**Value**|**trmchr'flags Meaning**|
|---|---|
|&h00000001|Alternate page support|
|&h00000002|Block fill support|
|&h00000004|Column insert/delete support|
|&h00000008|Multiple color support|
|&h00000010|Function key translation support|
|&h00000020|Is an Alpha Micro terminal|
|&h00000040|Has a status line|
|&h00000080|Horizontal split screen support|
|&h00000100|Erase to end of line support|
|&h00000200|Erase to end of screen support|
|&h00000400|Underscore attributes support|



A-Shell Reference 

Page 3273 

|**Value**|**trmchr'flags Meaning**|
|---|---|
|&h00000800|Blinking support|
|&h00001000|Dim video support|
|&h00002000|Reverse video support|
|&h00004000|Character insert/delete support|
|&h00008000|Line insert/delete support|
|&h00010000|Local printer support|
|&h00020000|Settable 80/132 column support|
|&h00040000|Selectable smooth scroll support|
|&h00080000|Has box drawing commands|
|&h00100000|Has "mode" type attributes|
|&h00200000|Has AM-70 style color commands|



A-Shell Reference 

Page 3274 

|**Value**|**trmchr'flags Meaning**|
|---|---|
|&h00400000|Has "no space" attribute commands|
|&h00800000|Variable number rows and columns|
|&h01000000|Enhanced tab(-1,192) support|
|&h02000000|A-Shell GUI extensions|



A-Shell Reference 

Page 3275 

## **UNIQUE** 

## **xcall UNIQUE, fname** 

UNIQUE generates a unique filename based on your current jobname. This can be handy for generating print files and other temporary files which are periodically erased. 

The parameter _fname_ (string variable, 10+ bytes) will be set to <jobnam>.T#@ where # is a digit from zero to nine, and @ is an alphabetic character from A to Z. It scans through these names in order until finding one that is not in use. Thus if the current job is TSKAAA, the first name returned (assuming it is not already in use) will be TSKAAA.T0A, followed by TSKAAA.T0B, etc. 

A-Shell Reference 

Page 3276 

## **USPSBS** 

_Updated  January 2013; see History_ 

## **xcall USPSBS, trackstr, routestr, barstr, status** 

USPSBS creates an encoded bar string for the US Post Office intelligent bar codes. 

## **Parameters** 

_trackstr_ (String, 21)  [in] 

tracking string 

_routestr_ (String, 12)  [in] 

route string 

_barstr_ (String, 66)  [out] 

returned encoded bar string. It is a character format equivalent of the graphic bar code, designed to be easy to convert to the graphic format. See the documentation on the USPS web page for specifications. 

_status_ (F)  [out] 

returned status code per the following table: 

|**Value **|**Description**|
|---|---|
|0|Sucess|
|-1|Parameter error|
|-2|Unable to loadusps4cb.dll|



A-Shell Reference 

Page 3277 

|**Value **|**Description**|
|---|---|
|||
|-3|Unable to locate the USPS4CB() function|
|-99|Not supported on current platform|
|>0|invalid_trackstr_and/or_routestr_|



## **Comments** 

The file usps4cb.dll is available from the US Postal Service's Intelligent Mail Barcode Resource Download Site and must be saved somewhere in the path or in the A-Shell bin directory. 

See the publications on the above web site for details on creating the _trackstr_ and _routestr_ values. 

See EXLIB:[908,52] for sample and test programs. 

## **History** 

- 2013 January, A Shell 6.1.1331:  support added for Unix (routine previously was for Windows only) 

- 2011 January, A Shell 5.1.1201:  added to A-Shell 

A-Shell Reference 

Page 3278 

## **USRCNT** 

## **xcall USRCNT, pcount {,lcount, mcount, ixcount}** 

USRCNT returns the number of physical nodes in use, logical nodes in use, maximum number of physical nodes allowed, and the number of instances of A-Shell that are running. 

## **Parameters** 

_pcount_ (F,6)  [out] 

returns the number physical nodes currently in use. Physical nodes count against the license. In theory, each physical workstation counts as a physical node, but due to the many ways in which devices can be attached and sessions established, the counter can sometimes be "fooled." However, for each physical node, there will always be at least one logical node. 

_lcount_ (F,6)  [out] 

returns the number of logical nodes (or jobs) currently in use. Logical nodes do not count against the license. When the number of logical nodes is greater than the number of physical nodes, it should be because of background sessions or multiple sessions originating from the same physical workstation. 

_mcount_ (F,6)  [out] 

returns the maximum number of physical nodes (i.e. the number specified in the license). 

_ixcount_ (F or I)  [out] 

returns the executable instance count, including the current instance. -1 indicates some kind of error, like an inability to execute the _ps_ command under Unix. 0 would indicate a different kind of error—i.e. that the current instance is detecting neither itself nor any other error while scanning the process or window list. 

For Windows, this is a count of windows sharing the A-Shell main window class (MIAMEWClass). Note this would include A- Shell/Windows and ATE, which could involve more than one actual ashw32.exe executable. Note that in a peer-to-peer environment, one peer running this function would not see the other peers that may be sharing the same copy of ashw32.exe. In this case, you should probably use SYSTAT as well to check for the possibility of other instances of A-Shell which share the ashw32.exe disk copy, but which are in different memory spaces or different workstations. 

A-Shell Reference 

Page 3279 

For Unix, it uses _ps_ to check for processes whose launch command references the current executable (which isn't necessarily named "ashell"). 

In either case if the _ixcount_ value is greater than the _lcount_ (logical instance) value, that implies that there are instances of A- Shell running that aren't sharing the same jobtbl.sys. 

This parameter was added to USRCNT in A-Shell build 988.4 of 10 May 07 primarily for the benefit of ASHUPD—i.e., to make sure there are no other instances of A-Shell running that would interfere with an update. The function might also be useful to applications attempting to monitor usage for the same reasons they are already using USRCNT. 

## **Example** 

This simple program demonstrates the use of USRCNT. 

```
MAP1 PCOUNT,F,6            ! # physical nodes
MAP1 LCOUNT,F,6            ! # logical nodes
MAP1 MCOUNT,F,6            ! # maximum nodes licensed
```

```
MAP1 IXCOUNT,F,6           ! # current instances
```

```
XCALL USRCNT,PCOUNT,LCOUNT,MCOUNT,IXCOUNT
```

```
? "# Physical Users:       ";PCOUNT
? "# Logical Users:        ";LCOUNT
```

```
? "# Licensed Nodes (max): ";MCOUNT
```

```
? "# Current Instances:    ";IXCOUNT
```

```
end
```

A-Shell Reference 

Page 3280 

## **VUESCR** 

## **xcall VUESCR, textarray, rows, cols, strow, stcol** 

VUESCR edits a rectangular array of text. 

## **Parameters** 

_textarray_ [in/out]  optional 

supplies the initial text and receives the updated text. It must be mapped as a string array, with the number of elements greater than or equal to the value of the _rows_ parameter, and the size of each element equal to the value of the _cols_ parameter. 

_rows,cols_ (Num)  [in] 

determines the dimensions of the rectangular area of text to be edited, and must correspond to the mapped dimensions of _textarray_ . 

_strow,stcol_ (Num)  [in] 

determines the starting position of the rectangle on the screen. A border will be drawn outside this rectangle, so for best results, the starting row and column should be two or greater. 

## **Comments** 

VUESCR is actually implemented as a front end to INMEMO, which already supports this exact function, although with different and more complex parameters. It is offered mainly as a convenience to programmers using the Swap (multi-session) utility under AMOS. 

A-Shell Reference 

Page 3281 

## **WAKNO** 

## **xcall WAKNO, jobno {,status}** 

WAKNO (Unix only) wakes up a job that is sleeping (in SLEEP or SLEEP.LIT). 

## **Parameters** 

## _jobno_ [in] 

is the job number of the job to wake up. (See PLYJOB for a way of getting the number of another job.) Note that in order to be able to send a signal like this to another process under Unix, you either have to be the superuser or have the same effective user id as the target user. 

_status_ [out]  optional 

returns the result of the operation: 

|**Value **|**Description**|
|---|---|
|-1|No such job|
|0|Success|
|1|Insufficient privileges to wake target user|
|3|No such process (job probably aborted uncleanly, leaving a phantom in the job table)|



A-Shell Reference 

Page 3282 

## **WINFLG** 

## **xcall WINFLG, flag {,feature}** 

The AMOS routine WINFLG was used within InSight to retrieve information about the current job and terminal environment. 

## **Parameters** 

_flag_ (Num)  [out] 

If called with just this one argument, returns 0 to indicate that inSight is not supported by A-Shell.  (Under AMOS it would have returned 1 if supported.)  If called with both arguments, then it returns flag = 1 if the corresponding feature is supported, else 0. 

_feature_ (Num)  [in] 

Indicates a particular feature to test support for. Features 1-32 are equivalent to those used by JOBDAT (which see).  Features 32-255 correspond to the equivalent TCRT or Tab(-1,x) numbers. Feature 256 indicates Multi or Office (not supported and thus set to 0 by A-Shell). 

## **Comments** 

If WINFLG was called with just the one argument, it was supposed to return 1 if InSight was supported, else 0. (A-Shell does not support InSight and thus returns 0.) If called with 2 arguments, then it returns _flag_ = 1 if the corresponding feature is supported, else 0. The features 1-32 are equivalent to those used by JOBDAT (which see). Features 33-255 correspond to the equivalent TCRT or Tab(-1,x) numbers. Feature 256 indicates Multi or Office (and is thus set to 0 by A-Shell). 

Since this routine is used very sparsely in the A-Shell community, A-Shell contains only a minimal implementation. Features 1-32 are supported, as in JOBDAT, but beyond that, A-Shell returns 1 for features 33-149, plus 202 and 203 (screen save/restore). In the case of Windows (except in Telnet mode), it also returns 1 for features 158-162 (mouse functions). 

## **History** 

- 2023 October, A Shell 7.0.1751: WINFLG now returns 1 indicating support for tab(-1,160) and tab(-1,162) if the current terminal driver is a "G" version (e.g. AM62G, AM75G, PCVTDV, ...) 

A-Shell Reference 

Page 3283 

## **XCALEN** 

_Added May 2016_ 

## **xcall XCALEN, idate, xcdates(), exitcode, xcflags, sr, sc, title, sdate, edate {,coldef, xcflags}** 

XCALEN.SBX is an XTREE-based implementation of a calendar control featuring the following extensions beyond what is available in the standard Month Calendar Control. The extensions can: 

- Apply different colors and font effects to each date, whereas the standard Month Calendar is limited to marking selected dates 

- in bold. 

- Store text associated with each cell that can be displayed as a tooltip. 

Source, samples and related functions can be found in SOSLIB:[907,49]. 

## **Sample Images** 

## _xcdates()_ (ST_XCALEN)  [in] 

DIMX-allocated array of individual dates of interest to mark on the calendar. Dates do not have to be in order. There is no particular limit to the number of dates in the array, but only one element per date is recognized, and there is no particular value to dates that all outside the range set by _sdate,edate_ . When the calendar is displayed, dates for which there is an element in the _xcdates()_ array will be shown with a "+" beside the day number, and will be given the background color specified in the BG field of the ST_CALEN element; see sample images. The ST_CALEN structure is defined—in ASHINC:XCALEN.DEF—as follows: 

## `defstruct ST_XCALEN` 

```
   map2 DATE,B,3        ! standard (ODTIM/IDTIM) separated date
```

```
   map2 BG,B,4          ! BackGround color (RGB value)
```

```
   map2 MARK,B,2        ! various indicator flags (not yet defined.)
```

A-Shell Reference 

Page 3284 

```
   map2 COMMENT,s,1024  ! text
```

```
endstruct
```

The COMMENT field may contain up to 1024 bytes of free-format text to associate with the date. The text is displayed as a tooltip when the mouse hovers over the date; see sample images. 

## _idate_ (B,4)  [in] 

initial date to select in calendar. Standard ODTIM/IDTIM format. 

_exitcode_ (Signed Num)  [out] 

Exit code indicating how control was exited: 

|**Code**|**Meaning**|
|---|---|
|-20001|Use clicked 'X' to close calendar|
|-20002|Out of range, navigating to previous month|
|-20003|Out of range, navigating to next month|
|-20004|User clicked date|



## - _sr, sc_ (Num)  [in] 

Initial upper left corner of dialog in standard row/col units or in millirows and millicols. 

A-Shell Reference 

Page 3285 

## _title_ (String)  [in] 

Title (caption) for dialog. Ignore if the XCALF_NOCAPTION flag set in _xcflags_ . 

## _sdate, edate_ (B,4)  [in] 

Starting/ending date of range to allow for navigation. Standard ODTIM/IDTIM format. When user tries to navigate outside this range, routine returns _exitcode_ -20002 or -20003. 

## _coldef_ (String)  [in] 

Optional Advanced Coldef Options to be appended to the one automatically built. Allows you to customize the behavior of the control based on the capabilities of XTREE. Note that since the _coldef_ string may grow quite large, and be frequently added to, you should probably use a dynamic string (s,0), lest you end up wasting time tracking down errors due to the string being truncated. 

## _xcflags_ (B,4)  [in] 

## Optional flags as defined in ASHINC:XCALEN.DEF: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XCALF_NOCAPTION|&h0001|Eliminate caption bar from dialog|
|XCALF_ARCEDIT|&h0002|Allow right click to edit text for date; see comments|
|XCALF_EDIT|&h0004|Edit text for the current date|



**Requirements** 

A-Shell Reference 

Page 3286 

Two icon files, nav_left_24.png and nav_right_24.png are used for the left/right navigation arrows and must be stored in the %miame%/icons subdirectory of the client workstation. You can replace them with any 24x24 png images using the same file names. 

## **Comments** 

Each call to the XCALEN.SBX routine scans the _xcdates()_ array, creates the control, and then puts the focus on the calendar grid, allowing the user to navigate between months (up until the limit set by the starting/ending dates specified in the _sdate,edate_ parameters). If allowed by the XCALF_EDIT flag, the user can right-click a date to edit the text associated with it. Or they can exit from the calendar mode by generating just about any other exitcode (i.e. ESC or click on another control). On return from the subroutine, the calendar control is still visible, so you can leave it on the screen for visible reference. 

Aside from the XTREE customization possible via the _coldef_ parameter, further customization would probably require making a copy of XCALEN.BP in SOSLIB:[907,49] and modifying it directly for your purposes. 

Other than the internal ability to edit the text for a date, responsibility for maintaining the array of date information (text and colors) is purely on the programmer and outside the realm of XCALEN.SBX. 

## **History** 

- 2016 March, A Shell 6.3.1507:  Routine added to A-Shell 

A-Shell Reference 

Page 3287 

## **XFOLD** 

_Reviewed and revised October 2024_ 

## **xcall XFOLD, string {,mode, control}** 

XFOLD converts (folds) a string to standard upper/lower case. 

## **Parameters** 

_string_ (String)  [in] 

contains the string to be folded or capitalized. 

_mode_ (Num)  [in] 

may be set to 0 for "word mode" or 1 for "sentence mode." In word mode, each word is capitalized, whereas in sentence mode, typically only the first word of a sentence is capitalized. If not specified, capitalizes as a name (i.e. word mode); see _Comments,_ below. 

_control_ (String)  [in] 

contains a list of delimiters, followed by a list of exceptions. The format is: 

```
/delimiters/exception1/exception2/.../exceptionN/
```

The "/" character in the above string can be any character, as long as it is used consistently and is not part of any of the delimiter or exception strings. The purpose of the exception list is to override the more simplistic capitalization logic, preventing things such as "John Doe Iii" or "Sigmund Freud, M.d." A typical control string might be: 

```
/ ,;:).!?/II/III/Jr/Sr/Mr/Mrs/Ph.D./M.D./i.e./NASA/IRS//
```

## **Comments** 

If only the first argument is specified, then _string_ will be capitalized as a name using an implied _control_ string of: 

```
"/ ,./II/III/Ph.D./M.D.//"
```

This will, for example, convert _string_ passed as "john q. PUBLIC ii" to "John Q. Public II". 

A-Shell Reference 

Page 3288 

For sentence mode, the delimiters list must contain first all of the word delimiters, then the period, followed by all of the other sentence delimiters. For example, in the list "\ ,;:.!?\", the period, exclamation and question mark are treated as sentence delimiters, while the space, comma, semicolon, and colon are treated as word delimiters. 

Each exception must represent a complete word token, and may not begin with a word or sentence delimiter. However, it may end with one. 

## **See Also** 

- The discussion "XCALL XFOLD question?" on the A-Shell Forum. 

A-Shell Reference 

Page 3289 

## **XFRMMO** 

## **xcall XFRMMO, opstat, ch1, link1, ch2, link2** 

XFRMMO is an utility to move or copy an INMEMO logical memo, either between two memo files or within a single file. If moving between files, it can also change the link size from 2 to 4 or vice versa. 

## **Parameters** 

## _opstat_ (Num)  [in/out] 

On input, must be set to 0 to copy (preserving the source memo) or 1 to move (same as copy followed by deletion of the source memo). On return, it will be set to one of the following values to indicate whether the operation succeeded: 

|**Value**|**Description**||**Value**|**Description**|
|---|---|---|---|---|
|0|Success||2|File full|
|1|Link error||3|System error|



_ch1_ (Num)  [in] 

is the open file channel for the source memo file. 

_link1_ (B,2 or B,4 to match the format of the source memo file)  [in] 

is the link to the source memo. Note that if _opcode_ is 1 (move), this memo will be deleted (and _link1_ returned as 0). 

_ch2_ (Num)  [in] 

is the open file channel for the destination memo file (which may be the same as _ch1_ ). 

A-Shell Reference 

Page 3290 

## _link2_ (Num)  [out] 

will return the new link to the destination memo. Use data type B,2 or B,4 to match the format of the destination memo file. 

A-Shell Reference 

Page 3291 

## **XLOCK** 

_Updated August 2020; see History_ 

## **(1) xcall XLOCK, mode, lock1, lock2 {,class}** 

## **(2) xcall XLOCK, mode, myjob, lock'array(1)** 

XLOCK provides an abstract symbolic scheme for locking anything, based on a pair of numeric values to which you assign your own meaning. Note that syntax two is used only for retrieving a list of locks ( _mode_ = 3). 

## _mode_ (Num)  [in/out] 

## determines the operation, per the following table: 

|**Value **|**Description**|
|---|---|
|0|Set lock specified by_lock1_and_lock2_. If successful,_mode_is set to 0. Otherwise (if a conflicting lock<br>exists),_mode_is set to the job number of the job holding the conflicting lock. See note about SBR=MXLOCK<br>below for information how what happens if your job has already set the lock.|
|1|Same as_mode_0, except that if the lock cannot immediately be set, it waits until it can.|
|2|Clear lock. On return,_mode_is set to 0 if your job did not own the lock (i.e. it was not cleared), else it is set<br>to the number of locks cleared (which could be more than 1 in the case of wildcards).|
|3|List locks. In this case,_mode_returns with the number of locks in the list; myjob is set to your job number,<br>and lock'array contains the list of locks.|



A-Shell Reference 

Page 3292 

|**Value **|**Description**|
|---|---|
|4|Same as_mode_0 but does not actually set the lock.|
|5|Same as_mode_1 but does not actually set the lock.|
|6|Check for lock without wait; equivalent to mode 0 but without setting the lock. Similar to 4—when the class<br>parameter is non-zero—but without any conflict/confusion with the reservations.|
|7|Expanded list; equivalent to mode 3 but the returned lock'array elements also contain the lock class. See<br>lokclass in_lock'array_below.|



## _lock#_ (B,2 or B,4)  [in] 

_lock1_ and _lock2_ together contain a pair of numbers which are being locked or released. The numbers themselves have no inherent meaning, but a typical use is for one to indicate a file channel number and the other a record number. A value of zero in either parameter acts as a wildcard. For example, the pair 22,0 matches all of the pairs whose first value is 22. (This might be useful for representing an exclusive lock on all records within file 22.) The double wildcard 0,0 matches all possible combinations. The range of values depends on whether the parameters are mapped as b,2 or b,4. 

## _class_ (Num, 0-65535)  [in] 

Optional lock pool identifier. May be used to avoid potential conflicts between applications that might otherwise be using the same range of lock values. See _Comments_ , below. 

## _lock'array_ 

```
map1 lock'array
```

```
   map2 lok'jobnum,b,2
```

A-Shell Reference 

Page 3293 

```
   map2 lok1,b,x        ! b,2 or b,4; must match size of mode param
```

```
   map2 lok2,b,x        ! "     "        "
   map2 lokclass,b,2    ! always 2 bytes
```

The A-Shell implementation of XLOCK is upward compatible with the AMOS one, so you can refer to the AlphaBASIC documentation for more details. Note the following A-Shell enhancements: 

- A-Shell supports _lock1_ and _lock2_ variables of either B,2 or B,4 (allowing values of up to two billion), whereas the AMOS 

- version is limited to two-byte values. 

- Under A-Shell, you have the option of treating a value previously locked by your job as available (default) or locked. In the 

- latter case, you must set the miame.ini setting SBR=MXLOCK; see the system parameters MXLOCK and AXLOCK, the latter of which controls whether a certain bug in the AMOS implementation will be emulated or not.) 

- The optional _class_ parameter allows you to create multiple locking pools (such as in multiple applications) which do not 

- conflict with each other. The standard version of XLOCK uses lock class 0 for normal locks and lock class 256 for pending exclusive locks. Lock class 1 is used by the Aesops routine LOCK.SBR, and classes 2 and 3 are used by the OmniLedger routines XFLOCK.SBR and XLOCKS.SBR, respectively. If you want to define your own, we suggest picking something in the range of 100 to 200. 

- An additional enhancement is that of lock "reservations." These were implemented to reduce the difficulty of establishing an 

- exclusive (or wildcard) lock on a file (or other resource, represented by the _lock1_ value) in which multiple jobs are actively placing individual record locks. The problem is that the job desiring the exclusive lock may have to wait an unreasonable amount of time, since as long as there is one lock in the _lock1_ resource, the exclusive lock cannot be set, and even worse, there is no way to stop additional jobs from coming along and setting locks. The idea of the lock "reservation" is that once set, no new locks can be set on the resource, except by jobs that already have one or more locks set on that resource. This allows those jobs already using the resource to finish their transaction, but any additional jobs will have to wait until after the exclusive lock activity is complete. To use this feature, set _mode_ to 4, _lock1_ to the resource you want exclusive control of, and _lock2_ to zero. 

A-Shell Reference 

Page 3294 

This acts just like _mode_ 0 (lock but do not wait) except that if the exclusive (wildcard) lock cannot be established, a reservation is set instead (using lock class 256). The calling job gets the same failure code as it would for _mode_ 0 (i.e. _mode_ is set to the job number owning the first conflicting lock). However, from that point on, no other jobs can set a lock conflicting with the reservation, unless they already have a lock set in that range. The calling job then repeats the _mode_ 4 request periodically until the return value indicates success (at which point the reservation will have been converted to a normal lock, or in other words, the lock class will be changed from 256 back to 0). 

- The final enhancement is the addition of two new _mode_ s which allow you to check for the presence of a lock without actually 

- having to place one. _mode_ 4 is like _mode_ 0 (no waiting), and _mode_ 5 is like _mode_ 1 (wait until available) except that _mode_ s 4 and 5 do not actually set a lock. It will be left as an exercise for the clever programmer to figure out what possible motivation there could be for such a capability. 

- The QUTL utility may be used to display the list of locks in use, as well as to forcefully clear them by resetting the job owning 

- the locks. 

- Note that XLOCK isn't really a file or record locking system, even though that's what people mostly use it for. It is really just a 

- mechanism for limiting access to arbitrary resources which are coded using a pair of numeric values. There is no inherent meaning to the numeric values contained in your "locks". It is the application—and not A-Shell or the operating system—that has assigned meaning to the numeric values, typically using the first number to indicate the file channel and the second to indicate the record number. 

- Modes 3 and 7 pick up the array size from the parameter passed, whether it is passed as an unformatted block, or as the first 

- element of the array. The value returned in _mode_ (number of locks set) will be the total number of locks set (as before), but the list will be limited to the size of the array. Previously it may have overrun the array if it was not large enough to hold all the locks. 

## **History** 

- 2020 August, A Shell 6.5.1688:  If an out-of-queue blocks condition, or other queue system failure occurs while trying to place an XLOCK, it now returns a non-zero value in the MODE parameter, and also displays a messagebox clarifying the problem, with abort/retry/ignore options. Previously it merely displayed "?Out of queue blocks" but did not return an error code, so the application had no way of recognizing the problem. Note that the issue didn't affect FLOCK, which does return status 103 for these queue error conditions. 

A-Shell Reference 

Page 3295 

- 2019 December, A Shell 6.5.1672:  Add _mode_ values 6 and 7. 

A-Shell Reference 

Page 3296 

## **XMPP** 

_Updated April 2020_ 

## **xcall XMPP, opcode, status, fromid, pw, server, port, toid, msg, msgid, flags {, timeout {, rcvfile}}** 

(Linux only) XMPP enables the sending of instant messages using the XMPP protocol (Extensible Message and Presence Protocol, aka Jabber) to third party instant messaging systems implementing that protocol. Compatible examples include the OpenFire messaging server and Pidgin client. 

## **Parameters** 

_op_ (Num)  [in] 

Operation code: 

|**Value**|**Meaning**|
|---|---|
|1|connect, send message, disconnect|
|2|connect, receive message(s), disconnect|
|3|connect, send message, receive message(s), disconnect|



_status_ (signed Num)  [out] 

Return code: 

A-Shell Reference 

Page 3297 

|**Value**|**Meaning**|
|---|---|
|0 :|ok (for op 1)|
|>0 :|# messages received (ops 2 and 3)|
|-1 :|routine abort during startup|
|-2 :|error opening thexmpp.logfile (when debug flags set)|
|-3 :|failure to create a connection context|
|-4 :|error during configuration of connection options|
|-5 :|failure to connect|
|-6 :|failure to disconnect|



## _fromid_ (String)  [in] 

JID (Jabber ID) of sender, using syntax name@domain. Must be recognized by server for authentication. _pw_ (String)  [in] 

A-Shell Reference 

Page 3298 

Authentication password for sender. Plain text, or may be optionally encrypted using MX_PWCRYPT. Modes 1-3 are supported; in the case of mode 3, use the FROMID as the encryption seed and omit the key parameter, to use the internal A-Shell generated key. 

_server_ (String)  [in] 

Hostname or IP address of messaging server 

_port_ (Num)  [in] 

Port to connect to server on (0 = default: 5222) 

_toid_ (String)  [in] 

JID of the receipient (individual or group), e.g. name@domain 

_msg_ (String)  [in] 

Text of message. There is no inherent limit to the length; dynamic strings (S,0) supported. 

_msgid_ (String)  [in] 

Short string to identify message, preferably unique. Mainly of use for tracking messages within the server. 

_flags_ (Num)  [in] 

Option flags (zero or more of the following): 

|**Value**||**Meaning**|
|---|---|---|
|AXMPPF_LOG|&h0001|output traces toashmpp.log|
|AXMPPF_TRUST_TLS|&h0002|trust all TLS certs|



A-Shell Reference 

Page 3299 

|**Value**||**Meaning**|
|---|---|---|
|AXMPPF_DISABLE_TLS|&h0004|disable TLS; use insecure connect|
|AXMPPF_DEBUG|&h0008|low level tracing toxmpp.log|



_timeout_ (Num)  [in] 

Number of seconds to wait for messages to be received. 

_rcvfile_ (String)  [in] 

File specification (A-Shell or native) of file to receive messages in. If not specified, default is ashxmpp.xml. 

## **History** 

2020 April, A-Shell 6.5.1678:  Added _opcode_ 2 and 3, revised status meanings, added new parameters _timeout_ and _rcvfile_ . Requires the libashxmpp.so.1 library to be upgraded to version 1.0.102+. 

- 2020 February, A Shell 6.5.1676: Routine added to A-Shell. 

A-Shell Reference 

Page 3300 

## **XOAUTH2** 

_Added January 2026_ 

## **xcall OAUTH2, opcode, status, clientid$, clientsecret$, option, auth'endpoint$, token'endpoint$, challenge$, scope$, refresh'token$, response$, handle, stsmsg$ {,file {,add'param}}** 

XOAUTH2.SBX is a wrapper for OAUTH2 which has the same parameter interface but with the following enhancements: 

- The initial request (opcode 1) combines the OAUTH2 opcode 1, the launching of the browser for the interactive 

- authorization step, and the subsequent opcode 2 to receive the access token (eliminating the need to explicitly call opcode 2 or to launch the browser.) 

- In the case of ATE, it automatically redirects the operation to the client in order to work around the obstacle of how to 

- launch a browser on from a Linux or other server environment. 

- It incorporates the necessary JSON logic for writing and extracting the parameters. 

- It adds some helpful user interface displays indicating the sequence of events, status codes, etc. 

- Since it is provided in compile-it-yourself source code, it is easily customizable. 

The source code to XOAUTH2.SBX may be found here: XOAUTH2.BP in EXLIB:[908,77] 

## **See Also** 

- OAUTH2XS 

## **History** 

2026 January:  Added to the EXLIB. 

A-Shell Reference 

Page 3301 

## **XOKEY, XUSER** 

## **xcall XOKEY, mode, msgname, msgdata** 

## **xcall XUSER, mode, msgname, msgdata** 

XOKEY is a variation of COMMON, used for passing data between programs in memory, supporting up to 400 packets of fifteen bytes each. XUSER is a disk-based version of XOKEY; the packets are stored in the file SYS:XUSER.SYS which will be created automatically if not present. 

## **Parameters** 

_mode_ (String,1)  [in] 

Operation to perform:  "P" to put (write), "R" to read (destructive), "G" to get (non-destructive read), "Z" to clear all packets 

_msgname_ (String,10)  [in] 

Name of message packet 

_msgdata_ (String,15)  [in/out] 

Data to read or write 

## **Comments** 

The Put ("P") operation scans the file from the start, using the first empty slot, or re-using the first slot matching _msgname_ , whichever comes first. This could result in multiple entries with the same _msgname_ . To eliminate that possibility, use the destructive Read ("R") first. Likewise, the Read and Get operations stop at the first matching _msgname_ . 

## **History** 

2025 February: These routines have existed in A-Shell for many years, but was only documented at this time. 

A-Shell Reference 

Page 3302 

## **XPPN** 

## **xcall XPPN, ppn, device, job, trmdef** 

XPPN returns the PPN, Device, Job, and Trmdef in the formats shown below. 

## **Parameters** 

```
MAP1 PPN
   MAP2 Project,B,2
   MAP2 Programmer,B,2
MAP1 Device,S,8             ! (e.g. "DSK1:")
MAP1 Job,S,6
MAP1 Trmdef,S,6
```

## **Comments** 

A confusing situation arises when PPN values, which by convention are always represented in octal notation (ranging from zero to 377, rather than zero to 255 as they would if represented in decimal), are stored in numeric variables. Since BASIC has no provision for displaying the value of a numeric variable in anything other than decimal, when the PPN [100,200] is stored in the Project and Programmer fields above and later printed using the PRINT statement, they would display (in decimal) as 64 and 128. To display them in their correct format as octal, you could use the MX_OCVT. 

Another approach would be to set SBR=XPPNOCT in the system configuration file, which causes XPPN to correct for the octal/decimal discrepancy by converting the returned Project and Programmer values such that they display in decimal as if they were octal. Thus, the PPN [100,200] would be returned as Project=100 and Programmer=200, which is probably what you were expecting. 

You might wonder why this was not done by default. The reason is that under AMOS, PPNs were stored as a pair of bytes (each byte ranging from zero to 377 octal). For closer compatibility, A-Shell internally uses the same representation, even though it is 

A-Shell Reference 

Page 3303 

arguably arbitrary since at the operating system level, PPNs are mapped to directories that are purely text strings. However, many existing BASIC programs and subroutines relied on the fact that PPNs could be stored in a pair of single byte variables, and thus at some point we would have had to deal with the conversion anyway. 377 decimal does not fit in a single byte, which is why this particular subroutine uses the somewhat non-AMOS-like technique of storing the PPN as a pair of two-byte variables. For comparison, GETJTB returns the PPN both as a single two byte field and as a pair of three-byte strings (for binary and octal representations). 

A-Shell Reference 

Page 3304 

## **XRUNLOG** 

_Added December 2022_ 

## **xcall XRUNLOG, evt, jcbrec, status** 

XRUNLOG.SBX enables customized activity tracking.It belongs to the special category of Hook subroutines which are really just defined interfaces allowing developers to plug in their own logic to customize or extend standard A-Shell behavior. 

## **Parameters** 

_evt_ (Num)  [in] 

## Specifies the event: 

|**Value**|**Event**|
|---|---|
|1|Start of A-Shell session|
|2|End of A-Shell session|
|4|Start of RUN|
|8|End of RUN|



## _jcbrec_ (ST_JCBREC)  [in] 

Contains a copy of the JOBTBL record for the current job. See ASHINC: JOBTBL.SDF in SOSLIB:[907,16]. _status_ (Signed Int)  [in/out] 

A-Shell Reference 

Page 3305 

Initially set to 0, this will contain the value passed back by the prior call to this SBX for this job. Provides a way for the SBX to link the start and end events together (by log file position, record number, key, etc.) 

If XRUNLOG.SBX is found in DSK0:[7,6] when A-Shell is launched, it will be called at the start and end of the A-Shell session, as well as at the start and end of each RUN. It is not called for LIT and SBX events. 

The sample program XRUNLOG.BP in SOSLIB:[907,54] creates a simple sequential file log of the events. It is similar in concept to the ashlog.log file when the INOUT and EXEC TRACE flags are set, but more focused and consistent in structure. The sample subroutine also contains a function that processes the raw log, creating a consolidated version with just one entry per session or RUN with some elapsed activity counts. 

## **History** 

- 2022 December, A Shell 6.5.1722  Routine added to A-Shell. 

A-Shell Reference 

Page 3306 

## **XSHLEX** 

_Added January 2017_ 

## **xcall XSHLEX, objectspec {,status, action, parms, dir, showflags, waitflag, clisvr, exitstatus}** 

XSHLEX.SBX provides a standardized and robust way of doing a "Shell Execute"—i.e. launch the application that goes with a specified file or URL object—without having to consider which platform you are using. This does not provide much advantage over MX_SHELLEX for those in a pure local Windows environment, but for developers programming across various environments, it eliminates the need for logic to deal with local/remote and file transfer considerations. For example, in an ATE environment, it detects if the object is a file on the server, and if so, transfers it automatically to the ATECACHE directory when it then launches the corresponding app. 

The parameters all correspond to the equally named MX_SHELLEX parameters, which see for specifications. Only the deviations/extensions from the MX_SHELL parameter descriptions are noted below. Also note that the order of the first two parameters is reversed from MX_SHELLEX, reducing the minimum syntax to a single parameter. 

_objectspec_ (String)  [in] 

File or URL to launch. Unlike MX_SHELLEX, the file spec may be in DevPPN format; the routine will figure out if it is relative to the server or the client. If on the server in an ATE or ZTERM connection, file will be transferred to the client for launch using ATEAPX.SBX. 

_status_ (Num)  [out] 

Combines status codes returned by MX_SHELLEX, with those of ATEAPX.SBX—which is used for file transfer if necessary—and adds a few more. The best reference, both for documentation and actual program usage, is the function Fn'Shell'Exec'Status'Description$() in FNSHELLEX.BSI in SOSLIB:[907,10] **.** 

_action, parms, dir$, showflag, waitflag, exitstatus_ 

same as for MX_SHELLEX 

_clisvr_ (String)  [in] 

A-Shell Reference 

Page 3307 

Similar to MX_SHELLEX usage, except that if omitted or blank, the routine will attempt to figure out if _objectspec_ is a file on the server or client. If the application knows the object is on the client PC, it can set it to "C" (for client) to avoid the selfdetermination logic. 

## **Comments** 

The fnshellex.bsi module (see link above) contains a convenient wrapper function Fn'Shell'Exec(objectspec$) for maximum simplicity, e.g.: 

```
STATUS = Fn'Shell'Exec(objectspec$)
```

## **History** 

- 2017 January, A Shell 6.3.1542:  Routine added to A-Shell. 

A-Shell Reference 

Page 3308 

## **XSTRIP** 

## **xcall XSTRIP, strarg** 

## **xcall XSTRIP, strarg, filter, opcode** 

XSTRIP performs various string editing operations. Note that in the first syntax, the routine is equivalent to XCALL STRIP (removes trailing blanks). 

## **Parameters** 

_strarg_ (String, 2+ bytes)  [in/out] 

the string to be operated on. 

_filter_ (String, 1+ bytes)  [in] 

contains filter info, depending on opcode. 

_opcode_ (Num)  [in] 

defines the operation. 

|**Opcode**|**Function**|
|---|---|
|1|All occurrences of any of the individual characters in the filter are removed from_strarg_.|
|2|All occurrences of characters NOT in filter are removed from_strarg_.|
|3|Remove Words._filter_contains a comma-separated list of words to be removed from_strarg_. Double<br>spaces resulting from the removal of a word are shortened to a single space. Example:|



A-Shell Reference 

Page 3309 

|**Opcode**|**Function**|
|---|---|
||`strarg = "THIS IS A TEST OF THIS XCALL ROUTINE"`<br>`filter = "THIS,TEST,ROUTINE"`<br>`XCALL XSTRIP,strarg,filter,3`<br>`Result: strarg = " IS A OF XCALL "`|
|4|Removes matching characters from start of string. For example:<br>`strarg = "THIS IS A TEST TO SEE WHAT IS HAPPENING."`<br>`filter = "SIHT "`<br>`XCALL XSTRIP,strarg,filter,4`<br>`Result: strarg = "A TEST TO SEE WHAT IS HAPPENING."`<br>Note: The removal process was terminated at the first character of_strarg_for which there was no match<br>in filter ("A").|
|5|Remove matching characters from the end of the string. Same concept as opcode 4 but starts at the end<br>of_strarg_and works backwards.|
|6|Pair-wise character substitution:_filter_must contain an even number of characters, interpreted as pairs.<br>Each occurrence in_strarg_of the first character in each pair (of filter) is replaced with the second<br>character of the pair. Example:<br>`XCALL XSTRIP,strarg,"A1B2",6   ! replace all "A" with "1"; "B" with "2"`|



A-Shell Reference 

Page 3310 

|**Opcode**|**Function**|
|---|---|
|7|Reduce multiple spaces to single spaces._filter_not used. E.g.:<br>`XCALL XSTRIP,strarg,"",7`|
|8|(not used)|
|9|Combines the action of opcodes 4 (strip leading characters) and 5 (strip trailing characters) to make it a<br>simpler alternative to Xcall TRIM when you want to strip something other than spaces and TABs.|



## **History** 

- 2024 August, A Shell 7.0.1762: added opcode 9. 

- 2011 May, A Shell 5.1.1215: XSTRIP added to the standard release, after fixing some bugs introduced in 5.1 during translation of the original proprietary version written by John Pruitt. 

A-Shell Reference 

Page 3311 

## **XTEXT** 

## **xcall XTEXT, opcode, flags, src, dst, srow, scol, erow, ecol, exitcode, txtctl {, auxdata, fmtdef}** 

XTEXT provides access to a general purpose Windows text editing control in the A-Shell GUI environment. It is similar in concept to the INFLD multi-line feature, but goes well beyond INFLD to offer such features as: 

- Ability to perform I/O to / from either text buffers or files. 

- Essentially no limit on the size of the text, particularly in file mode. 

- Optional RTF (Rich Text Format) support, including character attributes (bold, italic, etc.), fonts, paragraph styles, 

- justification, etc. 

- Search and replace. 

- Optional / configurable interface components, such as ruler, toolbar, status bar. 

- May be contained within another window or float independently (in which case it can have its own title bar and menu). 

- Ability to protect existing text when adding new text. 

Programmers familiar with XTREE may find that XTEXT is to a simple multi-line edit control as XTREE is to a simple list box, and in fact, the parameter structure and general design of XTEXT have a number of similarities to XTREE. 

XTEXT requires the presence of an external module, ter##.dll, which must be in the Windows system directory or the directory from which ashw32.exe was loaded. 

See the updated ashell.def (edit 135+) for definitions of all symbols used in XTEXT (they all start with TX) and xtext.map for the layout of the _txtctl_ parameter. 

See the program XTX1.BP in EXLIB:[908,40] for a working example and utility for testing the usage of various flags and parameter options. 

## **History** 

A-Shell Reference 

Page 3312 

2016 December, A-Shell 6.3.1541:  Add flag TXF_SILENT. 

- 2013 Feburary, A Shell 6.1.1338: XTEXT now automatically adds "Paste Special" to the context menu when complex clipboard formats are available. Depending on the formats, the menu option will open a submenu with more specific paste options, such as picture, spreadsheet, etc. To customize the wording of the menu option, add or modify the 004,011 message in the SYSMSG.xxx file. All SYSMSG.xxx included in the release package have been updated with rough translations. Note that if you don't want this capability, you can disable it by setting the TXMF1_EDIT_PASTESP flag in the `TXC.MENUMASK1` field. 

- 2011 Feburary , A Shell 5.1.1207: ter18.dll and hts13.dll are supported if using XTEXT, and support for earlier versions is dropped. The files txml2.dll and the Windows library msxml.dll version 2.x or newer is used by and required for the docx import feature. 

## **Subtopics** 

- Text Editing Overview 

- XTEXT Parameters 

- Other XTEXT Topics 

A-Shell Reference 

Page 3313 

## **TEXT EDITING OVERVIEW** 

Although at its simplest, text editing can be considered more or less the same as an INFLD field editing operation (particularly INFLD's multi-line mode), XTEXT allows for a much more sophisticated approach, which can be broken down into the following sub-operations: 

Create the control: The subroutine allows you to create a new control for each text editing session, or re-use an existing one. Up to five separate text editing controls can be defined at any one time. 

Load text into the control: You can supply text to be edited by specifying a text file (plain text or RTF), or by passing the text in a string buffer. Unlike INFLD, the control can also maintain its own copy of the text between editing sessions, so that it does not have to be passed back and forth with the application each time the control gains/loses the focus. 

Edit the text: The control allows for a full range of typical editing capabilities that will be familiar to most Windows users. The application has the ability to define various aspects of the display interface (size, toolbars, menus, rulers, window style, whether to display control characters, etc.), the editing format (e.g. wrap, whether character attributes are allowed), and keyboard commands (i.e. which function keys are passed to the control vs. causing the control to return to the application.) 

Retrieve text from the control: The application can request to retrieve the control's text automatically when the user exits the control, or as an independent operation such as when the changes to an entire screen are to be finalized. The application can retrieve the text directly into a string buffer, or indirectly via a text file. In the case of the string buffer, if the text is too large for the buffer provided, the application is given the option of allocating a larger buffer (using Dynamic Arrays (DIMX) ) and retrieving it again, or retrieving it in multiple pieces. 

Store the text: If you use the option for direct file i/o, then that can be your storage format. Otherwise, if you retrieve the text into a string buffer, the application is left to its own devices as far as storage goes. You might decide to use the ISAM-A variable length record capability, or perhaps just break it up into a series of fixed length records, or maybe even use INMEMO as a filing system. 

Destroy the control: The control may be destroyed automatically at the end of an editing operation, or explicitly under application control, or implicitly (as with other A-Shell AUI controls) when the screen is cleared. 

Printing: If text editing is limited to plain text, then printing can be handled as it is for any other text data (although you may have to deal independently with the question of how to format a variable-length string of text into a suitable printing format). 

A-Shell Reference 

Page 3314 

Most likely you will find that A-Shell's GDI Printing directives TEXTRECTANGLE and/or TEXTINDENT and/or XTEXT, along with the MX_GDICALC subroutine, are quite useful for printing variable-length blocks of text. 

If the text editing is more file-oriented, and especially if it includes character and other formatting attributes (RTF), you may want to enable the ability of the control to print its own contents directly to a printer, more or less like a normal word processing application would (see TXF_TOOLBAR and `TXC.TOOLBARMASK` for adding the printer icon to the toolbar, and `TXC.FMAPCTL` to allow the F4 key to invoke printing.) 

To embed RTF-formatted text directly into another A-Shell report, use the //XTEXT GDI Printing Directive. 

A-Shell Reference 

Page 3315 

## **XTEXT PARAMETERS** 

Parameters that supply data _to_ the routine are indicated with [in], and those used to get data _from_ the routine are labeled [out]. 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|opcode|Num|in|Specifies the operating mode.|
|flags|B,4|in|Used to enable exit keys and other options.|
|src|String|in|Source of text to be edited.|
|dst|String|out|Destination for updated text.|
|srow, scol,<br>erow, ecol|String|in|Position of the control, based on the grid system used by the parent control.|
|exitcode|F,6|out|Returns a code indicating how the list was exited.|
|txtctl|®|in/out|(Mapped structure) A collection of extended parameters and options.|
|auxdata|String|in/out|If a text string is supplied in the AUXDATA parameter, it will be used for the title of any<br>dialog box displayed underXTEXT's direct control. If AUXDATA is not specified, or null,<br>thenXTEXTcontinues to use the SYS:APPMSG.xxx 000,001 message string, which is<br>normally reserved for the application name.|
|fmtdef|String|in|Specify target printer.|



A-Shell Reference 

Page 3316 

**Parameter Type I/O Description** 

A-Shell Reference 

Page 3317 

## **OPCODE** 

## _Opcode_ determines the operational mode. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|TXOP_CREATE|1|This is the only operation you really need. It starts by creating a new text editing control or re-<br>using an existing one, based on the TXC.CTLNO field of the_txtctl_<br>parameter, which see for<br>details. The control is then loaded with text, based on thesrc<br>parameter andTXC.DOCFMT'SRC<br>field of the_txtctl_parameter. In this, the "normal" usage mode, a singleXCALL XTEXTcauses<br>the control object to be created and loaded with data. (If the_src_parameter is empty, the new<br>control starts out empty.) The focus is then put on the control, where the user can perform text<br>editing operations until some kind of exit key or event is triggered. At that point, unless the<br>TXF_DEFERSAVEflag is specified, the contents of the control are returned to the application via the<br>dst<br>parameter. Finally, unless theTXF_MODELESSflag is specified, the control is deleted.|
|TXOP_REEDIT|2|The reedit operation is identical to the TXOP_CREATE operation except that it operates on an<br>existing control and its existing contents. If you have more than one active text edit control<br>defined, then the TXC.CTLNO field of the_txtctl_parameter must indicate which one to reedit. The<br>src<br> parameter is ignored.|
|TXOP_DELETE|3|The operation deletes the control, and is only necessary when the control was created with the<br>TXF_MODELESS flag (otherwise it would have been deleted automatically). Note that you can<br>also delete the XTEXT control (like any other control) by clearing the screen with Tab(-1,0);|
|TXOP_DISPLAY|4|The display operation creates the control, displays it, and leaves it on the screen (regardless of<br>whether TXF_MODELESS set.|
|TXOP_SAVE|5|The save operation retrieves the current contents of the specified text control and either returns<br>it to the application or writes it to a text file, depending on theTXC.DOCFMT'DST<br> flags. This is|



A-Shell Reference 

Page 3318 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||useful in conjunction with previous TXOP_CREATE operations usingTXF_DEFERSAVEand<br>TXF_MODELESS _flags._(TXOP_SAVE overrides theTXF_DEFERSAVEflag.)|
|TXOPF_PRINT|&h010|May be added to TXOP_CREATE or TXOP_REEDIT to print anXTEXTdocument independently of<br>anything else and outside of the normal A-Shell printing subsystem.<br>The combination TXOP_CREATE + TXOPF_PRINT can be used to print anXTEXTdocument from<br>the source (file or buffer), while TXOP_REEDIT + TXOPF_PRINT can be used to print anXTEXT<br>document that is currently open and displayed.<br>You may also request to haveXTEXTdisplay a standard printer select dialog by setting the flag<br>TXF8_SEL_PTR_DLG (&h10000000) to theTXC.FLAGS8<br> field in the_txtctl_parameter.<br>If the printer dialog option is not selected, then printing via TXOP_CREATE + TXOPF_PRINT will<br>not display theXTEXT.|
|TXOPF_PREVIE<br>W|&h020|May be added to TXOP_CREATE, TXOP_REEDIT, or TXOP_DISPLAY to causeXTEXTto display the<br>print preview window. In the case of TXOP_CREATE or TXOP_REEDIT, the user will be left to<br>manipulate the preview, which also means that he/she will be able to print and/or return to edit<br>mode.|
|**Definition file:**<br>ashinc:xtext.def|||



A-Shell Reference 

Page 3319 

## **FLAGS** 

This parameter may be used to enable additional exit keys and other options. Specify as the sum of zero or more of the following. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|TXF_FKEY|&h00000001|Allow F1 through F16 (returning Exitcodes -1 through –16). You must also set<br>individual bits in TXC.FMAPAPP to indicate which function keys you want returned to<br>the app as exitcodes.|
|TXF_LEFT|&h00000002|EnableCTRL+LEFT-ARROW(Exitcode -40)|
|TXF_RIGHT|&h00000004|EnableCTRL+RIGHT-ARROW(Exitcode –41)|
|TXF_UP|&h00000008|EnableCTRL+UP-ARROW(Exitcode -42)|
|TXF_TAB|&h00000020|EnableTAB(Exitcode -44), andSHIFT+TAB(Exitcode -35)|
|TXF_HOME|&h00000040|EnableCTRL+HOMEkey (Exitcode –45)|
|TXF_END|&h00000080|EnableCTRL+ENDkey (Exitcode –46)|
|TXF_ENTESC|&h00000100|Enter key exits from control (Exitcode 0)|
|TXF_MODELESS|&h00000200|Leave text control on the screen after exit|



A-Shell Reference 

Page 3320 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|TXF_EOT|&h00000400|Start editing with cursor at end of text (rather than start)|
|TXF_DEFERSAVE|&h00000800|Defer (or skip) outputting text from the control to the_dst_parameter (unless<br>overridden by TXOP_SAVE_opcode_).|
|TXF_HSCROLL|&h00002000|Display horizontal scroll bar|
|TXF_VSCROLL|&h00004000|Display vertical scroll bar|
|TXF_RULER|&h00008000|Display ruler|
|TXF_STATUS|&h00010000|Display status bar|
|TXF_TOOLBAR|&h00020000|Display toolbar|
|TXF_READONLY|&h00040000|Read only mode. Note that unless you also set TXF_DEFERSAVE, the text will still be<br>output.|
|TXF_POSCUR|&h00080000|Set initial cursor position.|
|TXF_SILENT|&h00100000|Eliminates the user interface and causes the operation to exit immediately. This is<br>mainly useful in conjunction with TXOP_CREATE to convert a file from one format<br>into another.|



A-Shell Reference 

Page 3321 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|TXF_DISABLE|&h00200000|Disable control on exit|
|TXF_DEL|&h00400000|EnableDELexit (Exitcode –47)|
|TXF_MARGIN|&h00800000|Create space around border|
|TXF_NOCLICKOUT|&h01000000|Ignores any click outside of the control with exitcode <-32.|
|TXF_WRAP|&h02000000|Enable word wrap. Note that this flag may also be required to enable pasting of<br>images and inserting of tables. This flag and TXF_FITVIEW are normally both<br>required for proper display of HTML docs.|
|TXF_PRINTVIEW|&h04000000|Enable print view|
|TXF_PAGEMODE|&h08000000|Enable page mode|
|TXF_FITVIEW|&h10000000|Enable fitted view (text is wrapped to fit width of control). This flag and TXF_WRAP<br>are normally both required for proper display of HTML docs.|
|TXF_POPUP|&h20000000|Give text control its own popup (movable) window|
|TXF_MENU|&h80000000|May be combined with TXF_POPUP to create a text editing control window with a<br>complete menu bar. This exposes many new capabilities, particularly for RTF editing.|



A-Shell Reference 

Page 3322 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|**Definition file:**ashinc:xtext.def|||



A-Shell Reference 

Page 3323 

## **SRC** 

_Updated March 2023; "ATE..." section added_ 

The _src_ parameter specifies the source text to be edited, and is interpreted in conjunction with the `TXC.DOCFMT'SRC` field of the _txtctl_ parameter, in one of the following ways: 

• File: To specify a file to edit, set src to the filename, and set the TXFF_FILE flag in the `TXC.DOCFMT'SRC` field of _txtctl_ . In the ATE environment (i.e. when running under Unix with an ATE client), if the filename does not contain a backslash, then it is interpreted as being resident on the server and is automatically transferred to the %ATECACHEDIR% directory on the client workstation for editing. See _ATE File Comments_ below. 

- String Buffer: To specify a string buffer, map src as a string variable of suitable size, load the initial text into it, and do not 

- set the TXFF_FILE flag in `TXC.DOCFMT'SRC` field. 

- Current Control Contents: To reedit the current contents of an existing control, src is not required. Instead, set opcode to 

- TXOP_REEDIT, TXC.CTLNO to the text control number. 

- Format: Independent of whether the document source is supplied as a file or in memory, the low three bits of 

- TXC.docfmt'src should be used to specify the format. 

## **ATE File Transfer Comments** 

When editing a file in an ATE architecture, XTEXT uses the following rules to determine whether the file needs to be transferred from the server to the ATE client for editing: 

- If running locally on Windows (not via ATE), then the source file is assumed to be (has to be) visible directly from the 

- client (no transfer needed). Else... 

• If the TXFF_XFER flag bit it the `TXC.DOCFMT'SRC` of _txtctl_ is set, then the source file is assumed to be on the server and gets transferred to the client for editing. Else... 

• If the _src_ filespec does not contain a backslash, then it is assumed to be on the server and gets transferred to the client for editing. Else... 

- It is assumed to be directly accessible, either local or mapped to a shared network directory, and no transfer takes place. 

A-Shell Reference 

Page 3324 

The main point of confusion occurs when ATE is connected to a Windows server, and the _src_ is on the server but in native Windows notation, e.g. c:\somepath\somefile.txt. To force XTEXT to recognize that this is a server-based file that must be transferred to the client for editing, you either need to set the TXFF_XFER flag, or you can change the backslashes in the filespec to forward slashes. Windows accepts either, but the forward slashes will make it look like a Unix filespec to ATE and thus trigger the transfer logic. 

One other detail about the file transfer that sometimes hangs people up: for Unix servers, the default transfer method is FTP. If that method is not workable, you can force the alternate method (through the ATE communication channel) by setting the TXFF_RAWBUF flag bit in the DOCFMT'SRC field. For Windows servers, it always uses the RAWBUF method. 

## **History** 

- 2020 February, A Shell 6.5.1676: When either XTEXT or AUI_IMAGE needs to transfer a file between the server and client via {S}FTP, they now use FTP2 rather than the older—and now deprecated—FTPDLX routine. Among other advantages of FTP2 is that it doesn't require registering a DLL on he Windows side. 

A-Shell Reference 

Page 3325 

## **DST** 

The _dst_ parameter specifies the destination (where the updated text from the editing operation will be returned), and is interpreted in conjunction with the TXC.DOCFMT'DST field of the _txtctl_ parameter in one of the ways listed below. Note that while the destination and destination format are independent of the source, they can also be the same (i.e. the same filename or the same text buffer variable). 

- File: To output to a file, set _dst_ to the filename, and specify the TXFF_FILE flag in the TXC.DOCFMT'DST field of txtctl. 

- In the ATE environment (i.e. when running under Unix with an ATE client), if the filename does not contain a drive letter or 

- backslash, then it is interpreted as being resident on the server. Since the editing takes place on the workstation, the output is first saved to the local %ATECACHEDIR% directory and the transferred to the server. 

- Internal Memory Buffer: If you set the TXF_DEFERSAVE flag, the updated text is held in an internal memory buffer owned by the 

- control, and the _dst_ parameter is ignored. (The idea here is that you will subsequently make another call to reedit the control using _opco_ de TXOP_REEDIT.) 

• String Buffer: To output the updated text to a string variable, map _dst_ as a string of suitable size, and do not set the TXFF_FILE flag in TXC.DOCFMT'DST field. If the amount of text in the control is too much to fit, then the `TXC.OVERFLOW` field in the _txtctl_ parameter will be set to 1, and only the amount that actually will fit will be output. At that point, your application has the option of retrieving the text using one or more subsequent calls using _op_ code TXOP_SAVE. Initially the `TXC.SAVEOFFSET` field will be set to the position of the first unsaved byte (e.g. the size of _dst_ ), and subsequent save operations will start from that offset and then update the `TXC.SAVEOFFSET` field accordingly. If you prefer to get the entire text into a single text buffer, you can first allocate a string variable of sufficient size (probably using the DIMX statement), and then set the `TXC.SAVEOFFSET` field to -1 before calling XTEXT with _opcode_ TXOP_SAVE. (If you set `TXC.SAVEOFFSET` to 0 rather than -1 it will not realize that there was a previously incomplete save operation and will behave unpredictably.) 

The TXC.OUTBYTES field will be set to the total size of the updated text. So to retrieve the entire text in a single step without the possibility of overflowing, you can first edit the control with the TXF_DEFERSAVE flag set, then allocate a _dst_ variable of size matching `TXC.OUTBYTES` , then use opcode TXOP_SAVE to retrieve the text in one step. 

**Warning:** the _dst_ and _src_ parameters must reference separate variables, else the initialization of the _dst_ string will clear the _src_ string before it gets displayed. 

A-Shell Reference 

Page 3326 

## **SROW, SCOL, EROW, ECOL (XTEXT)** 

The parameters _srow, scol, erow, ecol_ (any numeric type) mark the upper left and lower right corners of the text editing box. Note that the size of the box does not affect the amount of text that can be edited, although it may affect the way the text is wrapped. See the _flags_ TXF_HSCROLL, TXF_VSCROLL, TXF_FITVIEW. 

If the TXF_POPOP bit is set in the _flags_ parameter, the pop-up dialog will initially occupy the space specified by these row/column coordinates, but the user will be able to drag and resize the dialog. If the coordinates are negative, they are interpreted as pixel coordinates, allowing you to position the popup window relative to the desktop rather than the dialog or main A-Shell window. 

A-Shell Reference 

Page 3327 

## **EXITCODE** 

The _exitcode_ parameter serves the same function as the corresponding parameter of the same name in routines such as INFLD and XTREE, i.e. it returns a code indicating how the control was exited, as summarized in following table. See the flags parameter for enabling other exit keys. 

|**Exitcode**|**Meaning**|
|---|---|
|0|Normal exit (Escape w/ update, Enter with TXF_ENTESC)|
|1|Cancel (Escape w/o update)|
|10|Abort (Ctrl+C)|
|11|Timeout; see TXC.timeout in thetxtctl<br>parameter.|
|-35|Shift+Tab (if TXF_TAB)|
|-40|Ctrl+Left-Arrow (if TXF_LEFT)|
|-41|Ctrl+Right-Arrow (if TXF_RIGHT)|
|-42|Ctrl+Up-Arrow (if TXF_UP)|
|-44|Tab (if TXF_TAB)|



A-Shell Reference 

Page 3328 

|**Exitcode**|**Meaning**|
|---|---|
|-45|Ctrl+Home (if TXF_HOME)|
|-46|Ctrl+End (if TXF_END)|
|-47|Del (if TXF_DEL)|
|-49 to -74|Another object clicked|
|-75|File(s) dragged-and-dropped on to a control with the<br>WS_EX_ACCEPTFILES attribute. SeeMX_DRAGDRO<br>P<br>.|
|-76 - 99999|Another object clicked|
|99|Unable to link to DLL|
|98|Invalid TXC.ctlno|
|97||
|96|Unable to load (or save) text file|
|95|Unable to allocate or lock memory|



A-Shell Reference 

Page 3329 

|**Exitcode**|**Meaning**|
|---|---|
|94|Unable to load text buffer into control|
|93|Control deleted by TXC.delctlid|



A-Shell Reference 

Page 3330 

## **TXTCTL** 

_Updated April 2022_ 

This is a structure containing various extended parameters and options. If omitted, suitable defaults will be supplied, although that will severely limit the capabilities of the tree control. For those parameters which are essentially Boolean options, 0=false and 1=true. Most of the fields in _txtctl_ are input-only, but a few, such as SAVEOFFSET are updated as well, and some are outputonly; these are indicated with "[in/out]" or "[out]" in the following table, which lists the structure members alphabetically for easy reference. To use the _txtctl_ structure in your program, include the xtext.sdf and xtext.def files and then map an instance of the structure for each XTEXT in the program, e.g.: 

```
MAP1 TXC, TXTCTL                ! define instance of TXTCTL structure named TXC
```

```
...
```

```
TXC.DOCFFMT'SRC = TXFF_TEXT
```

```
TXC.CTLNO = -1
```

```
etc.
```

Or include the xtext.map file which includes actual map statements for _txtctl_ , rather than a structure definition; in that case, members would be assigned as follows: 

```
TXC'DOCFFMT'SRC = TXFF_TEXT
```

```
TXC'CTLNO = -1
```

```
etc.
```

Note that the first method (declaring an instance of the defined structure _txtctl_ and using the structure dot member notation) has the advantage of making it easy to define and maintain separate copies of the structure for multiple XTEXTs. 

By convention in this document, we refer to the members of the _txtctl_ structure using structure.member notation, as if you had declared an instance of the structure _txtctl_ named TXC, as in the example above. 

A-Shell Reference 

Page 3331 

|**Member**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|BCOLOR|B,4|in|Background (window) color. SeeFCOLOR<br>.|
|BPROTCLR|B,4|in|Background protected color. SeePROTROWS<br>.|
|CTLID|B,2|out|Control ID (overall A-Shell AUI control list).|
|CTLNO|B,1|in/out|Specifies control to use.|
|DELCTLID|B,4|in|ID of control to delete on entrance (life sign). This functions exactly like the analogous<br>XTR.DELCTLID<br> parameter inXTREE, which see for important notes.|
|DOCFMT'DST|B,2|in|Format of output (dst<br>).|
|DOCFMT'SRC|B,2|in|Format of input (src<br>).|
|FCOLOR|B,4|in|Foreground (text) color.|
|FLAGMASK|B,2|in|1's indicate which flags to update|
|FLAGS#|B,4|in|Various low-level flags; see TXF#_xxx inASHINC:XTEXT.DEF<br>.|
|FMAPAPP|B,4|in|1's enable FKEY to be send to app (exitcode).|



A-Shell Reference 

Page 3332 

|**Member**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|FMAPCTL|B,4|in|1's enable FKEY to be sent to control.|
|FONTATTR|B,4|in|Expresses font attributes in the same way as doesfontattr in AUI_CONTROL<br>.|
|FONTFACE|S,32|in|Font typeface.|
|FONTSIZE|B,2|in|Font point size.|
|FPROTCLR|B,4|in|Foreground protected text color.|
|HFLAGMASK|B,2|in|Bitmap controlling interpretation of the TXC.flags# fields; ; same concept as for<br>_TXC.flagmask_.|
|HFLAGS#|B,4|in|HTML flags. See TXFH1_xxx and TXFH2_xxx inASHINC:XTEXT.DEF<br>for bit flag<br>definitions. Note that most options require that the source document format as well as<br>the destination (seeTXC.DOCFMT'SRC<br>and TXC.DOCFMT'DST<br>)have the TXFF_HTML<br>flag set —i.e. they may not work when converting from one document type to<br>another. Also, see the Comments underTXC.DOCFMT'DST<br> for important notes relating<br>to the TXF_PRINTFIEW and TXF_FITVIEW flags.|
|IDNAME|S,40|in|ctlname or parentname>ctlname|
|KBDSTR|S,11|in|Click code.|



A-Shell Reference 

Page 3333 

|**Member**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|MAXBYTES|B,2|in|Maximum bytes allowed (0 = unlimited).|
|MAXROWS|B,2|in|Optional row count limit. If specified, a warning dialog will display when the limit is<br>exceeded (as soon as it happens, periodically, and on exit). Text of dialog can be<br>customized via SBRMSG.xxx 023,002 and 023,003.|
|MENUMASK1,<br>MENUMASK2|B,4|in|TXC.menumask1 and TXC.menumask2 allow individual items and groups of menus to<br>be removed when the TXF_MENU and TXF_POPUP flags are used. See TXMF1_xxx and<br>TXMF2_xxx inASHINC:XTEXT.DEF<br>for the bit flag definitions.|
|MGNBOTTOM*|B,2|in|Bottom margin (twips). Mainly of interest in TXF_PRINTVIEW mode.|
|MGNFOOTER*|B,2|in|Footer margin (twips). Mainly of interest in TXF_PRINTVIEW mode.|
|MGNHEADER*|B,2|in|Header margin (twips). Mainly of interest in TXF_PRINTVIEW mode.|
|MGNLEFT*|B,2|in|Left margin (twips). Mainly of interest in TXF_PRINTVIEW mode.|
|MGNRIGHT*|B,2|in|Right margin (twips). Mainly of interest in TXF_PRINTVIEW mode.|
|MGNTOP*|B,2|in|Top margin (twips). Mainly of interest in TXF_PRINTVIEW mode.|
|MODIFIED*|B,1|out|Non-zero if text buffer modified.|



A-Shell Reference 

Page 3334 

|**Member**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|ORIENT|B,2|in|Orientation (0=dflt, 1=port, 2=land). Mainly of interest in TXF_PRINTVIEW mode.|
|OUTBYTES|B,4|out|Number of bytes output.|
|OUTINES|B,4|out|Number of lines output (or to be output).|
|OVERFLOW|B,1|out|Non-zero if text too big for_dst_param.|
|PAPERSIZE|B,2|in|Paper size (see DMPAPER_xxx). Mainly of interest in TXF_PRINTVIEW mode.|
|PARENTID|B,2|in|ID of parent of control (e.g. a dialog): 0 for a normal child control on the main<br>window.|
|PROTROWS|B,4|in|Rows to protect (-1 = all, -2 all but last).|
|SAVEOFFSET|B,4|in/out|Position in buffer to start next save (or -1 to restart a previously incomplete save<br>operation from the beginning).|
|SFLAGS|B,2|in|Search flags|
|SRCHKEY|S,30|in|String to search for|
|TIMEOUT|B,4|in|Milliseconds until timeout. The timer gets reset on keystrokes and on mouse activity|



A-Shell Reference 

Page 3335 

|**Member**|**Type**|**I/O**|**Description**|
|---|---|---|---|
||||within the control. If the timer expires,XTEXTwill return EXITCODE=11 (likeINFLD<br>andXTREE) and any editing changes will be saved.|
|TOOLBARMASK|B,4|in|1's remove object from toolbar (see TXTB_xxx).|
|WRAPWIDTH|B,2|in|Width in characters for word wrap.|
|XCOL|B,2|in/out|Cursor column on exit and optionally on entrance (base 1). See TXF_POSCUR.|
|XCUROFFSET|B,4|in/out|Absolute cursor position on exit and optionally on entrance. (base 0)|
|XROW|B,4|in/out|Cursor row on exit and optionally on entrance (base 1). See TXF_POSCUR.|
|**Definition file:**xtext.sdf||||



* **Warning:** setting any of the margin fields has the probably-undesirable side effect of triggering the text-modified flag. This results in the "text has changed - do you want to save" message box appearing even when no changes have been made. You can eliminate the spurious message/question by setting the TXF8_ESC_SAVE bit in TXC.flags8, and you could use another exitcode to distinguish abort/discard from save, but it might be preferable to just eliminate the margins. 

A-Shell Reference 

Page 3336 

## **TXC.WRAPWIDTH** 

This field only applies when the TXF_WRAP bit is set in the flags parameter, and neither of the flags TXF_FITVIEW or TXF_PRINTVIEW are set. In that case, it specifies the wrap width in character units. Note that with a proportional font, it may appear that the wrap trigger is different on each line. 

If TXF_FITVIEW is specified, then this field is ignored and the wrap width is equal to the control width. 

If TXF_FITVIEW is not specified and `TXC.WRAPWIDTH` is 0, then the wrap width will be determined by the ruler or the printed page width. 

If TXF_PRINTVIEW is specified, `TXC.WRAPWIDTH` is ignored and wrap is determined by the combination of the paper width 

( `TXC.PAPERSIZE` ), margins ( `TXC.MGNLEFT` _,_ `TXC.MARGINRIGHT` ), and font ( `TXC.FONTFACE` _,_ `TXC.FONTSIZE` ). 

If the TXFF_TEXT_LINES bit is set in the `TXC.DOCFMT'DST` parameter, the output lines will be terminated with line breaks at the point of the wrap (regardless of how the wrap was determined). 

A-Shell Reference 

Page 3337 

## **TXC.DOCFMT'SRC** 

This field contains flags which adjust the interpretation of the _src_ parameter. Choose no more than one value from each of the first two sections, and zero or more of the ATE Transfer Options, from the following table. 

|**Doc format**|**Value**|**Description**|
|---|---|---|
|TXFF_TEXT|0|Standard notepad-style text. CRLF is used to terminate paragraphs, not individual lines.|
|TXFF_TEXT_LINES|1|Text with line breaks. This only applies to the output, and if set, inserts line terminators at<br>the points where wrap occurs.|
|TXFF_RTF|2|RTF (Rich Text Format)|
|TXFF_HTML|4|HTML (browser mode)|
|TXFF_UTEXT|5|Unicode text|
|TXFF_SSE|6|Proprietary (SSE) format|
|**Storage medium**|||
|TXFF_STRING|&h0000|String variable (aka "buffer," as opposed to "file")|
|TXFF_FILE|&h0100|File (versus string/buffer). In the case of TXFF_HTML, this may also be a valid web URL.<br>See Browser Mode.|



A-Shell Reference 

Page 3338 

|**ATE Transfer Options**|**ATE Transfer Options**|**ATE Transfer Options**|
|---|---|---|
|TXFF_RAWBUFF|&h0400|May be set in the`TXC.DOCFMT'SRC`field to cause the source file to be transferred to the<br>ATE client via the ATE auxport transfer protocol, rather than via FTP. (This is the default<br>mode for ATSD, where FTP is typically not available but it may be set explicitly for Unix<br>applications. When`TXC.DOCFMT'SRC`is a buffer (i.e. TXFF_FILE flag is not specified), then<br>TXFF_RAWBUF may be set in the`TXC.DOCFMT'DST`field to cause the return buffer to be<br>sent directly (via the_stdin_channel) rather than via FTP. In both cases, the TXFF_RAWBUF<br>method is faster, provided the amount of text is less than about 4K. (FTP starts out slower<br>due to the need to establish a new connection, but eventually catches up due to<br>windowing and other flow maximization techniques.) Note that the TXFF_RAWBUF bit<br>should only be used in the`TXC.DOCFMT'DST`field for files that cannot contain binary data<br>(such as embedded objects).|
|TXFF_XFER|&h0800|May be specified in the source format field (`TXC.DOCFMT'SRC`) to forceXTEXTto interpret<br>the source file as being local to the server and requiring transfer to the client. Without this<br>flag, the PC filespecs (containing backslashes) will be assumed to be visible directly to the<br>client and thus not requiring file transfer. (This mainly a concern with ATSD where both<br>the server and client environments are Windows.)|
|**Definition file:**ashinc:xtext.def|||



## **Comments** 

TXF_WRAP and TXF_FITVIEW are both typically required for proper display of HTML documents. 

A-Shell Reference 

Page 3339 

## **TXC.DOCFMT'DST** 

This field is analogous to `TXC.DOCFMT'SRC` except applies to the interpretation of the _dst_ parameter. See the `TXC.DOCFMT'SRC` table for possible values. Note that the input and output options are generally independent (see _Comments_ , below). For example, you can input from a file in plain text format and output to a string variable in RTF format. You can also specify the same variable and options for both input and output in order to store the output on top of the input. 

## **Comments** 

There are a couple of exceptions to the above relating to HTML. First, when _src_ is a web-based HTML document, or a form, then the destination storage medium must be TXFF_STRING. In other words, when using XTEXT as a web browser, there is no real destination. You would normally have the TXF_READONLY flag set in this case anyway, so the question of output may be moot but TXFF_STRING avoids any ambiguity of intent. 

The second exception is that when editing files in HTML format (either with the intent of creating actual web documents or simply as simpler alternative to RTF to allow basic formatting such as bold), you must select the TXF_PRINTVIEW option in _flags_ in order to enable the `TXC.HFLAGS#` options that pertain to the output format options. In contrast, the TXF_FITVIEW option is intended for HTML browsing and only saves using a standard set of output options, ignoring most of the `TXC.HFLAGS#` bits. 

A-Shell Reference 

Page 3340 

## **TXC.OUTBYTES** 

This field indicates the total number of "user bytes" in the updated control available to be output, or that were already output. By "user bytes", we are referring to characters actually typed by the user, not to any formatting bytes that would be inserted automatically into the output stream based on the output format specified in `TXC.DOCFMT'DST` . 

In the case of plain text output (TXFF_TEXT or TXFF_TEXT_LINES), there are no extraneous formatting bytes needed, so the value can be used to determine the total size. This can be useful when outputting to a string variable using the TXF_DEFERSAVE option, as it would tell you how big of a variable you would need to retrieve the entire contents. But for output formats that include extraneous formatting bytes, such as RTF and HTML, the actual size required will be substantially larger than the value returned in `TXC.OUTBYTES` . You could, however, use a dynamic (self-expanding) string variable to receive the output, and then determine the actual length using the LEN() function. 

A-Shell Reference 

Page 3341 

## **TXC.SAVEOFFSET** 

This field is primarily useful when outputting to a string variable that is not large enough to hold the entire text. In that case, it indicates the starting position of the next byte to be saved, relative to the beginning of the text buffer. For example, if the _dst_ parameter was 5000 bytes long and the total size of the output text was 13000 bytes, then in the first save operation, 5000 bytes would be output to _dst_ and `TXC.SAVEOFFSET` would be set to 5000. On the next call (with _opcode_ set to TXOP_SAVE), the save operation would continue from that position, and again output until _dst_ was full (presumably another 5000 bytes). At this point, `TXC.SAVEOFFSET` would be set to 10000. On the next call with _o_ pcode TXOP_SAVE, the save would start from that offset and continue to the end of the file (13000) in this case. 

In another scenario, let's say that after receiving the first 5000 bytes, you decide that you would rather get it all in a single 13000 byte butter. In that case you could allocate a 13000 byte string to receive the entire block of text, and set `TXC.SAVEOFFSET` back to -1 so that the next save operation would re-start from the beginning. (The -1 tells the control to use the intermediate storage from the previous save operation.) 

A-Shell Reference 

Page 3342 

## **TXC.SRCHKEY** 

If this field is not blank, an edit operation ( _opco_ de TXOP_CREATE or TXOP_REEDIT) will start by searching for the specified string, based on the options set in the `TXC.SFLAGS` parameter. The search starts from the same place that the cursor would ordinarily start (see _flags_ TXF_EOT and TXF_POSCUR and parameters `TXC.XCOL, TXC.XROW, TXC.XCUROFFSET` ). 

If the search flag TXSF_EXIT is specified in `TXC.SFLAGS` , then the operation will return immediately. If successful, the _exitcode_ will be 0 and the cursor position parameters ( `TXC.XCOL, TXC.XROW, TXC.XCUROFFSET` ) will be set to indicate the location of the first match. If not successful, _exitcode_ will be set to -49 and the cursor position parameters will remain unchanged. To search for additional occurrences of the string, adjust the `TXC.XCOL` and/or `TXC.XROW` parameters by 1 (forwards or backwards, depending on the direction of the search) and repeat the operation. 

If the search flag TXSF_EXIT is not specified, then the normal editing operation will take place after the search. 

The following character sequences can be embedded in the search string to search for special control characters: 

|**Two-char**<br>**code in**<br>**TXC.srchkey**|**Matches special**<br>**char  in control**|
|---|---|
|^p|Paragraph marker|
|^t|Tab character|
|^m|Manual (hard) page break|
|^+|Em dash|
|^-|En dash|



A-Shell Reference 

Page 3343 

|**Two-char**<br>**code in**<br>**TXC.srchkey**|**Matches special**<br>**char  in control**|
|---|---|
|^^|^ character|



A-Shell Reference 

Page 3344 

## **TXC.SFLAGS** 

This field may contain one or more of the following options, affecting the way the search operation works. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|TXSF_SCROLL|&h0001|Scroll located text into view|
|TXSF_CASE|&h0010|Case sensitive search|
|TXSF_WORD|&h0020|Match whole words only|
|TXSF_BACK|&h0080|Search backwards|
|TXSF_EXIT|&h1000|Exit immediately after search|



A-Shell Reference 

Page 3345 

## **TXC.FLAGMASK1** 

This field controls the interpretation of the following flag fields ( `TXC.FLAGS1, TXC.FLAGS2` , etc.) These fields provide access to a large number of individual (mostly obscure) options in the text edit control. Each of the bits in both the low byte and high byte of `TXC.FLAGMASK` correspond to one of the `TXC.FLAGS?` fields. (The low bits in each byte, &h01 and &h0100, correspond to `TXC.FLAGS1` , etc.) 

If both bits (from the upper byte and lower byte) corresponding to a particular flag field are zero, then the bits in that corresponding `TXC.FLAGS?` field are OR'd into the current flag settings. In other words, if `TXC.FLAGMASK = &H0000` and `TXC.FLAGS1 = &H0201` , then the flags represented by the bits &h0201 would be activated, in addition to whatever flags are set internally be default. Since it is difficult to understand all of the reasons for the internal defaults, but it may be possible to recognize a particular flag that you'd like to set, this is by far the most likely way to use these fields. 

However, the `TXC.FLAGMASK` provides two other ways to interpret the `TXC.FLAGS?` fields. If the bit corresponding to a `TXC.FLAGS?` field in the upper word of `TXC.FLAGMASK` is set, then any bits which are set in that corresponding to `TXC.FLAGS?` field will clear the associated internal flag. This would only be useful in a situation you were able to identify a particular default flag that you wanted to turn off. 

The final possibility is where the bit in the upper byte of `TXC.FLAGMASK` is clear, but the bit in the lower byte is set. In that case, the corresponding `TXC.FLAGS?` field is used to set or reset ALL of the associated flags. For example, if `TXC.FLAGMASK = &H0001` and `TXC.FLAGS1 = &H0400` , then all of the flags represented by `TXC.FLAGS1` would be cleared, except for the one represented by the eleventh bit (&h0400) would be set. As with the previous case, this mode requires that you understand all of the flags for that flags word, since you will be setting or clearing all of them at once. 

A-Shell Reference 

Page 3346 

|**Flags**|**Description**|
|---|---|
|&h0000|(Additive mode) Enable flags specified by 1's in the<br>_TXC.flags?_fields|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|&h0001|Set/clear all flags in the_TXC.flags1_field|
|&h0002|Set/clear all flags in the_TXC.flags2_field|
|&h0003|Set/clear all flags in the_TXC.flags3_field|
|&h0004|Set/clear all flags in the_TXC.flags4_field|
|&h0005|Set/clear all flags in the_TXC.flags5_field|
|&h0006|Set/clear all flags in the_TXC.flags6_field|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|||



&h0100 Disable flags specified in the _TXC.flags1_ field 

A-Shell Reference 

Page 3347 

|**Flags**|**Description**|
|---|---|
|&h0000|(Additive mode) Enable flags specified by 1's in the<br>_TXC.flags?_fields|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|&h0001|Set/clear all flags in the_TXC.flags1_field|
|&h0002|Set/clear all flags in the_TXC.flags2_field|
|&h0003|Set/clear all flags in the_TXC.flags3_field|
|&h0004|Set/clear all flags in the_TXC.flags4_field|
|&h0005|Set/clear all flags in the_TXC.flags5_field|
|&h0006|Set/clear all flags in the_TXC.flags6_field|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|||



&h0200 Disable flags specified in the _TXC.flags2_ field 

A-Shell Reference 

Page 3348 

|**Flags**|**Description**|
|---|---|
|&h0000|(Additive mode) Enable flags specified by 1's in the<br>_TXC.flags?_fields|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|&h0001|Set/clear all flags in the_TXC.flags1_field|
|&h0002|Set/clear all flags in the_TXC.flags2_field|
|&h0003|Set/clear all flags in the_TXC.flags3_field|
|&h0004|Set/clear all flags in the_TXC.flags4_field|
|&h0005|Set/clear all flags in the_TXC.flags5_field|
|&h0006|Set/clear all flags in the_TXC.flags6_field|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|||



&h0300 Disable flags specified in the _TXC.flags3_ field 

A-Shell Reference 

Page 3349 

|**Flags**|**Description**|
|---|---|
|&h0000|(Additive mode) Enable flags specified by 1's in the<br>_TXC.flags?_fields|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|&h0001|Set/clear all flags in the_TXC.flags1_field|
|&h0002|Set/clear all flags in the_TXC.flags2_field|
|&h0003|Set/clear all flags in the_TXC.flags3_field|
|&h0004|Set/clear all flags in the_TXC.flags4_field|
|&h0005|Set/clear all flags in the_TXC.flags5_field|
|&h0006|Set/clear all flags in the_TXC.flags6_field|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|||



&h0400 Disable flags specified in the _TXC.flags4_ field 

A-Shell Reference 

Page 3350 

|**Flags**|**Description**|
|---|---|
|&h0000|(Additive mode) Enable flags specified by 1's in the<br>_TXC.flags?_fields|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|&h0001|Set/clear all flags in the_TXC.flags1_field|
|&h0002|Set/clear all flags in the_TXC.flags2_field|
|&h0003|Set/clear all flags in the_TXC.flags3_field|
|&h0004|Set/clear all flags in the_TXC.flags4_field|
|&h0005|Set/clear all flags in the_TXC.flags5_field|
|&h0006|Set/clear all flags in the_TXC.flags6_field|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|||



&h0500 Disable flags specified in the _TXC.flags5_ field 

A-Shell Reference 

Page 3351 

|**Flags**|**Description**|
|---|---|
|&h0000|(Additive mode) Enable flags specified by 1's in the<br>_TXC.flags?_fields|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|&h0001|Set/clear all flags in the_TXC.flags1_field|
|&h0002|Set/clear all flags in the_TXC.flags2_field|
|&h0003|Set/clear all flags in the_TXC.flags3_field|
|&h0004|Set/clear all flags in the_TXC.flags4_field|
|&h0005|Set/clear all flags in the_TXC.flags5_field|
|&h0006|Set/clear all flags in the_TXC.flags6_field|
|**Flags**<br>**(high**<br>**byte)**|**Description**|
|||



&h0600 Disable flags specified in the _TXC.flags6_ field 

A-Shell Reference 

Page 3352 

A-Shell Reference 

Page 3353 

## **TXC.FLAGS1** 

A set of flags that can be individually set to enable the corresponding options. See `TXC.FLAGMASK` . Note that all of the possible bits correspond to some feature (we only documented those that seemed even remotely interesting); on the other hand, even those that are documented are not necessarily fully implemented in XTEXT. 

By default, several of the flags represented by the various `TXC.FLAGS?` words are internally set, so care should be taken to not change the values of existing flags you do not understand. (Set `TXC.FLAGMASK` to 0 to turn on individual flags, or by set the bit(s) in the high byte of `TXC.FLAGMASK` to 1 to turn off individual flags.) 

|**Value**|**Description**|
|---|---|
|&h00000002|Show ruler measurements in metric units|
|&h00000004|Set the page orientation to that of the default printer. (Applies only when either the<br>TXF_PRINTVIEW or TXF_PAGEVIEW bits are set in_flags_.)|
|&h00000020|Disable the internal accelerator table. Also see`TXC.FMAPCTL`and`TXC.FMAPAPP`.|
|&h00000080|Show caret even in read-only mode|
|&h00008000|Automatic vertical scroll bar|
|&h00100000|Disable use of printer|
|&h00200000|Disable drag/drop for text|



A-Shell Reference 

Page 3354 

|**Value**|**Description**|
|---|---|
|&h00400000|Disable OLE editing|
|&h02000000|Show the page break lines even in read-only mode. (SeePage Breaks<br>.)|
|&h80000000|Swap decimal and comma in dialog boxes|
|**Definition file:**ashinc:xtext.def||



A-Shell Reference 

Page 3355 

## **TXC.FLAGS2** 

More flags similar to those in `TXC.FLAGS1.` 

|**Value**|**Description**|
|---|---|
|&h00000080|Show section page number on status bar|
|&h00000100|Do not change cursor shape as mouse moves over edit window|
|&h00000200|Scroll the text window while dragging the vertical scroll bar (smooth scroll)|
|&h00000400|Do not auto-repaginate while editing text|
|&h00000800|Do not save the original as a backup before saving text to file|
|&h00002000|Hide soft page break lines when in TXF_PAGEMODE|
|&h00004000|Protect the formatting of protected text|
|&h00008000|Do not write hidden text to RTF file|
|&h00010000|Do not apply shading to field text (e.g. dates, page numbers)|
|&h00100000|Always fully repaint text box|



A-Shell Reference 

Page 3356 

|**Value**|**Description**|
|---|---|
|&h02000000|Do not show cancel print dialog when printing|
|&h10000000|Do not adjust cursor when placing it over protected or hidden text|
|&h20000000|When cursor is not allowed within protected text, move it to start of protected<br>text rather than after it. (See next flag.)|
|&h40000000|Do not allow the cursor in the middle of protected text.|
|**Definition file:**ashinc:xtext.def||



ddd 

A-Shell Reference 

Page 3357 

## **TXC.FLAGS3** 

More flags similar to those in `TXC.FLAGS1.` 

|**Value**|**Description**|
|---|---|
|&h00000001|Wrap extra spaces at the end of the line to start of next line|
|&h00000010|Display text in gray in read-only mode|
|&h00001000|Use older RTF format (for older versions of Word)|
|&h00040000|Do not collect undo information|
|&h00400000|Scroll one line at a time when up or down arrow pressed|
|&h10000000|Read PNG images from RTF files|
|&h20000000|Do not adjust text color to contrast with background|
|&h40000000|Do not allow text selection with mouse|
|**Definition file:**ashinc:xtext.def||



A-Shell Reference 

Page 3358 

## **TXC.FLAGS4** 

More flags similar to those in `TXC.FLAGS1.` 

|**Value**|**Description**|
|---|---|
|&h00000001|Count paragraph character as 2 characters (CRLF)|
|&h00000002|Do not allow cursor anywhere in protected text|
|&h00000020|Smooth scroll|
|&h00000200|Save RTF pictures in binary (instead of hex) format|
|&h00004000|Disable OLE drop|
|&h00020000|Do not update date/time fields. (Does not apply to plain text)|
|&h20000000|Paste properties of last paragraph when text pasted in empty paragraph.|
|&h40000000|Print WMF (metafile) images as bitmaps|
|**Definition file:**ashinc:xtext.def||



A-Shell Reference 

Page 3359 

## **TXC.FLAGS5** 

More flags similar to those in `TXC.FLAGS1.` 

|**Value**|**Description**|
|---|---|
|&h00000001|Disable text drop from other applications. (Must be set when control first created.)|
|&h00000002|Group undo operations into one undo|
|&h00000004|Translate 'exact' row height to minimum row height in RTF input|
|&h00000010|Disable text selection using the keyboard|
|&h00000040|Ignore embedded objects when display status line number|
|&h00000800|Allow caret to stop before and after hidden text|
|&h00002000|Show page setup rather than print setup options in printer setup dialog.|
|&h00004000|Fully repaginate document on load (no matter how big)|
|&h00008000|Save PNG data in RGB format|
|&h00010000|Do not show space symbol (when showing marks)|



A-Shell Reference 

Page 3360 

|**Value**|**Description**|
|---|---|
|&h00400000|Save JPG, PNG, GIF images in WMF format|
|&h01000000|When applying an indent to a set of marked lines, give them all the same indent (rather<br>than keeping the relative indents).|
|&h08000000|Allow for unlimited OLE storage space|
|&h10000000|Display old style ruler|
|**Definition file:**ashinc:xtext.def||



|**Value**|**Description**|
|---|---|
|&h00400000|Save JPG, PNG, GIF images in WMF format|
|&h01000000|When applying an indent to a set of marked lines, give them all the same indent (rather<br>than keeping the relative indents).|
|&h08000000|Allow for unlimited OLE storage space|
|&h10000000|Display old style ruler|
|**Definition file:**ashinc:xtext.def||



A-Shell Reference 

Page 3361 

## **TXC.FLAGS6** 

More flags similar to those in `TXC.FLAGS1.` 

|**Value**|**Description**|
|---|---|
|&h00000008|Use printer-independent metrics for wrapping and pagination.|
|&h00000040|Embed pictures using real pixel size (ignore recommended size)|
|&h00001000|Insert dropped pictures as linked rather than embedded|
|&h80000000|Generate line break whenENTERpressed, andCARRIAGERETURNwhenSHIFT+ENTER<br>pressed (reverse of normal).|
|**Definition file:**ashinc:xtext.def||



A-Shell Reference 

Page 3362 

## **TXC.FLAGS7** 

More flags similar to those in `TXC.FLAGS1` . See definition file ashinc:xtext.def for full listing. 

A-Shell Reference 

Page 3363 

## **TXC.FLAGS8** 

More flags similar to those in `TXC.FLAGS1` . 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|TXF8_SEL_PTR_DLG|&100000000|Select printer dialog (TXOPF_PRINT)|
|TXF8_PROTECT_FORM|&h20000000|Protect form (only input fields can be changed)|
|TXF8_ESC_ABORT|&h40000000|Force ESC to exit w/o save|
|TXF8_ESC_SAVE|&h80000000|Force ESC to save and exit|
|**Definition file:**ashinc:xtext.def|||



A-Shell Reference 

Page 3364 

## **TXC.FMAPCTL** 

This is a 32 bit bitmap in which each bit set to 1 enables the corresponding function key to be sent to the control. For example, &h00000001 enables F1 to be sent to the control and &h00008000 enables F16 to be sent to the control. (The upper 16 bits correspond to Shifted F1 through F16.) The following table indicates how the control would normally interpret the function keys: 

|**Key**|**Action**|
|---|---|
|F1|Help|
|F3|Save|
|Shift+F3|Save As|
|F4|Print|
|Shift+F4|Printer Setup|
|F5|Search|
|F6|Replace|
|F10|Jump to line number|



**History** 

A-Shell Reference 

Page 3365 

- 2006 August, A Shell 4.9.963: XTEXT now supports an option to make the Save icon on the toolbar act like "Save As" (i.e. display a dialog to allow you to choose a filename and location) rather than just "Save." To active this option, clear bit 3 (corresponding to the Save command, which is equivalent to F3) and set bit 19 (corresponding to the Save-As command, or SHIFT+F3). For example, if you previously had `TXC.FMAPCTL = &H000000FF` (i.e. send all the functions corresponding to F1-F8 to the control), you would change this to &h000400EF to force the Save button to act like Save-As. Note that this would not affect the keyboard commands F3 and SHIFT+F3, which would continue to distinguish between Save and Save-As. 

A-Shell Reference 

Page 3366 

## **TXC.TOOLBARMASK** 

The flags in this bitmap field allow you to remove objects from the toolbar (and only apply if TXF_TOOLBAR is specified in the main _flags_ parameter. 

|**Symbol**|**Value**|**Item being Removed**|
|---|---|---|
|TXTB_ROW1|&h00000001|Entire first row of toolbar|
|TXTB_NEW|&h00000002|File | New button|
|TXTB_OPEN|&h00000004|File | Open button|
|TXTB_SAVE|&h00000008|File | Save button|
|TXTB_PRINT|&h00000010|File | Print button|
|TXTB_PREVIEW|&h00000020|File | Preview button|
|TXTB_CLIPBOARD|&h00000040|Clipboard buttons (cut, copy, paste)|
|TXTB_UNDOREDO|&h00000080|Undo/redo buttons|
|TXTB_FIND|&h00000100|Search (binoculars) button|
|TXTB_DATE|&h00000200|Insert-date button|



A-Shell Reference 

Page 3367 

|ell Reference|||
|---|---|---|
||||
|TXTB_PAGENUM|&h00000400|Insert-page # button|
|TXTB_PAGECOUNT|&h00000800|Insert-page count button|
|TXTB_SHOWMARKS|&h00001000|Show marks (e.g. paragraph) button|
|TXTB_HELP|&h00002000|Help button|
|TXTB_ZOOM|&h00004000|Zoom button|
|**Flags (second row)**|||
|TXTB_ROW2|&h00010000|Entire second row of toolbar|
|TXTB_STYLE|&h00020000|Paragraph style dropdown|
|TXTB_FONTFACE|&h00040000|Font typeface dropdown|
|TXTB_POINTSIZE|&h00080000|Font point size dropdown|
|TXTB_CHARATTR|&h00100000|Bold/italics/underline buttons|



A-Shell Reference 

Page 3368 

|ell Reference|||
|---|---|---|
|TXTB_ALIGN|&h00200000|Alignment buttons|
|TXTB_NUMLIST|&h00400000|Numbered list button|
|TXTB_BULLETS|&h00800000|Bullet list button|
|TXTB_INDENT|&h01000000|Indent buttons|
|TXTB_SHOW_HIDE|&h80000000|May be used in conjunction with TXF_RULER,<br>TXF_TOOLBAR and/or TXF_STATUS to<br>automatically remove the ruler, toolbar and<br>status ribbon when the control is in-active,<br>and re-display them when the control is re-<br>activated via TXOP_REEDIT.|
|**Definition file:**ashinc:xtext.def|||
|**Documentation can be imperfect. Only rely on definition file.**|||



A-Shell Reference 

Page 3369 

## **TXC.FCOLOR** 

The lower 3 bytes of this 32 bit field are used to specify a custom foreground text color as a set of RGB values. The low byte is the R (red) value, the second lowest byte is the G (green) value and the third lowest byte is the B(blue) value. The maximum for each field is 255. When all three are set to 255 (e.g. &h00FFFFFF) you get white; when all are set to 0 (e.g. &h00000000) you get black. However, to distinguish the latter case from the default (which is also &h00000000) you must set one of the bits in the upper byte to a non-zero value. For example, to set the text color to black, you might set `TXC.FCOLOR` to &h10000000. Since the default text color is black, this is not much of an issue, but the concept applies to all of the RGB-style color fields. 

## **History** 

- 2021 March, A Shell 6.5.1701:  The automatic use of the Active Background Color (introduced in 6.5.1698.0) can now be overridden by setting one or more bits in the high byte of the `TXC.BCOLOR` field. Note that even though XTEXT treats a `TXC.BCOLOR` value of 0 as meaning "default" (i.e. white), 0 is technically the RGB value for black. So if you want to override the Active Background Color feature, so that the background remains white even when actively editing, then you should set `TXC.BCOLOR` explicitly to white (i.e. -1 or &hFFFFFFFF). 

A-Shell Reference 

Page 3370 

## **TXC.PROTROWS** 

This field allows you to specify a block of existing lines of text to be protected from change. This is particularly useful in a rigorous transaction environment where your application encourages the use of comments but rightly makes it difficult for anyone to remove previously entered comments. Another possibility is to use this feature as a way of protecting a few header lines of text which instruct the user how text should be entered. If you set `TXC.PROTROWS` to a positive number, it protects that many lines, starting from the top. If you set it to a negative number, it protects all but a certain number of lines at the bottom: -1 protects all lines, -2 protects all but the last line, -3 all but the last two lines, etc. 

A-Shell Reference 

Page 3371 

## **TXC.IDNAME** 

This field allows you to specify names for the parent and/or XTEXT control. You may use any of the following formats: 

```
TXC.idname = "xtextname"
```

```
TXC.idname = "parentname>xtextname"
```

```
TXC.idname = ">xtextname"
```

Note that if the parent control name is specified this way, then it overrides anything in the `TXC.PARENTID` field (and that field will be updated on return with the numeric control ID matching the specified parentname.) 

Note that despite the similar format used by the INFLD V parameter, in this case a name by itself (with no ">") is interpreted as the name of the control rather than the name of the parent control (as in INFLD). 

A-Shell Reference 

Page 3372 

## **TXC.MAXBYTES** 

This field allow a maximum number of bytes to be specified for the text memo. Note that the mechanism for determining when the limit is reached is not perfect, and only operates during the processing of normal keystrokes. It does not operate during the paste operation, nor during the memo load, nor during replacement operations. (These loopholes may be closed in a later release.) Also, the field only supports a limit of up to 64K, on the theory that the space in the _txtctl_ structure is more valuable than the likelihood of somebody wanting to set a limit of more than 64K. However, if you see a problem with that, please comment back to the developer. 

A-Shell Reference 

Page 3373 

## **TXC.FLAGMASK** 

This 16 bit bitmap controls how the routine will interpret the `TXC.FLAGS#` fields. Because of the large number of flags, and the fact that some of them default to ON while others default to OFF, it is not practical for applications to have to consider and properly set/reset all of them. Instead, it is typically more convenient to force just a few individual flags ON, or OFF, or to replace a block of flags. These three modes are referred to "addition", "subtraction", and "replacement", respectively. In "addition mode", any bits set in the `TXC.FLAGS#` field will be added to the current or default flags for the control (i.e. forced ON or ENABLED). In "subtraction mode", any bits set in the `TXC.FLAGS#` field will be subtracted from the current settings (i.e. forced OFF or DISABLED). In "replacement mode", all of the flags corresponding to an entire 32 bit `TXC.FLAGS#` field are replaced (i.e. turned ON/OFF) according to the pattern of 1s and 0s in field. 

The default mode is addition, meaning that to enable any individual flags, just set the corresponding bits in the `TXC.FLAGS#` fields. (The specified options will be enabled; all the other options corresponding to the 0s in the `TXC.FLAGS#` fields will be left in their current or default state.) To specify subtraction or replacement mode for any of the `TXC.FLAGS#` fields, set the `TXC.FLAGMASK` bitmap to a combination of bit patterns from the following table: 

|**Bit**<br>**Pattern**|**Interpretation**|
|---|---|
|&h0001|Replacement mode for TXC.flags1|
|&h0002|Replacement mode for TXC.flags2|
|&h0004|Replacement mode for TXC.flags3|
|&h0008|Replacement mode for TXC.flags4|
|&h0010|Replacement mode for TXC.flags5|



A-Shell Reference 

Page 3374 

|&h0020|Replacement mode for TXC.flags6|
|---|---|
|&h0040|Replacement mode for TXC.flags7|
|&h0080|Replacement mode for TXC.flags8|
|&h0100|Subtraction mode for TXC.flags1|
|&h0200|Subtraction mode for TXC.flags2|
|&h0400|Subtraction mode for TXC.flags3|
|&h0800|Subtraction mode for TXC.flags4|
|&h1000|Subtraction mode for TXC.flags5|
|&h2000|Subtraction mode for TXC.flags6|
|&h4000|Subtraction mode for TXC.flags7|
|&h8000|Subtraction mode for TXC.flags8|



**Example** 

A-Shell Reference 

Page 3375 

```
TXC.flagmask = &h0410                                ! subtraction for TXC.flags3, replacement for TXC.flags5
TXC.flags1 = TXF1_METRIC or TXF1_HIDE_PAGE_BREAK     ! set these flags (addition)
TXC.flags3 = TXF3_EMBEDDED_TABLES or TXF3_NO_SCROLL  ! clear these flags  (subtraction)
```

```
TXC.flags5 = TXF5_GROUP_UNDO or TXF5_NO_KB_SEL       ! set these and clear all other TXF5_xxx flags
(replacement)
```

A-Shell Reference 

Page 3376 

## **FMTDEF** 

_Updated March 2026; see History_ 

You may specify the target printer, using standard Windows printer name syntax, by adding the following clause to the fmtdef parameter: 

## `Printer=name` 

where name is the descriptive name of the printer, as it appears in the print manager control panel applet. If there are other clauses in the _fmtdef_ parameter, terminate this one with a "~" or ",". If no printer is specified, the current default printer is used. 

The following directives can be added to the _fmtdef_ parameter to affect the preview settings: 

```
PVzoom=###        zoom %, 0-200%, 0=fitted to window; default 0
```

```
PVpages=#         # pages in preview display; 1 or 2; default 1
PVtoolbar=<bool>  1/0,T/F for preview toolbar; default=1
```

If more than one clause is present in the _fmtdef_ parameter, separate them with the tilde character. 

## **History** 

- 2026 March, A Shell 1784:  Add directives PVzoom, PVpages, PVtoolbar. 

A-Shell Reference 

Page 3377 

## **OTHER XTEXT TOPICS** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Modeless Operation 

- Multiple XTEXT Controls 

- Controls in Container Windows 

- Editing in a Standalone Window 

- Search / Replace 

- Page Breaks 

- Trapping Toolbar Commands 

- XTEXT as a Report Viewer 

- Copy and Paste 

- Browser Mode 

- ATE Issues 

- Spell Checking 

- Keyboard Commands 

- Tables 

A-Shell Reference 

Page 3378 

## **MODELESS OPERATION** 

In addition to the additional programming required (multiple XCALL XTEXT operations using different _opcode_ values), these present the problem of how to respond to the user clicking on the edit control when some other input field has the input focus (i.e. when not inside of an XCALL XTEXT operation). You can prevent this problem by disabling the control on exit (see flags TXF_DISABLE) or you can define a keyboard click-to-enable string in `TXC.KBDSTR` , which would be received by whatever input routine had the focus at the time the user clicked on the text control. This would allow your application logic to take appropriate action, presumably including executing a new XCALL XTEXT operation. If you neither disable the text control when inactive, nor define a click-to-enable string in `TXC.KBDSTR` , then the user may have the impression of operating on the control, but your program will not be aware of it. (That might be acceptable though, since the application could retrieve the current text at a later time by executing XCALL XTEXT with _opcode_ set to TXOP_SAVE.) 

The recommended format for `TXC.KBDSTR` , is "VK_xF###" where ### is the absolute value of the desired negative _exitcode_ value to be returned when the user clicks on the text control while another input control has the focus (i.e. INFLD, XTREE, AUI_EVENTWAIT, etc.) For example, "VK_xF901" would generate _exitcode_ -901. 

A-Shell Reference 

Page 3379 

## **MULTIPLE XTEXT CONTROLS** 

You may have multiple XTEXT controls defined and displayed at once. To do so, you must specify a unique control number (0=first, 1=second, etc.) in the `TXC.CTLNO` parameter, and use the flags TXF_MODELESS option (so that you can exit the first control without destroying it). See the note next to TXC.CTLNO for information on auto-assigning a control number. 

A-Shell Reference 

Page 3380 

## **CONTROLS IN CONTAINER WINDOWS** 

You may place a XTEXT control within a container window such as a modal dialog box or a tab control by setting the `TXC.PARENTID` parameter to the parent control ID. 

A-Shell Reference 

Page 3381 

## **EDITING IN A STANDALONE WINDOW** 

You may also invoke the text editor in what appears to be a standalone window, almost as if it was an independent application (with its own title bar and menu). To do this, set the TXF_POPUP bit in the _flags_ parameter (and set the `TXC.PARENTID` field to a suitable parent control.) As with other control/window arrangements, set the coordinates relative to the grid system of parent window, although once the control is displayed, the user will be able to move and resize it, almost as if it were independent of the application (except that it will still act like a modal dialog.) 

Note that as of build 953.3 you can specify the coordinates in absolute pixels by setting the _srow_ , _scol_ , _erow_ and _ecol_ parameters to the negative of the desired pixel coordinates. In that case, the `TXC.PARENTID` wo not affect the positioning, but it will still affect the "z-order" and the ownership of the popup XTEXT window. (For example, if you specify the parent ID of the current dialog, then the XTEXT popup window will be automatically deleted when the dialog is deleted, whereas if you set `TXC.PARENTID` to 0, the popup XTEXT window will not be affected by deletion of the current dialog.) 

A-Shell Reference 

Page 3382 

## **SEARCH / REPLACE** 

A search operation may be initiated either by the application (see `TXC.SRCHKEY` ) or by the user by clicking on the search icon (binoculars) on the toolbar (see TXF_TOOLBAR and `TXC.TOOLBARMASK` ) or by hitting F5 (assuming that `TXC.FMAPCTL` has been set to forward F5 to the control. The operator can continue searching for additional matches by hitting CTRL+F (search forwards) or CTRL+SHIFT+F (search backwards).. 

Currently replace operations can only be initiated by the user, by hitting F6 (again, assuming that that `TXC.FMAPCTL` has been set to forward F6 to the control). 

A-Shell Reference 

Page 3383 

## **PAGE BREAKS** 

Hard page breaks are represented by ASCII 12 characters (CHR$(12) or CTRL+L). Depending on the text editing software (e.g. VUE, EZTYP, WORD, NOTEPAD, XTEXT, etc.) these hard page breaks may display in different ways, from a cryptic "garbage character" (often appearing as a small box) to a row of ^^^^ to a graphic line with the words "Page Break" in the middle. XTEXT will normally use the latter approach, except for two situations: 

• If the ASCII 12 character is not on a line by itself, it will appear as a small rectangular symbol rather than a formal ("pretty") page break unless you set the TXF_WRAP bit in the _flags_ parameter. If you do not really want any lines to be automatically wrapped, then you can set the `TXC.WRAPWIDTH` field to a sufficiently large number, say 500, so that you do not get any unwanted line wraps. Note that when you specify a non-zero `TXC.WRAPWIDTH` value, it does not make sense to specify the TXC_FITVIEW or TXC_PRINTVIEW flags. 

• If you set the TXC_READONLY flag, ASCII 12 characters will appear as a small rectangular symbol rather than a "pretty" page break, unless you set the &h02000000 flag in the `TXC.FLAGS1` parameter. (You might just want to make that a default setting.) 

A-Shell Reference 

Page 3384 

## **TRAPPING TOOLBAR COMMANDS** 

Most of the toolbar commands perform editing operations (like the clipboard operations, undo, redo, etc.) that are best handled internally by the XTEXT control without bother the application. But the following five toolbar commands involve I/O operations which the application might want to intercept and handle in a custom manner: 

|**Toolbar**<br>**Command**|**Fkey Equivalent**|
|---|---|
|Help|F1|
|Open|F2 *|
|Save|F3|
|Print|F4|
|Search|F5|



* F2 by itself does not invoke the Open command, but clicking on the Open toolbar icon is handled (for the purpose of intercepting the command and returning an _exitcode_ ) as equivalent to F2. The other F keys (F1, F3, F4, F5, F6) invoke the corresponding action regardless of whether the toolbar icon is present. 

To intercept any of the above toolbar commands and return them to the application as exitcodes, set the TXF_FKEY flag, and also set the corresponding bits in the `TXC.FMAPAPP` field and clear them from the `TXC.FMAPCTL` field. For example, if display the Save icon on the toolbar and want to trap it in your application (rather than letting the control handle the command itself), then you would set &h0004 (tgurd bit, corresponding to F3) in `TXC.FMAPAPP` and clear the same bit from `TXC.FMAPCTL` . The user's click on the icon would then generate an _exitcode_ -3. 

A-Shell Reference 

Page 3385 

## **XTEXT AS A REPORT VIEWER** 

Here are some suggestions and things to consider when using XTEXT as a report viewer: 

- Since most reports use fixed-pitch type, you will probably want to specify a fixed pitch font (e.g. Lucida Console or Courier 

- New) in the `TXC.FONTFACE` field. Note that when specifying a font face name, you must also set the `TXC.FONTSIZE` to something reasonable (like 8). 

- Since there is no equivalent to the 80/132 column display modes of EZTYP, you will have to rely on the horizontal scroll bar 

- (TXF_HSCROLL). 

- Since you probably do not want to allow modification of the report, set the TXF_READONLY and TXF_DEFERSAVE flags. 

- See Page Breaks for information on making sure the hard page breaks display properly. 

- There is currently no equivalent of the EZTYP "goto page" function, but F10 pops up a dialog allowing you to go to a specified 

- line number. If the report has printed page numbers, you can also use the search function (on the toolbar or F5) search for a page number. 

- If you want the viewer to occupy the entire screen, set the coordinates to something like -1,-1,-2000,-2000. This would 

- correspond to pixel coordinates of (1,1) for the upper left corner and (2000,2000) for the lower right corner, but A-Shell will shift and/or trim the size of any popup window (you need the TXF_POPUP flag) to fit the screen. But, in that case, you had better not use the TXF_MODELESS option, or else the XTEXT control will obscure the rest of the app and not give you any easy way to get back to it. 

- To achieve similar functionality to the EZTYP command line, consider wrapping the XTEXT control in a dialog which contains 

- buttons, and perhaps even a command line, along the bottom of the dialog. For example, to implement a printing capability similar to EZTYP's, you could trap the printer toolbar icon (or F4; see Trapping Toolbar Commands) and then prompt the user for printing parameters such as starting/ending page, printer, etc. If you had created an EZPRTX.SBX to customize EZTYP printing, you could reuse that logic by calling the subroutine directly from your application. 

A-Shell Reference 

Page 3386 

## **COPY AND PASTE** 

XTEXT shares the clipboard with A-Shell (and the rest of Windows), allowing you to easily cut/copy/paste between it and other applications. The user can access the clipboard operations by any of the following methods, all of which are fairly standard among Windows applications: 

- Keyboard commands: CTRL+X (cut), CTRL+C (copy), CTRL+V (paste) 

- Toolbar commands: See TXF_TOOLBAR, and `TXC.TOOLBARMASK` for details on displaying the toolbar and selecting which toolbar 

- icons appear. 

- Context (right-click) menu: Right-clicking within the area of the XTEXT control will display a pop-up menu (aka "context 

- menu") containing options for the three clipboard commands. By default, the menu uses the words "Cut", "Copy" and "Paste", but you can customize them (either to confuse your users or for non-English environments) by adding the following items to the SYSMSG.xxx file (where xxx is the extension for the current language definition, as defined by the LANGUAGE statement in miame.ini): 

- `004,001,Cut` 

- `004,002,Copy` 

- `004,003,Paste` 

- In addition to pasting text, XTEXT will also paste clipboard images if the destination format ( `TXC.DOCFMT'DST` ) supports it. Note 

- however, that in some configurations, the TXF_WRAP flag may be required. 

Bitmaps are recognized as paste-able in addition to text. 

A-Shell Reference 

Page 3387 

## **BROWSER MODE** 

XTEXT may be used as a very simple web browser, by specifying the TXFF_HTML flag in the `TXC.DOCFMT'SRC` field and setting the TXF_READONLY flag. The usual source type options apply (TXFF_STRING and TXFF_FILE), except that in the TXFF_FILE case, the filespec can also be a web-based URL. For web-based HTML documents and forms, the destination ( `TXC.DOCFMT'DST` ) must be a string/buffer. 

In the case of a form, if the user clicks the SUBMIT button, XTEXT returns with exitcode=30 and the action, method, and data fields are output to the dst parameter in the following format: 

```
&url=<form url or filespec>&action=actionstr&method=
```

```
methstr&name1=value1&...&nameN=valueN
```

The fields _actionstr_ , _methstr_ and _nameN_ are as defined in the form itself. ( _methstr_ will be GET or POST.) The _valueN_ fields return the data entered by the user in the form. (Checkbox and radio button fields return 0 or 1 to indicate empty or checked.) If a value contains the character "&", the entire value string will be quoted. So you may want to use STRTOK to simplify parsing the returned string. 

## **Notes** 

- Requires that the module hts13.dll be present in the bin directory, and that you use TXFF_HTML with TXFF_FILE in the 

- `TXC.DOCFMT'SRC` or `TXC.DOCFMT'DST` fields. Only file mode is supported. 

- For browser mode, you must set TXF_READONLY. Otherwise it will be in editing mode, similar to the existing RTF editing mode. 

- You must use TXF_FITVIEW for all but the simplest files. 

- You may specify a web URL in the `TXC.DOCFMT'SRC` field, such as "http://www.microsabio.com". However, you may not output 

- to a web address. (We recommend using .HTM as the extension for local HTML files.) 

- You can use the HTML format as simpler version of RTF with the goal of supporting just a few text attributes. To minimize the 

- size of the outputted HTML file, you may want to set the `TXC.HFLAGMASK` and `TXC.HFLAGS1` as follows: 

```
TXC.hflagmask = &h0001   ! Set/clear all flags from HFLAGS1
```

```
TXC.hflags1 = &78006     ! strip out head, body, font, style tags
```

A-Shell Reference 

Page 3388 

## **ATE ISSUES** 

When XTEXT is used with ATE to edit files originating on a remote server (whether Unix or Windows), the source file or source text must be transferred from the remote server to the client PC in order for XTEXT to operate on it. Although this is handled automatically by XTEXT, here are some possible technical obstacles that could interfere with the desired result: 

• The server must have an FTP server that the client can access (no firewall or other security restrictions). Note that you can also configure ATE to use SFTP (via the SSH service on port 22 if FTP is not available or if you want better security). 

- The ATE client must be configured with a valid FTP login and password. Otherwise XTEXT will have to prompt the user, which 

- wo not be very efficient. 

- The FTP (or SFTP server) must use the same root directory as A-Shell on the server is using (because this is how XTEXT 

- constructs the filespecs in the generated FTP commands). 

• If the source is a file, XTEXT will look at the first line to see what kind of terminators it uses, and then select the appropriate file transfer mode (binary vs. ASCII) so that the copy seen by the control has the standard Windows CRLF terminators. One way this could fail is if, in order to close a security loophole in some FTP servers, the FTP ASCII transfer mode was disabled. In that case, if the source file had LF terminators, the control will display graphic boxes where there should be line breaks. Workarounds for that problem would include reconfiguring the FTP server to allow ASCII transfers, changing the file terminators on the Unix side from LF to CRLF (see OPTIONS=CRLF, CRNL in miame.ini), and switching from FTP to SFTP. Note that in the case of the vsFTP server (common on some Unix platforms), the relevant configuration setting is "ascii_download_available" in the /etc/vsftpd.conf file. 

- If the source is a string, then FTP is not used and the line terminators will not be adjusted, so the application string must 

- include CRLF terminators. 

- When the updated file or string is transferred back to the server, XTEXT will attempt to give it the appropriate line terminators 

- based on the standard terminators for the server OS and whether the OPTIONS=CRNL setting in miame.ini was specified. Also see the subtopic listed in the table of contents. 

## u **Non-FTP Channel Text Return** 

A-Shell Reference 

Page 3389 

XTEXT supports an alternate method of returning updated text to the server, which does not require FTP. This method works via the keyboard channel and only works when the destination is a string buffer—i.e. TXFF_FILE flag is NOT set in the `TXC.DOCFMT'DST` field. 

The primary motivation for this non-FTP mechanism is to deal with servers that do not have FTP support configured, or have it configured in a mode that prevents access to the directories where A-Shell lives on the server; this is quite common with Windows servers. It is also somewhat more efficient when editing small files, which would be consistent with the use of string buffer mode rather than file mode. 

This requires a current (later than 995) of ASHW32 on both sides. 

This mode is automatic with Windows servers (ATS), but you can also force it for Unix servers by setting the new flag TXFF_RAWBUF in the `TXC.DOCFMT'DST` field. 

A-Shell Reference 

Page 3390 

## **SPELL CHECKING** 

Spell checking requires the following modules be in the BIN directory: 

```
SPELL32.DLL
```

```
DICT25.APP  (application dictionary)
```

```
DICT25.D    (main dictionary data)
DICT25.I    (main dictionary index)
DICT25.S    (small/core dictionary)
DICT25.U    (user dictionary - optional, created as words added)
```

To activate spell checking, set `TXC.FLAGS4 = &H100` before calling XTEXT. 

Misspelled words will be underlined in red; right-clicking on them will provide a list of similar words and an option to either add the word or ignore it. Added words go into the DICT25.U file, which will be created if it doesn't already exist. 

A-Shell Reference 

Page 3391 

## **KEYBOARD COMMANDS** 

The following table shows the various miscellaneous keyboard commands that may be used in conjunction with XTEXT. 

|**Keystroke**|**Operation**|**Notes**|
|---|---|---|
|F1|Help|See TXC.FMAPCTL<br>.|
|F2|Open||
|F3|Save||
|Shift+F3|Save As||
|F4|Print||
|Shift+F4|Printer Setup||
|F5|Search||
|F6|Replace||
|F10|Jump to line number||
|Alt+F10*|Display font selection dialog||



A-Shell Reference 

Page 3392 

|ell Reference||||
|---|---|---|---|
|Ctrl+B*|Bold|Applies only if text is in RTF mode.||
|Ctrl+U*|Underline|||
|Ctrl+D*|Double underline|||
|Ctrl+I*|Italics|||



A-Shell Reference 

Page 3393 

## **TABLES** 

XTEXT supports tables. Note the following prerequisites and related factors: 

- The destination format must support them. (Each cell will appear as a separate paragraph if stored in plain text format.) 

- You will need to enable the menu (see the TXF_MENU _flags_ bit) in order to have access to the Table > Insert option in order to 

- create a table. There is no keyboard shortcut. 

- TXF_WRAP (see _flags_ ) is required. 

- At least one of TXF_PRINTVIEW, TXF_PAGEMODE or TXF_FITVIEW is also required. Note that TXF_PRINTVIEW by itself will display the table 

- "folded" into a single column for editing purposes, so adding one of the other bits is recommended. 

A-Shell Reference 

Page 3394 

## **XTREE** 

**xcall XTREE,** Srow **,** Scol **,** Answer **,** Array **,** Itemcount **,** Coldef **,** Exitcode **{** Erow **,** Ecol **,** XTREE Flags, File **,** Mmoclr **{,** XTRCTL **,** Filidx **,** Xinfo **}}** 

XTREE is a full-fledged implementation of a Windows "tree" control, supporting multiple columns and multiple levels of rows. The name "tree" comes from the ability to create a branching hierarchy of items, which at each level can be collapsed and expanded. Windows Explorer, for example, is essentially a tree control. 

For examples of the results produced by XTREE, and to get an idea of how XTREE has been used by various developers and for different purposes, see the online MicroSabio gallery of XTREE images. 

Note that many of XTREE's functions and capabilities are available in a text-oriented version called PCKLST. For information on the differences between PCKLST and XTREE, and how PCKLST/XTREE handles text versus GUI issues, see the note here. 

## **XTREE vs. PCKLST, Text vs. GUI** 

XTREE is an upward-compatible variation of the older routine PCKLST. XTREE and PCKLST are actually the same subroutine, so it does not really matter what name you use. It was split into two different names simply to make it easier to document and understand, since the uses of XTREE may diverge considerably from those of PCKLST, and also to avoid the potential confusion of people trying to use XTREE features that are not available in a text environment. Our recommendation is for you to use PCKLST if you need text mode compatibility and are (therefore) going to stick with the PCKLST features and semantics (as documented under PCKLST). Otherwise, if you are committed to the GUI environment and want to take advantage of the maximum feature set, use XTREE. To force PCKLST to use the GUI interface, see the documentation index for "PCKLST_GUI SBR system parameter." 

Depending on how you call it and the operating environment, the subroutine chooses one of two internal implementations. For text environments, it uses the INMEMO menu mode to display the list and allow you to choose an item. This will only be successful though if you limit yourself to the PCKLST feature set and argument semantics. For GUI environments, it uses a thirdparty tree control, which is licensed for A-Shell distribution. It resides in an external module, SftTree_IX86_A_##.DLL, which must be in the same directory where ashw32.exe resides. 

A-Shell Reference 

Page 3395 

## **Subtopics** 

- XTREE Inputs and Outputs 

- XTREE Parameters 

- XTREE Techniques 

- XTREE Sample Programs 

A-Shell Reference 

Page 3396 

## **XTREE INPUTS AND OUTPUTS** 

XTREE offers a choice of two ways of providing the data for the list: 

- Array; this is recommended, as it provides the most flexibility and is required for some of the more advanced features 

- Sequential file; most convenient for simpler configurations. Both fixed width and CSV formats are supported. 

XTREE supports three types of output: 

- A selected "item" (aka "row" or "record"). This is referred to as "single-selection mode." 

- An array of selected items ("multiple-selection mode"). 

- An array of updated cell values (either checkbox values or text strings). This only applies when the data contains editable 

- cells; see _flags_ XTF_EDITABLE, and advanced _coldef_ column formats E, u, U and T. 

Not all features support all types of input or output, or there may be differences in the way the parameters are interpreted or mapped. So as you read the documentation, please be alert for qualifications which reference one or more input/output combinations, such as "single-selection array mode" or "multiple-select file mode." 

## **Limits and Capacities** 

|**Item**|**Maximum allowed**|**Updated in Version...; old value**|
|---|---|---|
|Trees|32|1134 of Jan 09; 10|
|Columns|200, may be editable or not|1691 of Oct 2020; 100|
|Rows|no limit||
|Font definitions|4||



A-Shell Reference 

Page 3397 

|ell Reference|||
|---|---|---|
|List definitions|26||
|RGB definitions|93 (ASCII 33 - 125)|1665 of Aug 2019; 52|
|Combined mask length|1024||
|Exit characters|64||
|Length of title, footer in characters|128||



A-Shell Reference 

Page 3398 

## **XTREE PARAMETERS** 

Parameters that supply data _to_ the routine are indicated with [in], and those used to get data back _from_ the routine are labeled [out]. 

|**Parameter**|**Type**|**Type**|**I/O**|**Description**|
|---|---|---|---|---|
|Srow, Scol,<br>Erow, Ecol|String||in|Position of display.|
|Answer|||in/out|Sets and returns the identity of the selected row(s), and/or in the case of editable cells,<br>supplies and returns updated values.|
|Array|Array||in|In array mode, specifies an array of strings to be loaded into the list box.|
|Itemcount|Num||in|Specifies a number of items (i.e. "rows"), with the precise meaning being relative to the<br>opcode:|
|Coldef|String||in|Defines the column structure.|
|Exitcode|+/|-Num|out|Returns a code indicating how the list was exited; 0 indicates a normal exit via theENTER<br>key, 1 indicatesESCAPE. See the XTREE<br>Flags<br>parameter for enabling other exit keys.|
|XTREE Flags|B,4||in|Used to enable additional exit keys and other options.|
|File|String||in|Specifies a file to be used for input instead of the_array_parameter. This is referred to as<br>"file mode."|



A-Shell Reference 

Page 3399 

|**Parameter**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|Mmoclr|Struct|in|Specifies colors for various parts of the pick list.|
|XTRCTL|Struct|in/out|A collection of extended parameters and options.|
|Filidx|B,4|out|Creates an index to the file while it is being loaded into the array.|
|Xinfo|String|in/out|This optional parameter may be specified to allowXTREEto return additional information.|



A-Shell Reference 

Page 3400 

## **SROW, SCOL, EROW, ECOL** 

The parameters _srow, scol, erow, ecol_ mark the upper left and lower right corners of the display box, provided that _flags_ contains the option XTF_XYXY. Otherwise, they are interpreted as _row_ , _col_ , _strow_ , _endrow_ as in PCKLST. Note that since this XTREE supports horizontal scrolling and column resizing, the width of the display box is independent of the width of the data. Also note that the coordinates are relative to the main window or dialog, or to the control specified by `XTR.PARENTID` . 

A-Shell Reference 

Page 3401 

## **ANSWER** 

_Answer_ specifies and returns the identity of the selected row(s), and also passes back and forth updates to editable cell data. 

In the simplest case (single-selection array mode, no editable cells, no drag/drop), _answer_ is treated as in PCKLST, where it is a single numeric variable of any numeric type and is interpreted as the selected row number (first row is 1), e.g. 

```
MAP1 ANSWER,B,4          ! selected row for single selection
```

For multiple selection mode using array or file input (but no editable cells or drag/drop) (see flags XTF_MSEL, XTF_EDITABLE, XTF_DRAGDROP), _answer_ must be an unformatted variable mapped as follows: 

```
MAP1 ANSWER
```

```
   MAP2 ANSARY(x),S,1    ! each item is "0" if not selected, else "1"
```

```
                         ! (x) must be at least as large as addcnt
```

To support both single and multiple selection modes with a single form of the parameter, you can add the following MAP statement for the single selection response: 

```
MAP1 ANS,B,4,@ANSWER      ! selected row for single selection
```

You can still pass the unformatted ANSWER variable (rather than ANS), but XTREE will treat it as if a B,4 variable in single selection mode. In other words, in single selection mode, XTREE assumes that an unformatted answer parameter is overlaid by a four-byte binary. 

Note that although the rows may be sorted on the screen, either by the user or by XTREE based on the `XTR.COLUMNSORT` parameter, this does not affect the order of the original data, to which the row numbers returned in _answer_ remain relative. In other words, if _answer_ =5 on calling XTREE, it will select the fifth row in the source data ( _array_ or _file_ ), which may or may not appear as the fifth row on the screen, and which may be sorted again by the user to yet another position. Similarly, the _answer_ value(s) returned will not necessarily reflect the position(s) of the selected item(s) as displayed, rather their position in the source data (which remains unaffected by any sorting performed by XTREE). Also note that if _answer_ =0, the default selection will be the first row, except in the case of the append operation, in which case it will be the first row appended. Any other _answer_ values are always interpreted as relative to the combined data (original plus appended). 

A-Shell Reference 

Page 3402 

For more complicated situations (involving some combination of multiple selection, editable cells, and/or drag-and-drop), _answer_ must an array dimensioned at least as large as the number of rows of data in the tree, and whose row elements are formatted into one or more fields which must be precisely mapped according to the following principles: 

- If drag-drop allowed, the first field of every row must be a 4 character string which will return the original row number (1- 

- 9999). 

- If multi-selection allowed, the next field of every row is the one-byte selection flag (as described above). 

- If there are editable checkboxes/radiobuttons, then the next N fields will be for each of the editable checkboxes/radiobuttons, 

- according to the relative sequence in which they are defined in the _coldef_ parameter. Note that for each checkbox/radiobutton column that supports individual cell colors, the column width (in the main array and in the answer array) will be 2; otherwise it should be 1. Also note that all checkbox/radiobutton columns are represented in the answer array prior to any other kinds of editable columns, regardless of the order in which the checkboxes/radiobuttons and editable columns were defined. 

• Finally, for every editable column, there must be a corresponding field in each row of the answer array, whose size matches the defined size of the column. As with checkboxes and radio buttons, if the editable column supports individual cell colors, the width of the column in the answer array must be expanded by one to make room for the cell color byte at the start of the cell. And as before, the order of these editable columns in the answer layout must match the relative order in which they are defined in _coldef_ (as opposed to the order in which they appear in the raw data). 

## **See Also** 

- Editable Image Cells 

- XTREE Answer Examples 

A-Shell Reference 

Page 3403 

## **XTREE ANSWER EXAMPLES** 

Consider a tree with three editable checkbox columns. You would map the _answer_ array as follows: 

```
MAP1 ANSWER
```

```
MAP2 ANSARY(x),S,3    ! (x=# rows, 3=number of editable checkbox columns)
```

Or, perhaps more clearly: 

```
MAP1 ANSWER
```

```
MAP2 ANSARY(x)        ! (x) must be at least as large as addcnt
```

```
MAP3 ANS'CB1,S,1   ! first editable checkbox column
```

```
MAP3 ANS'CB2,S,1   ! second editable checkbox column
MAP3 ANS'CB3,S,1   ! third editable checkbox column
```

The encoding of these arrays is similar to that for multiple-selection mode, i.e. "0" = unchecked, "1" = checked, and " " (blank) causes the cell to be left blank (with no checkbox at all). For three-state checkboxes, "2" specifies the indeterminate state. 

If multi-selection is allowed, then the first column of the _answer_ array is reserved for the selection flags. For the example above, the multi-selection version should be mapped as: 

```
MAP1 ANSWER
```

```
MAP2 ANSARY(x)        ! (x) must be at least as large as addcnt
```

```
MAP3 SELECTION,S,1 ! selection flags (must be first)
```

```
MAP3 ANS'CB1,S,1   ! first editable checkbox column
```

```
MAP3 ANS'CB2,S,1   ! second editable checkbox column
MAP3 ANS'CB3,S,1   ! third editable checkbox column
```

A-Shell Reference 

Page 3404 

When editable text or combobox columns (see _cformat_ **E** and **l** ) are present, the same rule as for checkboxes applies, except that the width of the elements in the answer array must include the total width of all the editable columns. To continue the example above, if, in addition to the three checkbox columns there were also two editable text columns, one a standard edit 12 bytes wide and the other a combobox 25 bytes wide, and both the first checkbox and the first editable cell supported individual cell colors ( _cformat_ **B** ), the correct mapping of the answer array would be: 

```
MAP1 ANSWER
```

```
MAP2 ANSARY(x)          ! (x) must be at least as large as addcnt
```

```
MAP3 ANS'CLR1,S,1    ! color byte for first editable checkbox column
```

```
MAP3 ANS'CB1,S,1     ! first editable checkbox column
```

```
MAP3 ANS'CB2,S,1     ! second editable checkbox column
```

```
MAP3 ANS'CB3,S,1     ! third editable checkbox column
```

```
MAP3 ANS'CLR2,S,1    ! color byte for first editable text column
```

```
MAP3 ANS'TEXT1,S,12  ! first editable text column
```

```
MAP3 ANS'TEXT2,S,25  ! second editable text (combobox) column
```

Regardless of the relative position of the checkboxes (and radiobuttons) vs. the editable text columns in the source _array_ , the checkboxes and radiobuttons must precede the text columns in the _answer_ array, as shown above. 

## **Notes** 

• Although using a multi-level mapping as shown above is the easiest way to visualize the format of the _answer_ array, you may also map or dynamically allocate a single-dimension array (e.g. `DIMX ANSARY(X),S,Y` ) and pass that array to XTREE by specifying the first element (e.g. `xcall XTREE, srow, scol, ANSARY(1), ARRAY(1), addcnt,...` ), provided that you use substring modifiers or some other method to construct each row of the array according to the rules described above. Better yet, use a DIMX. 

A-Shell Reference 

Page 3405 

- Note that the order of the columns is relative to the order in which they are defined (in Coldef) and is not affected by the user 

- rearranging their order in the display. 

• The answer array can be initialized to nulls or blanks. Whenever the tree is loaded or re-entered, if the answer array is all blank, the editable cells will be loaded purely from the data array. However, if the answer array contains any non-blank / nonnull characters, then the answer array data will override the corresponding cells in the data array. Whenever XTREE exits, it will update the answer array cells to reflect the current status (with the exception of the color bytes - see next bullet). The concept is to use the data in the main array to represent the original data; and the data in the answer array to represent the current data. Beware that if, as a result of editing, you manage to clear all of the editable cells such that the entire answer array is blank, then on the next re-entry, the entire tree will be set back to the initial status per the data array. (To prevent this, you will either need to copy the blank answer array over the data array, or perhaps define a color column and plug in an explicit code for white, just to have a non-blank byte in the answer array, so that it is considered valid rather than uninitialized.) 

• On creation of the control, blank individual cell color bytes in the _answer_ array are initialized from the data array, like other _answer_ array fields). On return, they will be set to the current status (in this case, the current RGB Color Index) of the field, or blank for no (i.e. default) color. Note that to set a cell which currently has an individual cell color back to the default color, set the corresponding byte in the _answer_ array to blank prior to re-entry. (This works as of edit 1210, even with the XTF_NOREDRAW flag set; prior to that, blank was treated as "no change" rather than "no color", and XTF_NOREDRAW stifled color updates.) Note, however, that the default color for the cell in this case may not be the same as the default color for the entire tree; the cell default color may be affected by a column color. To override the column color and force the cell to use the tree's default (typically white) color, use the special RGB color index code "=". 

- Individual cells within an editable text column can be marked to ignore by setting the associated field in the answer array to 

- "|" (vertical bar), followed by whatever text you want to display in the cell (if any). See the advanced _coldef_ option RGBignore for an additional note on this, and the sample program XTRA5 for an example. (The description in the 3rd row is marked noneditable by this means.) 

• To disable an editable checkbox ( **T** ) or radio button ( **R** ) cell, add 4 to the numeric code in the answer array byte. For example, while 0 is unchecked/enabled and 1 is checked/enabled, 4 would be unchecked/disabled and 5 would be checked/disabled. See the sample program XTRA6 for an example of this (select the validation option, then as you click on Yes and No radio buttons, the corresponding N/A button will be enabled/disabled.) 

- Editable text and editable checkboxes are only supported in array mode (not file mode). 

A-Shell Reference 

Page 3406 

## **ARRAY** 

In array mode (i.e. when the _file_ parameter is empty) the _array_ parameter supplies the contents to be loaded into the XTREE grid. It may be specified in the form of an array of fixed length strings, whose layout is determined by the coldef parameter, or as gridmap; see History below. 

For the array case, you may either specify an explicit starting element (e.g. ARRAY(1)) or an unformatted variable under which the array is defined (ARRAYX in the example below). Note that you can use DIMX to dynamically allocate the array (either a simple array or a Dynamic Array of Structures), in which case you have to pass it to XTREE via the starting element. 

```
MAP1 ARRAYX               ! unformatted variable
```

```
   MAP2 ARRAY(50),S,100
```

Each array element must have at least one trailing null byte. Note that by using the overlay feature, you could support several array layouts with the same XTREE statement, i.e. 

```
MAP1 ARRAYX2,@ARRAYX      ! overlay on ARRAYX above
   MAP2 ARRAY2(10),S,60   ! array of ten sixty byte strings
MAP1 ARRAYX3,@ARRAYX      ! yet another overlay
   MAP2 ARRAY3(80),S,8    ! array of eighty 8 byte strings
```

Any text in an individual cell (in array mode) or line (in file mode) which follows a backslash ("\") will be hidden from view (unless the _cformat_ \ switch is specified). 

In single-selection **file** mode, the _array_ parameter is interpreted as an ordinary string to return the text of the selected items (all columns, but with right-justified columns stripped of trailing blanks.) If the XTF_FILANS flag is set, then array is ignored on entry; otherwise it should contain the text of the item to initially select, as returned from the prior call. In CSV mode (see XTF2_CSV), although the return string will contain all the columns (comma-delimited), on entry only the first column is used for locating the initially selected item. If you need more precision than that, use the XTF_FILANS flag/method. 

A-Shell Reference 

Page 3407 

In multiple-selection **file** mode, the _array_ parameter is ignored. The selection information is passed via the array of one byte flags in the _answer_ parameter, just as in multiple-selection **array** mode. 

For the gridmap case, specify the gridmap name with an empty pair of parens, e.g. 

```
xcall XTREE, sr, sc, answer, $grid(), count, exitcode, er, ec, flags...
```

Either form of gridmap is accepted, although the handling is somewhat different for the two types. In the case of _gridmap(int;varstr;varstr)_ , the handling is analogous to CSV mode except without a file. This is more memory efficient but doesn't support AutoFilter. 

In the case of _gridmap(int;int;varstr)_ , the grid data is expanded out to an array using column widths based on the actual maximum lengths of the data. 

In either case, the operation is limited to display and select only; no editing. The application may specify an empty, partial (pseudo columns only), or full _coldef_ . In the empty or partial case, the column headers are extracted from the gridmap—row 1 in the _int;int;varstr_ case). If the app supplies a _coldef_ with any real columns defined, the column names from the gridmap are ignored, and it is up to the app to make sure that the _coldef_ supplied actually matches the layout of the data. 

## **History** 

- 2023 September, A Shell 6.5.1742:  The tree data _array_ argument may now be supplied in the form of a gridmap. 

## **Subtopics** 

- Array Descriptors 

A-Shell Reference 

Page 3408 

## **ARRAY DESCRIPTORS** 

_Modified March 2016; minor edits_ 

Array descriptors provides an alternate method of specifying the answer and data arrays, using the following structure as defined in XTREE.SDF in SOSLIB:[907,16]: 

```
DEFSTRUCT ST_XTRARYDESC    ! [136] array descriptor
```

```
    map2 BASEADDR64             ! [136] address of base of array
        map3 BASEADDR'LO,B,4    ! [136] low 32 bits
        map3 BASEADDR'HI,B,4    ! [136] hi 32 bits (for 64 bit mode future)
    map2 LOADFROM,B,4           ! [136] element # to start loading from (base 1)
    map2 FLAGS,B,4              ! [136] misc flags
    map2 WIDTH,B,4              ! [136] array width
    map2 TOTROWS,B,4            ! [136] total rows in ENTIRE array
ENDSTRUCT
```

To retrieve the address of the base of the array (and for convenience, the width as well), use XCALL GETADR as follows: 

```
MAP1 xtary'desc,ST_XTRARYDESC
MAP1 xtary(5000),S,99
```

```
xcall GETADR, xtary(1), xtary'desc.BASEADDR64, xtary'desc.WIDTH
```

That would load the BASEADDR64 and WIDTH members of the structure. You can get the total number of elements using the .EXTENT() function: 

A-Shell Reference 

Page 3409 

```
xtary'desc.TOTROWS = .EXTENT(xtary())
```

Then just specify the desired starting row with an assignment: 

```
xtary'desc.LOADFROM = 1     ! start loading from 1st element
```

This descriptor structure can then be used in place of the data or answer array, e.g.: 

```
XCALL XTREE, srow, scol, answer, xtary'desc, itemcount, coldef, ...
```

Note that you still need to set the ITEMCOUNT parameter to the number of rows to be loaded, just as you normally would. (The TOTROWS member of the descriptor is just there as a safety check against accidentally trying to load more rows than exist. (Either way, XTREE has to trust you on the total size of the array, but if you use the .EXTENT() function as shown above, it should be easy to avoid mistakes there.) 

## **History** 

- 2012 June, A Shell 6.1.1307: XTREE Array descriptors added to A-Shell. 

A-Shell Reference 

Page 3410 

## **ITEMCOUNT** 

This parameter specifies a number of items—i.e. "rows"—with the precise meaning being relative to the opcode, as shown in the following table. _itemcount_ may be specified by any numeric data type. 

|**XTR.OPCODE**|**itemcount interpretation**|
|---|---|
|XTROP_CREATE|For array mode, set to # of items to load from the data_array_parameter. For file mode, set to 0 to load the entire<br>file.|
|XTROP_REPLACE|Same as forXTROP_CREATE. If less than the number of items already in the tree, the excess items will be deleted from<br>the tree.|
|XTROP_APPEND|# of items to append (from the data_array_parameter to the end of the existing items in the tree)|
|XTROP_DELETE|Ignored|
|XTROP_RESELECT|# of items currently in the tree (see_Comments_)|
|XTROP_DELSEL|Same as for XTROP_RESELECT|
|XTROP_PRINT|If tree doesn't already exist, set to # of items to load from the data_array_. Else set as for XTROP_RESELECT.|
|**Definition file:**ashell.def||



**Comments** 

A-Shell Reference 

Page 3411 

- In PCKLST, _itemcount_ specified the maximum number of items in the input array, and was ignored for file mode. XTREE obeys 

- it for both array and file mode, but interprets 0 as meaning to load the entire file. 

- Note that when loading an array starting from some position other than the first element, _itemcount_ must be adjusted so that 

- it does not cause the input operation to run past the end of the array. 

- For operations that don't involve adding data but may involve processing an _answer_ array (such as XTROP_RESELECT and 

- XTROP_DELSEL), _itemcount_ is mainly needed in order to identify the number of elements in the answer array when the _answer_ parameter is specified as an array element (rather than as an unformatted variable overlaying the entire array). 

Note: this parameter ( _itemcount_ ) was previously known as _addcnt_ . The documentation was changed in January 2011 to make its m&eaning clearer. 

A-Shell Reference 

Page 3412 

## **COLDEF** 

This input parameter, "column definition", defines the column configuration layout and other related details of the tree configuration, according to one of three syntax variations: 

- Traditional Coldef Syntax 

- Simple Multi-Column Coldef Syntax 

- Advanced Coldef syntax 

## **Advanced Coldef Syntax** 

To use the Advanced _coldef_ syntax, you must specify the XTF_COLDFX option in _flags_ , and then provide a _coldef_ string in the following syntax: 

## **cpos~ cwidth~ ctitle~ cformat {~option1 = value1{ ~option2 = value2...} ~~cpos~ cwidth...~~** 

This syntax specification consists of a series of column definitions, one per column, delimited by a pair of tildes (~~). Each column definition begins with four mandatory parameters ( _cpos_ , c _width_ , c _title_ and c _format_ ), each delimited by a single tilde, followed by zero or more optional Advanced Coldef Options using the form ( _optionN_ = _valueN_ ). This is admittedly cryptic, but has the virtues of being flexible, easily extensible, compact, and easy to map. 

|**Parameter**|**Description**|
|---|---|
|Cpos, Cwidth|Define the starting position and width of the column.|
|Ctitle|Sets column title (header), and optionally, footer text.|
|Cformat|Specifies formatting and sorting of column contents.|
|<more>|Advanced Coldef Options<br>.|



A-Shell Reference 

Page 3413 

## **See Also** 

- File Mode Coldef Extensions 

- Advanced Syntax Example for tips on specifying column attributes as well as widths 

- .OFFSIZ$ to simplify determination of _cpos_ and _cwidth_ for structure members 

A-Shell Reference 

Page 3414 

## **CPOS, CWIDTH** 

These parameters define the starting position and width of the column relative to the input source (whether array or file). The first position is 1. If you are defining the columns consecutively (in the same order as the input, then you can specify 0 for _cpos_ in which case it will assume that the column starts immediately after the end of the previous column. For comma-delimited file input, set _cwidth_ to 0 and _cpos_ to the field number. 

For CSV input, _cpos_ and _cwidth_ just need to be greater than zero; see XTF2_CSV for additional details. 

You may set both _cpos_ and _cwidth_ to 0 to define a pseudo-column, which does not count in the column numbering scheme, nor take up any display space in the control, but may instead be used to define advanced options that are not column specific or which may need to be defined in order to be referenced later. This may be referred to elsewhere as "Pseudo Column Zero." See the column options PopupMenu, HdrFont, HdrScale, Font, RGBfg and Scale for examples. 

Note that although the _ctitle_ and _cformat_ parameters are ignored for the pseudo column zero, they must contain something because two adjacent tildes mark the end of the column definition. By convention, specify a title of "X" and a format code of "H" (hidden), e.g. _coldef_ = "0~0~X~H~..." 

## **See Also** 

- Constant Data Column 

A-Shell Reference 

Page 3415 

## **CTITLE** 

_Revised March 2018_ 

This parameter must be a text string of any length to display as the column title/header; in addition it may optionally contain the column footer text. Note that the initial column display width is determined based on the largest string in either the title or any of the data items for that column. If you do not need a title for a particular column, set it to a blank (" "), otherwise you will end up with two adjacent ~ delimiters which will confuse the parser. You can embed line breaks in the header for a column using CR (i.e. chr(13)). 

You may embed a tilde in the _ctitle_ string (so as to appear in the column heading when the control is displayed) by replacing it with the HTML-inspired encoding "%7e." 

## **Alignment** 

Normally the column header text is aligned the same way as the data in the column is—i.e. based on the last _cformat_ field of the coldef parameter). You can now override this by starting the column header text with one of the three alignment characters: > (right), < (left), or | (center) followed by a space. For example: 

```
COLDEF="1~20~> Right Title~<S~~"   ! text left aligned, header right
```

Without the space in the 2nd position of the title, the < character would have simply been treated as the start of the title text. 

## **Footer** 

To define column footer text, append "::" to the title text, followed by the desired literal text. As with the column header, the text may start with an alignment character followed by a space. For example: 

```
COLDEF="1~20~> Right Title::Footer~<S~~"     ! text left aligned, header right, footer default (left)
```

```
COLDEF="1~20~> Right Title::| Footer~<S~~"   ! text left aligned, header right, footer centered
```

Instead of literal footer text, you may also specify a special command (=SUM) to display the total of the column. See Auto-Sum. 

Also note that in order for the footer to be visible, the `XTR.SHOWFOOTER` must be set to 1. See XTR.FOOTERSTYLE for details. 

## **History** 

A-Shell Reference 

Page 3416 

- 2023 June, A Shell 6.5.1734: _ctitle_ now recognizes HTML-style escaped characters, i.e. %xx where xx is value from 00-ff (hex). This is mainly a convenience for specifying hard breaks within a header or footer without having to resort to concatenating a chr(13) into the coldef string. For example, "1~20~Happy%0d~Hour~S~..." may be more convenient to code than "1~20~Happy"+chr(13)+"Hour~S~...". Note that a % not followed by two hex digits is treated as is; you can also use %% to indicate a literal %. 

- 2018 February, A Shell 6.5.1631: Auto-Sum added. 

- A Shell 5.1.1107 of 12 April 08:  New XTREE option to override the alignment of the column headers. Normally the column header text is aligned the same way as the data in the column is (i.e. based on the last _cformat_ field of the _coldef_ parameter). You can now override this by starting the column header text with one of the three alignment characters: **>** (right), **<** (left), or **|** (center) followed by a space. For example: 

```
COLDEF="1~20~> Right Title~<S~~"   ! text left aligned, header right
```

Without the space in the 2nd position of the title, the < character would have simply been treated as the start of the title text. 

A-Shell Reference 

Page 3417 

## **CFORMAT** 

_Updated March 2021; see History_ 

The _cformat_ parameter is made up of one or more of the following characters, which are used to determine how the column should be justified and sorted. Note that they do not cause the data in the column to be re-formatted. For example, if a column contains dates, it is up to the calling program to preformat them appropriately to match the _cformat_ specification. (The only purpose of defining such a column as a date is to allow sorting to work properly.) The most generic and common type would be **S** (string). 

Key to column codes: **E** : Editable Related; **C** : Color Related; **D** : Character / Data Type; **F** : Formatting or Sorting; **X** : Other. 

|**Code**|**Meaning**|**E**|**C**|**D**|**F**|**X**|
|---|---|---|---|---|---|---|
|!|Preserve foreground color<br>.||C||||
|@|List hierarchy<br> (level for multi-level tree).|||||X|
|#|Numeric data<br>,allows 0 - 9. Use<br>**.**<br> and<br>**-**<br> to allow decimal points and minus signs.|||D|||
|\|Literal backslash<br>.|||||X|
|.|(Decimal point) Use with<br>**#**to allow numbers with decimal points. SeeNumeric data<br>.|||D|||
|+|Added to T (Editable checkbox<br>)extends the checkbox functionality.|E|||||
|++|Added to T (Editable checkbox<br>)further extends the checkbox functionality.|E|||||



A-Shell Reference 

Page 3418 

|**Code**|**Meaning**|**E**|**C**|**D**|**F**|**X**|
|---|---|---|---|---|---|---|
|-|(Minus sign) Use with<br>**#**to allow numbers with minus signs. Negative numbers are<br>automatically displayed in red. SeeNumeric data<br>.||||||
|]|May be added to any column in a file-mode tree to force trailing blanks to be stripped before<br>loading the cell. (This is automatic in array mode, but in file-mode, the blanks may be needed<br>to preserve the interpretation of the returned selection string.)|||||X|
|=|Expand/Collapse State<br>.|||||X|
|0|(zero) Application-levelAuto-Filtering<br>.|||D||X|
|1, 8|Character Set<br> allows you to specify ANSI/Latin1 or UTF8 at the column level.|||D|||
|3|3 state version of checkbox. When used in conjunction with either<br>**T**or<br>**t**allows the checkbox to<br>have 3 states (0=unchecked, 1=checked, 2=indeterminate).|||D|||
|A|ASCII Sort<br>.||||F|X|
|B|Background cell color<br>.||C||||
|b|Background row color<br>.||C||||
|C|Row color<br>.||C||||



A-Shell Reference 

Page 3419 

|**Code**|**Meaning**|**E**|**C**|**D**|**F**|**X**|
|---|---|---|---|---|---|---|
|c|Row color option||C||||
|D|Standard Date Format<br>.|||D|F||
|d|Deprecated**.**Superceded by the expanded capability of code<br>**D**and retained only for backward<br>compatibility. Date in dd-mon-yr format.|||D|||
|E|Column contains editable text<br>.|E|||||
|f|Font definition column<br>.|||||X|
|H|Hidden column<br>.|||||X|
|HH|Conditional Hidden column<br>.|||||X|
|h|Indicates a column with times in it. This acts like a string column except for sorting purposes,<br>where any time format supported byIDTIMwill be recognized and sorted accordingly.|||D||X|
|I|(Capital i)Image column<br>.|||D|||
|K|Keep column position (i.e. do not allow it to be reordered by the user). Needed (as an override)<br>only when_flags_XTF_REORD set|||||X|



A-Shell Reference 

Page 3420 

|**Code**|**Meaning**|**E**|**C**|**D**|**F**|**X**|
|---|---|---|---|---|---|---|
|L|Lock column—i.e., do not allow it to be resized by the user or byXTREEitself. Must be<br>accompanied byDspwid<br> or Dspmin or else the column will become hidden.|||||X|
|l|(Lower case el).Combo Box<br>.Previously called "list," hence the<br>**l**<br> .|E||D|||
|ll|(Lower case double el) Use in place of<br>**l**<br> for list substitution in a non-editable column or tree.|||D|||
|M|Allow embedded CRLFs<br>.|||D|F||
|m|Used with<br>**E**to specify a multi-line edit, while retaining single-line display. For both multi-line<br>edit and display, use<br>**M**with<br>**E**.|E|||F||
|n|Causes empty cells to always sort to the bottom, regardless of whether sorting up or down. May<br>be used with any column type.||||F||
|O|(Upper case "O") Indicates that this column is allowed to overflow into the next column<br>(provided the next column contains the<br>**o**option and the cell is empty.)||||F|X|
|o|(Lower case "o") Indicates that an overflowing previous column may overwrite this column,<br>provided the cell is empty. This setting is not just automatic based on the prior column, because<br>of the possibility of the user reordering the columns at runtime. Note also that this could affect<br>the layout of the returned item in the array parameter; so if it is critical to you that all spaces<br>be preserved in that line, don't use this code.||||F|X|



A-Shell Reference 

Page 3421 

|**Code**|**Meaning**|**E**|**C**|**D**|**F**|**X**|
|---|---|---|---|---|---|---|
|P|TheFirst Position Reserved<br> option may be used with editable cells to indicate that the first<br>position is reserved for either a space (editable) or a<br>**|**<br> (not editable).|E|||||
|R|Editable radio button<br>.|||D|||
|r|Non-editable radio button. Just like<br>**t**(which see for details about the column data format)<br>except for the appearance (a circle with a dot in it rather than a square with a checkmark or<br>"tick").|||D|||
|S|String data (left justified by default).||||||
|s|Defines the column as being capable of referencing theList<br>. Similar in concept to<br>**B**<br>(Background cell color<br>) in that it reserves the first character of each cell in the column for the<br>index letters that associate the cell with one of the predefined lists.|||D|||
|ss|Use in place of<br>**s**for list substitution using a shared list in a non-editable column or tree.|||D|||
|T|Editable checkbox<br>.Also see<br>**+**above.|E|||||
|t|Non-editable checkbox<br>.|||D|||
|tt|Acts like<br>**t**, but instead of always displaying in dim intensity, instead uses the same formula<br>based on the value of the cell as with editable checkboxes. In other words, by default,<br>**tt**<br>checkboxes display in normal intensity; to force individual checkboxes to display as dim, add +4|||D|F||



A-Shell Reference 

Page 3422 

|**Code**|**Meaning**|**E**|**C**|**D**|**F**|**X**|
|---|---|---|---|---|---|---|
||to the cell value.||||||
|U|Application-editable only<br>.|E|||||
|u|Read-only editable<br>.|E|||||
|uu|Works like<br>**u**but displays only a frame around the cell rather than overlaying the cell with an<br>edit or combo control. This is just an aesthetic variation. Note that<br>**uu**automatically exits on<br>ENTER, rather than acting likeTAB, as it does in most other cell navigation situations. The theory<br>here is that<br>**uu**is mainly intended for people who prefer the keyboard to the mouse, for whom<br>ENTERwould be the most natural way to "select" (i.e. exit from) the current cell.|E|||F||
|V|Conditional validation<br>:if the cell changes during editing|E|||||
|v|Unconditional validation<br>:whether it changes or not|E|||||
|W|Auto-wrap columnar data onto multiple lines. SeeXTR.ITEMLINES<br> and_Comments_inAllow<br>embedded CRLFs<br>. Sample image here<br>.||||F|X|
|X|Conditional validation<br>.|E|||||
|x|Unconditional validation<br>.|E|||||



A-Shell Reference 

Page 3423 

|**Code**|**Meaning**|**E**|**C**|**D**|**F**|**X**|
|---|---|---|---|---|---|---|
|Z|Same as<br>**#**(numeric) except that it overrides aMask<br>, causing zero-value cells to display as<br>blank.<br>**S**has the same zero-blanking mask override, but<br>**Z**columns use the numeric sort rather<br>than the natural sort.|||D|||
|<|Left justify column (default).||||F||
|||Center justify column. This applies during editing, as well as for display.||||F||
|>|Right justify column. Note that in file mode, this causes the trailing blanks for this column to be<br>stripped, which affects the return data. See the_flags_option XTF_FILANS. This applies during<br>editing, as well as for display.||||F||
|^|Causes sort to be case insensitive. Note that whether case sensitive or not, the collating<br>sequence is based on the Windows locale and not the LDF.||||F||
||(blank)No Strip<br>.||||F|X|
|_|(underscore) May be used with editable columns to cause the edit cell to shrink to fit only the<br>number of allowed characters (so as to not give the user an initial false impression of the<br>number of allowed characters). This will probably only be reasonable when a fixed pitch font is<br>used.|E|||||



A-Shell Reference 

Page 3424 

## **CHARACTER SET** 

_Added November 2013_ 

_cformat_ switch: **1, 8** 

Two _cformat_ codes allow you to override the default character set at the column level: 

- **1** interprets the column data as ANSI/Latin1 

- **8** interprets the column data as UTF8 

The overall default character set for the tree is ANSI/Latin1, unless the XTF2_UTF8 flag is set, in which case it is UTF8. 

Note: the entire _coldef_ string is interpreted according to the default character set for the tree, so you cannot mix UTF8 and Latin1-encoded titles even though the corresponding columns are individually set with **1** or **8** . 

Two new sample programs, XUTF8B and XUTF8C illustrate both cases of mixed UTF8 and Latin1 columns. 

A-Shell Reference 

Page 3425 

## **ASCII SORT** 

## _cformat_ switch: **A** 

This is just like _cformat_ code **S** (String) except that it forces XTEE to use the standard ASCII sort instead of the "natural" sort. The **A** may be added to the **S** or used in place of it. Note that the LDF collating sequence applies, regardless of the sort algorithm. Note also that code **A** takes precedence over—has a higher priority than—code **#** (numeric sort). 

A-Shell Reference 

Page 3426 

## **ALLOW EMBEDDED CRLFS** 

_cformat_ switch: **M** 

Sample image here and another sample image here. 

Items in column may contain embedded CRLFs causing it to display using multiple lines. Note that `XTR.ITEMLINES` determines the maximum number of lines of text displayed in a cell. (Cells that exceed this number of lines will display an ellipsis or "+" to indicate that there is more data than can be displayed.) Also see _flags_ XTF_VARY (variable item height). Note that you cannot use embedded CRLF line breaks in file mode, because CRLF is used for the record terminator. 

## **Comments** 

When _cformat_ code **M** is combined with **E** (editable text cell), _cformat_ **m** is also implied. 

When **M** is specified for any of the "columns" in a property sheet (see XTF2_PROPSHEET), then it will be applied to all of them, since all of the logical "columns" effectively share the same display column, and the embedded CRLF feature is only adjustable at the display column level. This point applies also to _cformat_ code **W** . 

A-Shell Reference 

Page 3427 

## **- APPLICATION EDITABLE ONLY** 

_cformat_ switch: **U** 

This designation may be added to an editable text column (type **E** , Column contains editable text) to cause the column to only be updatable by the application. In other words, this will make the column editable but not-editable. Possible reasons for using this format type include: 

- You want to update the field when re-entering the tree with XTROP_REPLACE. (Only cells associated with the answer array are 

- updated when re-entering with XTROP_REPLACE, and only editable cells are in the answer array.) The alternative would be to use XTROP_REPLACE when re-entering the tree, in which case all of the data cells can be updated, but the operation is less efficient. 

- You want to use the same variable for both the answer and data arrays. This requires that all fields be "editable". 

## **History** 

- 2012 April, A Shell 6.0.1247:  Adding _cformat_ code **U** (application-editable only) to a checkbox ( **T** or **t** ) or radio button ( **R** or **r** ) now has the expected effect, i.e. the same effect as on regular text cells. That is, the checkbox/radio button becomes disabled to the user, but gets updated by the answer array. 

A-Shell Reference 

Page 3428 

## **BACKGROUND CELL COLOR** 

_cformat_ switch: **B** 

Sample images here and here and here. 

Allows you to specify custom background colors for individual cells. Unlike the other color column codes ( **b** , **C** , **c** ) this one is usually specified in conjunction with some other column type. The first character of the column data is assumed to be an RGB Color Index (see RGBfg) Any other value, or if the specified color index does not reference an RGBfg or RGBbg definition, then that cell will have the normal background color. Typically you would put a space in the first position for all the "normal" cells, and just use this feature to highlight a few special cells in the column. For example, if the cell contained "Asold out", it would display "sold out" with the background color associated with RGB color index A. Note that if you want the cell to be blank (i.e. just show a color), do not put any other data in the column, but use the Dspwid option to set the display width of the column. 

Also note that if the column contains editable data (E,U,u,T) then the first byte of the corresponding field in the Answer array must also be reserved for color codes. The purpose of using up an extra byte of the answer array for the cell color flag is to allow you to update the color of individual cells during editing validation. To simplify this, the color codes returned on exit will always be blank. Leaving them blank on re-entry causes the previously established color for the cell to be preserved. If you plug in an RGBbg color index value in the answer array for a particular cell and re-enter, that cell's color will immediately be updated accordingly. 

## **See Also** 

- RGBfgbg 

- First Position Reserved 

A-Shell Reference 

Page 3429 

## **COLUMN CONTAINS EDITABLE TEXT** 

_Rewritten May 2014_ 

_cformat_ switch: **E** 

Sample image here and another sample image here. 

When focus is placed on a cell in the column by clicking directly or by navigating with keyboard characters, the cell becomes an edit control, allowing the text contents to be changed. Aside from very basic editing parameters (type of characters, maximum length), validation is left to the application. The XTREE operation can be made to exit, allowing the application to retrieve the updated cell contents from the Answer array to validate/correct/reject the edit and then re-enter at a chosen cell. 

This option may be combined with and/or modified by several other  codes, Advanced Coldef Options, and _flags_ options. In particular: 

- _cformat_ **X** (Conditional validation) 

- _cformat_ **x** (Unconditional validation) 

- _cformat_ **U** (Application-editable only) 

- _cformat_ **u** (Read-only editable) 

- _cformat_ **l** (Combo Box) 

- InfDef 

- Mask 

## **See Also** 

- Editable Tree Controls 

A-Shell Reference 

Page 3430 

## **CONDITIONAL VALIDATION** 

_cformat_ switch: **X** 

The conditional validation option forces XTREE to return with Exitcode -48 whenever a cell in the corresp column has changed, or, in the case of editable read-only, is about to change, so that the application can perform validation. It may be combined with any _cformat_ code indicating a column whose contents can be changed by the user (e.g. **E** , **T** , **R** , **l** , etc.). 

In the normal case, the exit for validation is triggered after the cell has changed. If the application doesn't want to accept the change, it can either reset the cell itself, or force the user back into that cell to make an acceptable change. In contrast, for Read-only editable ( **u** ) cells, the conditional validation option exits (again with exitcode -48) when the user signals the desire to make a change but before any change has occurred, i.e. to allow for pre-validation. 

Whenever the conditional validation option forces an exit, in addition to exitcode being set to -48, the following fields within the xtrctl parameter will be set: 

- XTR.xrow and XTR.xcol will indicate the cell that previously had the focus. 

- XTR.targetrow and XTR.targetcol will indicate the cell that will get the focus next (i.e. the cell that was clicked or is otherwise 

- next in the navigation sequence). 

- XTR.validate will be set to 1 if the former cell needs validation (i.e. was changed); 2 if the latter (target) cell needs pre- 

- validation (for editable read-only), or 3 if they both need validation. 

## **See Also** 

- Editable Tree Controls 

- Unconditional validation (x) 

A-Shell Reference 

Page 3431 

## **PRESERVE FOREGROUND COLOR** 

_cformat_ switch: **!** 

May be used in conjunction with format codes **C** or **c** to force the foreground color to be preserved even when the row is selected. Normally, the foreground (text) color of selected rows is white, so as to offer good contrast with the color of the selection bar, which is usually blue. But this makes the rows which have custom text colors indistinguishable from the ones that do not (when selected). When **!** is specified, A-Shell will attempt to determine if the foreground color is "too close" to the color of the selection bar to distinguish; if so, then it uses black for selected text; otherwise it retains the original foreground color. (This is probably mainly of interest with multi-selection mode.) 

## **History** 

- 2012 April, A Shell 6.0.1248:  adding the _cformat_ code **!** to any column now assigns that and all remaining columns the "retain foreground selected color" feature. Previously it only applied to row colors; with this change, it can be applied to colored columns as well. 

A-Shell Reference 

Page 3432 

## **LIST HIERARCHY** 

_Updated September 2024; see History_ 

## _cformat_ switch: **@** 

For multi-level lists, a column must be defined using this type, and must also contain a digit indicating the hierarchical level of each row (0 through 63 with 0 being the top level.) Note that you would almost always want to also use the **H** code to hide this column, otherwise you will have a visible column containing the level indicators. Due to some internal complexities in the control, it may not be possible to hide the first column; to avoid this problem, make sure the **@** column is not the first one defined. 

The compound code **@@** may be used in place of just **@** to force the left/right arrow keys to always act as 

- expand/contract/navigate keys, even if the XTF_LEFT, XTF_RIGHT, or XTF_EDITABLE _flags_ are present. See XTREE Techniques Mouse and Keyboard. 

Note that in the case of Property Sheets, '@@' indicates level 2, and the left/right arrow expand/contract is automatically enabled if neither XTF_LEFT or XTF_RIGHT is specified. 

## **History** 

- 2024 September, A Shell 7.0.1762:  Resolve conflict between the normal list hierarchy '@@' (enabling the use of left/right arrows for expand/contract) and '@@' meaning level 2. 

- 2023 August, A Shell 1737:  Increase maximum number of multi-level trees from nine to 63. 

A-Shell Reference 

Page 3433 

## **NUMERIC DATA** 

_Re-written February 2019_ 

_cformat_ switch: **#** 

- Indicates that the column contains numeric data, which affects the way the column is sorted, the type of Auto Filtering that would be applied by default, and causes negative values to display automatically in red unless overridden by the NegFgBg option. 

Note that the **#** code does not prevent the display of non-numeric characters, nor does it automatically format them or even right-justify them. For these additional effects, see the **>** code and the Mask option. For editable cells, the **#** code only allows the input of numeric digits, so you may want to add the **.** and **-** codes to explicitly allow the entry of decimal points and minus signs—and/or use Mask. 

Note also that the **#** switch has a lower priority that the **A** switch. 

A-Shell Reference 

Page 3434 

## **LITERAL BACKSLASH** 

_cformat_ switch: **\** 

The backslash may be used to declare that a backslash within the column should be treated as a normal character, rather than as the start of hidden text (as would otherwise be the case when in file mode). Note that using the **\** type on any column effectively turns it on for all columns. 

## **History** 

- 2008 July, A Shell 5.1.1119: The determination of whether a **\** marks the beginning of hidden text in XTREE has been improved for array-mode trees. Previously, unless one of the columns specified the _cformat_ code **\** , all backslash characters were considered as the start of hidden text (from there to the end of the row). This was taking people by surprise, especially when the backslash occurred in an editable column (like in a filespec). The new rule is that a backslash will be treated as a literal character if ANY of the following is true: 

- The code **\** is present for any column (as before). 

- The backslash occurs prior to the last physical column in the array data (without regard to the order in which the logical 

- columns are defined). 

- The last physical column is editable. 

A-Shell Reference 

Page 3435 

## **BACKGROUND ROW COLOR** 

_cformat_ switch: **b** 

Allows you to apply custom background colors to individual rows. This is the same concept as _cformat_ **c** except that it only uses colors defined by RGBbg clauses (either on the pseudo column or on any other column). The column must contain a single character matching an RGB Color Index. 

Note that as with with other column types used to encode row attributes (see _cformat_ **b** , **c** , **C** , **f** , **@** ), rather than row data, you almost certainly want to pair this with the code **H** to hide the column. 

Sample image here. 

A-Shell Reference 

Page 3436 

## **ROW COLOR** 

## _cformat_ switch: **C** 

Allows you to apply custom foreground colors to specific rows. Column may contain an RGB Color Index which matches the index assigned to an RGBfg or specification on another column.  The corresponding color is applied to the foreground (text) of the remaining columns in the current row. Leave column blank (or "=") to use the default color scheme for that row. Note that you would almost always want to also use the **H** code with this column type to hide it. 

## **See Also** 

- RGBfgbg 

## Sample image here. 

A-Shell Reference 

Page 3437 

## **ROW COLOR OPTION** 

_cformat_ switch: **c** 

Identical to **C** , except that it takes effect starting from the first visible column even if the color definition column is not the first column. This is a workaround for a limitation in which trying to make the first defined column invisible does not always work. (XTREE seems determined to make the first column reappear.) 

Sample image here. 

A-Shell Reference 

Page 3438 

## **COMBO BOX** 

_cformat_ switch: **l** (lower case el) 

Similar to column format **E** except that instead of an edit control, a combobox control is used for editing the cell when the cell has the focus. The combo box choices must be defined with one of these Advanced Coldef Options: List, CellList, ListX and CellListX. There are three variations of comboboxes. In the default variation, the user can only select among the defined choices. If the **E** code is specified in addition to the **l** code, then the user will also be able to type in a text value that is not in the list. The third variation is the so-called "self-service" combo in which the list just contains "…" and when the user clicks on the dropdown button, it exits with _exitcode_ 29 (as in INFLD). 

Note: regardless of whether the **E** code is specified, combo box columns are treated like editable columns in that they must be represented in the answer array. In order to prevent individual cells or entire columns from being actually editable by the user, prefix the column data with a **|** (vertical bar). This may require expanding the column width, again both in the data array and answer array. 

A-Shell Reference 

Page 3439 

## **STANDARD DATE FORMAT** 

_cformat_ switch: **D** 

MM/DD/{CC}YY format or DD/MM/{CC}YY format, depending on language definition. Supports quite a bit of flexibility in formats, including dates with other delimiters (e.g. 12-31-24), no delimiters (e.g. 12312024), as well as dd-mon-{cc}yy format (e.g. 12dec-2024). If a two digit year is specified, XTREE uses the SBR=CCYY in miame.ini for determining the century. The default value is equivalent to SBR=CCYY:60, meaning that any YY value of 60 or higher is assumed to 19YY; otherwise it is assumed to be 20YY. 

Note that there is no internal validation or formatting logic associated with the **D** _cformat_ code. Its purpose is solely to inform the sorting routine so that it can interpret the column data to be able to effectively sort it in chronological order. For editable date columns, the only way to enforce a consistent format is to use the Advanced Coldef Options InfDef=D and Format=<format string>, which cause the Windows date/time picker control to be used for editing. 

Also note that date columns including both a date and a time (e.g. "25-May-24 08:25 PM") will be sorted taking both into account. 

## **History** 

- 2023 June, A Shell 6.5.1733:  Coldef "D" now recognizes SQL DATE and DATETIME formats CCYY-MM-DD {HH:MM{:SS}}. Previously they didn't sort properly. Note that if all the cells in the column are in that format, sorting will work with coldef "S" (string), but date filtering would not. 

A-Shell Reference 

Page 3440 

## **FONT DEFINITION COLUMN** 

_cformat_ switch: **f** 

Same concept as the color definition column ( _cformat_ **c** ) Column should be 1 character wide, and contain a space or digit 0-4. Space or 0 causes the default font to be used for that row, else references the first through fourth special fonts defined previously using the Font and/or Scale options with a pseudo column. 

A-Shell Reference 

Page 3441 

## **HIDDEN COLUMN** 

_cformat_ switch: **H** 

Allows you to start with a fixed format source of data (either array or file) and customize it at runtime by making selected columns invisible. Hidden columns are loaded into the list box just like any other data, so you would not want to over-use this technique with large data sets due to the wasted overhead. 

Note that the hidden column flag ( **H** ) overrides the Dspmin and Dwpwid options, but will itself be overridden by the XTR.USRFLG XTUCFG_COLWID option. 

## **History** 

- 2024 December, A Shell 7.0.1766:  Support _cformat_ **H** and **HH** (hidden items) in property sheet mode. 

## **Conditional Hidden Column** 

_Revised December 2024_ 

_cformat_ switch: **HH** 

Acts like **H** but only if the column is empty (if string) or zero (if numeric). 

## **Comments** 

The logic supporting this is tied to the data (rather than answer) array load operation. So adding data to the answer array for a previously hidden **HH** column and and re-entering with XTROP_RESELECT will not cause cause the column to become visible. But adding it to the data array and re-entering with XTROP_REPLACE should reevaluate the column to determine if it should become visible. 

In the case of Property Sheets (see History below), in order to re-enter a tree with changes to the contents that would affect the visibility of **HH** 'columns', it may be necessary to completely delete the tree (XTROP_DELETE) and recreate it (XTROP_CREATE). 

Note that checkboxes are normally treated by the **HH** filtering like string fields, so unchecked boxes (with "0" in the column data) will not be hidden, but empty boxes (" ") will be.  If you want to also hide unchecked boxes ("0"), you can add the **#** cformat code to the checkbox code, e.g. **t#HH** . 

A-Shell Reference 

Page 3442 

## **History** 

- 2024 December, A Shell 7.0.1766:  Add support for **HH** to property sheets.. 

- 2024 May, A Shell 7.0.1759: **HH** function added to XTREE. 

A-Shell Reference 

Page 3443 

## **IMAGE COLUMN** 

_Updated November 2022_ 

_cformat_ switch: **I** (upper case eye) 

## Sample image here. 

Column data contains the filename of an image file to display in the column. Supports JPG, BMP, PCX, GIF, TIF, PNG and ICO file types. The image filename may also be in the form of a URL,  e.g. http://www.mydomain.com/images/bigbang.png. You must also specify the options ImgSiz, ImgCount, and optionally ImgDir. You can include arbitrary text in the cell, along with the image, by appending a comma to the filename, followed by the arbitrary text. The column definition has to be wide enough to include both the filename and the desired display text. 

Note that although image cells can display additional text, and the text may be made editable (if the column is editable), the image filename itself is not editable. To change it, you need to programmatically change the filename in the column data and reload the tree. 

Note also that in the case of ICO files, you may either specify the .ICO file itself (as with the other image types), or you may specify an icon resource using the resname::dllname syntax. 

## **History** 

- 2023 August, A Shell 6.5.1739:  URL and WEBCACHE support added. 

- 2015 May, A Shell 6.1.1410: Support multiple image columns per XTREE. Previously only one was allowed. 

A-Shell Reference 

Page 3444 

## **FIRST POSITION RESERVED** 

_cformat_ switch: **P** 

Code **P** may be used with editable cells ( _cformat_ codes **E** , **l** ) to indicate that the first position (after any cell code bytes such as the color byte used with _cformat_ **B** ) is reserved for either a space (indicating editable) or a **|** (vertical bar) indicating that the cell is not editable. 

Note that the **|** prefix has long been supported as a code to indicate that the cell is disabled for editing, but it is sometimes awkward to use because of confusion over whether to shift the remaining characters over. The **P** option allows you to reserve a position (same concept as with the background cell color byte used with **B** ), which may be easier to use, depending on your application logic. 

Also note that feature is not necessary with the shared lists ( _cformat_ **s** used with CellList or CellListX), because in those cases, a space is already reserved for a prefix code, in which **|** is already an option. 

A-Shell Reference 

Page 3445 

## **EDITABLE RADIO BUTTON** 

_cformat_ switch: **R** 

## Sample image here. 

Similar to **T** (checkbox) but has the additional behavior of automatically clearing any other radio buttons in the same group when one of them is set. Thus a group of radio buttons may serve as a way of inputting a "one of" choice. See sample program XTRA6. 

By default, all of the radio buttons on a row are in the same group, whether contiguous or not. To define multiple groups of radio buttons (or a vertical group), see the "Group" option in Advanced Coldef Options. 

The XTRA6 sample program illustrates radio buttons with cell colors. 

See _cformat_ code **r** for non-editable radio button. 

A-Shell Reference 

Page 3446 

## **EDITABLE CHECKBOX** 

_Updated April 2022_ 

_cformat_ switch: **T** (standard) or **T+** (extended) or **T3+** (three-state extended) or **T++** (extra extended) 

An editable checkbox is represented in the data and answer arrays by a one-character column coded according to the following table: 

|**Code**|**Description**|
|---|---|
|0|Unchecked|
|1|Checked|
|2|Indeterminate|
|4|Unchecked, disabled|
|5|Checked, disabled|
|6|Indeterminate, disabled|
||A space blanks out the cell<br>entirely|



Note: values in the above table are _strings_ ("0", "1", etc.), not binary values. 

Extended 2-state checkboxes (T+) and 3-state checkboxes (T3+) support the following additional mouse & keyboard commands: 

A-Shell Reference 

Page 3447 

- When the focus is on a checkbox cell, CTRL+A sets (ticks) all the enabled checkboxes in the column. 

- When the focus is on a checkbox cell, CTRL+B resets (clears) all the enabled checkboxes in the column. 

- When the focus is on a checkbox cell, CTRL+Z reverses the action of the immediately preceding CTRL+A, CTRL+B, or SHIFT+CLICK. 

- To toggle (tick or clear) a range of checkboxes in the same column, click to set the first checkbox in the normal way, then 

- Shift+Click on the last checkbox in the range. Note that individual cell validation ( _cformats_ x,X,v,V) is not supported during a multi-cell toggle operation. 

Extra-extended ( **T++** ) 2-state or 3-state checkbox columns will have a 3-state checkbox added to the header of the column which is automatically set to the checked state if all the boxes in the column are checked; the unchecked state if all the boxes are unchecked, or the indeterminate state if there is a mixture (or if all of the boxes are indeterminate), as in this example: 

Clicking the checkbox in the header cycles through the check-all, uncheck-all, set-all-to-indeterminate (if 3-state), and back to the original mixed state (if applicable). 

The following special context menu commands (see PopupMenu) relate specifically to extended checkboxes: 

- $CBSET acts like CTRL+A (sets all checkboxes in the column over which the mouse was right-clicked to bring up the context 

- menu).  If the menu is activated by right-clicking on any column other than an extended checkbox column, this option will not appear on the menu. 

- $CBRST is like $CBSET, but acts like CTRL+B (reset or clear all checkboxes) 

- $CBUNDO acts like CTRL+Z.  Like $CBSET and $CBRST, it will only appear in the menu if the menu is activated for an extended 

- checkbox column.  In addition, if undo is not possible, the option will be grey. 

- $CBSETDEP is like $CBSET, but applies only to the dependents of the current item.  If the item clicked has no dependents, 

- the option will be grey.  If the tree is not multi-level (XTF_MLVL not set – see XTREE Flags ), the option will not appear at all. 

- $CBRSTDEP is like $CBSETDEP, but resets rather than sets the dependent checkboxes. 

Because the above context menu commands adjust to the runtime circumstances, they can be added to the common PopupMenu for a tree, without regard to whether the tree even contains extended checkboxes, rather than having to add them only to column-specific context menus.  The only reason why these items weren’t just automatically defined for extended checkbox 

A-Shell Reference 

Page 3448 

columns is to allow you to define the wording.  For example, for a tree in which the items represented styles of products, grouped into categories, you might define the context menu items as follows: 

```
Coldef = "0~0~x~H~PopupMenu=Order all styles,$CBSET;Cancel all,$CBRST;"; &
```

```
+ "Order all styles in category,$CBSETDEP;Cancel all in category;$CBRSTDEP;" &
```

```
+ "Undo;$CBUNDO~~"
```

The context menu might then appear as: 

## **Comments** 

- You must also specify the flag XTF_EDITABLE when using checkboxes. 

- If the checkbox column supports cell colors ( _cformat_ code **B** ) then the column data (in both the data and _answer_ arrays) 

- should be two characters wide (instead of one), with the first character reserved for the color code. 

- Use _cformat_ code **t** for non-editable checkbox, and code **3** for three-state checkboxes. 

- As long as the checkbox value column position is blank, the entire field contents will be displayed as text, even if the column 

- width is more than one. This might be useful in some exotic situations where a single column contains check-boxes in some rows, but text in others. The text would not be editable, regardless of the editable state of the column. See History. 

## **History** 

- 2024 December, A Shell 7.0.1766:  The combination of **E** and **t** now equivalent to **T** . 

- 2020 June, A Shell 6.5.1684:  Checkbox columns may now contain text as long as the first data position—i.e. the checkbox value character—is blank. 

- 2016 October, A Shell 6.3.1530.6: Column ordering for all the columns (up to the max of 100) can now be saved when using the TreeID mechanism with the XTUCFG_COLORD bit set in the `XTR.USRCFG` field. Previously the limit was 31 columns, which remains the limit when using the `XTR.COLORDER()` array method without the TreeID option. 

A-Shell Reference 

Page 3449 

- 2016 October, A Shell 6.3.1530.5: Extended checkbox columns may now be extended to a second degree by adding a second "+" (e.g. **T++** or **T3++** ). This adds a 3-state checkbox to the header of the column which is automatically set to the checked state if all the boxes in the column are checked; the unchecked state if all the boxes are unchecked, or the indeterminate state if there is a mixture (or if all of the boxes are indeterminate). Clicking the checkbox in the header cycles through the check-all, uncheck-all, set-all-to-indeterminate (if 3-state), and back to the origional mixed state (if applicable). 

- 2013 October, A Shell 6.1.1363: The PopupMenu options $CBSET, $CBRST, and $CBUNDO now return EXITCODE=-48 and `XTR.XVALIDATE=3` when validation (conditional or unconditional) is active for the column. $CBSETDEP and $CBRSTDEP return `XTR.XVALIDATE=4` . 

A-Shell Reference 

Page 3450 

## **- NON EDITABLE CHECKBOX** 

_Updated and reviewed July 2020_ 

## _cformat_ switch: **t** 

This should be a single character column, whose contents are "0" for an unchecked box, "1" for a checked box, or blank for a blank cell (with no checkbox). Non-editable checkboxes act just like other data columns, and do not require the XTF_EDITABLE _flag_ or have any correspondence with the _array_ parameter. 

## **Comments** 

- As long as the checkbox value column position is blank, the entire field contents will be displayed as text, even if the column 

- width is more than one. This might be useful in some exotic situations where a single column contains check-boxes in some rows, but text in others. The text would not be editable, regardless of the editable state of the column. See History. 

## **History** 

- 2024 December, A Shell 7.0.1766:  The combination of **E** and **t** now equivalent to **T** . 

- 2020 June, A Shell 6.5.1684:  Checkbox columns may now contain text as long as the first data position—i.e. the checkbox value character—is blank. 

A-Shell Reference 

Page 3451 

## **- READ ONLY EDITABLE** 

_Updated June 2016_ 

_cformat_ switch: **u** 

Similar to **U** in that it defines a variation on an editable text cell. While **U** causes the editing logic to skip over the cell in input mode, making it only updatable by the application, lower case **u** allows the cell to be given the edit focus but in read-only mode. Read only mode looks the same as regular edit mode except that the background of the cell is gray instead of white. 

The idea behind this feature is to give the user a sense of being able to edit the cell, but without allowing them to directly edit it. Instead, when the cell has the focus, most keys other than navigation keys will cause the XTREE to exit (with _exitcode_ = -48, as for normal cell editing validation), so that the application can then present a more customized cell editing capability. 

For example, in an appointment scheduler, you might want the user to be able to "edit" a cell in order to make or change an appointment, but you don't want them to just be able to type anything in the cell. Instead, they cause the cell to have the focus (using navigation keys or by clicking with the mouse) and then they can indicate the desire to update the cell by hitting ENTER, or any exit key, or for that matter, any normal character key. The application would then detect this event by the combination of the _exitcode_ (-48 for ENTER or printable characters, or the normal _exitcode_ for other exit keys) and determine the cell by the `XTR.XROW` and `XTR.XCOL` fields. Then it might pop up a dialog designed for editing an appointment. When that dialog is finished, the application can plug an updated value for the cell into the appropriate slot in the ANSARY parameter and re-enter the XTREE using `XTR.OPCODE 4` (reselect). 

Note that when re-entering, the initial focus will be determined by the `XTR.XCOL` and `XTR.XROW` fields (presumably still pointing the cell we were just in) and the `XTR.XNAVCOD` field, which contains the value of the key used to exit the field. Depending on that value, the initial focus may be advanced to another cell. For example, the standard action for the ENTER key is to advance to the next cell. If you don't want that, then zero out `XTR.XNAVCOD` before re-entering the XTREE. 

Also note: `XTR.XNAVCOD` can be used to determine which key the user entered to cause XTREE to exit. 13=ENTER, while values from asc("1") to asc("z") indicate the corresponding character key. 

## **- - Pre Exit on read only cell** 

The combination **uX** (editable read-only, with validation) causes an automatic exit with _exitcode_ -48 whenever the cell is ENTERED (rather than EXITED). 

A-Shell Reference 

Page 3452 

This makes some sense, given that you should not be able to modify the cell if it is read-only, so there isn't any point in post validation. But there is a point in pre-validation if you wanted to perform some action whenever the user selects one of these cells, either by clicking on it or using keyboard navigation.) 

Note that the `XTR.XVALIDATE` flag will be set to +2 to indicate that pre-validation of the cell identified by `XTR.TARGETROW` and `XTR.TARGETCOL` is needed. 

Also note that as of A-Shell 6.3.1516 there is no straightforward option to pre-validate an editable cell. However, you can simulate the effect by setting the adjacent columns to unconditional validation. In your program's validation routine, you can then detect when you are about to enter the column you wish to pre-validate by checking if it matches `XTR.TARGETCOL` . This will trap most cases of navigating into the column, except the user directly clicking on the column or the app directly starting on it. 

## **Comments** 

- This function supports individual cell colors. 

- Text in the cell is _not_ selected when starting the edit operation 

- Double-click exits with _exitcode_ -59. 

A-Shell Reference 

Page 3453 

## **UNCONDITIONAL VALIDATION** 

_cformat_ switch: **x** 

This flag may be used for "unconditional validation" of normal editable cells. When combined with **u** , it defeats the pre-validation and always causes post validation. The value of post-validating an edit of a read-only cell may be debatable, but this might be useful for the sake of uniformity if you want to validate between every cell movement. 

A-Shell Reference 

Page 3454 

## **NO STRIP** 

_cformat_ switch: (blank) 

When used in conjunction with a Mask, this code causes any leading spaces introduced as a result of the mask formatting to be preserved within the field. (Normally they are stripped before applying the column's justification.) 

This rather obscure feature may be useful in property sheets where you want to right justify some fields, but don't want them justified all the way to the right edge of the edit column (which may be wider than appropriate for the items in question, due to other, longer text items). For example, if  you have some numeric items that you want to right justify (so that they  line up with each other) but don't want way over at the right edge of the column, you can specify the combination of "<" (left justify), " " (no strip), and "Mask=###,###,###,###.##". The "<" will force the data to be left justified in the cell, but the no strip option will effectively  preserve right justification (provided that you are using a fixed pitch font). Typically in this case, you will want to make the column and mask wider than you would otherwise need, so that the displayed values are pushed farther to the right. The sample program XTRA15.BP in EXLIB:[908,21] has been updated to illustrate this. 

## **History** 

- 2011 January, A Shell 5.1.1202:  Added to A-Shell 

A-Shell Reference 

Page 3455 

## **EXPAND/COLLAPSE STATE** 

_Added April 2013_ 

_cformat_ switch: **=** (equals sign) 

This option is used for maintaining the expand/collapse state of items in a multi-level tree. When loading data items (XTROP_CREATE or XTROP_REPLACE), the column values will be processed as follows: 

|**Value**|**Action**|
|---|---|
|" "<br>(blank)|No special action|
|0|Force item to be collapsed|
|1|Force item to be expanded (immediate dependents<br>displayed)|
|"A"|Same as "1" but expand out all dependents of the<br>item|



Normally you would want to hide this column by adding **H** to the _cformat_ code. 

To retrieve the current expand/collapse state of the items on exit from the tree, you add the **U** code (e.g. = **HU** ) to make the column editable by the application so that the corresponding column of the answer array will be updated on return from the tree. This also means that item expand states will be potentially updated when re-entering the tree in XTROP_RESELECT mode. Note that in this case, you must use XTF2_ANSEQDATA flag (the answer and data arrays must be the same format, or perhaps even the same array). 

A-Shell Reference 

Page 3456 

## **History** 

- 2013 April, A Shell 6.1.1348:  Added to A-Shell 

A-Shell Reference 

Page 3457 

## **ADVANCED COLDEF OPTIONS** 

Zero or more of the following options may be specified to further define column options. Syntax is: 

## **~option = value** 

Each _option=value_ pair must be delimited on both sides by a single tilde, with a double tilde marking the end of the column definition. 

## **Example** 

```
COLDEF + = "10~15~Title~S~Color=3,7~Scale=200~Filter=PATTERN~ClickExit=-88,89~~"
```

The above example shows a complete definition for one column, starting in position **10** , with width **15** , column header " **Title** ", type **S** , and the three _option=value_ pairs. 

Note that both _option_ and _value_ are case sensitive. Additional examples may be found in the Advanced Syntax Example. 

|**Option**|**Description**|
|---|---|
|AutoNumber|Defines a column whose contents are filled automatically starting with the specified base number, and<br>incrementing by 1 for each data row in the tree.|
|Caption|Used with XTF2_POPUP to specify the caption of the popup window housing the XTREE.|
|CellList|Use to associate shared lists (combo boxes) with individual cells rather than entire columns.|
|CellListX|List substitution style (akaINFLD<br>**||L**) combo lists. SeeListX and CellListX<br>.|
|ClickExit|DefineExitcode<br>values for left and right click on the column. Applies to all columns if the ClickExit<br>clause is associated with column 0, otherwise applies only to the specific column. A right-click value in|



A-Shell Reference 

Page 3458 

|ell Reference||
|---|---|
||ClickExit takes precedence over PopupMenu. Format:<br>`ClickExit=<left exitcode>,<right`<br>`exitcode>`. See alsoXTR.KBDSTR<br>.|
|CollapseExit|Triggers an exitcode when a branch is collapsed.|
|Color|A pair of digits, comma separated, representing the desired foreground and background text color for<br>the column, from the A-Shell palette. Use only if you want the column to have a different color scheme<br>from the others. E.g.:<br>`Color=1,2`. (Foreground color one, background color two). Also see RGBbg,<br>RGBfg.|
|ColOptRows|Determines how many rows are considered when optimizing the column widths.|
|CtlName|You can assign a name to anXTREEcontrol by adding the_coldef_clause<br>`CtlName=name`to any column<br>(where_name_is the name you want to assign).|
|CurSym|Defines an alternate currency symbol to replace the $ in a mask (e.g.<br>`Mask=$###,###.##`).|
|Data|Use to define the contents of aConstant Data Column<br>.|
|DefaultFont|Sets the default font for the entire tree. The syntax is the same as forFont<br>.|
|DefaultScale|A font scaling percentage (100=normal), e.g.<br>`DefaultScale=120`. Works similarly to Scale, except<br>that it affects all subsequent columns, not just the current column. Furthermore, if specified with a<br>pseudo-column, it affects all the rows, eliminating the need to define a special font column with_coldef_<br>code "f". This makes it much easier to apply a scale factor to an entire tree. Note also that the<br>DefaultScale value is taken into consideration whenXTREEdetermines the row height for fixed-height<br>rows.<br>`HdrScale=0`and<br>`DefaultScale=0`are interpreted as requesting the default Windows desktop|



A-Shell Reference 

Page 3459 

|ell Reference||
|---|---|
||font size.|
|DragDropExit|`DragDropExit=###`, where ### is the negative exitcode to be generated when an item (or items)<br>from the source tree is/are dropped on to the destination tree. For example,<br>`DragDropExit=150`will<br>generate exitcode -150. SeeXTF2_DRAGDROP2|
|DragDropProtect|`DragDropProtect=###`allows ### rows at the top (or -### rows at the bottom) to be protected<br>from drag/drop operations. Note that because sorting would confuse the issue,<br>`DragDropProtect=###`<br>will automatically set HdrLines=### (if ### positive and HdrLines not already set), and<br>TotalLines=### (if ### negative and TotalLines not already set). Also supported is the syntax<br>`DragDropProtect=##,##,`which will protect rows at the top of the screen (first number) and the<br>bottom (second number); use positive values for each.|
|DropExit|`DropExit=###`may be used to forceXTREEto exit with the specified exit code (###) at the<br>completion of a Drag/Drop operation. Note that the exitcode will be -###—i.e.<br>`DropExit=88`will<br>return exitcode -88 on a drag/drop. This is the same syntax as<br>`SelChgExit=###.`|
|Dspmin|Similar to_Dspwid_except sets the minimum display width. (Unless the column is locked with the<br>_cformat_<br>**L**option, the user can resize the column, subject to this minimum.) E.g.<br>`Dspmin=5`. The<br>dspmin option is overridden by the hidden column (H) option.|
|Dspwid|Sets the initial display width of the column, e.g.<br>`Dspwid=10`.|
|EnterGoTo|`EnterGoto=#`specifies the column # to jump to when theENTERkey is hit.|
|ExitChars|Defines a set of characters that will force an exit from the tree.|



A-Shell Reference 

Page 3460 

|ExpandExit|Triggers an exitcode when a branch is expanded.|
|---|---|
|ExportFspec|`ExportFspec=<filespec>`will set the name of an exported CSV or XLSX file. If name is not<br>specified, system will use the TreeID for the export file name. If option is not specified, the filename will<br>revert to the previous default—XTREE-<jobnam> for the CSV2XL export and ASHGRID for the CSV<br>export.|
|ExportOptions|Sets various options related to the export-to-CSV function.|
|FastMax|`FastMax=#`sets the number of characters for an editable text or combo field which can be entered<br>before it automatically advances to the next field. Supercedes InfDef=F, which no longer does anything.<br>This clause is compatible with cell validation. Change In A-Shell 1377 of March 2014:<br>`FastMax=1`now<br>causes the cell to exit after clicking on a new selection in the dropdown list, or after using the up/down<br>arrow keys to change the selection and then hitting ENTER.|
|FileListX|In conjunction withLookupX<br>,automatically fills in a target cell based on the contents of a source cell,<br>using an external lookup table.|
|Filter|Overrides the default Auto-Filter type. Choices are CB, Range, Pattern, None.|
|FilterInitialState|If set to Disabled, causes the auto-filter button in the column header to initially be hidden. Users can<br>right-click on the tree to toggle the visibility of the auto-filter buttons.|
|FixedLayout|Causes XTREE to handle the specified column in a more "INMEMO-friendly" manner.|
|Fold|`Fold = <Upper or Lower>`. For editable cells, this flag causes contents to be automatically folded.<br>The folding applies during editing of cell but does not change the underlying data. See_Cformat_<br>**^**. Also|



A-Shell Reference 

Page 3461 

|ell Reference||
|---|---|
||see Coldef Default.|
|Font|A font face name and/or font attribute code, separated by a comma. See Coldef Default.|
|Format|Provides a way to configure the behavior of the Windows Time and Date Picker control associated with<br>an editable date and/or time column.|
|Footer|Set page footer.|
|FooterFont|Define footer font. Uses same syntax asHdrFont<br>.|
|FooterScale|Define scale for footer text. Uses same syntax as HdrScale.|
|FooterClickExit|Define exitcode(s) for clicking on footer. Same syntax asClickExit<br>.|
|Format|Sets options related to the Date/Time Picker control associated with an editable date/time column.|
|Group|Associate a radio button cell with aRadio Button Group<br>.|
|HdrClickExit|When specified, clicking on this column header causes an exit with the specified exitcode.|
|HdrDspMin|Set minimum display width for row headers in grid column units. (<br>`HdrDspMin=5`) See<br>XTR.SHOWROWHDR<br>.|
|HdrDspWid|Set display width for row headers in grid column units. (<br>`HdrDspWid=15`) SeeXTR.SHOWROWHDR<br>.|



A-Shell Reference 

Page 3462 

|ell Reference||
|---|---|
|||
|HdrFont|Same format and concept as_Font_, but applies to the header row.|
|HdrLines|This is analogous to the TotalLines option, but allows you to specify a number of lines at the top of the<br>tree that are to be treated as fixed headers and thus not included in sorting.|
|HdrScale|This is to_Scale_as_HdrFont_is to_Font_, e.g.<br>`HdrScale=125`.<br>`HdrScale=0`and<br>`DefaultScale=0`are<br>interpreted as requesting the default Windows desktop font size.|
|ID|Assigns a fixed numeric ID to a column. SeeXTR.COLID<br>for details.|
|ImgCount|Required with_cformat_<br>**I**<br> to allocate space for the image storage.|
|ImgDflt|Specifies the default image that will be displayed if and when the specified image is not found.|
|ImgDir|Optional with_cformat_<br>**I**<br> to specify the default image directory.|
|ImgSiz|Required with_cformat_<br>**I**<br> to define image size and scale parameters.|
|InfDef|Used to specify some variations ofXTREEeditable cell behaviour usingINFLD _type_codes.|
|ItemIconDir|Default directory for item icons. This is similar to ImgDir but for item icons. seeXTF2_ITEMICONS|
|ItemIcons|Define item icons.<br>`ItemIcons=closed-img,opened-img{,leaf-img}`; see XTF2_ITEMICONS<br>.|



A-Shell Reference 

Page 3463 

|ell Reference||
|---|---|
|||
|ItemIconSiz|`ItemIconSiz=iwidth,iheight,bpp`Similar to ImgSiz but for item icons; seeXTF2_ITEMICONS<br>.|
|ItemIconCount|`=<# icons to load>,<grow-by-value>`Similar to ImgCount but for item icons; see<br>XTF2_ITEMICONS<br>.|
|List|Define combobox entries for column typeL.|
|Listx|List substitution style (akaINFLD<br>**||L**) combo lists. SeeList<br>and ListX and CellListX<br>.|
|LoadOptions|Control loading of data into a tree.|
|LocValSBX|Specify local SBX forlocal validation<br>.|
|LookupX|Fills in a target cell based on the contents of a source cell, using an external lookup table.|
|Mask|Define a numeric formatting mask|
|MaskView|This is identical to the existing Mask option, except that the non-numeric mask characters (relative to<br>the current LDF) are stripped from the editable fields returned in the answer array. This is most<br>convenient when you plan to use the data returned from the tree in numeric calculations, where the<br>mask formatting characters may interfere with the conversion from string to number. Added in A-Shell<br>6.3.1514, June 2016.|
|NegFgBg|Allows control over the color used to display numeric cells with negative values.|



A-Shell Reference 

Page 3464 

|ell Reference||
|---|---|
|||
|PopupMenu|Defines a popup menu that will appear when the user right-clicks on a row.|
|ParentID|Specify the alphanumeric control ID (seeControl names<br>)of the parent control. XTR.parentid (in<br>XTRCTL<br>) must be set to zero.|
|Print|Disables printing on popup menu, including with ^P.|
|RGBbg|Define a background color, for a column or to be used for a row or cell.|
|RGBbg#|Associate checkbox and radio button states with background colors.|
|RGBfg|Define a foreground color specification.|
|RGBfgbg|Specifies foreground and background colors for individual cells.|
|RGBfgSel,<br>RGBbgSel|Define the foreground/backgroud colors for the selection bar; seeRGBfgSel and RGBbgSel<br>.|
|RGBfgHeaders,<br>RGBbgHeaders|Define the foreground/background colors for the header line; seeHeaders and Totals Colors<br>.|
|RGBfgTotals,<br>RGBbgTotals|Define the foreground/background colors for the totals line; seeHeaders and Totals Colors<br>.|



A-Shell Reference 

Page 3465 

|RGBbgOdd,<br>RGBbgEven|Define the default background color for the odd and even rows. This is typically used to create a "green<br>bar" effect to improve readability. Although this could be done using using individual row colors, the<br>problem is that sorting would mess up the effect by requiring that you handle your own sorting via<br>HdrClickExit. Note that any other color settings pertaining to individual rows or cells will override these.<br>The format for these is the same as forRGBfgSel and RGBbgSel<br>.If only specifying one of these values,<br>use RGBbgOdd.Sample image here.|
|---|---|
|RGBbgAll|`RGBbgAll=r,g,b`sets background color for all rows and columns. Affects even unpopulated rows,<br>unlike all other RGBbg options except RGBbgEven and RGBbgOdd.|
|RGBbgFooter|Define footer background color. Uses same syntax as RGBbgTotals.|
|RGBfgFooter|Define footer foreground color. Uses same syntax as RGBbgTotals.|
|RGBignore|Applies to editable text columns, and is equivalent to RGBbg except that it only applies to cells that are<br>marked to ignore. Cells are marked to ignore by placing a "|" in the first column of the answer array for<br>that cell.|
|Row/Col Header<br>Color Attributes|Provide the means for overriding row/column header color attributes.|
|Scale|A font scaling percentage (100=normal), e.g.<br>`Scale=50`. When associated with a real column, the font<br>defined (indirectly via the scale factor) affects just that column. When associated with a pseudo column<br>(i.e. with<br>`cwidth = 0`) it just serves to define the font so that it can be referred to by data in a font<br>definition column for applying specific fonts to individual rows (see_cformat_<br>**f**<br> in the table above). See<br>Font<br>and_Default Scale_.|
|ScrollMode|Change the operation of Up/DownArrows to act likeCTRL+UP/DOWN-ARROWS.|



A-Shell Reference 

Page 3466 

|ell Reference||
|---|---|
|SelChgExit|CausesXTREEto exit with exitcode -### whenever the selection changes.|
|Title|Set page title.|
|TotalLines|`TotalLines=#`where # is the number of lines at the bottom of the list which represent totals and thus<br>should not participate in sorting.<br>`TotalLines=1`is equivalent to setting flag XTF_TOTALS.|
|Tooltip|Specify a custom tooltip for the column.|
|TreeID|`Tree=<identifier>`identifies this tree uniquely to enableSaving User Adjustments<br>specific to this<br>tree.|
|VertAlign|Overrides default vertical centering of text or images within each cell. Choices are Top and Bottom—e.g.<br>`VertAlign=Top`.|



**Note 1:** When option is associated with the pseudo zero column, it becomes the default for all subsequent columns. That default can be overridden by individual column settings. 

A-Shell Reference 

Page 3467 

## **AUTONUMBER** 

_Added February 2020_ 

## **AutoNumber=<base>** 

Defines a column whose contents are filled automatically starting with the specified base number, and incrementing by 1 for each data row in the tree. This is similar to the XTR.SHOWROWHEADER feature in that the column appears immune to sorting, and that collapsed rows in multilevel trees are counted (causing visual gaps in the numbering), while rows filtered out are not counted. Unlike the row headers, an AutoNumber column otherwise shares most of the features of a normal column, i.e. can be in any position, have a column header, column color attributes, a context menu, click codes, can be moved or resized, etc. 

As with the constant data column feature (activated via the Advanced Coldef option "Data"), an AutoNumber column does not occupy any space in the data array. To indicate this, you must set the _cpos_ and _cwidth_ fields in the coldef definition to -1, e.g. `coldef$ += "-1~-1~ ~#~AutoNumber=1~RGBbg=200,225,250~~"` 

(Minus one, tilde, minus one, tilde, column title, tilde, format, tilde, advanced coldef options starting with AutoNumber.) 

Note that in the above example, the two minus one values and the AutoNumber clause are essential. The column title could be anything (blank in this example); the format code could be anything that makes sense for a numeric column. Additional advanced coldef options can be added as appropriate to specify a background color (as in this example), click codes, etc. 

## **History** 

- February 2020, A Shell 6.5.1675: Added to A-Shell 

A-Shell Reference 

Page 3468 

## **CLICKEXIT** 

## **ClickExit=<left click exitcode>, <right click exitcode>** 

Causes a single click on a cell in the column to generate an exitcode. Along with the exitcode, the XTRCTL fields TARGETROW and TARGETCOL will be set to the clicked-on cell. 

## **Examples** 

|**Code**|**Result**|
|---|---|
|`ClickExit=-88,89`|Left click generates exitcode -88, right click 89.|
|`ClickExit=0,-88`|Left click ignored, right click generates -88.|
|`ClickExit=-97,0`|Left click generates exitcode -97, right click ignored.|



A-Shell Reference 

Page 3469 

## **COLOPTROWS** 

## **ColOptRows=###** 

This option, Column Optimization Rows, is used to determine how many rows are considered when optimizing the column widths. In earlier versions of A-Shell, XTREE always looked at the first 100 rows, and this remains the default. But you can override the default by specifying this parameter. 

If ### is positive, it indicates the number of rows to consider for that column (max is 32767). If negative, it indicates the percentage of the total rows to consider. 

Any column that does not have a ColOptRows=### parameter will use the default # of rows (normally 100). To change the default, specify ColOptRows=### with the zero column. 

Note that the entire point of this exercise is to balance the column optimization with performance. The more rows that have to be considered, the longer it takes to arrive at the optimum width. The default of 100 rows is generally sufficient for "pretty good" optimization, and with negligible performance overhead. But, depending on the variability of the data in each column it may be that much less would be sufficient, or much more insufficient. As a rule of thumb, figure about 25 cells per millisecond of optimization time. 

So for a 1000 row x 30 column grid, the default optimization (looking at 100 rows) would take about 100 ms, while looking at all 1000 rows would take 10 times longer, or 1000 ms, which will be noticeable. But if only one of the columns has data of widely varying width, you could set ColOptRows=-50 (i.e. look at the first 50% of the rows) for that column, and perhaps change the default (for the other columns from 100 rows to 10 rows). That would reduce the number of cells considered from 30000 to 790, and thereby reducing the total optimization time from 1000 ms to about 27 ms. 

Although the length of this discussion may imply that it is very important to get the column width optimization right, keep in mind that the only downside of too little optimization is that some columns many initially be too narrow to show the widest cells without truncating, thus forcing the user to manually adjust the column width in order to see all the data. (Which can be done by either dragging the right column border, or double-clicking on it, in which case it optimizes that column considering all the rows.) 

On the other hand, too much optimization just wastes time, reducing responsiveness. But that isn't likely to become noticeable until you have upwards of 5000 cells to consider. 

A-Shell Reference 

Page 3470 

## **CURSYM** 

_Added January 2013_ 

## **CurSym=###** 

where ### is the decimal value of the ANSI (8-bit) character to use. 

This option is used to define an alternate currency symbol to replace the $ in a mask (e.g. Mask=$###,###.##). 

As with many other advanced _coldef_ options, if associated with the zero column, it becomes the default; else it only affects the specified column. So you could have Dollars in one column, Euros in another, and Pounds in a third. The most likely options would be: 

```
CurSym=128            ! Euro symbol
CurSym=163            ! Pound symbol
```

**Note:** ANSI character sets vary in support for some of the currency symbols. It is left to you to make sure that the value specified displays as desired in the font you are using. 

## **Comments** 

There are two complications here. One is that we are using the ASCII version of the XTREE control. (To really support non-ASCII characters, we should switch to the UNICODE version, which we may do at some point. For now, this is a workaround.) The other is that there is no way for us to be sure whether all existing XTREE masks which include the $ symbol really want to indicate dollar or the local currency. So rather than make it automatically default to the local currency, we opted to eliminate the possibility of breaking an existing application (and thereby forcing anyone who wants non-$ currency to add a new clause to their _coldef_ ). A side benefit of this approach is that it allows you to have different currency symbols in different columns or trees at the same time. 

## **History** 

- 2013 January, A Shell 6.1.1330:  Added to A-Shell 

A-Shell Reference 

Page 3471 

## **CONSTANT DATA COLUMN** 

_Added August 2015_ 

## **data=<text>** 

This allows you to define the contents of a column that is constant for all rows. This is essentially just a shortcut to redundantly specifying the same text in every row of the data array, and is typically most useful for columns containing "buttons", such as a "delete item" button on any row. Aside from specifying the column contents in the Data=<text> clause, you must also set the _cpos_ and _cformat_ parameters to -1. 

For example, you can define a column of delete "buttons" as follows: 

```
coldef += "-1~-1~Del~I~ImgSiz=16,16,24~ImgCount=1~Data=delete2::ashico1~ClickExit=-300,0~~"
```

## **History** 

- 2015 May, A Shell 6.1.1410: Added to A-Shell 

A-Shell Reference 

Page 3472 

## **DSPWID** 

## **Dspwid=<width in grid column units>** 

Sets the initial display width of the column (in character positions based on the standard character grid). For example, if set to 10, the column will occupy the same width as ten ordinary fixed-pitch characters (although it may display more in the typical proportional font.) If not specified, the initial column widths will be set wide enough to accommodate the longest data. This option is mainly useful for columns that may contain variable length text (see _cformat_ **W** option above), lest they expand to fill the entire pick list width, forcing the user to have to scroll horizontally (or manually resize the column) to see the other columns. (e.g. DSPWID=10). 

Also, this option may be used to specify a fudge factor adjustment (+/- pixels) rather than just a fixed size. To specify a fudge factor, insert a + or - after the =, e.g. 

```
Dspwid=+5   ! increase calculated width by 5 pixels
```

```
Dspwid=5    ! set width at 5 grid units
```

The fudge factor is particularly useful in situations where some minor internal miscalculation of the optimum column width is resulting in column data being truncated. 

Note that the Dspwid (and Dspmin) options are overridden by the hidden column (H) option. Also see Coldef Default. 

For property sheet mode (XTF2_PROPSHEET), _dspwid_ takes on a slightly different meaning. Since in this mode, all of the logical columns occupy the same display column, they cannot each have their own display width. Instead, Dspwid applies only to the width of the editable cell (i.e. when the cell is actively being edited; the units in this case are average character widths in the current font. This is similar to _cformat_ **_** (which see), but allows more flexibility, since it is often preferable to make the editable box slightly wider or narrow, in order to allow for variability in the character widths. 

## **Examples** 

Without a Dspwid specification (and assuming _cformat_ **_** not specified), the edit box will 

A-Shell Reference 

Page 3473 

occupy the entire width of the column, as shown here: 

With Dspwid=6, the edit box is reduced to fix approximately 6 characters, as shown here: 

## **See Also** 

XTF2_AUTOEXPCOL 

## **History** 

- 2011 April, A Shell 5.1.1213:  Dspwid now works with combo box cells in property sheet mode to limit the width of the combo box. Note that the width specified includes the dropdown button, so you may need to adjust it upwards. 

A-Shell Reference 

Page 3474 

## **ENTERGOTO** 

_Updated October 2013_ 

## **EnterGoto=#** 

This specifies the column number to jump to when the ENTER key is hit while editing a cell in this column. If #>0, it jumps to _defined_ column number in the next row. If #<0, it jumps to _defined_ column number in the current row. _Defined_ column numbers are based on the order in which they are defined in the _coldef_ string; this could be unrelated to the _display_ column # due to both hidden columns and reordering - see XTF_REORD. If EnterGoto is not specified, the default is for ENTER to act like TAB and advance to the next editable cell to the right, wrapping to the next row if necessary, unless the XTF2_ENTERNAVDOWN flag is specified. 

Beginning in A-Shell 6.1.1318, EnterGoto=# may now be set to 0 ( `EnterGoto=0` ) to cause the tree to exit on ENTER, with exitcode = -48. If you don't like exitcode -48, you can use the syntax EnterGoto=##### where ##### is >= 10000, or <= -10000, in which case it will return with exitcode set to the specified value offset by 10000. For example, EnterGoto=10099 will return exitcode 99, while EnterGoto=-12500 will return exitcode -2500. 

## **History** 

- 2012 October, A Shell 6.1.1318: Accept value of zero, as described above. 

A-Shell Reference 

Page 3475 

## **EXITCHARS** 

_Revised December 2023_ 

## **ExitChars=<list of chars>** 

Defines a set of characters that will force an exit from the tree, where <list of chars> can be any combination of the following: 

```
0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ
```

In addition to the above, a caret ('^') may be inserted in front of any of the alphabetic characters to indicate a control char, e.g. **^M** triggers an exit on receipt of a CR (ENTER key). 

## **Notes** 

- The alphabetic characters are not case sensitive. 

- The exitcode will be set to -51. 

- `XTR.XNAVCOD` will be set to the actual character entered 

- This feature is not column-sensitive. 

A-Shell Reference 

Page 3476 

## **EXPANDEXIT** 

_Added April 2013_ 

## **ExpandExit=clickcode** 

## **CollapseExit=clickcode** 

These two options trigger an exitcode when a branch is expanded or collapsed: 

_clickcode_ may either be an integer value as with the SelChgExit=### command (e.g. ExpandExit=402), in which case the click event will return exitcode -402, or it may use the format of the row-specific exitcodes supported by `XTR.KBDSTR` as of 6.1.1345, in which case it will return an exitcode specific to the item that was expanded. 

For example: 

```
ExpandExit=_xF5RRR
```

would generate an exitcode of -5003 when it expands item #3. 

## **Notes** 

- In the case of a click on an inactive XTREE, the ExpandExit and CollapseExit codes supercede the `XTR.KBDSTR` code. 

• The exitcodes are generated for user-triggered expand/collapse events, regardless of whether triggered by a mouse click or keyboard command. However, they are not generated for expand/collapse events which are triggered indirectly by the application, such as via the `XTR.EXPANDLEVEL` or by setting the focus on an item that requires expanding the parent item so as to make visible). 

- The expand-all and collapse-all keyboard commands (CTRL+SHIFT+PLUS and CTRL+SHIFT+MINUS) will act as if taking place on row 

- 0, in case the clickcode uses the current row as part of the exitcode. 

## **History** 

## - 2013 April, A Shell 6.1.1347:  Function added to A-Shell 

A-Shell Reference 

Page 3477 

## **EXPORTOPTIONS** 

_Updated February 2023_ 

## **ExportOptions=<options>** 

where <options> is a comma-delimited list of options related to the export function. Possible values for _options_ are: 

|**Value**|**Description**|
|---|---|
|Code|applies to ListX or CellListX columns, causing the code rather than the description to be<br>exported to the CSV.|
|Descr<br>(default)|export the description rather than the code.|
|No|Causes the associated column to be excluded from exporting. Applies to real columns only.|
|Yes|Causes the associated column to be included in the export, regardless of whether the column is<br>hidden in the display view. Note that hidden columns will be output according to their physical<br>position in the_coldef_. Applies to real columns only.|
|NoRowIf#|Causes the entire row to be excluded from the export if the value of the corresponding column<br>is not zero—or, in the case of a checkbox or radiobutton cell, is checked / set. This would<br>typically be used with an editable checkbox column to select rows to include or exclude from<br>the export. Applies to real columns only.|
|NoRowIf!|Opposite of NoRowIf#, i.e. excludes the row from the export if the column value is zero or<br>unchecked.|



A-Shell Reference 

Page 3478 

|**Value**|**Description**|
|---|---|
|PhyOrder|Causes the order of the columns in the export to be based on the physical order they are<br>defined in the_coldef_, rather than the display order, which is otherwise the default. This option<br>affects all columns, regardless of the column that it is specified with. Also note that the option<br>can be abbreviated to ExportOptions=Phy; any additional characters are ignored.|
|Attr|Include foreground/background color attributes when exporting to Excel using CSV2XL.<br>Automatic if exporting to XLSX, by setting the system option SBR=XTREE_CSV2XCLSX either in<br>the MIAME.INI or via MX_SBRFLG, or via the PopupMenu $EXPCSV2XLSX command.|
|NoAttr|Disable export of color attributes.|



As with most other Advanced Coldef Options it can be associated with a zero-column in order to make it the default for all other columns. 

## **See Also** 

- Exporting Tree to Spreadsheet 

## **History** 

- 2020 June, A Shell 1682:  Add new options Attr and NoAttr 

- 2018 January, A Shell 1626:  Add five new values for _options_ 

- 2017 July, A Shell 6.5.1609: Function added to A-Shell 

A-Shell Reference 

Page 3479 

## **FIXEDLAYOUT** 

_Added October 2015_ 

## **FixedLayout = True** 

When set, XTREE attempts to handle the specified column in a more "INMEMO-friendly" manner. INMEMO uses a fixed rectangular grid layout, which maps easily on to a 2 dimentional array of R rows by C columns, whereas "normal Windows" multi-line text fields do not typically impose any such concept on the format of the lines. Instead, the only limitation is the total number of characters allowed. Lines may or may not be wrapped according to the font and column display width, and you may also have embedded CRLFs marking hard line breaks. The "normal Windows" method, used by XTREE and INFLD, has various advantages, but is hard to reconcile with legacy printing forms and fixed record layouts. 

To use the new option, set `XTR.ITEMLINES` to the number of lines of text in your multi-line text cells. The width of each line will be inferred from the total width of the column as defined to COLDEF, with any remainder discarded. XTREE will then assume that the data for the cell is arranged accordingly, with each line space padded rather than terminated by CRLF. In addition to converting to and from that format, it will also attempt to prevent the user from exceeding the specified maximum number of lines and columns when editing the cell. 

For example, if `XTR.ITEMLINES` is 4 and the width of the CWDITH value for the column is 100, it will be treated as an array of 4 by 25 characters, and the user will be limited to no more than 4 rows, and no more than 25 characters on any one row. 

Notes / restrictions: Not compatible with XTF_VARY or XTF2_UTF8. This is purely a client-side enhancement; no changes needed on the server side, other than to your application to supply the column text in the alternate format. 

## **History** 

- 2015 October, A Shell 6.1.1420: Added to A-Shell 

A-Shell Reference 

Page 3480 

## **FONT** 

## **Font=<facename>, <fontattr>** 

(e.g. FONT=LUCIDA CONSOLE,8001) Either part can be omitted to accept the default for that parameter; omit the comma if the <fontattr> part is omittedThe font attribute must be specified as a single decimal value formed from the sum of one or more values in the first table below (FS_xxx) and one value in the second table (FA_xxx). See Comments below for further details. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|FS_UPRIGHT|&h00|Normal upright|
|FS_ITALIC|&h01|Italic|
|FS_UNDERLIN<br>E|&h02|Underline|
|FS_STRIKEOU<br>T|&h04|Strikeout|



|**Symbol**|**Value**|**Description**|
|---|---|---|
|FA_DONTCARE|0|Do not care|
|FA_THIN|1600|Thin|



A-Shell Reference 

Page 3481 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|FA_EXTRALIG<br>HT|3200|Extra Light|
|FA_LIGHT|4800|Light|
|FA_NORMAL|6400|Normal|
|FA_MEDIUM|8000|Medium|
|FA_SEMIBOLD|9600|Semibold, demibold|
|FA_BOLD|11200|Bold|
|FA_EXTRABOL<br>D|12800|Extrabold, ultrabold|
|FA_HEAVY|14400|Heavy|



Note that the above symbols, while recognized by the compiler, are not recognized as literal text by XTREE; they must be converted to the numeric equivalents. Also note the difference between the FA_xxx symbols used here, and the similar FW_xxx symbols used by the //SETFONT GDI printing directive; the FA_xxx symbols are shifted up 4 bits (16 times) from the FW_xxx symbols. 

A-Shell Reference 

Page 3482 

## **Comments** 

Note that there may not be a meaningful difference between some of the stroke weights; these are just hints to the font mapper. Most fonts only support a couple of levels of stroke weights. 

When a Font option clause is associated with a real column, it affects only that column. When associated with the pseudo-column zero,  it serves to define a font that can be associated with a row by means of the _cformat_ code **f** .  Up to 4 such Font clauses can be specified, and are implicitly numbered 1 thru 4 based on the order they appear within the _coldef_ .  Note that this logic also applies to the Scale option.  For example: 

```
Coldef += "0~0~x~H~Font=Lucida Console,1~Scale=125~~"   ! Font #1: italic, 125%
Coldef += "0~0~x~H~Font=Helvetica,9600~~"               ! Font #2: helvetica semibold, 100% (implied)
Coldef += "0~0~x~H~Font=,2~Scale=150~~"                 ! Font #3: default face, underline, 150%
Coldef += "1~10~SKU~S~Font=Cambria~~"                   ! Font (Cambria) applies to this column only
```

```
Coldef += "11~1~ ~fH~~"                                 ! Row font code: 0=default, 1-3 reference above
```

## `...` 

The above coldef statements define 3 fonts (referenced as "1", "2", and "3") available to be used as row fonts by inserting the digit into the hidden column defined in position 11 with _cformat_ code **fH** .  The column starting in position 1 (SKU) has it's own column font. Row fonts override column fonts, so the column font here would only apply to rows where  position 11 was blank or "0". 

Note that the up-to-four predefined row fonts are actually defined by either a Font or a Scale option, or both. If one is missing that part defaults. Each of these fonts must be defined in its own pseudo-column zero definition, i.e. must be separated from any other row font options by a double tilde as in the example above. 

## **See Also** 

- _cformat_ **f** (Font definition column) 

A-Shell Reference 

Page 3483 

## **FORMAT** 

## **Format=<format string>{| <style flags>}** 

The Format clause provides a way to configure the behavior of the Windows Time and Date Picker control associated with an editable date and/or time column. The clause is local to the column, and thus allows different date editing options for different columns (unlike the InfDef clause, which only allows the option of activating the Time and Date Picker for all columns). 

Whenever there is a Format= clause defined for an editable date or time column, the date/time picker control will be used instead of the regular edit control. 

The <format string> is made up of the following special characters/fields; any other characters are treated as literals: 

|**Symb**<br>**ol**|**Meaning**|**Symb**<br>**ol**|**Meaning**|
|---|---|---|---|
|d|one or two digit day|dd|two digit day (zero padded)|
|h|one or two digit hour in 12-hour<br>format|<br>hh|two digit hour in 12-hour<br>format|
|H|one or two digit hour in 24-hour<br>format|<br>HH|two digit hour in 24-hour<br>format|
|m|one or two digit minute|mm|two digit minute|
|M|one or two digit month number|MM|two digit month number|
|t|one letter AM/PM abbreviation|tt|two letter AM/PM|



A-Shell Reference 

Page 3484 

|**Symb**<br>**ol**|**Meaning**|**Symb**<br>**ol**|**Meaning**|
|---|---|---|---|
|y|one or two digit year|yy|two digit year|
|yyyy|full four digit year|||



The optional <style flags> (separated from the <format string> by a "|" character) may be expressed as the sum of one or more of the following options: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|MCS_WEEKNUMBERS|4|The month calendar displays week numbers<br>(1-52) to the left of each row of days|
|MCS_NOTODAYCIRCLE|8|The month calendar does not circle today’s<br>date|
|MCS_NOTODAY|16|The month calendar does not display today’s<br>date at the bottom of the control|
|MCS_NOTRAILINGDATE<br>S|64|(Vista+) Dates from the previous and next<br>months are not displayed in the current<br>month’s calendar|
|MCS_SHORTDAYSOFWE|128|(Vista+) Short day names are displayed in|



A-Shell Reference 

Page 3485 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|EK||the header|



For example: 

```
Coldef = "1~15~Date/Time~DE~Format=dd/MM/yyyy HH:mm|24~~"
```

The contents of that column should then look something like this: 

```
08/15/2024 13:21
```

And the drop-down calendar would neither circle today’s date nor display it at the bottom of the control (due to the style flags combination of 24, i.e. 8 + 16). 

Note that in columns containing both time and date, you should use the _Cformat_ code **D** but not **h** . Use h only when the column contains only a time. 

Note that XTREE parses the data in date cells based on the order of the day and month in the Format= clause, rather than on the local LDF setting. This should eliminate problems confusing and/or reversing the day and month when a date cell transitions between display and edit mode (since the transition requires that the cell's text contents be parsed into the sub-fields used by the date picker). 

**Warning** : if you supply date/time data in a format that doesn't match the defined format (including blank data) OR isn't compatible with IDTIM[XS] , the date/time picker will not be able to interpret your data. In such a case, if your InfDef clause contains "O" (for optional), the date/time picker will most likely replace your bad or empty data with the current date/time. Unfortunately this limits the format flexibility otherwise provided by the Format clause. (Future enhancements may allow for some additional time/date formats, but for now you are pretty much limited to numeric date format with slash or dash delimiters. If you need more flexibility than that, stick with the regular edit mode for dates.) 

A-Shell Reference 

Page 3486 

## **HDRCLICKEXIT** 

## **HdrClickExit=###** 

When specified, clicking on this column header causes an exit with the specified exitcode. It returns the `XTR.COLUMNSORT` and `XTR.SORTORDER` fields as if a sort had taken place, but it doesn't actually sort. 

The intent is to allow applications to implement their own sort logic. 

Note that when HdrClickExit=### is defined for a column, that column will not be sorted on entry even if the column appears in the initial `XTR.COLUMNSORT` array. If you want subsequent clicks on the column header to toggle between ascending and descending, you must leave the `XTR.COLUMNSORT` set to the specified column on re-entry. Otherwise the initial sort for any unsorted column will always be ascending. 

A-Shell Reference 

Page 3487 

## **HDRFONT** 

## **HdrFont=<facename>, <attribute code>** 

Same format, syntax and concept as **Font** , except that it affects the font of the header row, rather than the data items. By convention, you would define the HdrFont as part of a pseudo column (i.e. a column whose _cwidth_ = 0) but, regardless of which column this command appears in, it affects the entire header. Currently there is no way to have different fonts in different column headers. If more than one column specifies a **Hdrfont** , only the last one will have an effect. 

Coldef Default applies. 

A-Shell Reference 

Page 3488 

## **IMGSIZ** 

## **ImgSiz = iwidth, iheight, bpp {,fit, stretch, scaleq, discrete}** 

Specifies the maximum image size, along with the desired image depth and scaling options. 

_iwidth_ and _iheight_ are numeric pixel counts for the maximum size image. If the XTF_VARY bit is not set in the _flags_ parameter, then all images must be the same size. (In this case, XTREE will create an "image list" internally, which is the most efficient way to handle a lot of images.) Otherwise, the row height will vary with the actual image height, up to the maximum specified. 

_bpp_ specifies the desired bit depth (bits per pixel), which is used as a clue to the various image loading, conversion, and display routines. Supported values are 1, 8 and 24. If in doubt, set it to 24, which will give the best visual results—at a possible cost in memory usage. With 8, you may see some color substitutions leading to a posterization effect. With 1, you would get monochrome. 

The _fit_ and _stretch_ options apply only when the row height (and image size) is variable—i.e. the XTF_VARY bit is set in the _flags_ parameter. _Fit_ causes images that are smaller than the maximum size to be enlarged until they hit the maximum width ( _iwidth_ ) or height ( _iheight_ ). _Stretch_ is similar but stretches the images as needed so that they match both the _iwidth_ and _iheight_ values. When XTF_VARY is not specified, the _stretch_ option is automatic. 

_Scaleq_ selects a scaling algorithm (bilinear interpolation) which is somewhat slower but generally gives higher quality results than the default scale algorithm. 

_Discrete_ causes the images to be stored individually rather than as an internal "image list". This is mostly just a subtle technicality, but is required for icon images when the XTF_VARY option is not specified. 

Examples: 

```
ImgSiz=133,100,24,Fit
ImgSiz=75,50,8,Stretch,Scaleq
```

```
ImgSiz=16,16,24,discrete
```

A-Shell Reference 

Page 3489 

## **IMGCOUNT** 

## **ImgCount=<# images to load>, <grow-by value>** 

Specifies the number of images to be loaded into the XTREE, along with a "grow by" value which is a clue to the image list allocation routine but can generally be ignored (or set to 1). The image count would normally be the same as the maximum number of rows, unless you knew that many rows would not have images. Example: 

```
ImgCount=100,1
```

The "grow-by" value is automatically adjusted upwards according to usage. 

A-Shell Reference 

Page 3490 

## **IMGDFLT** 

_Written November 2022_ 

## **ImgDflt=<default image spec>** 

If ImgDflt is specified and the image file corresponding to the image file specification in an image cell doesn't exist, then XTREE will use the default image instead. 

## Notes: 

- The ImgDflt feature is only activated when the original cell data specifies a discrete image file that does not exist.  In other 

- words, if the cell contains an icon spec like nosuch::ashico1, the ImgDflt feature will not come into play. 

- The ImgDflt is not used if the corresponding cell data is empty. 

- You can reference the ImgDflt deliberately by putting "*" in the cell. This is equivalent to a filespec that doesn't exist, except 

- is cleaner and more efficient since it eliminates the need for a failed directory lookup. 

## **History** 

- 2022 November, A Shell 6.5.1722:  ImgDflt added to A-Shell. 

A-Shell Reference 

Page 3491 

## **IMGDIR** 

_Modified November 2022; see History_ 

## **ImgDir=dirspec** 

Specifies the default directory for the images, allowing you to avoid having to specify the complete directory redundantly for each image. The directory may be specified using either AMOS or native (Windows) syntax. It may also be a URL directory, e.g. https://www.mydomain.com/myimages (leaving off the trailing delimiter). Note that if a WEBCACHE directory is defined—with the OPENI and LOOKUP attributes—it will also be searched in addition to the ImgDir directory. Note also that images pulled down from a website will be cached for subsequent accesses in the %MIAME%\webcache directory. See History below. 

You may also specify the name of a DLL (when loading icons from a DLL) in order to be able to omit the "::dllname" from the icon specification in the cell data. In this case you must include the "::" in front of the DLL name in the ImgDir specification. For example, if you specify ImgDir=::ashico1 then in the cell data you can specify icon names within that DLL, such as "add" or "delete" without the ::ashico suffix. 

ImgDir is ignored if blank, not specified, and for any individual image file name that contains a directory specifier. For example: 

```
ImgDir=appimg:
```

```
ImgDir=c:\my documents\my images\app images
```

Example of a complete image column definition: 

```
COLDEF = COLDEF + "50~25~Images~I~ImgSiz=80,60,24,Fit,Scaleq~ImgCount=150,1~ImgDir=appimg:~~
```

Example of a DLL specification: 

```
ImgDir=::ashico1
```

## **See Also** 

- WEBCACHE 

A-Shell Reference 

Page 3492 

## **History** 

- 2023 August, A Shell 6.5.1739:  Add support for URL directory specification. 

- 2022 August, A Shell 6.5.1720:  ImgDir can now be used to specify the name of a DLL containing icons, allowing just the icon name to be specified in each cell. 

A-Shell Reference 

Page 3493 

## **INFDEF** 

_Updated March 2013_ 

## **InfDef=xxx** 

This advanced column option allows you to specify some variations of XTREE editable cell behaviour using INFLD _type_ codes. This only applies globally for all columns in the tree, and only the following _type_ codes are supported: 

|**Type**|**Description**|
|---|---|
|)|start cursor at end of field, requires e|
|2|When cursor is at the start of a field, left arrow navigates to the previous editable<br>cell.|
|D|In conjunction with a date field (_cformat_<br>**D**), causes the field to be edited by the<br>standard Windows Date and Time Picker control, rather than by the standard<br>Windows edit control. See_Comments_below and also seeFormat<br>.|
|e|force non-destructive|
|||I|Forces overwrite mode during editing (instead of the normal insert mode). You<br>most likely would want to use this feature in conjunction with non-destructive mode<br>(InfDef=<br>**||Ie**), particularly when FastMax=# is being used. Note that<br>**||I**is the<br>INFLDcode to force overwrite mode.|
||L|Regardless of cursor position within the field, right arrow navigates to the next<br>editable cell.|



A-Shell Reference 

Page 3494 

|**Type**|**Description**|
|---|---|
|L|When cursor is at the end of the field, right arrow navigates to next editable cell.|
|O|Indicates optional field. Mainly of use with dates and times  (e.g. InfDef=DO) to<br>add a checkbox to the Date and Time Picker to allow it to be optional.|
|t|In conjunction with a time field (_cformat_<br>**h**), causes the field to be edited by the<br>standard Windows Date and Time Picker control, rather than by the standard<br>Windows edit control.|



For example: 

```
Coldef = "1~8~Date~DE~InfDef=D~~"
```

Note that the InfDef clause is shared by all columns, so this method forces you to treat all editable date and time columns the same way. 

In the above example, since the column width is 8, the format will be set to MM/DD/YY (or DD/MM/YY depending on the LDF). Otherwise the year would be returned in CCYY format. 

The other method for activating or configuring the date/time picker control is to specify a Format clause. 

## **Comments** 

Warning about date picker column width: For Windows Vista and later, the width of a column using InfDef=D will be automatically expanded as needed to fit the Windows date picker control (when a cell in the column is edited). But prior to Vista, this does not happen, and worse, if the column width is not sufficient for the date picker, the editing operation may be confusing at best. To avoid this, you may want to specify a DspMin option sufficient to accommodate the date picker. (you will have to work out the actual minimum width using some trial and error, and/or err on the conservative side, since it changes according to the date format options specified, resolution, etc.) 

A-Shell Reference 

Page 3495 

## **LIST** 

_Updated July 2023; see History_ 

## **List=item1, item2, ...itemn** 

Used in conjunction with _cformat_ code **l** to define the choices that will appear in the combo box. 

As a convenience for applications sharing a list with INFLD, you can use the INFLD setdef syntax, which is the same as the above, except that the first character specifies the delimiter character, which is then used to separate the items. In the INFLD format, the list is typically terminated with two of the delimiter characters, although they aren't really necessary here since the list will be terminated by the tilde that marks the end of this and every other advanced _coldef_ option. 

## **Comments** 

- **Warning** : if the first character is neither alphabetic nor numeric, and it matches the last character in the list, then XTREE 

- assumes that it is the delimiter character. Otherwise, the delimiter is assumed to be a comma. This can lead to unexpected problems in lists of items that have both leading and trailing spaces—or any other non-numeric, non-alphabetic character. To avoid that possibility, make the delimiter explicit. 

• For self-service combos, set the list to three dots (e.g. List="..."). You can still pre-load the cell with a value, and even allow the user to change it (if the **E** code is specified). But if they try to display the dropdown list (by clicking on the down arrow button or typing ALT+DOWN-ARROW, it will exit with Exitcode= 29, so that your application can then display its own list or other control, independent of XTREE. 

- The INFLD "List substitution" ( _type_ **||L** ) format is supported via ListX and CellListX. 

- For selection-only lists (where the user can only select from the items in the list, as opposed to real combo boxes where a 

- new item may be entered), do not include the **E** code in _cformat_ . To allow a blank choice in such a case, you must add an explicit blank item to the list definition, i.e. `"List=red,blue, ~"` . Also note that any pre-loaded cell string must match an entry in the list, or else it will be displayed as blank when the cell becomes activated—i.e. turned into a combo box. 

- If the List= clause is associated with column 0, it can be shared by multiple columns. Any column which specifies the _cformat_ 

- **l** (list) option, which does not have its own List= specified, will use the shared list associated with column 0. Note that although 

- this capability overlaps somewhat with the CellList feature when it comes to sharing a single list between multiple columns, List= 

A-Shell Reference 

Page 3496 

is easier to use because it doesn't require a special character in every cell to identify the list. But List= lacks the flexibility to allow different lists within the same column. 

- To mark an individual cell within a combo box column as being non-editable, insert a vertical bar ("|") as the first character of 

- the cell data. The vertical bar will not display, but the cell will be prevented from gaining the focus. 

- There is no limit on the length of an individual combo list (defined with List= or CellList=). A 4K limit in an earlier version of 

- A-Shell has been eliminated. 

- Quote characters (") are treated as ordinary characters within all variations of the lists described here. If you had intended to 

- use them to include a literal comma within a description, you will instead need to just change your delimiter character. See _History_ . 

- See CellList for defining cell-specific combo lists. 

## **See Also** 

- "Dropdown lists" Mouse and Keyboard. 

## **History** 

- 2023 July, A Shell 1734: Adjusted handling of quote characters. 

A-Shell Reference 

Page 3497 

## **LOADOPTIONS** 

_Added February 2018_ 

## **LoadOptions=<option>** 

These two options are similar in concept to the like-named ExportOptions except that they apply to the operation of loading data into the tree. Typically the column is defined as a one character number, but could also be a checkbox. 

|**Type**|**Description**|
|---|---|
|NoRowIf#|Skips rows with a numeric value of non-zero|
|NoRowIf!|Skips rows with a numeric value of zero|



The intended usage would be for a situation where you are repeatedly displaying items from a large array, but with varying filtering such that each iteration of the display may show different items from the set. Rather than have to maintain two separate arrays (one with all of the items and one with just those to display), you can just add a column to the array to indicate (with 0 or 1) whether to display the item. 

## **Notes** 

- Only supported with Array Mode, not file or CSV mode. 

- Only applies to opcodes XTROP_CREATE and XTROP_REPLACE. 

- Purely a client-side feature; no special support or version requirements   on the server side. 

- Removing items from a tree, by resetting the value of the LoadOptions column and then doing an XTROP_REPLACE, is similar 

- to using XTROP_DELSEL, but the LoadOptions approach is somewhat more flexible (particularly in its reversibility), and probably easier to use. 

A-Shell Reference 

Page 3498 

- In the ATE environment, using the LoadOptions technique to add or remove a small number of rows is particularly efficient 

- due to optimization of the XTROP_REPLACE operation when only a few rows are changed. 

- See the sample program TSTXFLTR2.BP in EXLIB:[908,76] for an example. 

## **History** 

- 2018 Feburary, A Shell 6.5.1627:  Function added to A-Shell 

A-Shell Reference 

Page 3499 

## **LOOKUPX AND FILELISTX** 

_Added August 2018_ 

This feature, which involves both the LookupX and FileListX Advanced Coldef Options, automatically fills in a target cell based on the contents of a source cell, using an external lookup table. Conceptually it is similar to the combo/list/substitution capability— see ListX and CellListX, _cformat_ **l** and **ll** —except that the description returned from the lookup operation appears in a separate column from the initial code. In both cases, XTREE is able to supply the description for the code without having to exit to the application, but with LookupX, there is no need for a drop-down box, and the lookup table is supplied via an external file rather than embedded in the _coldef_ . 

The feature is intended for data-entry cases where the user is entering codes that you want to provide immediate visual confirmation of, by looking them up in a table and displaying the corresponding description. It fills the gap between small lists (where a combo box might make more sense) and very large, complex or rapidly changing database lookups (where only an exit to the application would make sense). Between those two extremes (say, lookup tables between 50 and 50K entries that are reasonably stable), providing the table to XTREE once and letting it do the lookups internally will be much faster and more convenient (especially in the ATE case where the turnaround time to exit and re-enter might be a significant fraction of a second, enough to slow the data-entry operation). 

For example, in a tree used to key in GL transactions, you might use this technique to echo the account description in a noneditable column when the account code is entered. Or, as in the example below, LookupX is being used to display the product description as the code is entered. 

LookupX requires the coordination of two Advanced Coldef options: 

```
FileListX=idx,fspec
```

```
LookupX=idx,targetcol
```

FileListX defines the table and associates it with an single character index code in the range of A-Z or a-z. Note that the index shares the same space with the ListX and CellListX lists, so must be unique relative to them. In fact, combo and list substitution columns, i.e. _cformat_ **l** or **ll** , may refer to lists defined by FileListX just as they can for CellListX. 

A-Shell Reference 

Page 3500 

The fspec can be an AMOS or native spec (from the client perspective). In the case of ATE, the search path will automatically include the %ate%\cache and %ate%\permcache directories, and it is up the application to transfer the file from the server if necessary. 

Tip: you may want to use the Fn'FileAgeDiff() function in FNFILEAGE.BSI in SOSLIB:[907,11] to determine when your FileListX file becomes out-of-date relative to the data file it was extracted from. And for ATE, the ATEAPX.SBX routine will be handy for syncing the file to the client. 

The file should be formatted as follows: 

```
code,description
```

```
code,description
```

```
etc.
```

As with the List{X} and CellList{X} lists, if the first character of the first code is neither an alphabetic character or a numeric digit, it is assumed to be the delimiter; otherwise the delimiter is assumed to be the comma. However, unlike the other list types, here the descriptions may may be quoted if they contain the delimiter. (So standard two-column CSV files should be acceptable.) 

To associate the list with a source and target column, add the LookupX= clause to the _coldef_ entry for the source column—i.e. the column containing the code, specifying the index used in the FileListX definition, and the targetcol (target column where the description will be echoed). 

As an example, the relevant parts of the _coldef_ for the sample tree illustrated above would look something like this: 

```
coldef$ += "0~0~x~H~FileListX=A,prod.csv~~"
```

```
coldef$ += .offsiz$(ST_XTR_ARY.code) + "~Code::Total~#En~LookupX=A,3~~"
```

```
coldef$ += .offsiz$(ST_XTR_ARY.qty) + "~Boxes::=SUM~|#En~~"
coldef$ += .offsiz$(ST_XTR_ARY.descr) + "~Prod Descr~S~~"
```

A-Shell Reference 

Page 3501 

Note that the FileListX is associated with a "zero" column, while the LookupX is associated with the real column where the code is entered. The two arguments to LookupX link it to the FileListX index (A) and to the target column where the description will be displayed (3). 

The lookup and fill operation is performed automatically whenever the source column is edited and changed. If there is no match for the code, the description will be blank. When loading data into a tree, the lookup will be performed only if the target column is blank. The theory here being that if the application is supplying descriptions, they are probably already correct and thus it would be a waste of time to look them all up again. 

Note that if you want the looked-up descriptions to be returned to the app with the answer array, use the "U" code for the description column. 

## **History** 

2018 March, A-Shell 6..5.1631.0: Added to A-Shell 

A-Shell Reference 

Page 3502 

## **MASK** 

## **Mask=mask** 

Defines a numeric formatting mask. Supports the same numeric mask options as the BASIC USING clause (e.g. "$###,###", "##.##", "#ZZZZ"). The mask is applied immediately before loading data into each cell, and again just prior to and after editing a cell (if the cell is editable). Note that: 

## **Notes** 

In most cases, you will want to also specify the column format code > to cause the formatted data to be right-justified in the cell. 

Although each column can have a separate mask, the total (combined) amount of mask storage is limited to 1024 characters. 

If you want zero values to show as blank cells, rather than formatted according to the mask, set the _cformat_ for the column to string ("S") rather than to numeric ("#"). 

## **Examples** 

```
Mask=$###,###.##
```

```
Mask=#ZZZZZ
```

```
Mask=###.##
```

## **History** 

- A Shell 5.1.1107.4 of 12 Apr 08:  The new NegFgBg allows control over the color used to display numeric cells with negative values. 

A-Shell Reference 

Page 3503 

## **NEGFGBG** 

_Updated February 2019; see History_ 

## **NegFgBg={fgidx, bgidx}** 

This parameter allows control over the color used to display numeric cells with negative values: 

Examples: 

```
NegFgBg=A
```

```
NegFgBg=A,B
```

```
NegFgBg=
```

By default, the foreground color is set to Red. If the above clause is added to the real column definition, or to the Pseudo Column Zero, then the specified fgidx (and optional bgidx) codes will be used to reference previously defined RGBfg or RGBbg definitions by their index codes. 

For example: 

```
COLDEF = "0~0~x~H~RGBfg=50,255,80,A~RGBbg=200,60,240,B~~1~10~Amounts~#~NegFgBg=A,B~~"
```

In the above case, the NegFgBg=A,B clause tells XTREE to display negative cells in the specified column using the foreground RGB color defined with index A (RGBfg=50,255,80,A) and the background color define with index B. 

If the optional {,bgidx} background color is not specified, then XTREE uses the default. 

If no argument is specified (i.e. NegFgBg=), then the automatic red display of negative numbers is merely disabled; in other words, negative numbers are treated just like positive numbers. 

Note that unlike most other Advanced Coldef Options, NegFgBg initially only works when applied to a "zero column" (i.e. to affect all columns), as in the example shown above. See History. 

## **History** 

A-Shell Reference 

Page 3504 

- 2019 February, A Shell 6.5.1655: added the ability to apply the NegFgBg option to individual columns 

A-Shell Reference 

Page 3505 

## **POPUPMENU** 

_Updated March 2018; see History_ 

## **PopupMenu = {+} text1, cmd1; text2, cmd2;...; textN, cmdN** 

A PopupMenu definition consists of a series of pairs of text/cmd items. It defines a popup menu (aka "context menu") that will appear when the user right-clicks on a cell. You may define a single popup menu to be used by all columns, and/or you may define popup menus that are specific to individual columns. 

The optional plus sign indicates that the following menu items should be added to a previously defined global PopupMenu, as discussed below. 

The <text> fields define what appears on that line of the popup menu, while the <cmd> fields define the key sequence that is transmitted if the user clicks on the option. See Virtual Key Symbolic Names. Also see Notes below for information on certain built-in special menu commands. 

To create a horizontal separator bar, set the <text> field to a string of dashes and leave the <cmd> field null (with no spaces between the dashes, the comma, and the semicolon.). 

For example, consider this PopupMenu definition: 

```
COLDEF = COLDEF + "0~0~X~S~PopupMenu=Retire,VK_xF101;Visit,VK_xF102;Pass
Through,VK_xF103;-----,;Attack,VK_xF104~~"
```

This would create a popup menu, which, when the XTREE control was right-clicked, would display four choices (Retire, Visit, Pass Through, and Attack) with a horizontal separator between the last two items (in a particularly feeble ergonomic effort to prevent inadvertent war). If the user then clicked on one of the items in the popup menu, XTREE would exit, setting exitcode to -101, -102, -103, or -104 depending on the item. The effect would be exactly as if you had defined buttons which transmitted the same key codes. Here is what it might look like: 

In addition to the exitcode, the `XTR.TARGETROW / XTR.TARGETCOL` and/or `XTR.XROW / XTR.XCOL` fields in the XTRCTL parameter will be set to indicate the logical row and column where the right-click occurred. 

A-Shell Reference 

Page 3506 

The popup menu defined above would be available to all columns because it was associated with the pseudo column zero (Cpos, Cwidth both set to 0). To define a popup menu that is specific to a column, just associate the PopupMenu specification with a real column, as in these two examples: 

```
COLDEF = COLDEF + "50~15~State/Province~S~PopupMenu=+-----,;Run for Governor,VK_xF105;Check State Tax
Rates,VK_xF106;Find State Capitol,VK_xF107~~"
```

```
COLDEF = COLDEF + "70~12~Country~S~PopupMenu=Obtain Passport,VK_xF108;Recall Ambassador,VK_xF109~~"
```

The first of the two column definitions above creates a column titled "State/Province" which has its own popup menu items that are appended to the shared popup menu— i.e. the one defined previously for pseudo column zero. The special character "+" at the start of the PopupMenu definition string is what causes the items to be appended to the shared popup menu rather than replacing it. Here is what the menu would look like: 

The second definition creates a column titled "Country" with a popup menu containing two items. Because the definition is for a real column and does not start with the special character "+", it replaces the shared popup menu entirely, resulting in something like this: 

## **Notes** 

**Disabling individual menu items** may accomplished by marking them as disabled with a "!" at the start of the item text, i.e.: `PopupMenu=!disabled item,VK_xF999; ...` See History. 

**Context menus:** Context menus may specify icons. See History, below, and the subtopic Icons. 

A-Shell Reference 

Page 3507 

**Updating Popup Menus:** On re-entry into an existing XTREE, the PopupMenu definitions are reprocessed for opcodes XTROP_CREATE (0) and XTROP_REPLACE (1), but not for XTROP_SELECT (4). So to modify the popup menu(s) in response to some user input, you must exit from XTREE back to the application, modify your complete _coldef_ definition string, then re-enter with `XTR.OPCODE` = XTROP_REPLACE. If you want the application to have the opportunity to update the popup menu, before displaying it, whenever the user right-clicks, use ClickExit to define a right-click exitcode. This will override the PopupMenu. Then use the ability to force the popup to display immediately on entrance, as described below. 

**Forcing Popup Menu to Appear Automatically:** You can force a popup menu to appear immediately on entrance to XTREE by setting `XTR.XNAVMASK` to 64. The position of the mouse will determine which column the popup menu will be requested for. This is the one case where PopupMenu will override ClickExit. 

**Special menu commands:** In addition to the standard kind of menu commands which are made up of literal or symbolic key sequences, certain commands are built-in and recognized by XTREE: 

|**Command**|**Description**|
|---|---|
|$CBSET{DEP}|These special context menu commands relate to extendedEditable<br>checkbox<br> columns, which see for details.|
|$CBRST{DEP}||
|$CBUNDO||
|$CBRSTX|Same as $CBRST but sets XTR.xvalidate bit &h08; see History|
|$CBSETX|Same as $CBSET but sets XTR.xvalidate bit &h08; see History|
|$CBUNDOX|same as $CBUNDO but sets XTR.xvalidate bit &h10; see History|



A-Shell Reference 

Page 3508 

|**Command**|**Description**|
|---|---|
|$COPY|Copy to Clipboard<br> the contents of the tree|
|$EXPCSV and $EXPTSV|Export<br> the contents of the tree to a delimited file|
|$EXPCSV2XL{:inispec}|Export to XLS<br>.|
|$PRINT|Format the XTREE for printing and display in an APEX print preview window<br>for possible printing.|
|$RESETCFG|Resets the saved column configuration to the default state. This is useful to<br>deal with the possibility of a user accidentally making a disastrous change<br>to their configuration, such as resizing a column to zero width, thus making<br>it disappear entirely. SeeSaving User Adjustments<br>. For example:<br>`COLDEF = "0~0~x~H~PopupMenu=Reset columns,$RESETCFG~~"`<br>$RESETCFG also resets the text scale adjustment factor—i.e. includes<br>$RESETSCALE. See History.|
|$RESETSCALE|Resets the overall text scale adjustment factor back to zero; equivalent to<br>Control /.|
|$SCALE+ and $SCALE-|Causes the fonts to be increased (+) or decreased (-) by about ten percent;<br>equivalent to Control + and Control -.|
|$SORT|Triggers an internal multi-levelSort<br>.|



A-Shell Reference 

Page 3509 

|**Command**|**Description**|
|---|---|
|||
|$SRCHCOL and<br>$SRCHALL|Provide expandedSearch<br>options|



## **History** 

- 2018 March, A Shell 6.5.1633:  $CBSETX, $CBRSTX and $CBUNDOX added. These new variations of the checkbox set, reset, and undo commands resolve a problem with the standard ones involving ambiguity over the possible interpretations of the XTR.validate = 3 that they return. 

- 2017 January, A Shell 6.3.1542:  (1) Individual menu items may now be marked as disabled. (2) Submenus now supported. (3) Indexed popup menus now supported. 

- 2013 July, A Shell version 6.1.1357: Added ability to include icons in context menus 

- 2013 Feburary, A Shell version 6.1.1338: A-Shell now automatically adds "Paste Special" to the context menu when complex clipboard formats are available. Depending on the formats, the menu option will open a submenu with more specific paste options, such as picture, spreadsheet, etc. To customize the wording of the menu option, add or modify the 004,011 message in the SYSMSG.xxx file. All SYSMSG.xxx included in the release package have been updated with rough translations. Note that if you don't want this capability, you can disable it by setting the TXMF1_EDIT_PASTESP flag in the `TXC.MENUMASK1` field. 

## POPUPMENU SUBMENUS 

_Added January 2017_ 

Beginning with A-Shell 6.3.1542 of January 2017, the XTREE PopupMenu supports submenus. The syntax is the same as for Hover/Context menus, i.e. set the cmd field (of the text,cmd; menu item pair) to "[SUB]" to mark the beginning of the submenu, and the text field of a subsequent item to "[ENDSUB]" to mark the end of the submenu. For example: 

A-Shell Reference 

Page 3510 

```
coldef$ += "0~0~ ~SH~PopupMenu=" &
```

```
    + "!Retire\tF2,VK_xF501;" &
```

```
    + "|arrow_right_green::ashico1|Peacetime,[SUB];" &
```

```
         + "|photo_portrait::ashico1|Visit\tF3,VK_xF502;" &
         + "|signpost::ashico1|Pass Through,VK_xF503;" &
```

```
         + "[ENDSUB],;" &
```

```
        + "-----,;" &
```

```
    + "|gear::ashico1|Wartime,[SUB];" &
```

```
        + "Attack,VK_xF504;Lay Siege,VK_x507;" &
        + "[ENDSUB],;" &
```

```
    + "-----,;" &
```

```
    ...
```

## The code above defines a PopupMenu which looks something like this: 

```
        Retire      F2               (disabled item)
```

```
        Peacetime                    (submenu with icon)
              Visit        F3        (submenu item with icon)
              Pass Through           (submenu item with icon)
        ---------------------        (separator)
        Wartime                      (submenu with icon)
              Attack                 (submenu item)
```

A-Shell Reference 

Page 3511 

```
        ---------------------        (separator)
```

```
        ...
```

## INDEXED POPUPMENUS 

_Added January 2017_ 

Beginning with A-Shell 6.3.1542 of January 2017, an enhancement to XTREE provides support for indexed PopupMenus. These allow for column- and/or row- specific context menus to be assembled by concatenating one or shared partial indexed menus. To accomplish these three new variations of the PopupMenu syntax are introduced: 

```
PopupMenu:?=lbl1,cmd1;lbl2,cmd2;...lblN,cmdN
```

```
PopupMenu={+}?{???}
```

```
PopupMenu={+}###
```

where each ? is replaced by an alphabetic character A-Z, and ### is replaced by a column number. 

The first variation defines a full or partial menu to be indexed by the letter replacing ?. The definition can be attached as an Advance Coldef Option clause to any column definition (zero column or a real column). Unlike the standard PopupMenu definition syntax, the resulting menu is not automatically invoked; it only becomes available for reference via one of the other syntax options associated with a real column. 

The second variation may be associated with a real column, indicating that the context menu for that column should be made up of the previously indexed menus associated with the ? character(s). The optional "+" prefix prepends the global PopupMenu to the start of the column-specific menu. For example: 

## `PopupMenu=+AQZ` 

indicates that the context menu for the column should be made from the global PopupMenu, combined with the indexed PopupMenus A, Q, and Z. 

A-Shell Reference 

Page 3512 

The third variation indicates that the specified column ### (current row) contains the list of indexed PopupMenus to be used for this column, thus allowing the possibility of a different set of context menu items for each cell. Note that the specified column ### would normally be hidden, but it doesn't have to be. 

See the sample program XTRA21 in EXLIB:[908,21] for an example. 

EXPORT 

_Updated April 2013; see History_ 

These two PopupMenu system commands are used to export the contents of the tree to a delimited file: 

## **$EXPCSV** 

## **$EXPTSV** 

The first exports the tree to CSV, the second to a tab delimited file (i.e. Tab Separated Values). To automatically open the file after exporting (i.e. to launch your registered spreadsheet program), append "+" to the $EXPCSV or $EXPTSV options, e.g.: `$EXPCSV+` 

```
$EXPTSV+
```

As an alternative to adding explicit export options to each XTREE, you can enable them globally by adding one or both of the following to miame.ini: 

```
SBR=XTREE_EXPCSV
```

```
SBR=XTREE_EXPTSV
```

To globally set the option to launch after exporting, add the following: 

A-Shell Reference 

Page 3513 

```
SBR=XTREE_EXPOPEN
```

The text for these automatically-added context menu options will be taken from SYS:SBRMSG.xxx lines 026,001 and 026,002, which default to the following (for the English version): 

```
026,001,Export (CSV)
```

```
026,002,Export (Tab Delimited)
```

So the above three SBR= commands would be equivalent to adding the following PopupMenu clause to the zero column of each tree: 

```
"PopupMenu=Export (CSV),$EXPCSV+;Export (Tab Delimited),$EXPTSV+"
```

Note that whenever a PopupMenu option containing a command string starting with "$EXP" appears explicitly in an XTREE definition, the corresponding global options will be ignored for that tree. (This allows you to customize the global option in particular cases and eliminates the problem of redundant menu options in programs where you already implemented the option explicitly.) 

You can also disable the global option by adding a dummy PopupMenu item with a "-" in front of the $EXP... command, e.g. 

```
"PopupMenu=xxx,-$EXPCSV"
```

The description field ("xxx" in the above example) is ignored (since the whole point of the "-$EXPCSV" is to remove the corresponding item from menu). 

## **History** 

- 2013 April, A Shell 6.1.1350:  CSV export now uses the list separator defined in the regional/locale settings, rather than comma. And the default file extension for TAB export is now CSV. 

- 2013 April: A Shell 6.1.1349:  Hidden columns are no longer included in the export. This refers to columns that either have the 

H _cformat_ flag, or which have been reduced to zero width. Columns that are simply scrolled out of view are not considered hidden. 

- 2012 December, A Shell 6.1.1326:  Function added to A-Shell 

EXPORT TO XLS 

A-Shell Reference 

Page 3514 

_Added February 2018_ 

You may export directly to XLS—rather than a tab or comma delimited file—using the PopupMenu system command: 

## **$EXPCSV2XL{:inispec}** 

$EXPCSV2XL is like $EXPCSV except that after creating the CSV file (which is named %temp%\xtree##.csv where ## is the job number), it calls CSV2XL.SBX to convert it to XLS. If no _inispec_ is specified, the default ini file for CSV2XL will be xtrcsv2xl.ini, with the search patch consisting of the current ppn, [p,0], and BAS:. If no xtrcsv2xl.ini is found in any of those locations, its uses the standard bas:csv2xl.ini. 

If the _inispec_ is specified—AMOS or native format, may include %ENV% variables—then is uses that filespec without any search path. 

Unlike the $EXPCSV and $EXPTSV options, there is no "+" variation to open the file after creating it. Instead, this is determined by the CSV2XL initialization file Launch option. 

As with the other export options, you can enable it globally by adding: 

## `SBR=XTREE_EXPCSV2XL` 

to miame.ini. In the case, there is no option for the ini file, which will always be the xtrcsv2xl.ini, using the search patch specified above. 

## **Color Support** 

The export to XLSX via CSV2XL function supports foreground and background colors. The feature can be enabled in one of three ways: 

- By setting the system option SBR=XTREE_CSV2XLSX, either in miame.ini or by setting the SBRF2_XTREE_CSV2XLSX flag using 

- MX_SBRFLG or AG_SBRFLAGS. 

- By explicitly adding a PopupMenu option using the new $EXPCSV2XLSX special command. 

- By adding the Advanced Coldef Option ExportOptions=Attr to any column, provided that the XTREE_CSV2XL global option 

- (previously labeled "Export (XLS)" and now labeled "Export (Data Only)" option is set. The XTREE_CSV2XL global option 

A-Shell Reference 

Page 3515 

continues to enable the generic CSV2XL export, which does not support colors or other attributes, except that the ExportOptions=Attr option will upgrade it to be equivalent to the XTREE_CSV2XLSX option. Note that ExportOptions may be applied to the zero column, in which case it enables output of color (and potentially other) attributes for all columns; otherwise it only applies to the column to which it is attached. Note that there is also an ExportOptions=NoAttr which overrides the option previously set globally. 

Example: 

```
coldef="0~0~x~H~ExportOptions=Attr~~"
```

```
...
```

```
coldef += "30~5~Test~S~RGBbg=22,33,44~ExportOptions=NoAttr~~"
```

The above column definitions start by enabling the export of attributes globally, and then disabling it specifically for the one "Test" column. 

## **Comments** 

Support for exporting color attributes to a spreadsheet requires CSV2XL.SBX 2.1(250) or higher (see below). 

When the attribute export is enabled, the spreadsheet output format will beforced to XLSX, regardless of the setting in the relevant CSV2XL ini file. 

See the topic "Export to XLS" for more details on exporting to a spreadsheet. 

## **History** 

- 2020 June, A Shell 6.5.1682:  Function added to A-Shell (color support) 

- 2018 January, A Shell 6.5.1626:  Function added to A-Shell (export to XLS) 

SEARCH 

A-Shell Reference 

Page 3516 

These two PopupMenu system commands are used to provide expanded search options: 

## **$SRCHCOL** 

## **$SRCHALL** 

Both options pop up a standard Windows "Find" dialog in which you can type in the string to search for and check a couple of search related options. $SRCHCOL searches just the column that was right-clicked to bring up the context menu, while $SRCHALL searches all columns of the tree. 

To add these search options globally, add the following to miame.ini: 

## `SBR=XTREE_SRCH` 

The text for the corresponding automatically-added context menu items will be taken from the SBRMSG.xxx messages 026,004 and 026,005, defaulting to: 

```
026,004,Search Column
```

```
026,005,Search All (^F)
```

Note that these search functions may conflict with editable cell validation since the interaction with the pop up function may trigger a cell validation exit before the function can be carried out. To avoid that scenario, XTREE may ignore the SBR=XTREE_SRCH directive in some cases. You may however force them to be enabled by using the explicit PopupMenu $SRCHxxx options. There is no danger of this resulting in two sets of search options in the menu, as the PopupMenu options will override/replace the corresponding MIAME.INI directives. 

The concept here is the same as for the $EXP options. Any explicit definition of a PopupMenu command starting with $SRCH will disable the appending of the automatic options, allowing you to customize the search options on a tree-by-tree basis.  You can also disable a globally enabled search by defining an option with the command "-$SRCH", e.g. 

```
"PopupMenu=xxx,-$SRCH"
```

## **Comments** 

The search logic normally only matches at the start of each cell (not counting leading spaces). But if you select the "Whole Word only" option in the search dialog, it will match the whole word anywhere in the cell contents. 

A-Shell Reference 

Page 3517 

As currently implemented, the search operation selects the entire item that the match occurs on, and also makes that column the active one (i.e. depresses the column header button). It does not highlight the cell, out of concern for possible confusion and conflicts with various editable cell configurations. 

## **History** 

2024 November A-Shell 7.0.1765:  Support added for searching the first column of a Property Sheet. 

- 2012 December, A Shell 6.1.1326:  Function added to A-Shell 

## PRINT 

## **Print,$PRINT** 

Selecting this option is equivalent to using the XTROP_PRINT opcode, except doesn't require exiting the current tree operation. 

To globally add the option to all trees, add the following to miame.ini: 

## `SBR=XTREE_PRINT` 

The text for the automatically-added menu items is taken from SBRMSG.xxx message 026,003, which defaults simply to: 

## `026,003,Print` 

If globally enabled, you can disable it by adding the following item to an explicit PopupMenu definition: 

```
PopupMenu=,-$PRINT
```

## **History** 

- 2012 December, A Shell 6.1.1326:  Function added to A-Shell 

## COPY TO CLIPBOARD 

_Added April 2013_ 

A-Shell Reference 

Page 3518 

This function provides support for copying selected items to clipboard. To add an option to the context menu to copy selected items to clipboard, add an entry to your PopupMenu containing the $COPY special command, e.g. 

## `PopupMenu=Copy to clipboard,$COPY~~` 

The $COPY option is automatically added to the context menu if either the `SBR=XTREE_EXPTSV` or `SBR=XTREE_EXPCSV` flag is specified in miame.ini. 

To support the Windows standard keyboard command CTRL+C to copy the selected items to the clipboard, specify the new flag XTF2_CTRLC_COPY. 

Note that in order to copy more than one item to the clipboard, the tree will need to support multiple selections (XTF_MSEL); 

otherwise only the current item will be copied. Also note that hidden columns are not included, but that the column headers _are_ included. 

## **See Also** 

- Export 

- Export to XLS 

- ExportOptions 

## **History** 

- 2013 April, A Shell 6.2.1349:  Function added to A-Shell 

## ICONS 

_Added July 2013_ 

Context menus, defined with PopupMenu=, may specify icons, using the same syntax as for AUI_MENU, i.e., by prepending an image specification clause enclosed in vertical bars to the menu text string. 

## **PopupMenu={|imgspec{=size}|}text, cmd; ...** 

A-Shell Reference 

Page 3519 

For example: 

```
PopupMenu= "|refresh::ashico1|refresh data,VK_xF502;" + "|delete.png=16|delete item,VK_xF503;" ...
```

As with AUI_MENU, when no {=size} clause is present, the system default menu icon size will be used (typically 16). Older versions of Windows may also limit the size to 16x16, while newer versions allow 24x24, 32x32 and beyond. 

## SORT 

_Added April 2022_ 

The PopupMenu command $SORT triggers an internal multi-level sort. Syntax: 

## **$SORT:#:#{:#}** 

where each # is replaced by a column number. Precede the column number with a minus sign to make the sort order descending rather than ascending. At least one column must be specified; the second and third column numbers are optional. For example: 

```
PopupMenu=Sort by State/City/Population,$SORT:5:4:-7~~
```

This would sort by column 5 (State,ascending), 4 (City,ascending), and then 7 (Population,descending). 

The motivation for this option is just to make multi-level sorting easier and quicker for the operator, who would otherwise have to use Ctrl-Click on the columns in the reverse order, possibly clicking one or move of the columns multiple times to get the right order. And compared to just exiting and re-entering with the application specifying the sort order in the XTRCTL fields, this is much faster since it doesn't require leaving the tree. 

Note that since the comma and semicolon characters are delimiters in the general PopupMenu syntax, you must not include them in any part of the $SORT command, which might otherwise be tempting when listing the columns involved in the sort. 

## **History** 

- 2022 March, A Shell 6.5.1713:  function added to A-Shell. 

A-Shell Reference 

Page 3520 

## **RADIO BUTTON GROUP** 

## **Group=###** 

Associates radio button cells within the current column with a specific radio button group, so as to allow more than one group of radio buttons in a row, or even a set of related cells in the same column to form a group. ### is the group number, 0-252. Columns without a Group= clause are assigned group 0.  Groups 253-255 are reserved for vertical groups: 

|**Group **|**Description**|
|---|---|
|255|Entire column is a single group|
|254|XTF_MLVL: Items with same immediate parent form a<br>group|
|253|XFF_MLVL: Items at same level form a group|



If the tree is not multi=level, all three of the above act like 255, i.e. only one radio button in the entire column can be selected at a time. 

Note that as with horizontal groups, enforcement of the only-one-selected-per-group rule occurs only when you change a radio button during editing. It is up to the application to enforce the rules during loading and display operations. 

A-Shell Reference 

Page 3521 

## **RGBBG** 

## **RGBbg=r, g, b {,index}** 

RGBbg may be used to define precise background colors to be used for columns, rows, or individual cells, as in this example: 

If the RGBbg option is specified on a real column definition, then it determines the background color for that column. Otherwise (if specified for Pseudo Column Zero) then it may serve as a way to define a color which will later be referenced by its RGB Color Index. 

Where R, G, and B are decimal values in the range of 0-255. The optional RGB Color Index provides the means to reference this color for a row or cell. 

RGB color specifications can be difficult to visualize, so you may want to take advantage of the A-Shell Settings | Colors dialog which provides a visual tool that displays the RGB values for color samples chosen from the entire color space. Click on any color in the first part of the dialog, then click the Define Custom Color button. Just cancel once you've found a set of suitable RGB values. 

## **See Also** 

- RGBbg# 

A-Shell Reference 

Page 3522 

## **RGBBG#** 

_Added February 2024_ 

## **RGBbg0=r,g,b** 

## **RGBbg1=r,g,b** 

## **RGBbg2=r,g,b** 

There are three numbered variations of the RGBbg# option, as shown above. 

These act similarly to other RGBbg options, except here they only affect radio buttons and checkboxes, causing the specified background color to be applied according to the state of the cell (0=cleared, 1=set, 2=indeterminate). 

## Notes: 

- The effect is immediate; there is no need to exit / reload the tree. 

- It only applies to cells that have a visible checkbox or radio button. 

- It applies equally whether the cell is enabled or disabled. 

- Unlike the generic RGBbg= clause, there is no optional index parameter. 

• When combined with other RGBbg clauses that affect the same column,  new state-specific versions take precedence. For example, if a checkbox column has the options RGBbg=200,200,200~RGBbg1=255,200,200~, then the cells containing a checkmark (state=1) will get the RGBbg1 value, while all the other cells (clear, indeterminate, or no checkbox) will use the standard RGBbg value. 

See EXLIB [908,21] sample program XTRA6 for an example. 

## **History** 

- 2017 May, A Shell 6.5.1604: Function added to A-Shell. 

A-Shell Reference 

Page 3523 

## **RGBFG** 

## **RGBfg=r, g, b {,index}** 

RGBfg has the same syntax and semantics as RGBbg except that it defines a foreground (text) color rather than a background color. The screen shot under RGBbg shows a custom foreground color for the first column. 

Originally, row colors (see _Cformat_ **C** and **c** ) were drawn only from the A-Shell palette, and identified by the palette index numbers 0-15. You can define a custom color using RGBfg or RGBbg on the RGB Color Index and then use it for a row foreground color by specifying the RGB Color Index. 

A-Shell Reference 

Page 3524 

## **RGBFGBG** 

_Added May 2018_ 

## **RGBfgbg=fgbg(fg,bg);fgbg(fg,bg)...** 

RGBfgbg provides the capability to specify foreground and background colors for individual cells. The setup is similar to that for the _cformat_ code **B** , whereby the first space of the cell is reserved for an optional code that references an RGB color, except that in this case, the color reference is to a pair of RGB colors for foreground and background. 

There are three parts to configuring this capability: 

- Add the _cformat_ code **BC** to the column definition, which signifies that the first byte of the column data is reserved for the 

- RGB Color Index or blank to indicate the standard/default color. Note that although "BC" may be seen as a sort of combination of the individual B and C codes, the interpretation of the combined "BC" code completely replaces their individual meanings. 

- Define a set of RGB values associated with index characters using RGBfg and/or RGBbg clauses, in the usual way, e.g. 

- RGBbg=50,100,150,A. These colors and their associated index codes may or may not be used for other purposes in the tree, but they are needed in order to define the color pairs used by the "BC" columns. 

- Specify one or more RGBfgbg clauses which associate a new color index code in the same A-Z,a-z range, with a pair of 

- individual color index codes using the syntax shown above. For example: 

## `RGBfgbg=A(A,B);f(Z,q);r(M,);P(,p);Z(,)` 

Each RGBfgbg clause can contain one or more fgbg(fg,bg) tuplets separated by semicolons. Each tuplet starts with a mandatory index character from the RGB Color Index which will be used to refer to the combined fg/bg color pair. The fg and bg codes representing the foreground and background colors are each optional (although the comma is mandatory); if omitted, that part of the color pair reverts to the default. 

Note that although the individual RGB index characters and the combined FG/BG index characters both occupy the same range as the RGB Color Index, they refer to different tables of colors. So you can have 93 individual colors associated with an index character, and in addition, up to 93 combined pairs associated with an index character. For a given index character, XTREE knows whether to refer to the individual or combined color table by the context, e.g. if the column definition contains "BC", then it will refer to the combined color table, whereas if it contains only "B" or "C" then it would refer to the individual table. However, 

A-Shell Reference 

Page 3525 

if you have fewer than 26 of each type of color index you may want to use upper case for one type and lower for the other, just to reduce confusion. 

For example: 

```
coldef += "0~0~x~H~RGBbg=50,100,150,A~RGBbg=75,125,175,B~~"
```

```
coldef += "0~0~x~H~RGBfgbg=A(A,B);B(B,A);C(A,);D(,B);z(,)~~"
```

The first line defines two individual RGB colors, indexed as A and B. The second line defines five fg/bg pairs, indexed as A, B, C, D, and z. We only partially followed the advice just given to separate the two types of indices by upper and lower case. 

The combined fg/bg index character A refers to foreground color A (50,100,150) and background color B (75,125,175). Combined fg/bg index character B refers to the same pair, but with foreground and background reversed. The combined fg/bg index character C refers to the A foreground color with the default background color. D refers to the default foreground color with background color B. And z is equivalent to " " since both the foreground and background colors of the pair are omitted, i.e. set to default.) 

The sample program XTRAFGBG in EXLIB:[908,21] illustrates this feature. 

## **History** 

- 2018 May, A Shell 6.5.1636: Option added to A-Shell. 

A-Shell Reference 

Page 3526 

## **RGBFGSEL AND RGBBGSEL** 

## **RGBfgSel=r,g,b** 

## **RGBbgSel=r,g,b** 

These determine the foreground and background color used to display the selected row(s) in the specified column. The default selection color is white for the foreground and blue for the background. Changing the default color is sometimes useful, either to make selected items stand out against highly colored cell patterns, or conversely, to make selected items blend into the background. The latter is sometimes useful in conjunction with editing, where you might otherwise get an annoying "flash" as the tree switches between cell editing and selection modes. 

Also see the XTRCTL table for the parameters `XTR.NFSELSTYLE` and `XTR.SELECTAREA` . 

A-Shell Reference 

Page 3527 

## **ROW/COL HEADER COLOR ATTRIBUTES** 

_Added September 2024; see History_ 

These parameters provide support for overriding row and column header color attributes. 

For columns: 

## **RGBfgColHeader=r,g,b** 

## **RGBbgColHeader=r,g,b** 

As with most other column attributes, specifying them for the 0 column establishes the default for the others but can still be overridden at the individual column level. Note that these refer to the "real" column headers, as opposed to the pseudo-headers established by the HdrLines=# option whose colors can be adjusted by the very similar RGBbgHeaders and RGBbgHeaders options. Also see HdrFont, XTR.HIDEHEADER, and XTR_HEADERSTYLE for other column header attributes. 

For rows: 

## **RGBfgRowHeader=r,g,b** 

## **RGBbgRowHeader=r,g,b** 

The row headers, however, unlike the column headers, cannot be assigned colors individually. Regardless of which column you associate the options with, they will affect all of the row headers. The exception to this rule is for Property Sheets (see XTF2_PROPSHEET), where the RGBfgRowHeader and RGBbgRowHeader options can be applied to individual "columns," keeping in mind that in Property Sheet mode, the tree is effectively rotated 90 degrees so that the column headers become row headers. Note that row headers are only visible if the XTR.SHOWROWHDR field is non-zero. 

## **Comments** 

For both row and column headers, since they are normally under the stylistic control of the Windows theme system, you have to set XTR.USETHEMES=0 in order for the above options to have an effect. 

## **History** 

A-Shell Reference 

Page 3528 

- 2024 September, A Shell 7.0.1763:  Parameters added to A-Shell, expand RGBxxRowHeaders to apply to individual rows in property sheet mode. 

A-Shell Reference 

Page 3529 

## **HEADERS AND TOTALS COLORS** 

## **RGBbgTotals=r,g,b** 

## **RGBfgTotals=r,g,b** 

## **RGBbgHeaders=r,g,b** 

## **RGBfgHeaders=r,g,b** 

These four parameters are used to establish the base colors for the special data lines at the top and bottom of the tree which have been flagged as headers or totals. 

Note that totals line(s) are defined via the XTF_TOTALS flag and/or TotalLines=# _coldef_ parameter; headers lines are defined by the HdrLines=# _coldef_ parameter. 

Also note that "header" lines defined via HdrLines=# should not be confused with the real column headers, which are not data lines at all and which do not have adjustable colors. The header lines we're talking about here are just data lines that have been designated "headers" so that they remain at the top, regardless of sorting. 

A-Shell Reference 

Page 3530 

## **SCROLLMODE** 

## **ScrollMode=tree** 

This clause may be used in conjunction with combo boxes (List=) to cause ordinary UP/DOWN-ARROWS to move the focus to the previous/next row, rather than to the previous/next item in the list. In other words, it causes ordinary UP/DOWN-ARROWS to act the same as CTRL+UP/DOWN-ARROWS. It also affects ordinary LEFT/RIGHT-ARROWS in selection-only combo boxes (where they normally act just like up/down). 

The intent of this obscure (and somewhat non-standard) 'feature' is mainly to minimize the possibility that users might accidentally change cell values when they were intending to just "arrow around" the grid. (This is much more likely within XTREE, where ordinary cells may turn into combo boxes when they get the focus, than with "normal" combo boxes that may appear in dialogs. 

Note that in all cases, when the drop-down list is displayed (via ALT+DOWN-ARROW or clicking on the drop-down button), the arrow keys will operate within the list (so it doesn't interfere with the ability to perform all the necessary combo box functions without using the mouse). 

The Mouse Wheel operation is similarly affected by the ScrollMode=Tree clause. 

As of 5.1.1174, ScrollMode=Tree also affects the operation of XTF_UP and XTF2_DOWN (affecting both editable and non-editable contexts). 

Once a ScrollMode command is encountered in the _coldef_ string, it becomes the default for any editable columns subsequently defined. The last encountered ScrollMode statement will determine the behavior in non-column-specific contexts (such as in using the UP/DOWN-ARROWS in non-editable contexts). 

ScrollMode=Tree may be associated with column 0 to make it the default for all columns (rather than having to do it individually for each column containing combos). 

A-Shell Reference 

Page 3531 

## **CELLLIST** 

_Modified December 2017; see History_ 

## **CellList=id, item1, item2, ...itemN** 

Using this option, shared lists (combo boxes) can be associated with individual cells rather than just entire columns. To implement, first define one or more lists (associated with column 0) using the CellList option. 

The format of CellList is identical to List except that it must begin with a single case-sensitive letter, a-z or A-Z, which serves as an identifier for the list, allowing up to 52 lists to be defined. 

To associate one of the predefined lists with a cell, use the _cformat_ code **s** to define the column as being capable of referencing the lists. _cformat_ **s** is similar in concept to B (background cell color) in that it reserves the first character of each cell in the column for the index letters that associate the cell with one of the predefined lists. 

## **Notes** 

- In addition to the index letters, which associate the individual cell with a pre-defined list, you can also use the following codes 

- to make the cell non-editable, or to treat it as a normal editable cell. 

|**Code**|**Description**|
|---|---|
|a-z, A-<br>Z|ID of a CellList (or CellListX)|
|||Marks the cell as display-only. (The remaining characters in the<br>column will be displayed in the cell)|
|*|Causes the cell to be treated as a normal edit (rather than combo<br>list)|



A-Shell Reference 

Page 3532 

# Same as * but limited to numeric digits only 

- If the column also uses _cformat_ **B** , then the first character of the column is for the cell color code, and the second character 

- will be for the CellList ID. 

- As with cell background colors, the byte reserved for the CellList ID must also be accounted for in the answer array. 

- There is no limit on the length of an individual combo list (defined with List= or CellList=). A 4K limit in an earlier version of 

- A-Shell has been eliminated. 

- The sample program XTRA5C illustrates some of these variations. 

## **History** 

- 2017 December, A Shell 6.5.1622:  CellList id codes can now include both upper and lower case characters (previously only lower case), extending the total range from 26 (a-z) to 52 (a-z, A-Z). 

A-Shell Reference 

Page 3533 

## **LISTX AND CELLLISTX** 

## **ListX = <code>, <descr>, <code>, <descr>,...** 

## **CellListX = <idx>, <code>, <descr>, <code>, <descr>,...** 

ListX and CellListX are just like List and CellList, respectively, except that the list of items consists of <code>,<descr> pairs, where the <code> is what you store in your application (and in the data and answer arrays) while the <descr> is what displays in XTREE. The concept and implementation is essentially the same as the INFLD **||L** "list substitution" field type. 

See the sample programs XTRA5 and XTRA5C in EXLIB:[908,21] for examples of using these clauses. Also see "Dropdown lists" Mouse and Keyboard. 

Also: the following note—see List for others—is deemed sufficiently important to repeat here: 

**Warning:** if the first character is neither alphabetic nor numeric, and it matches the last character in the list, then XTREE assumes that it is the delimiter character. Otherwise, the delimiter is assumed to be a comma. This can lead to unexpected problems in lists of items that have both leading and trailing spaces—or any other non-numeric, non-alphabetic character. To avoid that possibility, make the delimiter explicit. 

A-Shell Reference 

Page 3534 

## **PRINT** 

_Added January 2016_ 

## **Print=Disabled** 

This option was introduced to help solve a problem. Previously, specifying the -$PRINT PopupMenu option was removing the print option from the popup menu, but it was not disabling the ability to print/preview using the built-in ^P command. To disable that, this Advanced Coldef Option has been added. 

Note that it doesn't really matter what follows the = sign; the only option is to disable, since the default is for printing to be enabled. 

## **History** 

- 2016 January, A Shell 6.2.1423:  Added to A-Shell. 

A-Shell Reference 

Page 3535 

## **SELCHGEXIT** 

_Updated November 2017_ 

## **SelChgExit=###** 

This option causes XTREE to exit with exitcode -### whenever the selection changes—i.e. by moving it with the up/down arrows or by clicking on a new row. 

This feature can be handy in certain kinds of trees where you want to update some display items as soon as the user moves the selection bar, but beware of conflicts with the following modes and options: 

- edit mode (moving from cell to cell might trigger the "selection changed" event, interfering with the normal cell validation 

- logic.) 

- XTF_FAST mode (it isn't clear which would take precedence in the case of a single click). 

- Context menus (if the user right clicks on a row other than the one currently selected, the change of selection event may or 

- may not preempt the context menu.) (If it does preempt it, you might be able to re-enter immediately and continue though.) 

- ClickExit (again, it isn't clear which event will occur first.) 

## **Comments** 

A-Shell Reference 

Page 3536 

## **TOOLTIP** 

## **ToolTip=<tooltip text>** 

The limit on text size for any one tooltip is 1023 bytes. 

For all trees excluding property sheets, the tooltip will display when the mouse hovers over the column header and the tree is not currently editing a cell. (During cell editing, the only tree-related tooltip that will appear is the tooltip for that cell.) 

For property sheets, when not actively editing a cell, tooltips will display when the mouse hovers over a cell whose logical "column" has a tooltip. As with case above, during cell editing, the only tooltip display will be for the cell being edited. 

Known limitations: 

- Tooltips do not display while "editing" a checkbox or radio button cell. 

- There is no way to associate a tooltip with row headers. 

## **History** 

## - February 2011, A Shell 5.1.1205: Function added to A-Shell 

A-Shell Reference 

Page 3537 

## **TITLE AND FOOTER** 

_Documentation reorganized and this section added May 2014_ 

## **Title=<clause>** 

## **Footer=<clause>** 

Title is used as a page head and window title when using the XTREE print function. 

Footer allows you to specify a page footer to be used when printing an XTREE through the print/preview mechanism. 

_Clause_ can be up to 128 characters. It supports one or two "|" delimiters to separate it into Left|Center|Right. If no delimiters, the text is used as the right title, and the default left title is the date. If one delimiter, it is treated as Left|Right. _Clause_ also supports the following tokens: 

|**Token**|**Description**|
|---|---|
|%date%|Today's date using the current regional settings, short form.|
|%longdate%|Today's date using the current regional settings, long form.|
|%page%|Current page number.|
|%time%|Current time using the current regional settings short form (without seconds).|
|%total%|Total pages.|



A-Shell Reference 

Page 3538 

A-Shell Reference 

Page 3539 

## **ADVANCED SYNTAX EXAMPLE** 

To clarify the advanced form of the _coldef_ syntax, consider this example: 

```
COLDEF="0~0~x~H~Font=Playbill~~"                          ! row font #1
COLDEF=COLDEF+"0~0~x~H~Font=,2048~Scale=200~~"            ! row font #2
COLDEF=COLDEF+"0~0~x~H~HdrFont=Times Roman~~"             ! Header font
COLDEF=COLDEF+"0~0~x~H~HdrScale=150~~"                    ! Header scale
COLDEF=COLDEF+"1~1~x~fH~~"                                ! font column
COLDEF=COLDEF+"2~1~x~cH~~"                                ! color column
COLDEF=COLDEF+"3~15~PO #~SK~~"                            ! col 1
COLDEF=COLDEF+"18~10~Order"+chr(13)+chr(10)+"Date~D|~~"   ! col 2
COLDEF=COLDEF+"29~12~Amount~#~Dspmin=6~~"                 ! col 3
COLDEF=COLDEF+"52~40~Notes~SMW3~RGBfg=240,20,50~~         ! col 4"
```

This defines four pseudo columns (for the purposes of defining two row fonts, a header font style and a header font scale), plus two special controls columns (font and color) which do not display but which do contain data, and four visible data columns. 

Note that pseudo column definitions should start with "0~0~x~H~" (position 0, width 0, title "x", type "H"). The title and type specifiers do not actually matter, since the pseudo column is not displayed and contains no data, but they must be non-null, because two adjacent tildes marks the end of the column definition. 

Of the visible data columns, the first is supplied by the character positions 3 through 17 of the data source records ( _array_ or _file_ ), has a title of "PO #", contains string data, (left justified by default) and may not be reordered. The second occupies positions 1827 of the source data record, has a title of "Order Date" (broken into two lines), contains dates using the format mm/dd/yr (or dd/mm/yr, depending on the language definition), and is center justified. The third occupies positions 29-40 of the source records, has a title of "Amount", contains numeric data (right justified by default), and has a minimum width of 6 standard character cells. The last column comes from positions 52-91 of the source records, has a title of "Notes", contains string data, 

A-Shell Reference 

Page 3540 

supports both explicit line breaks (embedded CRLF) and also auto-wrap based.. It also specifies a custom text color RGB(240,20,50). Note that the last column width will always be set to accommodate the longest cell data, so the auto wrap option wo not have any effect, unless the column is moved by the user (via drag and drop on the column header), in which case it can be resized and the wrap will have a significant effect. 

Regarding the last column, note that because its definition starts in position 52 of the input data, while the previous column ended in position 40, the input data in positions 41-51 will be ignored (not loaded into the control, even in a hidden column). The display width setting of 20 refers to standard character cells (which are typically larger than the average proportional-font character width) so the column may display more or less than twenty characters for reach record. There is probably not much point in limiting it to twenty in this example, since it is the last column anyway. The only effect of the setting would be to limit how much screen space the column takes up when the control is scrolled all the way to the right. See the _xtrctl_ `XTR.ITEMLINES` and `XTR.TRUNCATED` parameters and _flags_ XTF_VARY, which affect how the column will deal with contents that does not fit in the display area provided. 

A-Shell Reference 

Page 3541 

## **TRADITIONAL COLDEF SYNTAX** 

The traditional syntax applies to single-column lists and consists of an arbitrary string to be used as a title. Unlike the PCKLST prompt parameter, XTREE ignores any bottom prompt (which was specified in PCKLST by inserting a chr(13) in the string to separate the top and bottom portions.) Note that there is one important limitation on the contents of the string: it must not contain any groups of two or more spaces enclosed by non-spaces, since this is how XTREE distinguishes between the traditional and simple multi-column syntax. 

A-Shell Reference 

Page 3542 

## **- SIMPLE MULTI COLUMN COLDEF SYNTAX** 

The simple multi-column syntax allows simple multi-column lists to be easily defined for GUI mode, in a way that is backwards compatible with text mode. It consists of a simple string containing the column titles spaced to match the actual column spacing in array. 

If the XTF_FCOLDEF bit is set in the _flags_ parameter, then the _coldef_ parameter is ignored and the first line of the input data is used in its place. (This is particularly convenient for simple multi-column file based data, since it allows you to keep the column titles with the data itself.) 

In order to recognize that a word is the beginning of a new column and not a continuation of the previous column, it must be preceded by two or more spaces. For example: 

```
MAP1 COLDEF,S,100,"Zip   City           State"
```

```
!                  12345678901234567890123456"
```

The above code would define a three-column list. In order for this to work, the layout of the input data (either in _array_ or the _file_ ) must match this layout. Note that one limitation of this method of defining the columns is that the actual column width in characters must be at least two columns wider than the column title. For example, if a column is to contain just a Y or N, but you want to display the title "Back Ordered?", then you would have to pad the column with about fifteen spaces to allow the column data to match up with the title string (unless this was the last column.) The Advanced Coldef syntax allow you to transcend this limitation. 

The columnar interpretation of _coldef_ presents a possible compatibility issue for existing applications counting on XTREE being upward compatible with PCKLST, namely that any _prompt_ string containing alphanumeric (non-space) characters separated by two or more spaces would be interpreted as a multi-column definition in the new version. The chance of this happening, though, seemed remote enough (and in the case of text mode, harmless enough), that we decided it was reasonable to simply require you to remove the ambiguity in any existing _prompt_ strings by eliminating the contiguous blanks if you are interested in using the GUI mode. 

A-Shell Reference 

Page 3543 

## **FILE MODE COLDEF EXTENSIONS** 

In very old versions of A-Shell, the _coldef_ parameter was ignored in file mode when the XTF_FCOLDEF flag was set. Now the _coldef_ parameter may be used in that situation to add to or replace the column definition in the file, and optionally to cause the first several lines of the data file to be skipped (i.e. so that header or other meta-data can be included in the file without being interpreted as data by XTREE). In order for the _coldef_ parameter to be treated as significant (when XTF_FCOLDEF is set), it must begin with "+", "-", or "=". Syntax: 

## **{-skipval}+<COLDEF string>** 

## **{-skipval}=<COLDEF string>** 

The optional {-skipval} clause, which must be first if present at all, is used to force lines of the data file to be skipped. If skipval is a number (e.g. "-5"), then XTREE ignores that number of lines at the top of the file (not counting the first line, which is interpreted as a column definition string due to the XTF_FCOLDEF flag). If skipval starts with a character other than 1-9, it is interpreted as a string label (31 chars max); data interpretation will start with the line in the file following the line that starts with the label string. (Warning: the label string should not include "+", "-", or "=".) For example, consider this file: 

```
1~5~Zip~#~7~30~City Name~S~~
```

```
bla bla bla
```

```
bla bla bla
```

```
xtreedata:
```

```
06104 Belmont
```

```
00922 Puerto Nuevo
```

## `<etc>` 

The file contains a column definition string in the first line, followed by three non-data lines, followed by N data lines. To tell XTREE to skip over those non-data lines, you could set the _coldef_ parameter to one of the following: 

A-Shell Reference 

Page 3544 

```
COLDEF = "-xtreedata:"   ! skip until after "xtreedata:" label
```

```
COLDEF = "-3"            ! skip 3 lines
```

Instead of, or in addition to skipping lines, you can also use the _coldef_ parameter to append to, or replace, the column definition string in the file. To append, use "+" followed by a legal _coldef_ definition string. Appending is useful when you want to add something non-data specific, such as a popup menu, which may depend on runtime application logic. To replace, use "=" followed by a legal _coldef_ definition string. Replacement is probably most useful when you didn't really want to put the column definition in the file at all, but needed to in order to use the -skipval feature (since all of these special _coldef_ parameter features discussed here require the XTF_FCOLDEF flag). Some legal examples: 

- `! use column definition from the file, as is.` 

```
COLDEF = ""
```

```
! skip 3 lines (plus column def line), append popupmenu to col. def.
```

```
COLDEF = "-3+0~0~x~H~PopupMenu=Eat,VK_xF100;Drink,VK_xF101~~
```

```
! skip to "data:" label, replace col. def entirely
```

```
COLDEF = "-data:=1~5~Zip~#~RGBbg=50,100,200~~7~30~City~S~~
```

Note that column definition string following the "+" or "=" in the examples above must meet all of the normal _coldef_ syntax rules, including ending with ~~. 

A-Shell Reference 

Page 3545 

## **EXITCODE** 

This output parameter returns a single numeric code indicating how the tree was exited. For the most part, these exitcodes are common to other several routines (INFLD, XTEXT, EVENTWAIT). 

|**Value**|**Depends On**|**Description**|
|---|---|---|
|29||Indicates user clicked on drop-down arrow of a "self service" combo cell.|
|11|XTR.timeout|Time out in milliseconds|
|10|XTF_CTRLC|Ctrl+C. Note that XTF_CTRLC works even if Ctrl+C has been disabled (seeCCOFF).|
|1||Escape|
|0||Normal exit by hitting Enter or double-clicking on an item|
|-1 thru -16|XTF_FKEY|F1-F16 (enable with XTF_FKEY)|
|-35|XTF_TAB|Shift+Tab. If not enabled for exit, Tab and Shift+Tab may be used in conjunction with<br>editable cells to navigate between them.|
|-40|XTF_LEFT|Left-Arrow. When editing a cell, left arrow will operate within the cell; use CTRL+LEFT to<br>generate exitcode.|
|-41|XTF_RIGHT|Right-Aarrow. When editing a cell, right arrow will operation with the cell; use|



A-Shell Reference 

Page 3546 

|**Value**|**Depends On**|**Description**|
|---|---|---|
|||CTRL+RIGHT to generate exitcode.|
|-42|XTF_UP|Up-Arrow|
|-43|XTF2_DOWN|Down-Arrow on last row|
|-44|XTF_TAB|Tab key|
|-45|XTF_HOME|Home key|
|-46|XTF_END|End key|
|-47|XTF_DEL|Del key|
|-48|_cformat_codes x,X|Exit for validation of an editable cell, typically on exit from the cell, except in the case of<br>_cformat_uX, where the exit for validation occurs on entry into the cell. See the various<br>editable cell controls in_cformat_<br> and Editable Tree Controls<br>for more details.|
|-51|ExitChars<br>=|Exit on receipt of character defined in list (Advanced Coldef Options<br>)|
|-59||Double-click on a read-only editable cell (_cformat_code<br>**u**)|
|-75|XTF2_DRAGDROP|File has been dragged and dropped on the XTREE control, when enabled via|



A-Shell Reference 

Page 3547 

|**Value**|**Depends On**|**Description**|
|---|---|---|
|||XTF2_FILEDROP.|
|(others)||A click on any other control which generates a standard virtual key click string (e.g.<br>VK_xF101) will causeXTREEto exit with the corresponding exitcode.  Several of the<br>Advanced Coldef Options also allow configuration of exitcodes for specific events (e.g.<br>ClickExit, DropExit, PopupMenu, etc.)|



A-Shell Reference 

Page 3548 

## **XTREE FLAGS1** 

_Updated May 2017_ 

This parameter is used to enable exit keys and other options according to the tables below. Note that although most of the _flags_ are optional niceties, a few are critical to proper XTREE operation. In particular, XTF_XYXY is required, and XTF_COLDFX is nearly always appropriate. The parameter can be mapped in one of three ways: 

```
MAP1 FLAGS,B,4          ! (XTF_xxx)
```

## or 

```
MAP1 XFLAGS
```

```
   MAP2 FLAGS,B,4       ! (XTF_xxx)
   MAP2 FLAGS2,B,4      ! (XTF2_xxx)
```

or 

```
MAP1 XFLAGS, ST_XFLAGS  ! (defined in ashinc:xtree.sdf)
```

The second or third form is required if you want to use any of the XTF2_xxxx flags (i.e. XTREE Flags2 ), but in that case, note that you must specify XFLAGS (i.e. the structure) rather than either _flags_ or _flags2_ in the parameter list. 

To set individual flags, just add (or combine using the "OR" operator) the corresponding symbols or values, for example: 

```
FLAGS = XTF_XYXY or XTF_COLDFX
```

## or 

```
XFLAGS.FLAGS2 = XFLAGS.FLAGS2 or XTF2_DRAGDROP2
```

A-Shell Reference 

Page 3549 

_flags2_ and the XTF2 symbols have their own section here: XTREE Flags2 . Also see XTR.MISCFLAGS for additional flags and more information. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTF_FKEY|&h00000001|Allow F1-F16 (returning Exitcodes -1 through –16)|
|XTF_LEFT|&h00000002|Enable Left arrow (Exitcode -40)|
|XTF_RIGHT|&h00000004|Enable Right arrow (Exitcode –41)|
|XTF_UP|&h00000008|Enable Ctrl+Up arrow on first row (Exitcode -42). See "Locating and Selecting Items<br>... Use the Up/Down-arrow keys " inMouse and Keyboard<br>.|
|XTF_TAB|&h00000020|Enable Tab key (Exitcode -44), and Shift+Tab (Exitcode -35)|
|XTF_HOME|&h00000040|Enable Home key (Exitcode –45)|
|XTF_END|&h00000080|EnableEnd key (Exitcode –46)|
|XTF_ENTESC|&h00000100|ControlsESCAPEandENTERkeys when in editing mode. Note that INMEMO used this<br>flag value for the "no auto-shrink" option, which isn't applicable to XTREE.|
|XTF_MODELESS|&h00000200|Leave list box on the screen after exit from the subroutine.|
|XTF_TIMOUT|&h00000400|For thePCKLST(text mode) only, sets a 200 second timeout—i.e., acts as if user|



A-Shell Reference 

Page 3550 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||had hitESCAPE. ForXTREE, ignored; use XTR.TIMOUT instead.|
|XTF_FST|&h00000800|Fast selection mode. InPCKLST, this means menu items can be selected by<br>entering the minimum number of characters to uniquely identify the item. (Without<br>the XTF_FST flag,ENTERwould be required to complete the selection.) ForXTREE,<br>this means that a single click (completes the selection operation, rather than<br>requiring a double-click or a click followed by Tab).|
|XTF_FCOLDEF|&h00001000|Control interpretation of first record.|
|XTF_XYXY|&h00002000|Interpret the 1st and 2nd parameters (_row, col_) as starting row, starting col, and<br>the 8th and 9th parameters (_strow, endrow_) as ending row, ending col. Mandatory<br>forXTREE, optional forPCKLST.|
|XTF_SORT|&h00004000|Allow sorting.|
|XTF_REORD|&h00008000|Allow column reordering by drag and drop. (Note that if enabled globally, it can still<br>be turned off for individual columns.)|
|XTF_MSEL|&h00010000|Allow multiple selections.|
|XTF_MLVL|&h00020000|Multi-level (hierarchical) row support. This will be set automatically if the first<br>column defined in_coldef_uses the@ code<br>.Sample images here<br> andhere.<br> Also see<br>Multi-level Lists<br>.|



A-Shell Reference 

Page 3551 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTF_COLDFX|&h00040000|_Coldef_parameter uses the advanced syntax.|
|XTF_VARY|&h00080000|Variable height rows. Calculation is subject to maximum number of text lines per<br>item as set in the_xtrctl_XTR.itemlines parameter.|
|XTF_NOSEL|&h00100000|Exit immediately, rather than waiting for the user to make a selection. (This only<br>makes sense in conjunction with XTF_MODELESS; also see xtrctl XTR.opcode)|
|XTF_DISABLE|&h00200000|Disable the tree control on exit.|
|XTF_DEL|&h00400000|Enable Del exit (Exitcode –47)|
|XTF_FILANS|&h00800000|Return result via row number in_answer_parameter.|
|XTF_CTRLC|&h01000000|Causes Ctrl+C to set Exitcode 10 (as inINFLD) instead of 1.|
|XTF_EDITABLE|&h02000000|Indicates anEditable Tree Control<br>—i.e. containing one or more editable columns.<br>Note that although_cformat_codes (E, T, etc.) may appear to activate editing mode<br>by themselves, this flag needs to be set manually so that it can inform the handling<br>of the_array_parameter before the_coldef_parameter can be parsed.|
|XTF_TOTALS|&h04000000|Declare that last line of data contains totals (and thus is not to be sorted).|
|XTF_NOREDRAW|&h08000000|Defeats redraw/refresh of data.|



A-Shell Reference 

Page 3552 

|**Symbol**|**Value**|**Description**|
|---|---|---|
||||
|XTF_DRAGDROP|&h10000000|Item drag-drop (within a singleXTREEcontrol).|
|XTF_SPLIT|&h20000000|Activates split or dual-pane mode.|
|XTF_NOZEROEX|&h40000000|PreventsXTREEfrom exiting with EXITCODE 0.|
|**Definition file:**ashinc:xtree.def|||



- Hex Decimal Values 

Jump to XTREE Flags2 table. 

A-Shell Reference 

Page 3553 

## **XTF_COLDFX** 

In XTREE, indicates that _coldef_ parameter uses the advanced syntax. 

In PCKLST, indicates that the _prompt_ parameter is actually an XTREE advanced Coldef syntax specification, rather than simply a title string. However, because of the limited capabilities of PCKLST, it pays attention only to the _cwidth_ and _ctitle_ fields for the first column ( _cpos_ should be 1, and _cformat_ should be **S** ). _ctitle_ is used for the PCKLST top title. All XTREE Advanced Coldef Options are ignored except SelChgExit. Using this format doesn't provide a lot of advantages in the PCKLST context, but it does allow programs that work in both PCKLST (text) and XTREE (GUI) modes to take advantage of a wider range of XTREE features when operating in the GUI mode without breaking compatibility with PCKLST in the text mode. For example: 

```
prompt = "1~14~Pizza Menu~S~DefaultScale=120~ExitChars=01~SelChgExit=103~~"
```

The above string indicates that the width of the elements in the array is 14, that "Pizza Menu" should be used as the top title/prompt, and that the routine should exit with exitcode -103 whenever the selection bar is moved.  The DefaultScale and ExitChars options are ignored by PCKLST (but would be valid for XTREE). 

A-Shell Reference 

Page 3554 

## **XTF_DRAGDROP** 

XTREE supports item drag-drop, within a single XTREE control, as a means of allowing the user to re-order the rows and to communicate the new order back to the application. For drag/drop between XTREEs, see XTF2_DRAGDROP2. For example, you may want to present a list of fields available for export and allow the user to determine the output order by rearranging the list using drag/drop. Or you may want to load up an XTREE with a list of all of your illegally downloaded MP3 tunes and use the drag/drop feature to create ordered play lists. 

To enable the feature, specify the XTF_DRAGDROP bit in the _flags_ parameter, and insert two fields at the start of the _answer_ array, along the lines of how you would set up the _answer_ array for editable cells. The first field is a four-character string to return the original row number for the given display row, and the second field is a one-character item selection flag, just as you would have for multi-selection. 

For example: 

```
MAP1 ANSWERX
```

```
   MAP2 ANSARY(MAX_ROWS)
```

```
      MAP3 ORG'ROW,S,4    ! original row number of this display row
      MAP3 SELECTION,S,1  ! selection flags
      MAP3 CB,S,1         ! a checkbox column
      MAP3 EDATA,S,8      ! a 8 character editable column
      <etc>
```

Note that the `ORG'ROW` field must be first, followed by the `SELECTION` field, followed by any editable checkboxes, followed by any other editable cells. In the example above, the `ORG'ROW` and `SELECTION` fields would be mandatory while the `CB` and `EDATA` fields would only apply if you happened to have one editable checkbox column and one editable text column.) 

The `SELECTION` field is treated just as it would be when multi-select is enabled (i.e. `SELECTION(I)="1"` if item I is selected, or "0" if not.) Note that the presence of a `SELECTION` array usually indicates that multiple selection is supported, but in this case it does not necessarily imply that. In fact, the drag-drop operation currently only works for one row at a time, although you can 

A-Shell Reference 

Page 3555 

still allow multi-selection for reasons independent of drag-drop. In normal (single selection) case, all of the `SELECTION()` entries will be "0" except for the one selected item.) 

The `ORG'ROW` field is formatted as a decimal number of up to 4 digits with leading spaces. This imposes a maximum of 9999 rows when using drag-drop, which is a reasonable limit since drag-drop becomes somewhat impractical anyway when you have more than several dozen items. 

Since the array used to load items is not returned by XTREE, and all other related return data specifying row numbers is coded relative to the original order of the rows (as opposed to the last display order), the `ORG'ROW()` array provides the only way for the app to determine what the last display order was. This might even motivate you to enable drag/drop just for the purpose of being able to easily process the array data according to the way the user sorted it. 

The `ORG'ROW()` array is ordered according to the display order of the rows, unlike all the other arrays within the _answer_ array, which are ordered according to the original array order. As an example of using `ORG'ROW()` , the following code would print the original array data according to the display order (resulting from drag/drop and/or column sorting): 

```
FOR I = 1 TO MAX_ROWS
```

```
    J = VAL(ORG'ROW(I))
```

```
    IF (J > 0) PRINT ARRAY(J)
```

```
NEXT I
```

## **See Also** 

- XTF2_DRAGDROP2 for drag/drop operations involving more than one XTREE control. 

- XTF2_FILEDROP for dragging a file from an Explorer or Windows Shell dialog and dropping it on an XTREE control. 

- The entries for _DragDropExit, DragDropProtect_ and _DropExit_ in the table of Advanced Coldef Options. 

A-Shell Reference 

Page 3556 

## **XTF_NOREDRAW** 

When used with `XTR.OPCODE 4` (select from existing control), defeats all redraw/refresh of data, which makes for a "cleaner" reentry, assuming that none of the parameters which might affect the display have changed. Without this flag, re-selecting from an existing control will reset the columns, possibly adjust the vertical scroll, etc. The sample program XTRA3 demonstrates this. 

Note that it is possible to use the XTF_NOREDRAW flag along with opcode 4 (reselect) even when you are updating data in the editable cells prior to the reselect. In early versions of XTREE, XTF_NOREDRAW disabled the updating of the editable cells from the _ansary_ parameter on reentry. XTF_NOREDRAW might be useful in this circumstance to eliminate unwanted display adjustments taking place during the reentry process. 

A-Shell Reference 

Page 3557 

## **XTF_NOSEL** 

When a call using XTF_NOSEL follows a click on the inactive tree, it returns the location of the click in the `XTR.TARGETROW` and `XTR.TARGETCOL` fields. This is useful in the following scenario: 

Your program is waiting in some state other than XTREE (perhaps INFLD), but there is a visible (inactive) XTREE control on the screen. The user clicks on a cell in the XTREE. This returns the _exitcode_ defined by `XTR.KBDSTR` to whatever routine is waiting on input. Your program sees that the exitcode is from clicking on the inactive XTREE, but you want to know what cell was clicked. So you call the XTREE, with _opcode_ XTROP_RESELECT and with the XTF_NOSEL flag set (for an immediate exit). On exit, your program can get the location of the click from `XTR.TARGETROW / XTR.TARGETCOL` . 

Note that this operation only makes sense in conjunction with XTF_MODELESS; also see _xtrctl_ XTR.OPCODE. 

A-Shell Reference 

Page 3558 

## **XTF_SPLIT** 

This flag enables a split (or dual-pane) mode, allowing two sets of columns to be scrolled horizontally independently. This is typically useful when you have a lot of columns (so horizontal scrolling is needed) but you want one column, or perhaps a few columns, to always be visible. By putting those columns in the left pane, they will be immune to the horizontal scrolling taking place in the right pane. Two fields in the _xtrctl_ structure, XTR.LEFTPANECOLS and XTR.LEFTPANEWIDTH, are used to control column size and spacing; see those topics for related inforamtion. 

In most respects, the dual pane mode should act just like the regular, single-pane mode. Both panes remain vertically synchronized at all times. However, in editable mode, there is currently an assumption that you would probably confine the editable cells to the right pane, and thus the editable cell navigation operates on this principle, although you could still select an editable cell in the left pane with the mouse. 

Two sample programs are available: XTRA2S is a variation of XTRA2, with the zip column in the left pane by itself. XTRA5 has been upgraded to offer an option of how many columns, if any, to put in the left pane. (If none, it works as before in single-pane mode.) 

Sample image here. 

A-Shell Reference 

Page 3559 

## **XTREE FLAGS2** 

_Updated July 2018; see History_ 

This parameter is a continuation of the flags parameter, providing additional bits for additional options. Note that both _flags_ and _flags2_ are passed to the subroutine as a single structure containing both sets of flags. See XTREE Flags for details on how this must be mapped. Also see XTR.MISCFLAGS for additional flags and more information. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTF2_HOME_CTRL|&h00000001|Exit on <HOMEorEND> without Ctrl+. SeeXTF2_HOME_CTRL and _END_CTRL<br>.|
|XTF2_END_CTRL|&h00000002||
|XTF2_NAVCOL|&h00000003|Combo of above for editing and navigation.|
|XTF2_PORTRAIT|&h00000004|Portrait or landscape printing.|
|XTF2_LANDSCAPE|&h00000008||
|XTF2_AUTOEXPCOL|&h00000010|Auto expand columns.|
|XTF2_CSV|&h00000020|Support for CSV format.|
|XTF2_PGUPDN|&h00000040|EnablePAGE-UP / PAGE-DOWN(exitcodes 4, 6).|
|XTF2_DOWN|&h00000080|EnableCTRL+DOWNon last row (exitcode -43). See "Locating and Selecting|



A-Shell Reference 

Page 3560 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||Items ... Use theUP/DOWN-ARROWkeys " inMouse and Keyboard<br>.|
|XTF2_NORESPONSE||Eliminates return of any response information for a particularXTREEcall.|
|XTF2_CLRDEFER|&h00000100|TellsXTREEto ignore any previous inactive click and to clear any secondary<br>events associated with it. See discussion ofClicks on Inactive XTREEs<br>. Also<br>tellsXTREEto discard any unprocessed keyboard characters at the start of the<br>start of the XCALL operation (so that the session starts out waiting for new<br>keyboard and mouse events, rather than processing ones that occurred prior to<br>the subroutine).|
|XTF2_PROPSHEET|&h00000800|Property sheet (aka "vertical") mode.|
|XTF2_ANSEQDATA|&h00001000|Used to indicate that the layout of the answer array is the same as that of the<br>data array.|
|XTF2_DRAGDROP2|&h00002000|Drag/drop between trees.|
|XTF2_SAVRES|&h00008000|CausesPCKLSTto save the screen area.|
|XTF2_POPUP|&h00010000|Causes the tree control to be created as a popup rather than as a child control.|
|XTF2_ENTERNAVDOWN|&h00020000|Alters the default cell editing navigation response to theENTERkey, provided<br>there is no EnterGoto option defined for the current column. When specified,|



A-Shell Reference 

Page 3561 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|||instead of acting likeTABand moving to the next editable cell to the right,<br>ENTERacts likeDOWN-ARROW, except that from the last row it wraps back up to<br>the top.|
|XTF2_PIXCOORDS|&h00040000|Causes the coordinates units to be treated as pixels. Equivalent to<br>MBF2_PIXCOORDS inAUI_CONTROL.|
|XTF2_ITEMICONS|&h00080000|Specify "item icons."|
|XTF2_CTRLC_COPY|&h00100000|Enables use of Ctrl+C to copy selected item(s) to clipboard. SeeCopy to<br>Clipboard<br>.|
|XTF2_UTF8|&h00200000|Provides support for UTF8.|
|XTF2_FILEDROP|&h00400000|Adds extra space to each row to fill out the allotted vertical area of the tree.|
|XTF2_AUTOFILTER|&h00800000|EnablesAuto-Filtering<br>.|
|XTF2_FILEDROP|&h01000000|Enables file drag-drop from Explorer.|
|XTF2_NOAUTOFILTER|&h02000000|Enables disabling of AutoFilter.|



- Hex Decimal Values 

A-Shell Reference 

Page 3562 

## **History** 

2018 July, A-Shell 6.5.1640: Added XTF2_AUTOFILTER. 

A-Shell Reference 

Page 3563 

## **XTF2_FILEDROP** 

Flag XTF2_FILEDROP enables the ability to detect when a file is dragged from Explorer—or a Windows Shell dialog such as a File Open dialog—and dropped on the XTREE control. The drop event triggers exitcode -75. The application must then call MX_DRAGDROP to retrieve the filespec of the dropped file, with which it can do whatever it wants, perhaps adding the file name or related attributes as an item to the tree contents. 

## **See Also** 

- XTF_DRAGDROP to drag and drop within a single tree, for item re-ordering.. 

- XTF2_DRAGDROP2 for drag/drop operations involving more than one XTREE control. 

A-Shell Reference 

Page 3564 

## **XTF2_AUTOEXPROW** 

_Added August 2015_ 

Flag XTF2_AUTOEXPROW works analogously to XTF2_AUTOEXPCOL to add extra space to each row to fill out the allotted vertical area of the tree. It only applies to trees with fixed height rows—i.e., XTF_VARY flag not set. It is normally accompanied by the XTMF_INTHEIGHT flag (in `XTR.MISCFLAGS` ) which has a similar/related purpose. While XTMF_INTHEIGHT by itself (without XTF2_AUTOEXPROW) cause the height of the tree to shrink slightly, so as to avoid having a partially visible row at the bottom, XTF2_AUTOEXPROW causes the row heights to expand slightly, avoiding the partial row at the bottom but also avoiding the need to shrink the tree height. 

Note that while XTF2_AUTOEXPCOL may seem to make XTMF_INTHEIGHT superfluous, the requirement of making each row the same height may result in a small pixel remainder after dividing the extra space between the rows. The XTMF_INTHEIGHT flag will then eliminate that by making a small adjustment to the overall height. 

## **History** 

- 2015 August, A Shell 1315:  Flag added to A-Shell 

A-Shell Reference 

Page 3565 

## **XTF2_UTF8** 

_Added November 2013_ 

You may display and edit non-Latin1 characters (Cyrillic, Greek, Korean, etc.) in XTREE by specifying the XTF2_UTF8 flag and then using the UTF8 encoding for special characters in the data array, file, and/or ansary. If you don't specify the XTF2_UTF8 flag, XTREE will assume that any characters > chr(128) are Latin1-encoded (as it has in the past). 

Note: the column widths specified in the _coldef_ parameter remain in units of 8-bit bytes, so if you expect a column to contain UTF8-multi-byte-encoded characters, make sure to expand the column width accordingly. 

See the sample program XUTF8A in EXLIB:[908,21]. 

## **History** 

- 2013 October, A Shell 1365: Flag added to A-Shell 

A-Shell Reference 

Page 3566 

## **XTF2_HOME_CTRL AND _END_CTRL** 

The XTF_xxxx_CTRL flags, as their names hopefully suggest, affect the behavior or need for the combination of the CTRL key with the xxxx (HOME or END) key. When set, and assuming that the corresponding XTF_HOME and/or XTF_END flags are also set, then these bits reverse the behavior of the CTRL key in conjunction with the HOME and END keys. Thus, HOME and END without the CTRL key will be interpreted as exit keys, while CTRL+HOME and CTRL+END will be interpreted as navigation keys (to jump to the first/last row). 

Historical note: prior to 5.1.1133, HOME and END navigated to the first/last row of the tree, unless you used the CTRL key with them (and the XTF_HOME and/or XTF_END flags were set), in which case they acted as exit keys. Between 1133 and 1146, they acted as exit keys even without the CTRL key. Then starting with 1146, the original behavior was restored (and the XTF2_xxxx_CTRL flags were introduced to allow you to choose between the two behaviors). 

A-Shell Reference 

Page 3567 

## **XTF2_NAVCOL** 

The XTF2_HOME_CTRL and _END_CTRL flags, when used in an editable tree where XTF_HOME and/or XTF_END are not set, allows HOME and END to, in some types of editable cells, navigate to the first / last editable cell on the current line. By "some types" we mean essentially any kind of editable cell except one that allows you to directly edit the contents of (i.e. a standard editable text cell), since in the latter case, HOME and END are captured by the edit box itself to move the cursor to the beginning and ending of the cell, rather than to move between cells. But for checkboxes, radio buttons, read-only cells, etc., these new keys provided yet another navigational shortcut for power users. 

Note that for convenience and perhaps clarity, a symbol has been defined in ashinc:xtree.def: 

```
define XTF2_NAVCOL = &h00000003  ! (XTF2_HOME_CTRL+XTF2_END_CTRL)
```

Also note that these flags have no effect in non-editable situations, provided the keys are not enabled as exit keys (via XTF_HOME / XTF_END). If they are enabled as exit keys, then the XTF2_NAVCOL flags reverse the action of the simple keys and the keys with CTRL+. In other words, when set, CTRL+HOME will navigate to the first row, while HOME will exit; otherwise, CTRL+HOME exits and HOME navigates. 

A-Shell Reference 

Page 3568 

## **XTF2_AUTOEXPCOL** 

This flag will auto-expand the columns to fill the width of the tree control, eliminating the blank space that will otherwise appear when `XTR.CLOSEDENDED` is 1 and the overall tree control is wider than it needs to be for the current data. 

```
define XTF2_AUTOEXPCOL= &h00000010     ! Auto Expand Columns to fill control
```

The expansion operation increases the width of the visible columns by a uniform percentage rather than by a fixed number of pixels, thus preserving the relative widths. The last column will pick up any extra pixels left over from rounding and if there is no vertical scroll bar. 

The flag is ignored in split (XTF2_SPLIT) and open-ended `(XTR.CLOSEDENDED=0)` controls. 

## **Comemnts** 

Note that XTF2_AUTOEXPCOL does not automatically override the wrap option in the last column. If any columns have the wrap attribute, XTF2_AUTOEXPCOL assumes that there will be a vertical scroll bar and calculates the column width expansion accordingly, leaving the wrap settings in place. The only downside of this is that if there are not enough items to require a vertical scroll bar, you could end up with a vertical white strip on the right edge, where the vertical scroll bar would have gone. 

A-Shell Reference 

Page 3569 

## **XTF2_CSV** 

_Updated August 2015_ 

Setting this flag allows you to use a CSV file as the input for the XTREE. There are several variations on how columns and other attributes can be defined: 

· If you do not specify a column definition string in _coldef_ (XTF_COLDFX), XTREE will auto-define columns based on the number of fields in the first row of the CSV file. (Currently it sets them all to a generic string type, although perhaps in the future an attempt will be made to auto-detect numeric and date columns). In the typical case, XTREE assumes that the first row of the CSV file contains the column names, which will be used to build the XTREE column headers. If your CSV does not contain such a header row, you can specify `XTR.HIDEHEADER=1` (in _xtrctl_ ), in which case the first row will be treated as data, and there will be no column headers. 

· You may specify your own column definitions using the standard _coldef_ syntax, either in the CSV file itself (in which case set both the XTF_FCOLDEF and XTF_COLDFX flags), or in the _coldef_ parameter (in which case set XTF_COLDFX as you would normally). However, note that if any real columns are defined, then only those columns will be properly recognized during the load operation. You may choose to define only pseudo-columns (with cpos=0 and cwidth=0, i.e. "0~0~x~H~...~~") in order to define other attributes, such as colors, fonts, popup menus, etc., in which case the actual column definitions will be autogenerated as in the first case described above. Note that whenever any real columns are defined using the advanced _coldef_ syntax (in either _coldef_ or in the file), it is assumed that there is no other header row in the file. If there is, use the skip syntax described below to skip over it. 

- When defining real columns, set _cpos_ to the column number and _cwidth_ to 1. It doesn't actually matter what you set them to, 

- as long as they are both greater than zero, but this is a reasonable convention to minimize confusion later. 

· To skip over lines at the top of the file, you can begin your _coldef_ parameter with a {-skipval} clause. Note that when XTF2_CSV is specified, the {-skipval} clause does not require XTF_FCOLDEF (i.e. doesn't require any column definitions in the data file), and it doesn't have to be followed by "+" or "=" and a valid _coldef_ definition. So in other words, you can skip lines by starting the _coldef_ parameter with a {-skipval} clause, whether or not you use any other _coldef_ features. 

Assume the CSV file looks like this and that we are specifying the XTF2_CSV flag in all cases: 

```
Account, Name, TrxDate, Amount
```

A-Shell Reference 

Page 3570 

```
12345,"Smith,Fred",08/15/09,999.12
```

```
12346,"Jones,Jane",08/16/09,100.00
```

If _coldef_ ="", and neither the XTF_COLDFX nor XTF_FCOLDEF flags are set, XTREE will recognize and display 4 columns of data, creating headers from the first line. 

If `XTR.HIDEHEADER=1` , then it would treat the first line above as data, rather than as headers, and no header bar would be created. 

If XTF_COLDFX is set and _coldef_ ="-1", then it would skip the first line. (When skipping, even if `XTR.HIDEHEADER=0` , there will still be no header bar unless the _coldef_ string contains real column definitions.) 

If _coldef_ ="0~0~x~H~HdrScale=200~~" (and XTF_COLDFX set), then the header scale will be set to 200, but the headers and column information will still be taking from the file (because the _coldef_ does not define any real columns). 

If _coldef_ ="-1=1~1~Acct#~#~~2~1~Name~S~~3~1~Date~D~4~1~Amount~#~~", then the first line of the data file will be skipped (due to the "-1=" at the start of the _coldef_ , and the columns will be defined by the _coldef_ string in the normal way, except that due to the XTF2_CSV flag, the _cpos_ and _cwidth_ parameters do not matter (but must be >0). By convention, we have specified _cpos_ values which equate to the field number, but there is currently no way to rearrange the columns with this technique. 

If we replaced the standard CSV header line at the top of the CSV file with a _coldef_ string, as follows: 

```
1~1~Acct#~#~~2~1~Name~S~~3~1~Date~D~4~1~Amount~#~~
```

```
12345,"Smith,Fred",08/15/09,999.12
```

```
12346,"Jones,Jane",08/16/09,100.00
```

Then we could specify XTF_FCOLDEF and XTF_COLDFX to have XTREE retrieve the column definitions from the file. Optionally, we could add to the column definitions by setting the _coldef_ parameter to "+" followed by a legal set of column definitions (presumably pseudo-columns in this example). 

A-Shell Reference 

Page 3571 

## **See Also** 

- Program XTRCSV.BP in EXLIB:[908,21]. 

## **History** 

- 2015 August, A Shell 6.1.1515:  You may now use the notation "\n" to embed a CRLF within a field, provided the _cformat_ format column contains the "M" (allow embedded CRLFs) option. This avoids complications with parsing CSV files containing line breaks inside of fields. 

- 2013 May, A Shell 6.1.1351: XTF2_CSV now automatically disables the hidden text feature—i.e., it now treats backslash as a normal data character. The feature was causing more confusion than it was worth, and is only being preserved for traditional file mode. 

A-Shell Reference 

Page 3572 

## **XTF2_NORESPONSE** 

This flag may be specified to eliminate the return of any response information for a particular XTREE call. This is purely of interest in the ATE environment as a performance enhancement, since the return of response information causes the application to have to wait for the network turnaround time, which is small but adds up. In order to be effective, it must be used along with the XTF_NOSEL flag, which is used when you want to display some data without waiting for a user section or editing action. 

**Warning** : do not use this flag along with `XTR.CTLNO = -1` , since in that case you won't get back the updated tree control number, which could make it difficult to reference the tree on subsequent calls. 

A-Shell Reference 

Page 3573 

## **XTF2_ANSEQDATA** 

This flag may be used to indicate that the layout of the answer array is the same as that of the data array. The main limitation is that it does not support drag/drop or multi-selection. (It may be extended in the future to the more general case). The current primary motivation is to permit the use of same array (or identically formatted ones) for both the answer and data in trees involving checkboxes. (You were already allowed to use the same array for both parameters, but it wouldn't have worked with checkboxes due to the normal rule requiring checkboxes to be placed at the start of each row in the answer array.) 

The flag is set automatically when you pass the same variable for both the answer and data parameters. 

## **History** 

- 2011 September, A Shell 5.1.1231: XTF2_ANSEQDATA can now be used even when the array contains fields that are not editable, or possibly not even defined. Previously, if the array width didn't match the sum of the widths of the editable columns, the data layout got out of sync with the tree layout. 

- 2011 January, A Shell 5.1.1202:  Flag to A-Shell 

A-Shell Reference 

Page 3574 

## **XTF2_PROPSHEET** 

_Updated September 2024; see History_ 

## Sample image here. 

A "property sheet" is a control made up of two columns and a variable number of rows; the first column contains labels (attributes); the second column contains the data corresponding to the labels (attribute values). 

There is nothing stopping you from implementing such a structure with a two-column XTREE. But it is difficult, if not impossible, to support a variety of different data formats (checkboxes, radio buttons, different widths of editable text, lists, etc.), since in the property sheet configuration, they would all be in the same column and the XTREE configuration scheme tends to limit each column to a single data format. 

The XTF2_PROPSHEET option addresses this by effectively rotating the tree 90 degrees so that the columns (according to the _coldef_ ) are displayed as rows. The column titles become the row headers or labels. 

Property sheet mode also supports multi-level. To configure this, specify the _cformat_ code **@** for each "column" (i.e. each item) that should appear at level 1. Columns (i.e. items) without this code will appear at level 0. To designate an item at level 2 or below, add  additional **@** codes (one per level). For example: 

```
coldef = "1~1~Shipping Info~S~~"         ! Level 0 (no "@")
coldef = coldef + "2~30~Address~SE@~"    ! Level 1 (one "@")
coldef = coldef + "32~30~City~SE@~"      ! Level 1 (one "@")
```

```
...
```

## **Comments** 

Here are some points and limitations to keep in mind: 

• You are limited to a single row of data (which appears as a column). In fact, rather than specify an array of one item, you can just specify a singular structure (whose fields line up with the column definitions.) Since the usual object is to edit this structure, 

A-Shell Reference 

Page 3575 

you can specify a copy of the same structure for the answer parameter (remember to set the XTF2_ANSEQDATA flag), or specify the same variable for both parameters. 

- None of the following are supported: XTF_MSEL, XTF_DRAGDROP, XTF_REORD, XTF_SORT, XTF_SPLIT. 

- Column colors (RBGbg, RGBfg) are not (yet) supported. But you can assign background colors to individual cells using 

- _cformat_ **B** . 

- Since the attribute value display column is actually coded as a row, you can use the _cformat_ codes normally designed for row 

- attributes to assign a color or font to the display column; see _cformat_ **b** , **C** and **f** . 

- If you are using anything but left justification, and if there is any possibility of cells extending logically beyond the control 

- width, you should XTR.'CLOSEDENDED mode and XTF2_AUTOEXPCOL. Otherwise, you may end up column data that doesn't appear unless you use the horizontal scroll bar to scroll to the right. 

- If Dspwid=# is specified for an editable cell, it determines the width of the edit box when a cell is being actively edited. This 

- provides an alternate method (besides _cformat_ **_** ) to adjust the width of the edit box to be more appropriate for the maximum number of characters allowed in that cell. If Dspwid is not specified, then the _cformat_ **_** logic is used, and if that isn't specified, the edit box width will be the same as the column width. Note that in the property sheet case, the units of Dspwid are taken to be characters, rather than grid units (as in the non-property sheet case.) 

See the EXLIB:[908,21] sample programs XTRA15.BP and XTRPSH.BP for examples of property sheets.. 

## **History** 

- 2024 December, A Shell 7.0.1766:  Support _cformat_ **H** and **HH** (hidden items) in property sheet mode. 

- 2024 September, A Shell 7.0.1762:  Resolve conflict between the normal list hierarchy '@@' (enabling the use of left/right arrows for expand/contract) and '@@' meaning level 2.  See List Hierarchy. 

- 2011 January, A Shell 5.1.1202:  Added to A-Shell 

A-Shell Reference 

Page 3576 

## **XTF2_DRAGDROP2** 

This flag enables drag/drop operations between different XTREE controls. To enable, set the flag in the source tree, and specify the advanced _coldef_ option, DragDropExit=###, in the destination tree. ### is the negative exitcode to be generated when an item (or items) from the source tree is/are dropped on to the destination tree. For example, DragDropExit=150 will generate exitcode -150. 

## **Comments** 

- This form of drag/drop (inter-tree) does not require any special mapping of the _answer_ array (as is required with the intra- 

- tree drag/drop activated by XTF_DRAGDROP). 

- Both forms of drag/drop are essentially independent (you can have either one or both). 

- No distinction is made regarding the exact position of the drop within the target control. The only information returned to the 

- application will be the selection information for the source tree, and the DragDropExit exitcode from the target tree. 

- It is left to the application to complete the operation signified by the drag/drop action. Typically this would involve copying 

- the selected items from the source tree to they destination tree, and perhaps removing them from the source tree. 

The sample program XTRA4.BP in EXLIB:[908,21] has been completely rewritten to demonstrate a simple shopping cart application using this capability. 

## **See Also** 

- XTF_DRAGDROP to drag and drop within a single tree, for item re-ordering.. 

- XTF2_FILEDROP for dragging a file from an Explorer or Windows Shell dialog and dropping it on an XTREE control. 

## **History** 

- 2011 January, A Shell 5.1.1203:  Added to A-Shell 

A-Shell Reference 

Page 3577 

## **XTF2_SAVRES** 

This flag causes XTREE/PCKLST to save the screen area unless the XTROP_DELETE opcode is used, in which case it causes PCKLST to restore the area previously saved. Note that PCKLST will automatically save and restore the area of a pop-up, without using this flag, provided that the XTF_MODELESS flag is not set. If XTF_MODELESS is set, then you can set the XTF2_SAVRES flag (in 2nd 4-byte flag word, i.e. flag2) in the first call to create the list display, and again in the final XTROP_DELETE call to remove it. The flag currently does not affect XTREE (GUI mode), which does something like this automatically already. 

## **History** 

- 2011 June, A Shell 5.1.1221:  Added to A-Shell 

A-Shell Reference 

Page 3578 

## **XTF2_POPUP** 

This flag causes the tree control to be created as a popup rather than as a child control. This is mainly useful when creating an XTREE in the main window (rather than in a dialog) that may overlap other controls, and where you want those other controls to remain visible. Normally, XTREE will save and then remove any overlapping controls when it is displayed in a main window, because otherwise those controls may "bleed" through (interfering with the visual and operation aspects of the XTREE control). The feature was added primarily to improve compatibility with the text mode of PCKLST when it is used to create multiple overlapping "pick lists". That always worked fine in text mode; now it works fine in GUI mode as well. 

The flag is defined in ashinc:xtree.def as: 

```
define XTF2_POPUP = &h00010000  ! implement as popup rather than child
```

Note that the new mode constrains some of the more advanced behaviors of XTREE, so it should probably only be used in simple "pick lists" (as you have when XTREE is called by PCKLST). In particular, popup mode is incompatible with editable tree mode. 

## **History** 

- 2011 June, A Shell 5.1.1221:  Added to A-Shell 

A-Shell Reference 

Page 3579 

## **XTF2_ITEMICONS** 

_Added March 2013; see History_ 

XTREE's item icons are similar to the existing cell images ( _cformat_ type **I** ) except: 

- Item Icons are associated with items (one per item) rather than cells. 

- Item Icons are always displayed at left edge of the item row. 

- For multi-level trees, you can define a set of three item icons (in the 'zero column') corresponding to the three types of multi- 

- level items (expandable, expanded, and leaf). In this case the icon will automatically change when an expandable item is toggled between expanded and collapsed. 

• To specify individual icons for specific rows (rather then use just the expandable/expanded/leaf icons), you create a column using the new _cformat_ code **i** to hold the icon spec. Unlike the **I** image column, which can contain both an image spec and display text, the **i** column only contains the image spec. Also, unless you want to display the image spec as text, the **i** column should be hidden, i.e. **iH** . 

Note that despite the terminology difference (icons versus images), you can use either type of image in either case (i.e. discrete image files, including .ico files, and icons embedded in a DLL, e.g. folder::ashico1). We use the term "icons" here to clarify that these images are meant to act like icons (i.e. be small, fixed in size, and symbolize some attribute of the item). 

To activate item icons, specify the new flag XTF2_ITEMICONS in the flags2 parameter. By default, XTREE will use the following images for the icons: 

```
%MIAME%\icons\FldCls_16.png     (16x16 closed folder)
```

```
%MIAME%\icons\FldOpn_16.png     (16x16 open folder)
```

```
<internal blank icon>           (no icon for the leaf items)
```

You can override the choice of icons by specifying an advanced _coldef_ option containing image specifications (any A-Shell supported type) for the three types of multi-level items: 

```
ItemIcons=closed-img,opened-img{,leaf-img}
```

A-Shell Reference 

Page 3580 

Note that if the tree is not multi-level, all of the items are considered leaf items and thus would receive the icon corresponding to the leaf items; the icon specified for expandable and expanded items would be ignored. 

Three additional new Advanced Coldef Options may also be associated with ItemIcons: 

```
ItemIconDir=<default image directory>
```

```
ItemIconSiz=iwidth,iheight,bpp
```

```
ItemIconCount=<# icons to load>,<grow-by-value>
```

These are analogous to the ImgDir, ImgSiz and ImgCount options associated with "I" image columns, except here they are all optional. 

The default for the ItemIconSiz option is 16,16,24 (i.e. 16x16 image size and 24 bpp). 

The ItemIconCount option is only applicable when you are have an "i" column in order to specify individual item icons (beyond the three defined in the ItemIcons option). 

A blank cell within an "i" column will default to using the icon for that type of item (defined explicitly or implicitly by the ItemIcons option). In order to override the default icon with a blank icon, you can use the special icon specification "#". 

The sample program XTRA21 in EXLIB:[908,21] illustrates a number of variations of ItemIcons. 

The standard distribution now includes FldCls_16.png, FldOpn_16.png and Leaf_16.png icons in the icons subdirectory. 

## **History** 

- 2013 March, A Shell 6.1.1340:  Function and documentation added to A-Shell 

A-Shell Reference 

Page 3581 

## **XTF2_NOAUTOFILTER** 

_Written August 2023_ 

This flag allows applications to disable the AutoFilter feature no matter how it was enabled. Since it can be enabled via global settings in the MIAME.INI—see `OPTIONS=XTAUTOFILTER` —this allows applications to disable the feature for a single tree at a time. Some reasons you might want to disable it is to avoid end user confusion in places where filtering doesn't make sense, such as in multi-level trees (where filtering only affects the top level), or in extremely large trees (to reduce overhead), or simply for testing purposes. 

## **History** 

- 2023 August, A Shell 6.5.1730:  Function and documentation added to A-Shell. 

A-Shell Reference 

Page 3582 

## **FILE** 

This specifies a sequential file to be used for input instead of the _array_ parameter. When non-null, the interpretation of _array_ , _addcnt_ , and _answer_ parameters changes as follows. 

If neither the multiple selection (XTF_MSEL) nor XTF_FILANS flags are set, then _array_ becomes an ordinary string, which is used to pass in the default selection (text) and to get back the item chosen by the user, and _answer_ is ignored. Note that here the default selection mechanism works only on the first column; if its cells are not all unique, you may not end up with the desired item selected. The workaround is to use XTF_FILANS to select the default by row number, or to add a first column that is unique. 

If XTF_MSEL is not set but XTF_FILANS is set, then _array_ is still treated as an ordinary string which returns the text of the item chosen, but _answer_ is used exactly as in array mode (to return the row number of the selected item, and to pass in the default row number). 

If the multiple selection flag (XTF_MSEL) is set, then _array_ is ignored and _answer_ is treated as an array of one byte selection flags, exactly as for multiple-selection array mode. _addcnt_ should be set to 0 to load the entire file, or else set to the number of records (lines) to be loaded. 

The default selection process (in single-selection mode) works only on the first column. If the cells in the first column are not all unique, then you may not end up with the desired item selected. The only workaround is to add a first column that is unique, or to switch to the array mode, which identifies selections by the array index. Also note that XTREE supports the PCKLST "hidden text" feature, which allows you to pass hidden text in the last column of the data by preceding it with a \. Although this technique is useful for associating control information with list items without having to display it, a better way to do this with XTREE is to just define a hidden column. The \hidden text feature is preserved just for compatibility with PCKLST. 

XTREE supports the PCKLST "hidden text"feature, which allows you to pass hidden text in the last column of the data by preceding it with a backslash ("\").  Although this technique is useful for associating control information with list items without having to display it, the feature is support merely for backward compatibility with PCKLST and is otherwise deprecated. The preferred approach to embedding hidden data with XTREE is to define a separate hidden column. Note that in CSV mode (a variation of file mode; see XTF2_CSV), the special treatment of the backslash applies to every column, not just the last. To treat the backslash as a normal data character, use the advanced Coldef feature XTF_COLDFX and add the "\" code to the _Cformat_ specification for any column. 

A-Shell Reference 

Page 3583 

## **MMOCLR** 

As in PCKLST, may be used to specify colors for various parts of the pick list, although in the GUI mode, the interpretation of color –1 is slightly different. Instead of specifying the current foreground or background color, it specifies the Windows default color for that particular part of the pick list display. (This will result in a typical-looking list box with black text on a white background, while the column headers are gray buttons.) The format of MMOCLR is: 

## `MAP1 MMOCLR` 

```
MAP2 BFCLR,B,1,-1    ! Border Foreground (NA in GUI mode)
```

```
MAP2 BBCLR,B,1,-1    ! Border Background (NA in GUI mode)
```

```
MAP2 TFCLR,B,1,-1    ! Text Foreground (default black)
```

```
MAP2 TBCLR,B,1,-1    ! Text Background (default white)
```

```
MAP2 AFCLR,B,1,-1    ! Arrow Foreground (NA in GUI mode)
```

```
MAP2 ABCLR,B,1,-1    ! Arrow Background (NA in GUI mode)
```

```
MAP2 PFCLR,B,1,-1    ! Title Foreground (default black)
```

```
MAP2 PBCLR,B,1,-1    ! Title Background (default gray)
MAP2 WFCLR,B,1,-1    ! Warnings & messages Foreground (NA in GUI)
```

```
MAP2 WBCLR,B,1,-1    ! Warnings & messages Background    "  "
```

```
MAP2 SFCLR,B,1,-1    ! Orig. Status line Foreground      "  "
```

```
MAP2 SBCLR,B,1,-1    ! Orig. Status line Background      "  "
```

```
MAP2 RFCLR,B,1,-1    ! Reserved (unused) Foreground      "  "
MAP2 RBCLR,B,1,-1    ! Reserved (unused) Background      "  "
```

A-Shell Reference 

Page 3584 

The individual fields within MMOCLR are shown above initialized to -1, which is what you must do to get default colors, since color 0 is black. (Specifying MMOCLR with all the fields un-initialized will result in a not-very-interesting black on black display.) Note that the colors for individual columns can be overridden using the **advanced** form of the _coldef_ parameter. 

Since the XTREE color scheme is largely standardized by Windows conventions, and may be customized by _coldef_ options, in most cases the MMOCLR parameter is superfluous and may be replaced by a literal 0 in the parameter list, e.g.: 

```
xcall XTREE,srow,scol,answer,array,count,coldef,exitcode,erow,ecol,flags,file,0,xtrctl
```

A-Shell Reference 

Page 3585 

## **XTRCTL** 

_Updated April 2022_ 

This is a structure containing various extended parameters and options. If omitted, suitable defaults will be supplied, although that will severely limit the capabilities of the tree control. For those parameters which are essentially Boolean options, 0=false and 1=true. Most of the fields in XTRCTL are input-only, but a few, such as COLUMNACTIVE are updated as well, and some are output-only; these are indicated with "[in/out]" or "[out]" in the following table, which lists the structure members alphabetically for easy reference. To use the XTRCTL structure in your program, include the xtree.sdf and xtree.def files and then map an instance of the structure for each XTREE in the program, e.g.: 

```
MAP1 XTR, XTRCTL                ! define instance of XTRCTL structure named xtr
```

```
...
```

```
XTR.OPCODE = XTROP_CREATE
```

```
XTR.CTLNO = -1
```

```
etc.
```

Or include the xtree.map file which includes actual map statements for XTRCTL (rather than a structure definition); in that case, members would be assigned as follows: 

```
XTR'OPCODE = XTROP_CREATE
```

```
XTR'CTLNO = -1
```

```
etc.
```

Note that the first method (declaring an instance of the defined structure XTRCTL and using the structure dot member notation) has the advantage of making it easy to define and maintain separate copies of the structure for multiple XTREEs. 

By convention in this document, we refer to the members of the XTRCTL structure using structure.member notation, as if you had declared an instance of the structure XTRCTL named XTR, as in the example above. 

A-Shell Reference 

Page 3586 

|**Symbol**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|CLOSEDENDED|B,1|in|Set size of last column to "open ended" or fixed.|
|COLID|B,1|in|Associate column with a numeric ID.|
|COLORDER<br> (31)|B,1|in/out|Array indicating the display order of the first 31 physical columns. For example,<br>COLORDER(3)=7 would indicate that physical column 7 is actually in display<br>position 3.  Supports up to 127 physical columns. The 8th bit (values 128+)<br>indicates the physical column (-128) is hidden.|
|COLUMNACTIVE|B,1|in/out|Col # with focus (for kbd search)|
|COLUMNSORT (3)|B,1|in/out|Array indicating physical column numbers for up to to three sort levels. See<br>SORTORDER(3).|
|CTLID|B,2|out|Returns standard control ID of XTREE control (allowing access by AUI_CONTROL)|
|CTLNO|B,1|in/out|Specifies which XTREE control to use.|
|DELCTLID|B,4|in|Control to delete when XTREE load is complete; used with progress/lifesigns.|
|EXPANDLEVEL|B,1|in|0=collapse, #=expand through level # (9 max)|
|FILTERED|B,1||Returns 1 if one or more display rows had been removed through filtering upon|



A-Shell Reference 

Page 3587 

|**Symbol**|**Type**|**I/O**|**Description**|
|---|---|---|---|
||||exit from the tree.|
|FLYBY|B,1|in|Fly-by highlighting? 0=no, 1 = first column, 2 = entire row.|
|FOOTERSTYLE|B,1|in|Controls the display and style of column footers.|
|GRIDSTYLE|B,1|in|0=vert solid, 1=horz solid, 2=both, 3=vert dotted, 4=horz dotted, 5=both. See<br>XTR.SHOWGRID.|
|HEADERSTYLE|B,1|in|Column header style flags|
|HIDEHEADER|B,1|in|Hide headers? (0=no)|
|ITEMLINES|B,1|in|Display lines per item.|
|KBDSTR|S,10|in|Click code.|
|LEFTINDEX|B,1||Left-most visible column|
|LEFTPANECOLS|B,1|in|Number of columns in left pane.|
|LEFTPANEWIDTH|B,1|in|Width of left pane.|



A-Shell Reference 

Page 3588 

|**Symbol**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|MISCFLAGS|B,1|in|Miscellaneous flags (overlays XTR.TRUNCATED, which is now deprecated).|
|MISCFLAGS2|B,1|in|Miscellaneous flags2.|
|NFSELSTYLE|B,1|in|Determines how selected item(s) are highlighted, mostly when tree is inactive|
|OPCODE|B,1|in|Opcode.|
|PARENTID|B,2|in|ID of parent of control (e.g. a dialog). To specify parent by its alphanumeric<br>control name, set XTR.PARENTID to zero and add the ParentID=<name> clause<br>to any column; seeAdvanced Coldef Options<br>.|
|ROWHDRSTYLE|B,1|in|Options related to row headers. SeeSHOWROWHDR<br>. The style flags are the<br>same as those used forXTR.HEADERSTYLE<br>.Sample image here.|
|SCROLLTIPS|B,1|in|Show scroll tips (0=no).|
|SEARCHMODE|B,1|in|Options for implicit selection based on typing.|
|SELECTAREA|B,1|in|Clickable area and style.|
|SHOW3D|B,1|in|Use 3D style? (0=no).|



A-Shell Reference 

Page 3589 

|**Symbol**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|SHOWBUTTONS|B,1|in|Control visibility of the expand/collapse (+/-) button for multi-level trees.|
|SHOWBUTTONS0|B,1||No longer used. SeeSHOWBUTTONS<br>.|
|SHOWFOOTER|B,1|in|See FOOTERSTYLE<br>.|
|SHOWGRID|B,1|in|Show grid lines (0=no, 1=yes).Sample image here.|
|SHOWROWHDR|B,1|in|Determines whether row headers are displayed.|
|SKEY|S,10|in|Search key.|
|SORTORDER (3)|B,1|in/out|Array indicating sort order corresponding to the 3 sort levels specified in the<br>COLUMNSORT(3) array. 0=ascending, 1=descending.|
|SYNCCTLNO|B,1|in|CTLNO (+1) of a second 'scroll slave' tree. SeeSync Scrolling<br>.|
|TARGETCOL|B,1|in/out|Column of "target" cell; seeTARGET<br>.|
|TARGETROW|B,4|in/out|Row of "target" cell; seeTARGET<br>.|
|TIMEOUT|B,4|in|Timeout (ms).The timer is reset after each keystroke and after each mouse<br>event; you can avoid the timeout by just wiggling the mouse. If the timer|



A-Shell Reference 

Page 3590 

|**Symbol**|**Type**|**I/O**|**Description**|
|---|---|---|---|
||||expires, XTREE will return EXITCODE=11 like INFLD timeout.|
|TOPINDEX|B,4|in/out|Force the initial display vertical scroll position.|
|TREELINESTYLE|B,1||Style of lines linking child lines to parent: 0=none, 1=solid, 2=dotted|
|TRUNCATED|B,1|in|Deprecated, replaced byMISCFLAGS<br>. Show dots if text truncated?|
|USECOLORDER|B,1|in|Use COLORDER() to reorder? 1=yes, requires USRCFG=0.|
|USETHEMES|B,1|in|Use Windows themes? (0=no)|
|USRCFG|B,1||Used forSaving User Adjustments<br>.|
|XCOL|B,1|in/out|Column of last cell to have the focus (see TARGETCOL).|
|XNAVCOD|B,1|in/out|Used in cell editing|
|XNAVMASK|B,1|in/out|"    "     "    "|
|XROW|B,4|in/out|Row of last cell to have the focus. SeeTARGET<br>.|



A-Shell Reference 

Page 3591 

|**Symbol**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|XVALIDATE|B,1|out||
|||||



A-Shell Reference 

Page 3592 

## **XTR.OPCODE** 

## `XTR.OPCODE` determines the operational mode, from one of the following choices. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTROP_CREATE|0|(0) Normal usage. Create a new control.|
|XTROP_REPLACE|1|(1) Use existing control but replace data within it|
|XTROP_APPEND|2|(2) Append data to an existing control|
|XTROP_DELETE|3|(3) Deletes anXTREEcontrol, and is only necessary when the control was created with the<br>TXF_MODELESS flag (otherwise it is deleted automatically). Note that you can also delete the<br>XTREEcontrol (like any other control) by clearing the screen with Tab(-1,0) or by deleting the<br>parent dialog.|
|XTROP_RESELECT|4|(4) Reselect from an existing control|
|XTROP_DELSEL|5|(5) Delete selected rows|
|XTROP_PRINT|6|(6) Print and print preview via APEX|
|**Definition file: ashell.def**|||



A-Shell Reference 

Page 3593 

## **XTROP_CREATE** 

In this, the "normal" usage mode, a single XCALL XTREE causes the control object to be created and loaded with data. Unless the XTF_NOSEL flag is specified, the control will then receive the focus and wait for the user to perform an action that causes it to exit. On exit, unless the TXF_MODELESS flag is set, the control is deleted. If both XTF_NOSEL and XTF_MODELESS flags are set, the operation is essentially _display_ —i.e. create the tree if necessary, configure it, load the specified data, display it, and return. 

You may specify the XTREE control number (0-31) in XTR.CTLNO or or set it to -1, in which case the next available XTREE control control number will be used (and returned in `XTR.CTLNO` ). If an XTREE control already exists with the specified number, the opcode will effectively be converted to XTROP_REPLACE, except that certain optimizations will be adjusted to work better for the case of a complete replacement of the tree contents—whereas XTROP_REPLACE is normally optimized for the case where only some of the data elements are changing. 

A-Shell Reference 

Page 3594 

## **XTROP_REPLACE** 

The XTROP_REPLACE operation allows you to replace the contents of an existing tree, without actually deleting the tree and recreating it. This is similar to XTROP_CREATE, except that it is optimized for the case where the new tree contents are similar to the old (same layout with minor additions/deletions/changes, as opposed to a complete new tree configuration). If the changes are particularly minimal, you can specify the XTF_NOREDRAW flag to minimize the visual "flash" that otherwise may occur when the various visual attributes are recreated and re-optimized. 

## **ATE Notes** 

When using opcode XTROP_REPLACE in array mode, the server side of XTREE compares the new data Array with the old and applies two optimizations designed to minimize the amount of data sent between the server and ATE client. If the data is completely unchanged, it switches to XTROP_RESELECT, which eliminates the need to transmit or re-load the new data array entirely. Otherwise, if only a few rows have changed, then only those rows are transmitted and re-loaded. These optimizations are mostly useful in situations where cell-to-cell movement causes an exit and reentry, and you are obligated to use XTROP_REPLACE rather than XTROP_RESELECT because you have to make minor changes (such as updating a few other cells in response to a cell editing change), or you can't be sure if the data actually changed because you have to recreate the data from primary sources. A multi-user appointment scheduler would be an example of the latter, where you have to reload the schedule data from the database because you don't know if another user made a change in the meantime. 

These optimizations have evolved over the period from edits 1150 to 1200, the server and client coordinate with each other to use only the optimizations that both understand, but work best when both sides are at the newest level. 

A-Shell Reference 

Page 3595 

## **XTROP_APPEND** 

The append operation is just like replace, except that the data passed in the source array or file is appended to the existing data in the control. In the case of array mode, the best way to handle this is to define an array large enough for all the items. For example, you might plan on a maximum of 1000 items, but initially load only 50. If you then append another 75, put them in the array positions from 51 to 125, and specify ARRAY(51) as the Array parameter and 75 for the Itemcount parameter. This way, your array continues to correspond to the current state of the list, so that you can make sense of the returned selection information. 

**Warning:** XTROP_APPEND is incompatible with cell editing. If you want to append rows to a tree that has editable cells, you should do it in two steps: 

- Do the append with the XTF_NOSEL flag added, which will cause the operation to exit immediately without waiting for a selection 

- or for any cell editing. 

- Use XTROP_RESELECT to resume editing the expanded set of rows. 

The alternative would be to just add the new rows to your data and answer arrays, then use XTROP_REPLACE with Itemcount set to the new total number of rows. As a result of various optimizations to XTROP_REPLACE since XTROP_APPEND was first introduced, the overhead of the replace operation is probably little different from the append anyway. 

A-Shell Reference 

Page 3596 

## **XTROP_RESELECT** 

The XTROP_RESELECT operation is used to re-enter (i.e. put the focus on) an existing (modeless) tree. It is similar to the create, replace, and append operations except without the overhead of recreating/reconfiguring the control or reloading the data. The Array or File parameter is ignored. For editable trees, the Answer array is processed though, allowing you to make changes to the context or attributes of the corresponding cells. For example, after the user makes changes to one cell, causing the tree to exit, the application may make additional changes to related cells prior to putting the editing focus on the next cell. 

For non-editable trees, the initial selection(s) is/are typically determined by the Answer parameter. For editable trees, the `XTR.TARGETROW` _,_ `XTR.TARGETCOL, XTR.XNAVOD` and `XTR.XNAVMASK` parameters in the XTRCTL structure typically determine the position of re-entry. The primary exception to the typical case is when the last event for the tree in question was a click that generated an _exitcode_ when the tree was inactive/unfocused, the location of the click will take precedence over the answer or `XTR.XXX` parameters. The scenario is as follows. Imagine that some control has the focus, say, an input field. The user then clicks on an XTREE that was inactive. This generates an exitcode (based on the XTR.KBDSTR field of the clicked-on tree), causing the input field to exit. The user's expectation would be that the tree would become active, with the row or cell clicked on being selected. The application can tell from the exitcode which control (or which tree) was clicked, but it can't tell which row or cell was clicked, so it can't set up the answer or `XTR.XXX` parameters to start with that row or cell selected. However, the tree itself has local memory and can remember the the fact and location of the prior click event; it uses that information to override the selection coordinates passed by the application. In cases where you don't want that feature, you can set the XTR2_CLRDEFER bit in the XTREE Flags2 parameter. 

The XTRA4 and PCKMNU programs in EXLIB:[908,21] illustrate this. 

A-Shell Reference 

Page 3597 

## **XTROP_DELSEL** 

This opcode deletes just the row(s) identified by the Answer parameter. It acts similarly to XTROP_RESELECT, not loading any new records. But instead of selecting the row(s) identified by _answer_ , it deletes them. It then waits for a new selection, unless the XTF_NOSEL flag is set, in which case it exits immediately. Note that the original data rows are not internally renumbered, so if you are trying to keep your internal array synchronized with the control, you should only mark the items deleted but not compact the array. For example, if you delete item #2, then reselect from the same array, item #3 will appear in position #2 on the screen, but if you select it, it will still be identified as item #3. 

XTROP_DELSEL will mainly be of use in situations where you have a large number of items, making it inefficient to delete and reload the entire control each time you want to get rid of one. This would be particularly true if you did not really need to keep track of the items being deleted within the context of the original array. (For example, you might start with a list of possible items to choose from, and then as you choose them, they are deleted from that list and moved to another list, like in a shopping cart application. You do not really need to keep track of the state of the original list, because when the order is confirmed, you would work from the list of chosen items, rather than from the list of available items.) 

See the sample program XTRA4 for an illustration of moving items between two XTREE controls. 

A-Shell Reference 

Page 3598 

## **XTROP_PRINT** 

This option invokes a variation of the APEX Print/Preview facility to allow the contents of the specified XTREE to be printed, with an initial print preview mode. Sample image here. 

Unfortunately this cannot be invoked in such a way as to allow the XTREE data to be merged with other application-generated data in the same report, but may still be a useful utility function. Note that you can also invoke the operation from the special control dialog reachable via CTRL+SHIFT+DOUBLE-RIGHT-CLICK. 

## **Notes** 

Normally, XTROP_PRINT is used to print an existing TREE control, which is referenced via the XTR.CTLNO parameter. In this case, the print-related options will already have been established when the tree was created, and the _coldef_ parameter passed with the XTROP_PRINT call will not be processed. Thus, any print-related flags such as XTF2_LANDSCAPE, and _coldef_ options, such as Title need to be established when the tree is created, not when it is printed. 

If you want to adjust the tree configuration prior to printing, it is best to set `XTR.CTLNO` to -1 to create a new instance of the control just for printing. In this case, all of the parameters will be processed, just as they would with XTROP_CREATE. This method requires 5.1.1156+. 

The printing logic ignores columns that do not fit within the width of the page. (In order to print additional columns, you would need to recreate the tree using the technique mentioned above, with alternate column layouts.) 

To adjust the page headers and footers when printing from XTREE, see the Advanced Coldef Options topics "Footer" and "Title.". 

A-Shell Reference 

Page 3599 

## **XTR.CTLNO** 

When multiple XTREE controls are in simultaneous use, specifies which one (range is 0 to 31) to use for this call. If XTR_OPCODE = XTROP_CREATE, you can set `XTR.CTLNO` to –1 to have XTREE automatically assign the next available control number. If the control is modeless, you will need to save the returned `XTR.CTLNO` value for referencing it in subsequent calls. 

Note: `XTR.CTLNO` enumerates/identifies only the XTREE controls, using a numbering scheme only meaningful to XTREE. See `XTR.CTLID` for the standard control ID (which can be specified in the AUI_CONTROL ctlid parameter) to perform standard control operations on the XTREE control such as hide, move, etc. 

Here is an illustration of multiple XTREEs on the screen at once, for which you absolutely need to keep unique `XTR.CTLNO` values. 

A-Shell Reference 

Page 3600 

## **XTR.COLID** 

_Modified September 2021_ 

This option allows you to associate a column with a numeric ID which is not affected by either the physical column number (position in the _coldef_ array) or logical column number (display position). This can be potentially useful for associating validation or other column-related logic with columns in trees containing many editable columns, especially during development, when the column numbers are likely to be fluid. 

To associate an ID number with a column, add the Advanced Coldef Option to its _coldef_ definition: 

## `ID=###` 

where ### is an integer in the range of 1-255, e.g. ID=25. 

On exit from the tree, the XTR.COLID field in the XTRCTL structure will be set to the column ID corresponding to the physical column set in XTR.XCOL, i.e. the exit column (if relevant). 

## **History** 

- 2020 September, A Shell 6.5.1689: Feature added to A-Shell. The XTRCTL map and structure definitions in XTREE.SDF and XTREE.MAP have been updated according. The end of the structure now looks like this... 

```
defstruct XTRCTL         ! extended XTREE parameters
```

```
        map2 OPCODE,B,1             ! 0=normal (create), 1=replace data,...
```

```
        map2 CTLNO,B,1              ! 0=1st pcklst ctl, 1=2nd, 2=3rd
```

```
        map2 ITEMLINES,B,1          ! max # dsp lines of text per item
```

```
        map2 TREELINESTYLE,B,1      ! 0=none,1=solid,2=dotted
```

```
    ...
```

```
    ...
```

```
        map2 SHOWROWHDR,B,1         ! [131] see XTRHF_xxx
```

```
        map2 CTLID,B,2              ! [133] A-Shell ctl #
```

A-Shell Reference 

Page 3601 

```
        map2 LEFTINDEX,B,1          ! [137] Left-most visible column
        map2 SHOWFOOTER,B,1         ! [138] Show footer
        map2 FOOTERSTYLE,B,1        ! [138] same XTHSF_xxx flags as HEADERSTYLE (6.3.1537+)
        map2 COLID,B,1              ! [140] column ID
        map2 UNUSED2,X,12           ! [142] unused
                                    ! (total size = 128)
```

```
EndStruct
```

Note that there is no requirement to define column ID's for every column, nor any rule against using the same ID for multiple columns, which might make sense if they share common validation or other processing logic. 

A-Shell Reference 

Page 3602 

## **XTR.ITEMLINES** 

_Updated June 2013; see History_ 

For XTREE controls with variable height items (XTF_VARY), specifies the maximum number of lines of text that will be displayed for a single item. For fixed height items—i.e. when the XTF_VARY flag is not specified)— `XTR.ITEMLINES` determines the display height of every row. Sample image here. 

|**Value**|**Description**|
|---|---|
|-1<br>or 255|Produces a row height equal to that needed for editable cells, which<br>is typically about one and a half rows high. (This is automatic when<br>the tree contains editable cells.)|
|-2|Adjust row heights to largest row font (+4 pixels leading)|
|-3|Same as -2 but with only 3 pixels of leading|
|-4|Same as -2 but with only 2 pixels of leading|
|-5|Same as -2 but with only 1 pixel of leading|
|-6|Same as -2 but with no extra leading|
|-8|See History|



**History** 

A-Shell Reference 

Page 3603 

- 2013 June, A Shell 6.1.1354:  Add support for -8. Although -6 theoretically provides no extra leading, it turns out that when using the XTF_VARY flag, the rows are more tightly spaced than `XTR.ITEMLINES = -6` (without XTF_VARY); `XTR.ITEMLINES = -8` comes closer to the emulating the XTF_VARY spacing. 

- 2012 April, A Shell 6.0.1248:  Add support for -3, -4, -5, -6 

- 2011 September, A Shell 5.1.11233:  Add support for -2 

A-Shell Reference 

Page 3604 

## **XTR.SELECTAREA** 

_Update August 2018; see History_ 

This field actually encodes two separate parameters for related sets of options. One defines the area in which you may click to make a selection, and the other defines how the selection is highlighted. Choose one from the Area options and one from the Style options: 

## **Area Options** 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTRSEL_AREA_ANY|&h0000|Anywhere on row, including tree lines, row headers|
|XTRSEL_AREA_CELLS|&h0001|Any cell of row|
|XTRSEL_AREA_CELL1|&h0002|Only first cell of row|
|XTRSEL_AREA_CELL1T|&h0003|Only text in first cell of row|



## **Style Options** 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTRSEL_STY_ALL|&h0000|Highlight entire row|
|XTRSEL_STY_CELLS|&h0010|Highlight all cells of row|



A-Shell Reference 

Page 3605 

|**Symbol**|**Value**|**Description**|
|---|---|---|
||||
|XTRSEL_STY_NONE|&h0020|Eliminates the blue selection bar, in which case the only indication of which is the<br>current item will be a dotted outline around the contents of the first cell. Why<br>would anyone want to make the selected item hard to see? Because in trees which<br>operate more as grids, the blue highlighted cell in the first column may be<br>confusing or aesthetically incongruous. Note that this only applies to single-select<br>trees.|
|XTRSEL_STY_CELL1|&h0030|Highlight first cell only|
|XTRSEL_STY_CELL1T|&h0040|Same as XTRSEL_STY_CELL1 but highlight only the text (rather than the entire<br>cell).|
|XTRSEL_STY_ALL_GRD|&h0050|STY_ALL + gradiant; see Note 1, below|
|XTRSEL_STY_CELLS_GRD|&h0060|STY_CELLS + gradiant; see Note 1, below|
|XTRSEL_STY_CELL1_GRD|&h0070|STY_CELL1T + gradiant; see Note 1, below|
|XTRSEL_EDIT_KEEP|&h0080|Keep the first column selection indicator (blue bar) on during editing. Depending<br>on the tree layout and other factors, you may find this more aesthetically pleasing.<br>In particular, it reduces the "flash" when cell-to-cell movement requires exit/re-<br>entry. See History.|



A-Shell Reference 

Page 3606 

Note 1: These are equivalent to the existing options (without the _GRD suffix) except that if the version of Windows supports the GDI+ subsystem, the selection bar is turned into a gradiant with a dotted outline. (Eye candy) 

## **History** 

- 2018 August, A Shell 6.5.1644:  XTREE refinement:  XTR.SELECTAREA bit XTRSEL_EDIT_KEEP now works with the other XTRSEL_SEL_xxx (selection bar) styles, preserving the entire selection bar display during editing. For example, 

```
XTR.SELECTAREA = XTRSEL_AREA_ANY or XTRSEL_STY_ALL or XTRSEL_EDIT_KEEP
```

will leave selection bar highlighting the entire row during editing. Note that this is a visual change from the prior interpretation, in which XTRSEL_EDIT_KEEP acted like XTRSEL_STY_CELL1 during editing, highlighting just the first cell on the row. To get the old behavior, 'OR' the two together—i.e. XTRSEL_EDIT_KEEP or XTRSEL_STY_CELL1. 

Also note that in the case of gradient selection style, the style is temporarily changed to the normal selection bar during editing and then changed back to the gradient style during selection. 

A-Shell Reference 

Page 3607 

## **XTR.KBDSTR** 

_Updated April 2014_ 

This field may be used to specify a click string (see Virtual Key Symbolic Names) to generate an exitcode when the XTREE control is clicked while inactive, e.g. "VK_xrF401". Since the field is only ten characters long, to allow for longer forms of the click string to be used, the initial "VK" may be omitted, e.g. "_xrF401". 

For standard click strings, although the exitcode does not capture information about the specific location of the click within the control (i.e. row and col), this information is made available internally to the target control so that when the application activates it, the control has the possibility of responding to the location, for example, to select the row clicked on. For single-selection trees, in order for this to work, you must set the answer parameter to 0, otherwise the specified answer value will override the clicked row to determine the new selection. For multi-selection trees, the clicked row will be added to the existing selections. An extended from of the click string (described below) allows the exitcode to be customized to indicate the row and/or column where the click occurred. 

## **Coordinates on Inactive Trees** 

You may also use `XTR.KBDSTR` to retrieve row and/or column coordinates of click events on inactive trees, by coding the `XTR.KBDSTR` field as follows: 

## `_x{r}{d}F##{R..R}{C..C}` 

In other words, using the standard Virtual Key Symbolic Name syntax, except with the leading "VK" removed, and with some of the numeric digits at the end replaced with a string of zero or more "R" characters (representing row digits) and zero or more "C" characters (representing column digits). For example: 

## `_xF1RRRC` 

The above format would return exitcodes in the range of -10000 thru -19999 where the last digit represented the column clicked on (1-9) and the next three digits to the left represent row clicked on (1-999). So -10493 would indicate that the user clicked on row 49, column 3. -10000 would indicate some kind of click event that wasn't specifically on a particular cell. 

```
_xrF2RRRR
```

A-Shell Reference 

Page 3608 

The above would be useful in cases where you just wanted the row number, and would return exitcodes from -20001 to -29999 for rows 1 thru 9999. As with standard extended virtual key codes, the "r" in between the "_x" and "F" indicates that right clicks will be distinguished by returning a positive exitcode value rather than negative. 

```
_xF5CC
```

The above example returns exitcodes -501 thru -599, representing clicked columns 1 thru 99. 

## **See Also** 

- Clicks on Inactive XTREEs 

- Sample program XTRA4.BP in EXLIB:[908,21]. 

## **History** 

- 2013 October, A Shell 6.1.1383: An inactive right-click on a tree now always sends the standard left-click exitcode, regardless of whether the `XTR.KBDSTR` field contains an "r". Normally an "r" is required, e.g. "VK_xrF101", to support right click, and in that case the exitcode is positive rather than negative. But in this case, the only logical application response is to XCALL XTREE in either case, so making a distinction was just leading to application bugs. 

- 2013 March, A Shell 6.1.1345:  Add ability to retrieve row and/or column coordinates of click events on inactive trees. Eliminated 16-bit bottleneck that limited exit codes to the range of +/- 32K. If using ATE, both the server and client must be at least 6.1.1345.0 in order for XTREE to handle an inactive click exitcode from another XTREE, outside the +/- 32K range. 

A-Shell Reference 

Page 3609 

## **XTR.SKEY** 

If this field is non-null, and the current XTREE is in single-select mode, and the `XTR.COLUMNACTIVE` parameter is not zero, then the initial selection is established by searching the active column for the specified string (overriding the ANSWER parameter, which normally sets the initial selection). Note that: 

- SKEY does not require a trailing null 

- A match will succeed as long as the contents of SKEY matches the start of the data in the column (i.e. "Ab" will match "Abbey 

- Road"). 

- SKEY is not cleared or set by XTREE 

A-Shell Reference 

Page 3610 

## **XTR.TOPINDEX** 

This field may be used to force the initial display vertical scroll position. To activate the feature, set `XTR.TOPINDEX` to the desired first visible row (1=first). Once set, it will be updated on exit, so that a subsequent re-entry will enter in the same position. To disable the feature, set it to 0. Note that this will override the default logic which normally tries to position the vertical scroll so that the initially selected row is visible. 

`XTR.TOPINDEX` may be set to -1 on input in order to tell XTREE to return the new topindex on exit, but not to attempt to set it on entrance. This applies only when re-entering an existing tree with XTROP_RESELECT or XTROP_REPLACE with XTF_NOREDRAW set, and with `XTR.TARGETROW=0` . 

`XTR.TOPINDEX` is not returned relative to an inactive XTREE when the inactive tree is clicked while another tree has the focus. This was conflicting with the new-and-improved logic for handling clicks on inactive trees. The optimum way to respond to a click event on an inactive XTREE is to set `XTR.TOPINDEX, XTR.TARGETROW` , and `XTR.TARGETCOL` all to 0 before entering the clicked-on tree (using XTROP_RESELECT). 

A-Shell Reference 

Page 3611 

## **XTR.DELCTLID** 

This field may be used to specify the ID of a control that should be deleted just before XTREE updates its display and starts waiting for user input. This is handy for deleting "in progress" displays (see Animated Graphics) that you create prior to calling a large or complicated XTREE that may take more than a couple of seconds to load. See the sample program XTRA7 for an example of this. 

Note that XTEXT has an analogous field ( `TXC.DELCTLID` ) in its txtctl parameter. Most of the comments in this topic relating to `XTR.DELCTLID` and XTREE apply equally well to `TXC.DELCTLID` and XTEXT, except the xtr.miscflags linkage with the standard and custom progress bars. 

This field is declared as B,4 rather than the usual B,2 used for storing control IDs to allow for the possibility that the control you want to delete when XTREE becomes active, was actually created externally. In that case, it would not have an A-Shell control ID, but it would have a standard window handle, which you can place in this field instead of the control ID. See MX_FINDWINDOW for one possible method of determining the window handle of an externally-created control. 

## **Automatic Updating of Progress Bar During Load** 

In the case of ATE, the contents of the tree must be sent from the server to the client, which could potentially take several seconds, depending on the amount of data and the speed of the connection.  To keep the user informed of the load progress, XTREE supports an internal mechanism to update your progress bar as the data is transferred. See the XTMF_STDPRGBAR and XTMF_CUSPRGBAR flags in XTR.MISCFLAGS for details. 

## **Notes and Warnings** 

If the XTREE control has no explicit parent (i.e. its parent is the main window), then if you create a modal dialog to contain your <processing> or <in progress> display, the XTREE will by default become a child of that dialog. This will not work, because when XTREE deletes the dialog, it will end up deleting itself. Fortunately, there are multiple workarounds: 

- Make your <processing> dialog be modeless by adding the MBF_MODELESS bit to its ctype. Since modeless dialogs do not 

- automatically become the parent of controls with no explicit parent of their own, the XTREE will remain independent. 

- Do not use a dialog for your <processing> display. Instead, just use an ordinary control without a parent, just like XTREE is, 

- so that they become siblings. (You can even put it right where the XTREE would normally display.) 

A-Shell Reference 

Page 3612 

## • Put the XTREE in a dialog of its own. 

When `XTR.DELCTLID` is specified and `XTR.PARENTID` is zero, you must take care that there are no controls (aside from the `XTR.DELCTLID` control) that would be overlapped by the XTREE screen area. Normally, in this situation, XTREE will save, hide, and later restore any such controls. But doing this would cause the <processing> control to be restored on exit from XTREE (if it was overlapping). 

A-Shell Reference 

Page 3613 

## **XTR.EXPANDLEVEL** 

This field allows you to control the expanded/collapsed state of the items when the tree is created or re-entered. Set the field to a value between 0 and 63, indicating the maximum level to expand (0=all items collapsed so that only the level 0 items are visible, 63=all items expanded). You may optionally specify one of the two flags listed below: 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTEXPF_SAVE|&h40|Save current expand/collapse status on exit|
|XTEXPF_RESTORE|&h80|Restore saved status (on XTROP_REPLACE reentry)|



## **Notes** 

XTEXPF_SAVE can be used with any of the level values (0-63) in `XTR.EXPANDLEVEL` to start out with the specified uniform level of 

expansion but save the user-modified status on exit. But XTEXPF_RESTORE overrides all other options unless there was no previously saved status, in which case XTEXPF_RESTORE is ignored. 

XTEXPF_RESTORE assumes that the order of the rows has not changed since the previous exit from that tree. Since the 

expand/collapse status is associated only with the row numbers as displayed, changing the sort order on reentry would result in the wrong items being expanded or collapsed. 

## **See Also** 

- Expand/Collapse State 

## **History** 

- 2023 August, A Shell 1737:  Increase maximum number of multi-level trees from nine to 63. 

A-Shell Reference 

Page 3614 

## **XTR.COLORDER** 

This field provides a means of rearranging the display order of the first (up to) 31 columns. As background, if the XTF_REORD flag is specified (and the _cformat_ **K** is not specified on the columns in question), XTREE allows users to re-order the columns by dragging and dropping the column headers. This, combined with the horizontal scroll capability, may lead to a situation where, in order to satisfy different user desires, an application loads an XTREE with many more columns than can be seen at once, figuring that users can always scroll, or even drag the columns around as desired. But after the initial thrill wears off, the users tire of this routine and would be much happier if they could preserve their own preferred column order. The `XTR.COLORDER` array, along with the `XTR.USECOLORDER` field/option, makes this nearly trivial to support. Just set `XTR.USECOLORDER` to 1 and XTREE automatically saves the updated column arrangement in the `XTR.COLORDER()` array. All the application needs to do then is to save those 31 bytes in a user preferences file so that it can be recalled the next time the user wants to see this particular XTREE. 

## **Notes** 

`XTR.COLORDER(1)` specifies the "real" column which is displayed in the first position; `XTR.COLORDER(2)` specifies the "real" column displayed in the second position, etc. If the user shrinks a visible column to zero width, effectively making it hidden, this will be noted in the array by adding +128 to the column number. 

If you are manually using `XTR.COLORDER` to set a column order, you do not have to specify all the columns. For example, if there were 10 columns defined, you could determine which of the 10 displayed in the first three positions as follows: 

```
xtr.colorder(1) = 5     ! real column #5 will be displayed first
```

```
xtr.colorder(2) = 8+128 ! real column #8 will be second (but will be invisible)
```

```
xtr.colorder(3) = 2     ! real column #2 will be displayed third
```

```
xtr.colorder(4) = 0     ! remaining columns will retain their natural
```

(The first zero in the `XTR.COLORDER` array effectively terminates the forced part of the ordering, with the remaining columns using "natural" ordering.) 

A-Shell Reference 

Page 3615 

Unless you set the XTF_REORD bit in the _flags_ parameter, the user will not be able to reorder the columns by drag-and-drop, but that would not stop the application from using `XTR.USECOLORDER` and `XTR.COLORDER` to override the natural (or "real") column ordering. 

Changing the display order of the columns does not affect the way columns are numbered in any of the other parameters (such as `XTR.COLUMNSORT, XTR.COLUMNACTIVE` , etc.) In other words, the application does not need to be "aware" of how the columns are ordered. 

## **See Also** 

- Saving User Adjustments 

A-Shell Reference 

Page 3616 

## **XTR.LEFTINDEX** 

_Added March 2015; see History_ 

This field allows the application to control the horizontal scroll position on entering the tree. 

The field acts analogously to `XTR.TOPINDEX` , substituting the left-most visible column for the top-most visible row. When set by the application, XTREE will attempt to set the horizontal scroll so that the specified column (first column = 1) is visible at the left edge of the display window. This however will be overridden if necessary to make the target column ( `XTR.TARGCOL` ) visible, or if it is simply impossible to accommodate. 

As with `XTR.TOPINDEX` , if the `XTR.LEFTINDEX` field is non-zero on entrance, it will be updated on exit to indicate the left-most column that is partially or wholly visible on exiting the tree. Since the field resolution doesn't support fractional columns, this may result in a partial-column shift when exiting and re-entering. You can avoid that by either setting the field back to zero, or specifying the XTF_NOREDRAW flag. 

## **History** 

- 2015 March, A Shell 6.1.1306:  Field added to A-Shell 

A-Shell Reference 

Page 3617 

## **XTR.LEFTPANECOLS** 

This specifies the number of columns to be in the left pane. Note that this counts physical columns that have a non-zero data width, whether or not the column is hidden, and it is based on the order in which they are defined in the _coldef_ parameter and not necessarily the order they appear in the physical input data. So columns which use _cpos_ and _cwidth_ of zero do not count, but all other columns do—including the special column needed for multi-level support, hidden color columns, etc. 

A-Shell Reference 

Page 3618 

## **XTR.LEFTPANEWIDTH** 

_Updated August 2022: See History_ 

This may optionally specify a display width for the left pane, using the same column units used by the _dspwid_ parameter (for defining column widths). If zero, then XTREE will try to determine the optimum width by adding up the optimum display widths of the initially visible rows. You can also set it to -1 (or 255) to put the splitter bar separating the panes exactly in the middle of the XTREE. 

If you specify a size that is too wide, the left pane will initially occupy the entire XTREE but the user will still be able to move the splitter bar from the right edge to make the right pane visible. 

If you specify a negative value (other than -1), it acts the same as if it had been positive, except that the left pane horizontal scroll bar will be based on the specified width. This generally has the effect of initially graying out the scroll bar, which is usually desirable. 

## **History** 

- 2022 August, A Shell 6.5.1720:  As an alternative or workaround to the splitter position optimization logic built in to the control for split-pane configurations, which does not always work properly, you can now set XTR.LEFTPANEWIDTH = -2 to force A-Shell to use it's own manual width calculation. The manual method is less precise and slower than the logic built in to the control, but less likely to be completely wrong. 

A-Shell Reference 

Page 3619 

## **XTR.CLOSEDENDED** 

This field in XTRCTL allows toggling between the open-ended and closed-ended modes for the last display column. In the default open-ended case ( `XTR.CLOSEDENDED=0` ), the last column expands automatically as needed for the longest cell contents, or to fill the width of the tree, whichever is wider. This effectively disables wrap on the last column, since when adding text, you never hit the right edge. A horizontal scroll bar will be added automatically if the contents of the open-ended last column results in the combined column widths being greater than the tree display width. 

In the closed-ended case ( `XTR.CLOSEDENDED=1` ), the final column width is calculated in the same way that all the other column widths are calculated, which may result in empty space between the end of the last column and the edge of the tree. To eliminate that empty space and distribute it amongst the columns,specify the XTF2_AUTOEXPCOL bit. 

## **Examples** 

`XTR.CLOSEDENDED=1` , without XTF2_AUTOEXPCOL: 

`XTR.CLOSEDENDED=1` , with XTF2_AUTOEXPCOL: 

A-Shell Reference 

Page 3620 

## **XTR.XVALIDATE** 

_Modified October 2015; see History_ 

|**Value **|**Description**|
|---|---|
|1|Value will be set to 1 if the cell indicated by`XTR.XROW`and`XTR.XCOL`needs validation. Previously you had to rely<br>on exitcode -48 to identify when validation was needed, but this is not adequate when the event which terminates<br>an editable cell operation is a click on another control that generates its own exitcode. In that case, the exitcode<br>returned to the application will be that of the clicked-on control, and the`XTR.XVALIDATE`flag will be handy to<br>indicate that the cell identified by`XTR.XROW`and`XTR.XCOL`needs to be validated.|
|2|In some cases, the cell which needs to be validated is not the one that last had the focus, i.e. the one referenced<br>by`XTR.XROW / XTR.XCOL`, but the one which gets the focus, i.e.`XTR.TARGETROW / XTR.TARGETCOL`. This is often<br>the case with checkboxes, which exit for validation only when checked, and is always the case with read-only<br>editable cells, which exit for validation just before they get the focus. In these cases,`XTR.XVALIDATE`will be set to<br>2.|
|3|This could have two possible meanings, depending on the context. One possibility occurs when clicking out of a cell<br>that requires post-validation and into a cell that requires pre-validation or validation-on-click, in which case it<br>means that both the`XTR.XROW / XTR.XCOL`and`XTR.TARGETROW / XTR.TARGETCOL`cells need validation. The other<br>possibility is that the user selected the $CBSET, $CBRST, or $CBUNDO command from a PopupMenu to set, reset,<br>or undo the state of all the checkboxes in the current column.|
|4|Indicates that the user clicked on a $CBSETDEP or $CBRSTDEP PopupMenu command to set or reset the<br>dependent checkboxes for the current item.|
|5|In an editable tree without validation, a value of 5 indicates that at least one cell was changed during the session.|



A-Shell Reference 

Page 3621 

See XTR.TARGET... for some detailed examples of validation scenarios. 

## **History** 

- 2013 October, A Shell 6.1.1363: The PopupMenu options $CBSET, $CBRST, and $CBUNDO now return EXITCODE=-48 and `XTR.XVALIDATE=3` when validation (conditional or unconditional) is active for the column. $CBSETDEP and $CBRSTDEP return `XTR.XVALIDATE=4` . 

- 2015 October, A Shell 6.1.1420: Add value 5. 

A-Shell Reference 

Page 3622 

## **XTR.TARGET** 

`XTR.TARGETROW` and `XTR.TARGETCOL` are used in conjunction with `XTR.XROW` and `XTR.XCOL` and cell editing to identify the cell that should next get the focus, or a click on which was responsible for forcing XTREE to exit. If `XTR.XVALIDATE` = 2 or 3, then this cell should be validated before re-entry. See Typical Cell Editing Scenarios for examples and more information. 

When in an XTREE editable cell that requires validation, if you use the mouse on the vertical scroll bar to scroll the row out of view, the returned `XTR.TARGETROW` value will be set to the top or bottom of the visible range of rows, whichever is closest. This counteracts the "boomerang scroll" effect whereby using the scroll bar when in an editable cell would work only until the mouse was released, after which if XTREE exited for validation, when the app returned, the `XTR.TARGETROW` would still be pointing to the cell that was being edited, thus snapping the scroll operation back to the original position. 

Note that when entering a non-editable multi-select tree, the `XTR.TARGETROW` establishes which row gets the focus. The focused row will be identified by a dotted line around it, and is not necessarily selected nor even visible, but when you use the DOWNARROW, the focus and selection will move to the next row below the one that had the focus. `XTR.TOPINDEX` works in multi-select mode also, to set the vertical scrolling position. Prior to A-Shell 997.3, the first selected row over-rode the `XTR.TOPINDEX` . 

A-Shell Reference 

Page 3623 

## **XTR.SEARCHMODE** 

This field controls the behavior of an implicit search mechanism that moves the selection bar based on matching characters typed against items in the current column. This is not to be confused with the PopupMenu explicit search functions. 

## The options are defined as follows; see SOSLIB:ASHINC:XTREE.DEF for the latest version. 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XTRSRCH_TOP_ALL|0|(dflt) all chars, items, from top|
|XTRSRCH_TOP_ONE|1|one char, all items, from top|
|XTRSRCH_NONE|2|no search|
|XTRSRCH_TOP_ALLX|3|like TOP_ALL but skip collapsed deps|
|XTRSRCH_TOP_ONEX|4|like TOP_ONE but "  "|
|XTRSRCH_NXT_ONE|5|like TOP_ONE but start from current item and wrap|
|XTRSRCH_NXT_ONEX|6|like TOP_ONEX but "  "   "|
|XTRSRCH_NXT_ALL|7|like TOP_ALL but start from current item|
|XTRSRCH_NXT_ALLX|8|like NXT_ALL but skip collapsed deps|



A-Shell Reference 

Page 3624 

The options can be understood as follows: 

- "_TOP" vs. "_NXT": Indicates whether the search operation always restarts from the top, or from the current item. In the 

- latter case, it wraps from the bottom back to the top. 

- "_ALL" vs. "_ONE": Indicates whether the search is based on all the characters in the cells of the current column, or just the 

- one first character. In the _ALL case, characters typed within 1 second of the previous character are added to the search key; after 1 second, the key is reset. So for example if you type "AB" within 1 second of each other, it will search for items starting with the combination "AB" (not case sensitive). If more than 1 second passed between the "A" and the "B", it restarts the search looking for items beginning with "B". The "_ONE" option effectively sets the timer to zero, so that each character typed restarts the search. 

- "X" (_ALLX, _ONEX): The "X" on the end indicates that collapsed child items are skipped. Otherwise, the search considers all 

- items, and if it matches a collapsed child item, that child and all its siblings and parents are expanded. 

## **See Also** 

- PopupMenu Search 

- System parameter SBR=XTREE_SRCH 

A-Shell Reference 

Page 3625 

## **XTR.MISCFLAGS** 

_Updated May 2015; see History_ 

## A collection of miscellaneous on/off options affecting the entire tree: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|XTMF_TRUNCATED|&h0001|Show "…" if cell contents need to be truncated for display. This field overlays the old<br>`XTR.TRUNCATED`field, which is now deprecated.|
|XTMF_INTHEIGHT|&h0002|For trees with fixed-height items (seeXTF_VARYin XTREE<br>Flags<br>), adjusts overall tree height<br>to avoid the partial display of an item at the bottom.|
|XTMF_INHERITBG|&h0004|Causes the left margin area (if any) to inherit the background color of the first column,<br>rather than the default background color of the tree. See example below.|
|XTMF_STDPRGBAR|&h0008|Causes a standard progress bar to display during loading of large trees over ATE<br>connections. See "Loading," below.|
|XTMF_CUSPRGBAR|&h0010|Same as above, but instead of creating a progress bar, uses one created by program. See<br>"Loading," below.|
|XTMF_LOADABORT|&h0020|Allows user to ESC to abort the loading process; result is same as if user waited until tree<br>was displayed and then hit ESC (exitcode 1). See "Loading," below.|
|XTMF_EDITONLY|&h0040|CausesXTREEto attempt to remain in cell editing mode, and avoiding selection mode, to<br>the extent reasonable possible. There are still situations and events that will result in|



A-Shell Reference 

Page 3626 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|||XTREEreverting to selection mode, but this option will minimize them.|
|XTMF_NOEXTARGET|&h0080|This addresses an obscure situation involving dual editable trees. Normally, if the user<br>clicks on Tree #2, row X, col Y while editing Tree #1, the return value of`XTR.TARGETROW`<br>and`XTR.TARGETCOL`will be set according to clicked cell in the external Tree #2.<br>`XTR.XROW / XTR.XCOL`will be set to the cell Tree #1 that was last active at the time of that<br>external click. If the XTMF_NOEXTARGET flag is set, the location of click in the external<br>tree is ignored and the returned`XTR.TARGETROW / XTR.TARGETCOL`will be set the same as<br>`XTR.XROW / XTR.XCOL`, i.e. to the cell last active before the click. A rationale for this subtle<br>feature may be found inthe A-Shell Forum post"Multiple XTREE's target row/col<br>question."|



## **Examples** 

Here are examples of the effect of the XTMF_INHERITBG flag. In the left image the flag is set, in the right image it is not: 

## **Loading** 

The three loading-related flags provide options to improve the user interface during loading of large trees over ATE connections, which might take several seconds and therefore leave the user wondering if the process died or something went wrong. 

If using the custom progress bar option (XTMF_CUSPRGBAR), you must create your own progress bar with a control id of "xtrProgBar". Optionally, you can embed it inside of a container dialog, along with other controls. If you want the container dialog deleted when the tree is ready to display, it must have the control id "xtrProgDlg". 

A-Shell Reference 

Page 3627 

Note that the progress bar/dialog option probably supersedes the `XTR.DELCTLID` feature, although they are not mutually exclusive. The progress bars are handled exclusively on the server side during the data transfer to ATE, while the `XTR.DELCTLID` feature is handled on the client side. For that reason, before using the XTMF_CUSPRGBAR option, you should use AUI_ENVIRONMENT to verify that you are actually running in the ATE environment. Otherwise the custom dialog you create will not get deleted by XTREE, unless you also obtain the numeric ID of the "xtrProgBar" control and plug it into the XTR.DELCTLID field. 

## **History** 

- 2015 May, A Shell 6.1.1409: Add XTMF_NOEXTARGET 

- 2013 May, A Shell 6.1.1352: Add XTMF_EDITONLY 

- 2013 April, A Shell 6.1.1349:  Add XTMF_STDPRGBAR, XTMF_CUSPRGBAR and XTMF_LOADABORT to help with time problems when loading data over telnet connections. See "Loading" above. 

A-Shell Reference 

Page 3628 

## **XTR.MISCFLAGS2** 

_New October 2025_ 

## A collection of miscellaneous on/off options affecting the entire tree: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|XTMF2_IECWE|&h01|Ignore ExitChars While Editing. Otherwise, ExitChars are active in all contexts. Note that<br>even when the flag is set, they remain active in editable checkboxes, but not in any other<br>kind of editable field.|



## **History** 

- 2025 October, A Shell 7.0.1779: Add XTMF2_IECWE and also this topic and above table. 

A-Shell Reference 

Page 3629 

## **XTR.NFSELSTYLE** 

This flag determines how selected item(s) are highlighted. All but the last option apply only when the control does not have the focus. 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|XTNFS_GRAY|0|Gray selection bar (when inactive)|
|XTNFS_BLUE|1|Blue selection bar (when inactive)|
|XTNFS_FRAME|2|No selection bar (when inactive)|
|XTNFS_NONE|3|No selection bar (when inactive)|
|XTNFS_NOFOCRECT|&h80|No selection bar (when inactive)|



## **See Also** 

- XTR.SELECTAREA 

A-Shell Reference 

Page 3630 

## **XTR.HEADERSTYLE** 

This field supports flags relating to column header style. The style flags are: 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|XTHSF_VCENTER|&h00|vertically centered in header cell|
|XTHSF_TOP|&h01|top alignment|
|XTHSF_BOTTOM|&h02|aligned at bottom of header cell|
|XTHSF_NOHIGHLIGHT|&h20|headers are buttons, but don't get auto-highlighted when the column is active.|
|XTHSF_BTNSTAY|&h40|header buttons stay down when clicked (if not =NOHIGHLIGHT)|
|XTHSF_DISABLED|&h80|header disabled, cannot be clicked|



XTHSF_VCENTER, XTHSF_TOP and XTHSF _BOTTOM control the vertical alignment of the header text. The default is XTHSF_VCENTER. 

XTHSF_NOHIGHLIGHT causes the column headers to act/look like ordinary text cells, rather than as buttons. This will eliminate the highlighting of the column headers in editable trees, which is sometimes distracting. 

The last two flags are somewhat obscure, but are documented here for completeness: 

XTHSF_BTNSTAY causes the header buttons to stay in the down position when clicked. This is only effective when not sorting, so this is of minimal value also. 

A-Shell Reference 

Page 3631 

XTHSF_DISABLED flag disables the click-sensitivity of the headers—which effectively disables sorting, so is more or less subservient to the XTF_SORT flag. 

**Note** : In addition to these various options relating to the style of the header, be aware that you can hide the header entirely by setting the `XTR.HIDEHEADER` field to 1. 

A-Shell Reference 

Page 3632 

## **XTR.SHOWROWHDR** 

This field determines whether row headers are displayed, and should be set to one of the following options. 

|**Symbol**|**Value **|**Meaning**|
|---|---|---|
|XTRHF_NONE|0|no row headers|
|XTRHF_BTNCNT0|3|display numeric buttons, starting from 0|
|XTRHF_TITLECNT0|4|display numeric titles, starting from 0|
|XTRHF_BTNCNT1|5|display numeric buttons, starting from 1|
|XTRHF_TITLECNT1|6|display numeric titles, starting from 1|



The difference between "titles" and "buttons" is that buttons are clickable (as a way of selecting the row item). Sample image here. 

Here is an example of row buttons, with `XTR.SHOWROWHDR = XTRHF_BTNCNT1` and `XTR.ROWHDRSTYLE = XTHSF_BTNSTAY` : 

A-Shell Reference 

Page 3633 

## **XTR.SHOWBUTTONS** 

_Revised December 2020; see History_ 

This options controls whether the +/- buttons—used with multi-level mode to expand/contract levels—are visible, and whether one click or two expands/collapses the levels. 

The interpretation of the first two fields preserves compatibility with older programs, but now allows the application to hide the top level or lower level buttons, if desired. 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
||0 or 1|show the buttons|
|XTSBF_HIDE0|&h0002|causes the top level buttons to be hidden|
|XTSBF_HIDE|&h0004|causes the lower level buttons to be hidden|
|XTSBF_LCLICK|&h0040|single click expands/collapses|
|XTSBF_DBLCLK|&h0080|double click (or ENTER) expands/collapses|



## Notes on XTSBF_LCLICK and XTSBF_DBLCLK: 

- When enabled, these options may make it easier for the user to operate a multi-level tree, reducing the amount of hand-eye 

- coordination otherwise needed to click precisely on the +/- button. 

A-Shell Reference 

Page 3634 

- Burying these options in the XTR.SHOWBUTTON field may be slightly counter-intuitive since they have nothing to do with 

- whether the buttons are visible, but the features are closely related enough that it seemed better than introducing yet another field to the XTRCTL structure. 

- Note that the double-click option probably only makes sense when there is no other action or meaning associated with parent 

- tree items, since it stifles the ability to "choose" the item. 

## **History** 

- 2020 December, A Shell 6.5.1693  Added XTSBF_LCLICK and XTSBF_DBLCLK. See "Notes" above. 

A-Shell Reference 

Page 3635 

## **XTR.FOOTERSTYLE** 

_Rewritten March 2018_ 

The two footer-related XTRCTL fields, `XTR.FOOTERSTYLE` and `XTR.SHOWFOOTER` , control the display and style of column footers. As with column headers, column footers remain fixed in position, unaffected by scrolling, as in the example below. Do not confuse these controls with page Title and Footer. 

To enable the display of a footer, set the `XTR.SHOWFOOTER` field to 1. The `XTR.FOOTERSTYLE` field can be used to adjust the attributes of the footer, using the same options as in the XTR.HEADERSTYLE field for the headers. 

To define the display contents of each column in the footer, append a clause to the ctitle field of the _coldef_ . The footer clause must begin with a pair of colons (::) followed by a string of text which has follows the same syntax as for the header. For example: 

```
COLDEF += "1~6~Code::Total~#~~"       ! Title/header="Code", Footer="Total"
```

```
COLDEF += "7~6~Boxes::=91658~#E~~"    ! Title/header="Boxes", Footer="91658"
```

Although you can update the footer text each time you re-enter the tree (with XTROP_REPLACE or XTROP_RESELECT), in a case like the one above where the footer contains the total for the column, see the special footer command Auto-Sum. 

You may also define font, scale, and color attributes using the following new Advanced Coldef Options: 

```
FooterFont=     (same syntax as for HeaderFont)
```

```
FooterScale=    (same syntax as for HeaderScale)
RGBbgFooter=    (same syntax as for RGBbgTotals)
RGBfgFooter=    (same syntax as for RGBfgTotals)
```

## **History** 

A-Shell Reference 

Page 3636 

- 2018 June, A Shell 6.5.1637:  Footer text (XTR.SHOWFOOTER) may now include embedded CRLF line breaks in order to show multiple lines (same idea as for headers). For example: `coldef += "1~15~Header::> Footer1" + chr(13)+chr(10)+"Footer2#~~"` 

- 2018 February, A Shell 6.5.1631: Auto-Sum capability added; see next topic. 

- 2016 November, A Shell 6.3.1537:  Footers added to XTREE. 

## **Subtopics** 

- Auto-Sum 

A-Shell Reference 

Page 3637 

## **- AUTO SUM** 

_Updated September 2019_ 

To insert a column total into the footer (that auto-computes and auto-updates as cell values change), set the footer text to "=SUM." For example: 

```
coldef += "20~10~Qty::=SUM~#E~~
```

```
coldef += "30~12~| Weight::| =SUM~#E~~
```

## **Comments** 

The footer must be made visible, by setting XTR.showfooter = 1. See XTR.FOOTERSTYLE for other display attributes of the footer. 

Note that the footer in question here is the one built-in to the grid, mirroring the header, not to be confused with the Advanced Coldef Options "Footer=", which defines a page footer for printing, or "TotalLines=", which defines pseudo-footer lines that are actually regular items in the grid. 

As illustrated in the second example, the optional header/footer alignment code—"| " for centering—precedes the "=SUM". Typically it isn't necessary to specify an alignment code for the footer though, as the =SUM option will automatically use the same alignment as the column being summed. 

The Auto-Sum includes all of the numeric cells in the column. 

Beginning with A-Shell 6.5.1666, Auto-Sum can be limited to specific levels in a multi-level tree. As with the regular Auto-Sum feature, it is activated by inserting one of the following tokens into the header, or more typically, the footer part of the header: `=SUM                            ! standard auto-sum` 

```
=SUMLVL(#)                      ! auto-sum just level #
=SUMLVL(#,#,...#)               ! auto-sum the specified levels
```

A-Shell Reference 

Page 3638 

The last level in the parenthesized list may have a "+" appended to it, e.g. =SUMLVL(#,#+) indicating all of the levels from the specified one down. So for example, =SUM(0,2+) would include all levels except level 1. 

This example includes levels 0, 1 and 2 in the Auto-Sum: 

```
coldef += "20~10~Qty::=SUM(0,1,2)~#E~~
```

## **History** 

- 2019 September, A Shell 6.5.1666:  Refinement: Add the ability to limit the Auto-Sum feature to specific levels in a multi-level 

tree. 

- 2018 September, A Shell 6.5.1647:  Refinement: Auto-Sum totals now red if negative. 

- 2018 February, A Shell 6.5.1631: Auto-Sum capability added. 

A-Shell Reference 

Page 3639 

## **FILIDX** 

This optional parameter (B,4) may be specified in conjunction with file mode to create an index to the file while it is being loaded into the array. The index is dynamically allocated and kept in memory and a "handle" to the index is returned in the _filidx_ parameter. The variable _filidx_ cannot be used directly, nor should it be altered by the application. Its only use would be to pass it to the MX_FILEPOS function, along with the desired line number (of the selected item), in order to efficiently seek to the selected item. This is mainly of use with multiple-selection file mode, since the selected items are identified only by line number via the answer array. 

See the sample program XTRFIL.BP in EXLIB:[908,21] for an example of using _filidx_ . 

Note that you should only use one _filidx_ variable within a program, and you should not modify its value. If you follow this guideline, A-Shell will automatically free up the memory used by the index for each new XTREE call and when the program ends. 

A-Shell Reference 

Page 3640 

## **XINFO** 

This optional parameter, _xinfo_ , may be specified to allow XTREE to return additional information. _xinfo_ must be mapped as a string (fixed or dynamic). Note that if not using _filidx_ , you may specify "" as a placeholder for it. 

The only information returned in _xinfo_ is a list of multiple exitcodes that apply to the tree just exited (primarily useful in trees where a single event might logically be associated with more than one exitcode). The format is as follows: 

```
0,exitcode1,exitcode2,exitcode3,...,exitcodeN
```

e.g. 

```
0,-48,-902
```

The first byte ("0" in the above case) indicates the format of the remainder of the string. So in order to allow programs to avoid confusion when the format of this string gets updated in the future, it should do something like this: 

```
if xinfo[1,1] = "0" then
```

```
    <process list of exitcodes>
```

```
else
```

```
    <report error: unsupported xinfo format>
```

```
endif
```

To give an example of where multiple exitcodes might be handy, consider the case of an editable tree that also contains _PopupMenu_ exitcodes. While editing a cell, the user may decide to right-click to see the popup menu, and then select one of the options that generates an exitcode. In this case, you may effectively have two exitcodes: one for cell validation (-48) and one for the _PopupMenu_ selection. In this case, the validation exitcode would probably take precedence as the one returned in the main exitcode parameter. Previously, the other events would have gone without notice. Now, if the _xinfo_ parameter is specified, the other exiticode(s) will be passed back in it, allowing the application to respond appropriately to the multiple events. 

A-Shell Reference 

Page 3641 

## **XTREE TECHNIQUES** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Exporting Tree to Spreadsheet 

- Drag and Drop 

- Auto-Filtering 

- Clicks on Inactive XTREEs 

- Initial View Position 

- Mouse and Keyboard 

- Sorting 

- Multi-level Lists 

- Modeless Operation 

- Appending 

- Editable Tree Controls 

- Multiple Tree Controls 

- Controls in Container Windows 

- Destroying Pick Lists 

A-Shell Reference 

Page 3642 

- Typical Cell Editing Scenarios 

- Saving User Adjustments 

- Scenarios Involving Multiple Trees 

A-Shell Reference 

Page 3643 

## **EXPORTING TREE TO SPREADSHEET** 

_Updated October 2025; see History_ 

XTREE offers the ability to export the tree contents to a spreadsheet via a configurable context menu (right-click or PopupMenu) option. The output format is initially CSV, but there are also options that take advantage of CSV2XL by embedding directives into the CSV file and then passing it through CSV2XL to create an XLS or XLSX output. 

## **See Also:** 

- PopupMenu 

- ExportOptions 

- ExportFspec 

- System parameter XTREE options 

- CSV2XL 

## **History** 

- 2025 October, A Shell 7.0.1779: Images (other than icons) are now included in the export to Excel. Requires CSV2XL.SBX 2.2(311). 

- 2023 February, A Shell 6.5.1724: When exporting to XLSX, embedded CRLF's (ASCII 13 plus ASCII 10) are now exported as "^m". Requires CSV2XL 2.1(268) to be effective. 

- 2022 February, A Shell 6.5.1711: Exporting to a spreadsheet now supports the footers if XTR.SHOWFOOTER=1. Also, when exporting in the full XLSX mode (see SBR=XTREE_EXPCSV2XLSX), if the Advanced Coldef Parameter Title is defined, it will be used as a banner. The special macro tokens (e.g. %date%) are supported but %page% and %total%—which don't make any sense in the banner of a spreadsheet—are just converted to blanks, as are the justification separators (|). 

A-Shell Reference 

Page 3644 

## **DRAG AND DROP** 

XTREE supports three different drag-and-drop scenarios: 

- Drag and drop within a single tree, for item re-ordering. XTF_DRAGDROP. 

- Drag and drop of items between two XTREE controls. See XTF2_FILEDROP. 

- Dragging a file from an Explorer or Windows Shell dialog and dropping it on an XTREE control. See XTF2_FILEDROP. 

A-Shell Reference 

Page 3645 

## **- AUTO FILTERING** 

_Updated April 2023; see History_ 

Auto-filtering is a mechanism, similar to that available in Windows Explorer or Excel, by which the user can click on a special button in the column header to access an automatically-generated dialog of filtering options, which can then be used to temporarily remove (hide) some of the items from the tree. The user interface looks like this: 

The feature is enabled by setting the XTF2_AUTOFILTER (&h00800000) bit in the FLAGS2 member of the FLAGS structure/parameter. It also may be turned on for all XTREE calls with the setting OPTIONS=XTAUTOFILTER in miame.ini. Auto-filter currently is limited to array-based trees. 

At the simplest level, the filtering is entirely a client-side affair, auto-configured by XTREE and controlled by the user, invisible to the application, and lasting only for the life of the tree. Items remaining in the tree retain their original physical record/row numbers so that selecting or editing a specific item appears the same the application regardless how many other items had been filtered out. 

## **Filter Types** 

There are five different types of filters, including _none_ , which are automatically selected based on the column attributes, or which can be manually select by means of these Advance Coldef Options: 

- Filter=CB 

- Filter=CBX 

- Filter=RANGE 

- Filter=PATTERN 

- Filter=NONE 

The **CB (checkbox)** filter is the most automatic of the filter types. Each time you bring it up, it analyzes the data currently in the column and reduces it down to a set of up to ten checkbox options which are either complete values (e.g. Red, Green, Blue), 

A-Shell Reference 

Page 3646 

starting characters (e.g. R, G, B), or ranges of starting characters (e.g A-D, E-G, H-Q, R-). The user can select one or more of the options to filter out all the others. There is also a "select all" option to bring the previously filtered items back. 

The **CBX** filter is similar to the old Filter=CB but instead of grouping the items by the first one or two characters, it lists them all. CBX is the default filter type. See _History_ below for when CBX was introduced. 

The **RANGE** filter prompts for from/to values and works for numbers and dates/times. In the case of dates/times, the from/to values can be in any of the formats supported by the sort logic. See History note below, specifically A-Shell 1649.0.1. 

The **PATTERN** filter is essentially just a string character match, case insensitive, and position independent. The pattern "oo" will match "Oolong Tea", "COOKIES", "foo", etc. Currently the emphasis is on simplicity; wildcards or regex expressions are not supported but may be added later depending on feedback. 

The **NONE** option prevents any filter from being assigned. Otherwise, if no Filter type is specified, XTREE will choose one—or none—based on the column attributes. 

## **Defaults** 

If you have auto-filtering enabled—either via OPTIONS=XTAUTOFILTER or by explicitly specifying the XTF2_AUTOFILTER bit in flags2 —but have not specified an explicit FILTER option, XTREE will choose a filter type according to the following rules: 

- If the column type is string and: a) the width is greater than 30; or b) supports embedded CRLF; or c) otherwise allows 

- multiple lines ( _cformat_ **M** or **m** ), the default filter type is PATTERN. 

- If the column type is numeric and width > 1, the default is RANGE 

- If the column type is string but the column data contains only numeric characters (including comma, period, space, and a 

- leading minus sign), the default is RANGE. 

- Otherwise, the default is CBX. 

Note that in the case of a multi-level tree, only the top level is considered. 

## **Filter Button Visibility** 

The user accesses the filter feature via the buttons in the column headers (see image above), and normally whenever filtering is enabled, the buttons are visible.  But in some cases it may make sense to hide them, possibly to minimize clutter or free up 

A-Shell Reference 

Page 3647 

space for column header text in narrow columns.  The rules and configuration options affecting the visibility of the filter buttons are as follows: 

- When enabled globally (via OPTIONS=XTAUTOFILTER) but not locally (via the XTF2_AUTOFILTER flag), the initial filter button 

- state will be hidden. Otherwise it will be visible for all columns that have either explicit or default filters (i.e. anything but Filter=NONE). 

- The developer may explicitly set the initial state to hidden via the Advanced Coldef Option FilterInitialState=Disabled.  (If 

- specified for the zero column, it affects all columns, otherwise it only affects the column(s) for which it is specified. 

- The user may toggle the filter button visibility via the context menu options: 

- If the tree has a TreeID specified, then if the user changes the state of the filter button visibility, the changes will be saved 

- and used as the initial state the next time that tree is displayed. 

## **Application Filtering** 

The application can participate in the filtering operation by defining a "filter status" column (one character wide), using _cformat_ **0** (zero). Typically you would want to hide such a column by also specifying the **H** code. Once defined, the application can pre-filter (i.e. hide) rows, prior to calling XTREE to load them into the tree, by setting the column to "1". A space or "0" is treated as visible. 

Note that this is similar to the LoadOptions=NoRowIf# capability except that rows filtered by a **0** column can be unfiltered by the user, whereas rows filtered out by the NoRowIf# cannot. 

The application can also be notified of the visibility state of each row on exit from the tree, by adding the _cformat_ code **U** to the column. In this case the field must also appear in the answer array and will be set by XTREE to "0" for visible and "1" for filtered out (invisible). On re-entry into the tree in XTROP_RESELECT mode, any changes made by the application to the filter state column in the answer array will be applied to the tree (i.e. hiding or unhiding rows). Note that except in the XTF2_ANSEQDATA case—where the answer and data arrays have the same format, or are actually the same—the filter state column is positioned with the checkboxes, i.e. after the drag-drop and multi-select fields, but before any editable text fields. 

For the XTROP_REPLACE operation, rows are first loaded from the data array and are then updated based on the answer array. In the case where there is an updatable filter status column ( **0U** ) and rows had been filtered out during the previous editing session, this will result in all of the rows being first added—because the data array is not updated by the filtering operation—and then the 

A-Shell Reference 

Page 3648 

filtered-out rows will be removed during the answer array load. There is nothing wrong with this two-step approach other than inefficiency; if you have very large trees, it would be more efficient to transfer the updated filter status indicators from the answer array back to the data array before reloading the tree with XTROP_REPLACE. 

The sample program XTRA5.BP in EXLIB:[908,21] been updated to illustrate various auto-filter features. You need to enter '1' to the auto-filter prompt when running it. 

## **Comments** 

- Columns with a filter option other than NONE will have a check-mark button at the right edge of the column header. So 

- filtering requires that the headers be visible. Columns with active filter criteria applied will display a strange symbol to the left of the column title meant to represent filtering. This symbol takes the place of the old up/down sort indicators, which have been moved to the top edge of the column header. 

- When multiple columns have filter specifications, they are combined with the "AND" operation. For example, if you filter the 

- name column to include just the names starting with A and F, and also the price column to include just the range from $9.99 to $39.99, then only those rows which meet both criteria will remain visible. You can remove the filter from one column: for a checkbox filter, click "Select All"; for the other types, enter an empty pattern or range. Or you can remove the filters from all the columns by clicking on the "clear" button in any column's filter dialog. 

- On multi-level trees, filtering only applies to the top level, and all the dependents are filtered along with the top-level parent. 

- Filter=None may be associated with the zero column to disable auto-filtering for the entire tree. This may be useful if you've 

- enabled auto-filter globally (in miame.ini) but want to disable it for a particular tree. Previously, to accomplish this you would have had to add the Filter=None option to each column. 

- The filter buttons in the header can also be toggled on/off as a group via the Context menu.  See History below. 

## **See Also** 

- XTAUTOFIILTER in System Parameters 

## **History** 

## - 2023 April, A Shell 6.5.1729:  Add CBX filter. 

## - 2023 January, A Shell 6.5.1724:  Several Auto-Filter refinements: 

A-Shell Reference 

Page 3649 

• If auto-filtering is enabled globally via the OPTIONS=XTAUTOFILTER directive in the miame.ini, but not set explicitly for the current tree (via the XTF2_AUTOFILTER flag), then the initial state of the filter buttons will be hidden, but can be activated (made visible) via the context menu. This is intended to make it easier to enable auto-filter globally without having to worry about the overcrowding of narrow column headers or general clutter caused by the filter buttons in trees where filtering may not be important. 

- Add a new Advanced Coldef Option (FilterInitialState=Disable) which can be used to hide the filter button from specific 

- columns (or the entire tree if added to the zero column definition), while still allowing it to be activated via the context menu. 

- Add a new option to the context menu to toggle the filter button for just the current column. 

- Vastly improve (10-50X) the speed of filtering operations. 

- 2021 December, A Shell 6.5.1709:  Specifying Filter=NONE on a zero-width column now sets the default for subsequent real columns. 

- 2021 March, A Shell 6.5.1701:  Minor refinements to filter dialogs, including text localization (SBRMSG.xxx 026,###). 

- 2021 February, A Shell 6.5.1699: Added a "Toggle All Filter Buttons" option automatically to the context menu when XTF2_AUTOFILTER is enabled. The option toggles the visibility of the filter button in the column headers of any column not actively being filtered. The point is mainly to free up header space when the columns are tight. Note that even without the filter buttons, you can still use the context menu to filter a column to the clicked-on cell value. 

- 2020 October, A Shell 6.5.1690: The CB and Pattern filter types now treat blank cells as normal. Previously, there was no way to filter out the non-blank cells using the CB filter because it didn't present a checkbox option for blank. And in the case of the pattern filter, a blank pattern was matching everything. 

- 2020 June, A Shell 6.5.1682:  Filter=none may now be associated with the zero column to disable auto-filtering for the entire tree. 

- 2018 October, A Shell 6.5.1649.6.2, further development / refinement:  (1) Columns with _cformat_ **s** or **l** now eligible for AutoFiltering. Previously required S or # as well. (2) Disable the context menu filter-to-value option for child items. Filtering only applies to the top level; child items are filtered along with their parents. 

- 2018 October, A Shell 6.5.1649.0.2, further development / refinement:  the context menu now contains smart options to clear the current column filter or all column filters when applicable. It also contains a new option to filter the column by the value of the clicked-on cell. 

A-Shell Reference 

Page 3650 

- 2018 October, A Shell 6.5.1649.0.1, further development / refinement:  the Range filter type has been split into two variations: Filter=RangeStr and Filter=RangeNum. In the case of Filter=Range, it will decide for itself which kind of range makes the most sense. The string version (RangeStr) uses the ASCII collating sequence for the range selection, while the numeric version (RangeNum) now removes any non-numeric formatting characters from each cell and then uses the value to compare against the from/to range limits. 

- 2018 July, A Shell 6.5.1640: Added feature to A-Shell. 

A-Shell Reference 

Page 3651 

## **CLICKS ON INACTIVE XTREES** 

When the user clicks on an inactive XTREE, it creates potential complications for the application. Typically, the `XTR.KBDSTR` parameter of the inactive XTREE will be used to generate an exitcode indicating which control was clicked, and the control currently with the focus will exit with that exitcode. The application would then typically call XTREE for the clicked-on tree. The complications arise when the click event has (or should have) more consequences than simply putting the focus on that XTREE. 

For example, if the target tree uses SelChgExit or ClickExit, the click event might logically need to trigger one or both of those exitcodes. In the case of a right-click, if there was a context menu defined, the user would expect it to appear (in addition to the tree getting the focus). 

The act of clicking on the inactive tree might also have ramifications for the control that previously had the focus, perhaps INFLD or even another XTREE. For example, in either of those cases, exit validation may be needed, which could potentially put the application the position of having to ignore the original click on the inactive tree, in order to enforce some data entry rules in the previously active tree or field. 

The general procedure for dealing with these complications is (and has been) as follows: 

- The click on the inactive tree generates the exitcode associated with the `XTR.KBDSTR` field for that tree. 

- The currently active control (presumably being handled by a subroutine) exits with that exitcode. 

- The application performs any exit validation or cleanup necessary for the field/control just exited. 

- Assuming no problems so far, it then calls XTREE (probably with XTROP_RESELECT) to activate the tree just clicked on. 

- Once activated, that tree should try to proceed with processing the secondary events associated with the click that occurred 

- when the tree was inactive. For example, if it was a right-click on a column that had a PopupMenu, it should then display the context menu. Or if the click caused the selection to be moved to another row and SelChgExit was defined, then the tree should exit with the exitcode defined for the SelChgExit. If the inactive click was on a checkbox cell, the contents of the checkbox should now be toggled, and if validating, the tree should exit with exitcode -48. Etc. 

- The XTF2_CLRDEFER flag may be specified to disable the post-reentry processing described in the previous paragraph. This would 

- be useful in the case where the operation interrupted by the click on the inactive XTREE wasn't properly completed, causing the application to effectively ignore the inactive XTREE click. But at some point later, the application may decide to call that XTREE 

A-Shell Reference 

Page 3652 

again for other reasons, in which case we don't want the tree to then attempt to respond to the deferred events associated with the original click. Note that this is effectively automatic after about 2-3 seconds have elapsed since the inactive click event, so the XTF2_CLRDEFER flag is only really needed when you are calling the inactively-clicked XTREE without much delay. 

## **Comment** 

The inactive click may  generate row/column/cell-specific exitcodes; see XTR.KBDSTR. 

The Xinfo parameter allows the tree to return multiple exitcodes. 

A-Shell Reference 

Page 3653 

## **INITIAL VIEW POSITION** 

If the tree control contains more rows and/or columns than can fit in the space determined by the _srow_ , _scol_ , _erow_ and _ecol_ parameters, vertical and/or horizontal scroll bars will automatically be added. By default, the initial scroll position will be at the top and to the left. Although there is no option to over-ride the scroll position directly, you can do it indirectly by specifying a row (or set of rows) to be selected, a cell to be edited, and/or a column to have the focus. The details for accomplishing this vary somewhat with the type of the tree. 

For editable trees, the most direct way to establish the position is to set the `XTR.TARGETROW` and `XTR.TARGETCOL` parameters to the cell that you want to edit. This will force the cell to be brought into view (adjusting the vertical and horizontal scroll as needed). If these parameters are zero, then the initial position will be determined as it would for non-editable trees. 

For non-editable trees, the vertical position will be determined by the initially selected item(s). For array-based trees, and filebased trees which are either multi-select or have the XTF_FILANS flag, this is determined by the value(s) passed in the _answer_ parameter. For single-select file-based trees without the XTF_FILANS flag, the initially selected row is determined by the string in the _array_ parameter. In all of these cases, XTREE will adjust the vertical scroll so that the selected item (or first selected item in the case of multi-selection) will be visible. 

An exception to the above is that the combination of `XTR.SKEY` and `XTR.COLUMNACTIVE` may be used to select an initial item by searching for a matching string. 

The horizontal scroll position (for non-editable trees, or when `XTR.TARGETROW` and `XTR.TARGETCOL` are zero) is determined by the `XTR.COLUMNACTIVE` parameter. 

Note that item numbers and column numbers are always based on the initial order in which they are loaded or defined. Sorting and column reordering will obviously affect the display order, but will not affect the internal numbering. Thus, even if you select the first item and set the first column to be active, this could result in the tree being scrolled to the bottom and far right (or any other position) depending on the sorting and column reordering options. 

A-Shell Reference 

Page 3654 

## **MOUSE AND KEYBOARD** 

_Modified September 2019; see History_ 

XTREE follows most of the standard Windows keyboard and mouse conventions. The following describes some of the special cases that might not be otherwise obvious. 

## Printing: 

- CTRL+P invokes the print/previewer (see XTROP_PRINT) 

Font Scaling: 

- CTRL+PLUS increases the existing font sizes by about 10% 

- CTRL+MINUS decreases the existing font sizes by about 10% 

- CTRL+SLASH ( "/" ) resets the fonts to the original sizes 

## Locating and Selecting Items: 

- Use the UP/DOWN-ARROW keys, or a single LEFTCLICK to move the selection bar. Note that when the XTF_UP and/or XTF2_DOWN flags 

- are specified (to enable exiting the tree with up and/or down arrow), there must be a delay of 1/3 or more seconds prior to the up or down key press in order for the exit operation to take place (so as to minimize the chance of accidentally exiting while rapidly scrolling up or down the items). Note also that the ClickExit clause can be used to cause a single click to exit. 

• To locate an item by its text, click once in the relevant column (to make that column be the "active" one), then type the character(s). As you type, it will select the first row whose cell text in the current column matches what you've typed. The match logic resets after a delay of approximately one to two seconds without any characters being entered. Note that clicking on the column header may sort the column (see Sorting). Also note that the default "active" column is established by the `XTR.COLUMNACTIVE` field in xtrctl. 

A-Shell Reference 

Page 3655 

- Hit ENTER or Double-Click to exit with the current item selected. 

## Multi-level trees: 

- The PLUS and MINUS keys (on the main keyboard or on the numeric pad section) are equivalent to clicking on expand/collapse 

- button for the current level. 

- CTRL+SHIFT+PLUS and CTRL+SHIFT+MINUS, expand or collapse levels, are sensitive to the level of the current item. When 

- expanding, XTREE only expands items at that level that are visible , along with all of their dependents. When contracting, it only contracts from the current level down. For example: to make the top two levels visible but none below that, start with CTRL+SHIFT+PLUS on a top level item to expand all, then CTRL+SHIFT+MINUS on a 2nd level item to contract the levels below that. 

- CTRL+UP-ARROW and CTRL+DOWN-ARROW moves the selection bar to the prev/next item which is at the same level as the current 

- item, but which has a different parent. If necessary, this will cause the target item to be made visible by expanding its parent(s). 

- Provided there is no conflict—i.e. in the absence of XTF_EDITABLE, XTF_LEFT, or XTF_RIGHT—LEFT/RIGHT-ARROWS act similarly to 

- PLUS/MINUS (expand/contract) but also move the selection up or down to the next level, allowing rapid navigation of multi-level trees with just the arrow keys. You can force this behavior to override conflicting flags by using the compound _cformat_ code **@@** instead of just **@** . Feature added in 5.1.1220. 

## Multi-Selection Trees: 

- CTRL+A selects all items, CTRL+B deselects them. 

- LEFTCLICK selects current item, clearing all other selections. 

- CTRL+LEFTCLICK toggles the current item, preserving other selections. 

- SHIFT+LEFTCLICK selects all the rows from the previous selection to the current row. 

## Trees with Editable Cells: 

- TAB and SHIFT+TAB change the focus to the next/prev editable cell, provided the XTF_TAB flag is not set. 

A-Shell Reference 

Page 3656 

- Arrow keys will navigate between cells that do not themselves trap the arrow keys for editing purposes. For example, editable 

- text cells would trap the left and right arrows for editing within the cell. In such cases, you can use CTRL+ARROW for inter-cell navigation. See Combo Boxes for more details. 

- LEFTCLICK on a cell to select it for editing. Note that depending on the cell validation options in _cformat_ , and possibly a 

- ClickExit clause, clicking on another cell may cause XTREE to exit back to the application for validation purposes. 

- CTRL+' (Control Apostrophe) may be used within an editable text cell to copy/paste the contents of the cell above it, as in 

- Excel. 

- CTRL+C (copy), CTRL+V (paste), and CTRL+Z (undo) work as they do in Excel, Word and many Windows applications. 

Combo boxes: 

- When the focus is on a combo box within a cell, the up/down arrows would normally cycle among the possible selections. But 

- if the ScrollMode=Tree clause is specified, unless the drop-down list is visible, the up/down arrows advance to the prev/next row (as if CTRL+UP or CTRL+DOWN). 

- For selection-only combo boxes (where you are limited to selecting one of the predefined choices), if the list of choices 

includes a blank item, then the DELETE key (or SPACEBAR) will select it. Alphanumeric keys will select the first item that starts with the specified character. 

## Dropdown Lists: 

- When the focus is on a cell containing a dropdown list (which differs from a combo box in that you can only select among the 

- existing choices – see List) typing a character will jump to the first matching item in the list. If there are multiple items which start with the same character, hitting the character again will cycle among them. This can be seen in the XTRA5 example 

program, where hitting "B" repeatedly while in the Description column will cycle between "Boxer", "Bell Bottoms", and "Black Standard Tee". 

Checkboxes: 

A-Shell Reference 

Page 3657 

- SPACEBAR or LEFTCLICK to toggle the checkbox. 

## Extended Checkboxes (T+): 

- CTRL+A sets (ticks) all enabled checkboxes in the column, Control=B resets (clears) them. 

- LEFTCLICK on an clear box sets it, and if followed by SHIFT+CLICK on another clear box in the column, will set all the boxes 

- between them, inclusive. 

- CTRL+Z undoes either of the above actions, if executed while a checkbox in the affected column has the focus and no 

- intervening events have occurred. 

- RIGHTCLICK may display checkbox-specific context menu options if defined (see Editable checkbox) 

Popup Menus: 

- If a popup (or "context") menu is defined (see PopupMenu), use a single RIGHTCLICK or CTRL+SHIFT+F10 to display it. 

## Column Configuration: 

- To reorder columns (if enabled via the XTF_REORD flag), use the mouse to drag the columns by their headers. See 

- `XTR.USECOLORDER` (in _xtrctl_ ) and Saving User Adjustments for details on how/whether such column reordering will be automatically remembered. 

- To resize columns (if not disabled by the _coldef_ "L" code or limited by the _Dspmin_ in Advanced Coldef Options), click on the 

- right vertical border of the column (when the mouse cursor changes to a double arrow) and drag the column border left or right. 

- CTRL+PLUS (Ctrl with the plus key), CTRL+MINUS (Ctrl with the minus key) and CTRL+MOUSEWHEEL will increase or decrease the 

- size of all of the text in the tree by approximately seven percent. 

- CTRL+SLASH (the slash may need to be on the numeric keypad) will reset the text to the original size. (Equivalent to the 

- $RESETSCALE special PopupMenu command) 

A-Shell Reference 

Page 3658 

• CTRL+SHIFT+SLASH (the slash may need to be on the numeric keypad) will reset all of the user-controlled configuration options (text size, column sizes and order) to the original settings. (Equivalent to the $RESETCFG special PopupMenu command). 

• To sort the rows of the tree by the values of a column, click on the column header. Subsequent clicks on the header will cycle through the three possibilities (ascending, descending, and original). To sort by more than one column, start by sorting on the primary column, then for the secondary and tertiary sort columns, hold down the Control key while clicking the column header. Also see Sorting, the following topic, for more details. 

## **See Also** 

- Drag and Drop. 

## **History** 

2025 October, A-Shell 7.0.1780:  Support CTRL+SHIFT+F10 as an equivalent to RIGHTCLICK for context menu 

2019 September, A-Shell 6.5.1668:  Change behavior of CTRL+SHIFT+PLUS and CTRL+SHIFT+MINUS, expand or collapse levels, so that they now sensitive to the current item Previous, those keystrokes expanded or collapsed _all_ levels. 

2011 July, A-Shell 5.1.1225: Using the LEFT-ARROW from a child row now jumps to the parent (provided XTF_LEFT is not set, or @@ is used to override it). Conversely, RIGHT-ARROW from a parent row whose children are already expanded jumps to the first child (provided XTF_RIGHT not set or @@ is used). With this, plus the expand/contract on left/right feature added in 1220.0, XTREE now matches the handling of the arrow keys in the Windows registry editor. 

- 2011 June, A Shell 5.1.1221: XTREE refinement: SHIFT+RIGHT within an editable text cell now marks text rather than advancing to the next cell. (CTRL+RIGHT advances.) 

A-Shell Reference 

Page 3659 

## **SORTING** 

XTREE supports the following kinds of sorting. 

## **- User Controlled Sorting** 

When specified, the user can click on a column header to sort the list based on the data in that column. On the first click, a small up-arrow will appear in the column header, indicating that the column has been sorted with the lowest value items at the top (which is actually descending order). Clicking it again will reverse the order, and a third click will restore the original (physical) order. Multiple-column sorts can be achieved by holding down the Control key while clicking on the column headers. For example, in a tree containing columns for Countries, States, and Cities, you can sort by cities within states by clicking first on the Cities column header, then while holding the Control key down, click on the States column header. When sorting multi-level trees, the child rows are always kept with their original parents. In other words, the top level rows are sorted, then the children within each parent item are sorted, and so on. 

Depending on the column type, XTREE uses one of the following sort algorithms: 

- ASCII Sort _cformat_ code **A** ) 

- Natural Sort ( **S** ) 

- Numeric Value Sort ( **#** or **Z** ). 

- Date ( **D** or **d** ) - Supports variations of mm/dd/{cc}yy and dd/mm{cc}yy depending on the locale, or dd-mon-yr 

- Time ( **h** ) - mm:hh{:ss} {AM/PM} 

- Checkboxes and radio buttons ( **T** , **t** , **tt** , **R** , 

- **r** ) 

- Images ( **I** ) are not actually sorted but rather grouped 

## **- Application Controlled Sorting** 

The application can determine the initial display order of the rows by setting the fields `XTR.COLUMNSORT` and `XTR.SORTORDER` . This does not require that the XTF_SORT flag be set. If it is set, then the user can proceed to override the original sort order by the 

A-Shell Reference 

Page 3660 

method described above. If the user changes the sort order, the `XTR.COLUMNSORT` and `XTR.SORTORDER` will be updated on return, giving the application the ability to later re-display the tree data in the order last specified by the user (or not). 

Note the following: 

- To override the built-in sort logic, use the HdrClickExit Advanced Coldef Option to trap the user's click on the header. The 

- application can then resort the data rows any way it likes and reload the tree using XTROP_REPLACE. 

- Whether user- or application-controlled, sorting only affects the display order. It has no effect on the internal order of the 

- data. Any row index indicators passed into or returned from the routine will continue to be relative to the original, physical order of the source data. (For example, if sorting causes the first item of the source data to be repositioned to the end, selecting it will still return _answer_ set to 1.) 

- Use the Advanced Coldef Options _HdrLines_ and _TotalLines_ directives (and/or XTF_TOTALS flag) to prevent the headers and/or 

- totals from being sorted with the other rows. 

## **Context Menu Sorting** 

The application can also provide the user with pre-configured multi-level sort options on the context menu via the PopupMenu $Sort directive. 

## **Comments** 

Sorting a column by clicking on the header cycles between ascending, descending, and original (physical array) order. 

## **History** 

- 2024 November, A Shell 7.0.1765:  Image columns can now be 'sorted'. Since there is no natural order to images, this operation only serves to group the same images together. 

A-Shell Reference 

Page 3661 

## **- MULTI LEVEL LISTS** 

The ability to create multi-level lists is the reason why this routine and control is called XTREE (and not XTABLE or XLIST). But they do present several additional considerations and complications discussed below. 

**Determining which items are displayed:** Absent any special instructions, the default is to start with just the top level items displayed. The program can override this when the tree is first displayed via the XTR.EXPANDLEVEL parameter. For even more control, a special control column using the _cformat_ code **=** allows the program to ascertain and also set the Expand/Collapse State for every item. 

**User controls for expanding/collapsing:** See the multi-level tree section under Mouse and Keyboard techniques. Note that under application control you could augment the user controls. For example, to auto-expand a level whenever the parent is selected, you could use the SelChgExit and/or ClickExit Advanced Coldef Options in conjunction with the expand/collapse state column type to force the tree to return to the application whenever the selection changes, and then programmatically set the expand/collapse flag. Similarly you could respond to the selection (via double-click or ENTER) of a parent item to force expansion. Also see ExpandExit to intercept the user's request to expand/collapse an item. 

**Options for the expand/collapse indicators:** By default, each item with dependent children will be preceded by a +/- button that can be clicked to expand or collapse the dependents. See XTR.SHOWBUTTONS for options concerning the visibility of the expand/collapse buttons. You can also associate an icon with each of the three item states (expandable, expanded, leaf) similar to the way Explorer shows folder and file icons; see XTF2_ITEMICONS for details. 

**Sorting:** When sorting a column in a multi-level tree, only the top level (level 0) items are sorted. The dependents move along with their respective parents but are not themselves sorted within each group of siblings. See the Sorting section under Mouse and Keyboard techniques for more details. 

**Column Definitions by Level:** Since you can only have one set of column definitions, when using multiple levels, typically the higher levels may have blank columns, and you may need to interpret the contents of the columns differently depending on the level. In file mode, the level flag (as defined by the @ code in coldef ) is returned with the selection, allowing you to interpret the result appropriately. In array mode, you get back the selected array index(es) and can refer to the original array data to determine the level of the selected item(s). Note that the array index returned will be relative to the array you pass, and is not affected by sorting. 

A-Shell Reference 

Page 3662 

## **MODELESS OPERATION** 

In addition to the additional programming required (multiple XCALL XTREE operations using different XTR_OPCODE values), these present the problem of how to respond to the user clicking on the list box when some other input field has the input focus (i.e. when not inside of an XCALL XTREE operation). You can prevent this problem by disabling the control on exit (see flags XTF_DISABLE) or you can define a keyboard click-to-enable string in XTR_KBDSTR, which would be received by whatever input routine had the focus at the time the user clicked on the tree control. This would allow your application logic to take appropriate action, presumably including executing a new XCALL XTREE operation. If you neither disable the pick list when inactive, nor define a click-to-enable string in XTR_KBDSTR, then the user may have the impression of operating on the control, but your program will not be aware of it. (It could, however, retrieve the current selection(s) at some later time by executing XCALL XTREE with XTR_OPCODE set to 4 and _flags_ set to include XTF_NOSEL, which would have the effect of simply returning the current selection information.) 

The recommended sequence for XTR_KBDSTR is chr(7)+chr(250)+###. (where ### is the desired _EXITCODE_ number to be returned from the INFLD call which receives the sequence.) For example, to return _EXITCODE_ 175 to INFLD when the user clicks on the pick list (while an INFLD operation is active), set XTR_KBDSTR=chr(7)+chr(250)+"175." (Note the trailing period.) 

A-Shell Reference 

Page 3663 

## **APPENDING** 

When adding items to an existing tree control, care should be taken about the array index numbers. For example, if you initially load a tree control with a ten item array, then append another ten item array to it, the control will know that the second set of ten items should be internally numbered eleven to twenty, but it will be up to your program to realize that item fifteen is really the fifth item of the second set of ten loaded. One way to avoid this confusion is to maintain a single array which matches the contents of the tree control, even if you did not load them all at once. In the example just cited, rather than passing two separate arrays (or worse, overwriting the original array with the second set of items), it might be better to map an array large enough for all the items, and then just add to it as you add to the tree control. The trick here is to specify the appropriate starting array index, rather than (1). For example: 

```
MAP1 ARRAY(50),S,100
```

```
FOR I = 1 TO 8
```

```
ARRAY(I) = <data>
```

```
NEXT I
```

```
! now create the control with the first 8 items...
```

```
XTR_OPCODE = 0  ! (create)
FLAGS = XTF_MODELESS + XTF_NOSEL
```

```
ADDCNT = 8
```

```
xcall XTREE, SROW, SCOL, ANSWER, ARRAY(1), ADDCNT, COLDEF, EXITCODE, &
```

```
   EROW, ECOL, FLAGS, "", MMOCLR, XTRCTL
```

```
! now load up an additional 12 items, adding them first to array
```

```
FOR I = 9 TO 20
```

```
ARRAY(I) = <data>
```

A-Shell Reference 

Page 3664 

```
NEXT I
```

- `! append these items to the existing tree control...` 

```
XTR_OPCODE = 2  ! (append)
```

```
ADDCNT = 12
```

```
! note that we pass ARRAY(9) rather than ARRAY(1) ...
```

```
xcall XTREE, SROW, SCOL, ANSWER, ARRAY(9), ADDCNT, COLDEF, EXITCODE, &
```

```
   EROW, ECOL, FLAGS, "", MMOCLR, XTRCTL
```

```
ADDCNT = ADDCNT + ADDCNT
```

Now the 20 items in our local copy of ARRAY() match up with the contents of the tree control, so that when we receive a selected item number via the ANSWER parameter, we can reference the corresponding item in our local array directly, as ARRAY(ANSWER). 

The initial selection(s) are determined (by the _answer_ parameter) in the same way as when creating a new list, except that if you do not specify an initial selection, the default will be the first item appended. If you do specify one or more selections in the _answer_ parameter, they re interpreted relative to the combined list after appending, not relative to the just the appended items. That is, setting _answer_ =2 will select the second row in the table, not the second row appended. 

A-Shell Reference 

Page 3665 

## **EDITABLE TREE CONTROLS** 

XTREE supports editable text columns, combo boxes, checkboxes, and radio buttons. To activate this feature, set the XTF_EDITABLE option in the XTREE Flags parameter, and define one or more columns using the E (editable text) or T (editable checkbox) or R (editable radio button) or L (list selection) options in the _coldef_ parameter. (You must use the Advanced Coldef syntax.) You must also map the Answer in such a way to allow the updated text and/or checkboxes to be returned there.) You will probably also want to change the selection style in the `XTR.SELECTAREA` field of the XTRCTL parameter so that the selection indicator does not highlight the entire row (which makes it distracting to see the editable fields.) 

XTREE is a "tree" rather than a "grid" control, so its primary function is to display data and allow the user to select items. It doesn't support individual cell formats or functions, like a spreadsheet would. But its editing capabilities should suffice for a wide variety of scenarios which combine the need to display a lot of data in rows and columns, with lightweight editing capabilities. 

As a simple example, consider an application where you have a list of invitees to an event, and you want to check off those that show up. You might have several display columns for each person, with a single column of checkboxes to indicate if they have arrived. In this case, there would be no need for validating the data after each check either, although you might want to allow the operator to double-click on the person's name to print a badge. Another example would be a simple inventory sheet that lists all of the parts and has an editable text column allowing you to enter the amount on the shelf. A more sophisticated example might be a student grade book containing one row per student, and one column per assignment, where the teacher could enter data into any cell. 

When the XTF_EDITABLE flag is set, as long as the first column is not editable, you will be able to move the selection indicator up and down with the arrow keys, and select an item by hitting ENTER.The left and right arrow keys, however, will move the "focus" to the first editable cell in the appropriate direction, after which the arrows and TAB / SHIFT+TAB keys will move from editable cell to editable cell. 

If the first column is not editable (and the XTMF_EDITONLY flag is not set in XTR.MISCFLAGS), you can exit from editing mode (back to row selection mode) by clicking on the first column. Unless the XTF_ENTESC flag is set, you can also do this by hitting ESCAPE. (Otherwise ESCAPE exits the tree.) To exit from editing mode and out of the tree entirely (back to the calling program), you can double click on an item (not in an editable column), or use a function key (assuming the XTF_FKEY flag is set in the flags parameter) or click on an external button or control (even another XTREE) programmed to generate an exitcode (see MBF_KBD and XTR.KBDSTR), or any other event that triggers an exitcode. If the XTF_ENTESC flag is set you can also hit ESCAPE (from any cell) or hit ENTER from the last editable cell in the tree. 

A-Shell Reference 

Page 3666 

If you need to perform validation of the data on a cell by cell basis (without waiting for the user to exit from XTREE), you can add the "x" or "X" flag to any editable column. The lower case "x" forces XTREE to exit immediately (with exitcode -48) as each editable text cell loses the focus. The application can examine the `XTR.XROW` , `XTR.XCOL` , `XTR.TARGETROW, XTR.TARGETCOL,` and `XTR.XNAVIGATE` fields (see XTR.TARGET... and XTR.XVALIDATE) for information on which cell(s) need to be validated. The upper case version, "X", is the same except that it only exits if the data in the cell changed. Checkboxes and radio buttons treat both - "x" and "X" equivalently, in both cases exiting immediately when the item is clicked (i.e. which changes its value). Read only editable cells ("u") also treat "x" and "X" the same, as they exit immediately before getting the focus, rather than after losing the focus. 

See the Answer parameter for details on how it must be structured in order for editable cells to function properly. 

Note that you can cause individual rows (cells) within an editable text column to be ignored (skipped over) by setting the first data character of the corresponding entry in the Answer array to "|". Also see First Position Reserved ( _cformat_ **P** ) which may simplify use of the " **|** flag. 

The editable option is only supported with array mode (not file mode). 

## **See Also** 

- The sample program XTRA5 in EXLIB:[908,21] for a good example of editing and validation. 

- XTRA6 in EXLIB:[908,21] for radio buttons and multi-line cell editing. 

- XTRA9 in EXLIB:[908,21] for changing colors of individual cells based on editable contents. 

## **Subtopics** 

- Local Validation SBX 

- Re-entry After Cell Validation 

- Editable Image Cells 

- Client-Side Table Lookup 

A-Shell Reference 

Page 3667 

## **LOCAL VALIDATION SBX** 

_Reviewed and Revised May 2024_ 

As an alternative to _external_ (server-side or application-level) validation, where XTREE returns from the xcall back to the application, _local_ (client-side) validation is also supported via an internal call from XTREE to a specified SBX resident on the client. The advantage of local validation is an improvement in responsiveness by eliminating the overhead of exiting from the XCALL, passing all of the information back to the application which then has to XCALL XTREE again, passing all the relevant parameters back again. The difference is most noticeable in ATE environments, where the parameters have to be passed across a network connection between the client and server, but it also applies, to a lesser degree, to environments where the application and XTREE are executing on the same machine.  A secondary advantage of the local validation method is that by encapsulating the validation / formatting logic in an SBX, it may be possible to share certain validations across many programs. 

To enable local validation, you must first specify the name of the SBX via an Advanced Coldef Option: 

## `LocValSBX=name` 

The option must be applied to the zero column, as only one SBX can be specified for each tree. The SBX name should be specified without any path or extension. The SBX is expected to be found either in the current directory or in the BAS: directory. If not found, no local validation occurs. 

To specify local validation for a column, add one of these new _cformat_ codes to the column definition: 

|**Value**|**Validation Description**|
|---|---|
|V|Conditional validation (if the cell changes during editing)|
|v|Unconditional validation (whether it changes or not)|



## Note that these are analogous and parallel to the server-side validation codes **X** (conditional) and **x** (unconditional). 

A-Shell Reference 

Page 3668 

Typically you would only want to perform one style of validation per column, i.e. local/client or traditional/server, but it is possible to specify both, in which case the local validation is performed first. This technique could be useful as a 

transitional/experimental technique. Depending on the information returned from the local validation routine, it can disable the server validation, although you can force the server validation to occur regardless of the local validation result by doubling the **X** or **x** code. For example: 

|**Value**|**Validation Description**|
|---|---|
|v|local unconditional|
|xv|local unconditional, possibly followed by server unconditional|
|XXV|local conditional always followed by server conditional|



The local validation SBX performance advantage comes with a couple of limitations: 

- It has visibility to only the current answer row. It cannot see the data array row (assuming answer and data arrays are separate), nor can it see any other row in the answer or data arrays. 

- Unlike the traditional/server validation, which runs outside of XTREE and therefore has tremendous latitude as to how, or even whether to return to the tree, the local validation must return to the tree. Its only options are to update the current row, to select which cell on the row to re-enter in, and to force XTREE to exit with a specified exitcode. 

## **History** 

## - 2022 April, A Shell 6.5.1715:  Add feature to A-Shell 

## **Subtopics** 

- Validation Syntax and Parameters 

A-Shell Reference 

Page 3669 

- Validation Operations 

A-Shell Reference 

Page 3670 

## **VALIDATION SYNTAX AND PARAMETERS** 

## **xcall <NAME>, op, treeid, ansrow, cpos, clen, xtrctl, status, exitcode** 

## **Parameters** 

## _op_ (Num)  [in] 

Indicates operation/request from XTREE. 1 indicates the first version (as documented below). Subroutine should respond to anything other than recognized _op_ values by setting _status_ to XVF_BAD_OP. 

_treeid$_ (String)  [in] 

Tree identifier as set by the Advanced Column Option _TreeID_ clause. 

_ansrow_ (X)  [in/out] 

The current row of the answer array, i.e. the one corresponding to xtr.XROW 

_cpos_ (Num)  [in] 

Starting position in _ansrow_ of exit column (i.e. xtr.XCOL) 

_clen_ (Num)  [in] 

Length of the column specified by xtr.XCOL 

## _xtr_ (XTRCTL)  [in/out] 

On input, this is a copy of the XTRCTL as it would be returned to the traditional/server validation. On return, the xtr.TARGETCOL should specify the re-entry column. See _Identifying Exit Column_ below. 

## _status_ (Signed Num)  [in/out] 

Indicates status of validation operation. On input it will be set to XVF_INCOMPATIBLE, under the theory that any compatible validation SBX will change it to one of the other status values on return: 

A-Shell Reference 

Page 3671 

|**Symbol**|**Value**|**Meaning**|
|---|---|---|
|XVF_NOP|9000|Incompatible validation module|
|XVF_BAD_OP|9001|Unsupported op - indicates this SBX doesn't support the op value passed. (SBX<br>is out of date, new XTREE version?)|
|XVF_ERROR|9002|Internal error occurred in the SBX|
|XVF_NV|9003|Field Not Valid (fails validation criteria). SBX would normally also set<br>xtr.TARGETCOL to xtr.XROW to re-enter at same cell. Any changes to_ansrow_<br>made here will be updated back to the XTREE._Exitcode_should be set to 0<br>unless you want to force an app-level validation exit.|
|XVF_OK|9004|Field Valid; no update to row data required._Exitcode_should be set to 0 to<br>prevent a redundant app-level validation exit. (App can still override that in<br>coldef - see below)|
|XVF_OK_UPD|9005|Field Valid;_ansrow_has been modified (so XTREE needs to re-load the cells on<br>this row)._Exitcode_should be set to 0 to prevent a redundant app-level<br>validation exit. (App can still override that in coldef - see below)|



Note XTREE updates the tree contents based on changes made here to the _ansrow_ ONLY when the return _status_ is XVF_NV or XVF_OK_UPD. In all cases, unless _exitcode_ # 0, XTREE will re-enter at the cell determined by XTR.TARGETCOL. 

Beyond that, the _status_ value is mainly for debugging purposes.  See Debugging below. 

A-Shell Reference 

Page 3672 

The main return values of significance to XTREE are xtr.TARGETCOL (where to re-enter), _exitcode_ (whether to exit to app), _ansrow_ (containing and updates to cells on the row), and any message boxes displayed to tell the user about validation problems. 

_exitcode_ (Signed Num)  [in/out] 

On input, contains the _exitcode_ value that XTREE will send back to the application if no action taken here. -48 indicates column tagged for normal app-level validation; if the value is not reset here, it will cause XTREE to exit with the specified _exitcode_ following the local validation. On output, set to 0 to re-enter the tree directly, or any other _exitcode_ to pass back to the app. 

_valver_ (Num)  [out] 

Returns the edit # of this module. This is purely for debugging purposes, which see below. 

A-Shell Reference 

Page 3673 

## **VALIDATION OPERATIONS** 

## **Activating Local Validation** 

1. The _coldef_ for the XTREE must specify LocValSBX=xxxxxx in the zero column definition, where xxxxxx is the name of this SBX, i.e. LocValSBX=xtra24v 

2. Add the **V** (conditional) or v (unconditional) local validation _cformat_ codes to any column for which you want local validation. You can combine the **V/v** codes with existing **X/x** codes to enable local validation followed by app-level validation if the local 

validation isn't available or doesn't clear the _exitcode_ ; see above. Doubling the **X** or **x** code forces app-level validation regardless of what the local validation returns. 

## **Identifying Exit Column** 

One potential complication with separating the validation logic in an SBX apart from the application that sets up and calls XTREE is the increased difficulty of identifying the column to be validated. For this, there are multiple, possibly overlapping, strategies: 

1. Use the physical exit column (xtr.XCOL). This is the least robust since any change to the column layout in the main program will potentially change some or all of the physical column numbers. 

2. Use xtr.COLID. These values are assigned to columns by adding the Advanced Coldef Option ID=# to the coldef specification for each column requiring validation. These ID numbers do not need to be in any particular order or consecutive, and they are immune to rearrangement of the physical columns. This is the best general strategy. 

3. In cases where some of the validation logic can be shared between columns of the same general type, you can use xtr.COLTYPEID to identify the type. This requires use of the Advanced Coldef Option TYPEID=# in the _coldef_ specification for those columns. For example, you may have a set of shortcuts and other formatting logic that apply to all dates across your application. These could be implemented in functions that were associated with your COLTYPEID values and shared across multiple validation modules. This example uses two COLTYPEID values: 1 for a basic date that defaults to today, with various abbreviated forms expanding to mm/dd/yy, and 2 for the same but with no default, allowing a blank date. 

## **Retrieving Cell Data From Row** 

Typically validation starts with the cell just exited. You can retrieve that cell either via _ansrow_ [ _cpos;clen_ ] or by using a structure definition for the answer row, matching the one used in the application, in which case you can just access the fields directly, e.g. _ansrow_ .trxdate. 

A-Shell Reference 

Page 3674 

In cases where you want to validate some other cell(s) besides the one just exited, you will almost certainly need to use the structure definition method. 

Beware of potential problems with numeric cells using masks containing thousands separators or currency (e.g. $###,###.##) since most string-to-number conversions will terminate at the first non-digit, non-decimal point character. To avoid that problem, use .VALX(cell$). 

## **Updating The Row Contents** 

If you update the row contents, you need to set _status_ to XVF_OK_UPD or XVF_NV to signal to XTREE that the tree data needs to be updated. 

There is no particular harm to always returning XVF_OK_UPD for successful validation, regardless of whether you updated the row data, but returning XVF_OK instead of XVF_OK_UPD when you didn't make any change does allow XTREE to avoid the operation of updating the cells in the row and thus is more efficient. 

You can only update cells on the current row. If only updating the exit cell, you can do it by writing to _ansrow_ [ _cpos;clen_ ], but if updating any other cells on the row, there is no practical way other than to define the same answer row structure here as in the application and then use it to reference the cells on the row, e.g. _ansrow_ .trxdate = mm/dd/yy 

When updating cells in the row, ideally you should fill the entire cell, using a mask or pad() to space fill the trailing nulls. But if you don't, XTREE will replace any nulls left embedded in the _ansrow_ with spaces. 

## **Failed Validation** 

If the cell fails the validation, set return _status_ = XVF_NV and set xtr.TARGETCOL back to the exit column (xtr.XCOL). If you don't set xtr.TARGETCOL back to the exit column and don't otherwise display an error message, the user might not realize that the validation failed. Note however that any updates to the row data made here will be transferred back to the tree when the return status = XVF_NV, just as it would be for XVF_OK_UPD. This allows the validation routine more latitude in communicating back to the user.) 

## **- Multi Row Validation** 

Local validation currently only provides visibility to a single row, so if you need multi-row validation, you need to use traditional application-level validation. 

## **Relationship between Local and Traditional Validation** 

A-Shell Reference 

Page 3675 

Local validation is triggered first, based on the **V** (conditional) or **v** (unconditional) _cformat_ code. If the column definition also calls for traditional application-level validation ( **X** or **x** ), then the _exitcode_ parameter will set to -48 coming in to this routine. On return, if _exitcode_ is not zero, XTREE will exit with that exitcode. So in almost all cases you will want to set _exitcode_ to 0; the exceptions would be where you want to force an application-level exit. 

Even when the returned _exitcode_ is set to 0, the application can force application-level validation by doubling the **X** or **x** _cformat_ code. For example, if the _cformat_ = **VXX** then if the cell is changed, XTREE will first call the local validation routine, and then regardless of what it returns, it will exit with the normal -48 _exitcode_ . This capability is mainly of use as a transition strategy. For example, if you want to implement local validation in an existing program with application-level validation routines, you might start by reimplementing the validation logic in an SBX. You can then easily enable or disable the local validation (for testing, debugging, etc.) merely by placing or removing the SBX from the client. 

## **Debugging** 

The typically debugging technique is to embed DEBUG.PRINT statements which can be activated by the SET DEBUG TAGS command. But note that in the ATE environment, the SET command is executed on the server and doesn't affect the ATE client, so you can’t set specific tags that way. Instead, it's probably best to just use ordinary DEBUG.PRINT statements without (level,tags) qualifiers, in which case you can activate them by using the right-click menu on the System Messages window to set debug mode on the client. 

Another built-in debugging tool is the XTREE trace option. Open the System Messages window, right click on it for Properties, and then check the XTREE option. The window will then display details about each time the app calls XTREE, each time it returns to the app, plus each call to the local validation routine will generate the following two traces: 

```
Local Validation XTRA24V > Xcell=1,3, Tcell=1,4, colid=2, typeid=1, treeid=XTRA24, exitcode=0
```

```
Local Validation < target=1,4, status=9004, exitcode=0, valver=100
```

The first trace line shows information being passed to the local validation routine XTRA24V: _xtr.XROW, xtr.XCOL, xtr.TARGETROW, xtr.TARGETCOL, xtr.COLID, xtr.COLTYPEID,_ the TreeID, and the _exitcode_ . 

The second trace shows the information being returned: _xtr.TARGETROW, xtr.TARGETCOL,_ the _status_ , returned _exitcode_ , and the _valver_ (version indicator set by the validation routine.) 

## **Calling the Local Validation Routine from the Application** 

A-Shell Reference 

Page 3676 

There is nothing stopping you from using the local validation routine at the application level! But the application code would need to handle the logic to re-enter the tree. 

A-Shell Reference 

Page 3677 

## **- RE ENTRY AFTER CELL VALIDATION** 

If you use the X or x column codes to force XTREE to exit to the application for the purposes of cell validation, then you probably want to be able to re-enter the XTREE with a minimum of overhead and visual distraction. Here are few tips to facilitate this: 

• The `XTR.TARGETROW` and `XTR.TARGETCOL` parameters (see XTR.TARGET...) determine which cell will have the focus on re-entry. But if the specified cell is not editable, then XTREE will revert to selection mode (i.e. the focus will be on an item or row, with the idea of being able to select it, rather than on a cell for the purposes of editing it.) The user can typically proceed from selection mode into editing mode by clicking on the desired cell or by using navigation keys. 

• In most cases, the preferred opcode ( `XTR.OPCODE` ) is XTROP_RESELECT. The eliminates the re-loading of the data source array into the tree. All editable cells, however, will be updated. So it is possible to update any cells, not just the one that was just edited or that will get the focus. 

• To further reduce visual thrashing, set the XTF_NOREDRAW bit in the XTREE Flags parameter. This doesn't stop the editable cells from being updated, but does skip all of the positioning and sizing optimization logic that determine how the tree initially appears (particularly the column widths). 

• If data outside of the set of editable cells needs to change (rows added, etc.), then you will need to revert to opcode XTROP_REPLACE. In this case, the XTF_NOREDRAW flag has a slightly different effect: it doesn't stifle any display optimization logic, but it does eliminate the otherwise automatic deletion of the existing data before the new data is added. The main advantage of this is a slight reduction in the visual "flash." 

A-Shell Reference 

Page 3678 

## **EDITABLE IMAGE CELLS** 

Image cells (editable or not) may contain two text strings: an image file specification and some text to display along with the image in the cell (separated from the file spec by a comma). When updating an editable image cell during re-entry, you can use any of the following formats in the answer array field corresponding to the cell: 

|**Answer**|**Operation**|
|---|---|
|<blank>|clear text in cell, leave image alone|
|imgspec|replace existing image, clear text|
|imgspec,|same as above|
|text|leave image alone, replace text|
|,text|delete existing image from cell, replace text|
|imgspec,text|replace image, replace text|



Note that XTREE distinguishes between the "imgspec" and "text" cases by whether the field contains a valid image extension. 

On return from XTREE, the _answer_ array cells will contain just the text that displays in the cell along with the image, unless you edit the cell, in which case it will contain exactly what was entered. 

A-Shell Reference 

Page 3679 

## **- CLIENT SIDE TABLE LOOKUP** 

Table lookup refers to the scenario where the user enters a value in one column and the program looks up and automatically fills in a corresponding value in another column, such as a G/L account number and description or a State abbreviation and name. Although you can implement this using normal cell editing techniques, if the set of possible values is reasonable in size (hundreds rather than thousands or tens of thousands), and relatively static, it makes sense to pass the table to XTREE in advance and let it do the lookups internally on the client side rather than having to go back to the application for each lookup. This is especially true in the ATE environment, where the overhead of exiting back to the application on the server for the lookup operation is much greater. 

See LookupX and FileListX for details. 

A-Shell Reference 

Page 3680 

## **MULTIPLE TREE CONTROLS** 

You may have multiple XTREE controls defined and displayed at once. To do so, you must specify a unique control number (0=first, 1=second, etc.) in the XTR_CTLNO parameter, and use the flags XTF_MODELESS option (so that you can exit the first list without destroying it). This kind of arrangement can be useful for allowing the user to move items between two categories, or to present in one list box a set of possible items, and use the other to store the ones that have been chosen. 

See XTR.CTLNO for information on auto-assigning a control number. 

See also Scenarios Involving Multiple Trees. 

A-Shell Reference 

Page 3681 

## **CONTROLS IN CONTAINER WINDOWS** 

You may place an XTREE control within a container window such as a Modal Dialog Box or Tab Control. In the case of dialogs, this is automatic. (That is, if a dialog box is active when the XTREE control is created, it will automatically be a child of that dialog, and it is not necessary to set the XTR_PARENTID parameter.) In the case of a Tab control, you must specify the control ID of the Tab control in the XTR_PARENTID parameter. In either case, the coordinates will be interpreted as being relative to the client area of the container window. 

If you are going to open an XTREE in the middle of a screen, such that it will overlap other controls, it is highly recommended that you put it inside a dialog. Otherwise, to prevent the controls already present from "bleeding through" the XTREE, A-Shell will automatically save and delete any controls which overlap the XTREE's rectangle, and the restore them on exit. But that effect may seem a bit awkward, whereas a pop-up dialog is not only cleaner looking, but allows the user to move it around to see what is underneath. See the sample programs XTRA2 and XTRA5 for examples of XTREE controls within dialogs. 

A-Shell Reference 

Page 3682 

## **DESTROYING PICK LISTS** 

This happens automatically in the normal modal case (i.e. when XTF_MODELESS not set). Otherwise, you must explicitly destroy the tree control using XTR_OPCODE 3, or, since it is just another control object (like buttons, static text, etc.) it may be destroyed using Tab (-1,0). If the XTREE control is within another control (such as a dialog or Tab), then you may also destroy it by using AUI_CONTROL or Tab (-10,20) with opcode 4 and specifying the control ID of the parent. 

A-Shell Reference 

Page 3683 

## **TYPICAL CELL EDITING SCENARIOS** 

• If cell (3,5) is being edited, and the user clicks on cell (6,7), and the (3,5) cell requires validation (see _coldef_ codes x and X), then XTREE will exit with `XTR.XROW=3` , `XTR.XCOL=5, XTR.TARGETROW=6` and `XTR.TARGETCOL=7` . `XTR.XVALIDATE` will be set to 1 to indicate that the cell identified by `XTR.XROW / XTR.XCOL` should be validated. The _exitcode_ will be -48 (cell validation). If the application calls XTREE again to continue editing, the operation will start at the cell identified by `XTR.TARGETROW / XTR.TARGETCOL` If it doesn't like the contents of the cell that was just edited (3,5), it can force re-entry at that location by setting `XTR.TARGETROW` and `XTR.TARGETCOL` to `XTR.XROW` and `XTR.XCOL` (or it can just zero out `XTR.TARGETROW` and `XTR.TARGETCOL` to accomplish the same thing). 

- In the example just described, if, while editing cell (3,5) the user hits a navigation key (such as TAB or DOWN-ARROW) to move 

- the focus to another cell, then the outputs will be the same as just described, except that `XTR.TARGETROW / XTR.TARGETCOL` will be set to indicate the next cell to get the focus (based on the navigation key used and the layout of the tree.) `XTR.NAVCOD` will indicate the navigation key used. 

- Another variation of the example just given would be if, while editing cell (3,5) the user right-clicked on a cell that was not 

- editable but which had a context-menu defined. In that case, the context menu would first be displayed, and XTREE would wait for a menu option to be selected. If the user canceled the menu, the editing of cell (3,5) would resume. Otherwise, XTREE would exit with the _exitcode_ corresponding to the chosen menu option, but the `XTR.XROW` , `XTR.XCOL, XTR.TARGETROW, XTR.TARGETCOL` and `XTR.XVALIDATE` fields would be set just as in the first example. If the application tried to re-enter with changing the `XTR.TARGETROW` and `XTR.TARGETCOL` , if would enter in selection mode with the focus on that row, rather than in cell editing mode (since the cell was not editable). 

• A similar case occurs when the user terminated a cell editing operation by clicking on some control outside of XTREE. In this case, the `XTR.XROW / XTR.XCOL` will still point to the cell that was being edited, and `XTR.XVALIDATE` will be set to 1 to indicate whether it needs validation. But `XTR.TARGETROW / XTR.TARGETCOL` will be 0, since the target location is outside of the context of XTREE. If the application re-enters, since `XTR.TARGETROW / XTR.TARGETCOL` are 0, XTREE will use the incoming `XTR.XROW / XTR.XCOL` to set the starting focus. 

• A variation of the cased just describe is where the user is editing a cell and clicks on a cell in another XTREE. In this case, `XTR.XROW, XTR.XCOL` and `XTR.XVALIDATE` will be set according to the cell that was being edited, just as in the previous case. But `XTR.TARGETROW` and `XTR.TARGETCOL` will point to the cell that was clicked on in the other XTREE. The application will be able to identify this case by the fact that the _exitcode_ value will correspond to the other XTREE. It would presumably then want to 

A-Shell Reference 

Page 3684 

transfer the `XTR.TARGETROW / XTR.TARGETCOL` values to another copy of the _xtrctl_ structure (corresponding to the other XTREE) and then re-enter that XTREE. 

• When the editable cells in question are not text cells but checkboxes, it works slightly differently. Since checkboxes change value immediately when clicked, if they have the X or X code for validation, they will exit immediately at that time (rather than when the focus is moved to another cell). So if we go back to the first example above but imagine that the two cells in question, (3,5) and (6,7) are checkboxes, then if the user clicked on the (6,7) checkbox while the (3,5) checkbox had the focus, the return codes would all be the same as in that example, except that `XTR.XVALIDATE` would be set to 2 to indicate that it is the `XTR.TARGETROW / XTR.TARGETCOL` cell that needs validating. 

• If the focus is on an editable checkbox, and the user then clicks it, or uses the space bar to toggle the checkbox, if the column is coded for validation, XTREE will exit with both `XTR.XROW / XTR.XCOL` and `XTR.TARGETROW / XTR.TARGETCOL` pointing to that same cell. In this case it doesn't really matter whether `XTR.XVALIDATE` is returned as 1 or 2, since in either case, it is the same cell that needs validation. 

Note that `XTR.XVALIDATE=1` means that the `XTR.XROW/XTR.XCOL` cell (i.e. the one we just left) needs to be validated; while 2 means that the `XTR.TARGETROW/XTR.TARGETCOL` cell needs to be validated (the one we just clicked or are navigating to). In the case of checkboxes, they exit for validation only when the checkbox value changes, which occurs immediately when you click, rather than when you move the cell focus (as would be the case with a normal editable cell). So if you are focused on a checkbox at 5,7 and you click another checkbox at 3,9 then `XTR.XROW/XTR.XCOL` will be returned as 5,7, while `XTR.TARGETROW/XTR.TARGETCOL` will be returned as 3,9. But the checkbox that has changed is the one at 3,9 (the one clicked), so it is the one that should be validated. 

A-Shell Reference 

Page 3685 

## **SAVING USER ADJUSTMENTS** 

XTREE provides two built-in methods for preserving display adjustments (column sizing, ordering, sorting, etc.) between calls. The first involves the use of the XTR.COLORDER array to return the size and position of the columns to the application so that it may save it and recall it later. The second method is somewhat more powerful and requires no application involvement other than the following changes to the code calling each XTREE: 

- Use the new advanced _coldef_ directive TreeID to give the tree a unique identity, so that any user-directed modifications can 

- be associated with just that one tree. See notes below. 

- Assign the `XTR.USRCFG` field (in _xtrctl_ ) to one or more of the following, based on which user-configuration options should be 

- allowed to override the application-supplied values: 

|**Symbol***|**Value**|**Description**|**Other Parameters Over-ridden**|
|---|---|---|---|
|XTUCFG_COLWID|&h0001|Column widths|Dspwid (coldef),cformat H<br>switch|
|XTUCFG_COLSRT|&h0002|Sort order|`XTR.sortorder, XTR.columnsort`|
|XTUCFG_COLORD|&h0004|Column order|`XTR.usecolorder, XTR.colorder`|
|XTUCFG_FONT|&h0008|Text scale adjustment|See Mouse and Keyboard|
|XTUCFG_COLACT|&h0010|Active column|`XTR.columnactive`|
|XTUCFG_SRTORD|&h0012|Sort & active col|`XTR.columnactive, XTR.sortorder, XTR.columnsort`|
|XTUCFG_ALL|&h00ff|All||



A-Shell Reference 

Page 3686 

|**Symbol***|**Value**|**Description**|**Other Parameters Over-ridden**|
|---|---|---|---|
|**Definition file:**ashinc:xtree.def||||



The TreeID may consist of an alphanumeric name, with an optional :# suffix where # is the version of the tree (an integer value). The idea of the version is so that if you modify the tree layout during an application update, XTREE will know not to apply previously saved configuration details to the new tree layout. 

The TreeID (maximum 32 chars) may also contain "%p" which will be replaced at runtime by the name of the current program. The feature is mainly useful for XTREEs that are implemented within SBX routines that might be called by multiple programs, where you want to allow the user to maintain a separate configuration in each case. So for example, you might use 

```
TreeID=SelCus-%p:1
```

For ATE, see History notes below. 

User configuration adjustments are saved in the Registry automatically, provided that TreeID is defined. (If `XTR.USRCFG` is zero, the settings will be saved on exit, but not restored on entrance, which is one way to force the configuration back to applicationspecified settings.) 

Another way to deal with the possibility that the user accidentally makes a disastrous change to the configuration (like resizing a column to zero width, thus making it disappear entirely), is to define a Popup Menu and add to it the new special command $RESETCFG. For example: 

```
COLDEF=COLDEF+"0~0~x~H~PopupMenu=Misc,VK_xF666;Reset Columns,$RESETCFG~~"
```

Selecting this option from the menu will cause the tree configuration to be immediately reset back to the way the application had originally intended. 

The configuration information is saved in the Registry as: 

```
HKCU\Software\MicroSabio\A-Shell\XTREE\treeid
```

A-Shell Reference 

Page 3687 

where treeid is the value specified in the TreeID= _coldef_ clause, but with the version stripped. The version is saved as a sub-field rather than part of the key, to reduce the proliferation of Registry entries. 

## **History** 

- 2016 October, A Shell 6.3.1530: Number of columns whose reordering can be maintained between sessions expanded from 31 to the maximum number of columns supported by XTREE. 

- 2011 August, A Shell 5.1.1229:  Prior to ATE 5.1.1229, the "%p" code (for program name) did not work at all, and in fact, 

rendered the TreeID inoperable. As of ATE 5.1.1229, it does work, although subject to the server version. For server versions prior to 5.1.1217, "%p" is translated to "ATE". As of edit 1217, A-Shell on the server began transmitting the program name to ATE, allowing "%p" to be translated to the proper application program name. 

- 2008 October, A Shell 5.1.1126: Ability for users to save/restore their own adjustments added to A-Shell. 

2008 October, A-Shell 5.1.1127: Column configuration now saved even when tree is exited with ESCAPE (since this is a common exit not necessarily considered as "cancel"). The only way to exit without saving is now CTRL+C. 

A-Shell Reference 

Page 3688 

## **SCENARIOS INVOLVING MULTIPLE TREES** 

Programs which present multiple XTREE controls on the screen at once require additional consideration in order to deal with the complexities of the user clicking on one XTREE control while another one has the focus. This section will attempt to cover the basic issues involved and look at some specific examples. Note that some of the principles here (particularly the subject of the next section) apply more generally to clicking between any control and XTREE (and not necessarily between multiple XTREEs). 

## **Subtopics** 

- Click on Inactive Tree 

- Multiple Exitcodes 

- Sync Scrolling 

A-Shell Reference 

Page 3689 

## **CLICK ON INACTIVE TREE** 

When one control has the focus (whether an XTREE, INFLD, or some other), and the user clicks on another XTREE, the event is signaled by processing the XTR.KBDSTR parameter associated with the clicked-on tree. This will cause the current controlhandling routing (XTREE, INFLD, AUI_EVENTWAIT, etc.) to exit with the corresponding exitcode. The application would then typically invoke an XCALL XTREE operation for the clicked-on tree (as determined by the exitcode) to allow the user to work with that tree. 

Obviously in order to be able to identify the clicked-on tree, each tree should have a unique exitcode (i.e. a unique XTR.KBDSTR). While this generally applies to any control for which a click event should result in the application giving the control focus, clicking on an inactive XTREE has additional complications in that it may matter exactly where on the tree the click occurred (i.e. the row and column). For example, if the user clicks on an editable cell at location (3,5), there would be a reasonable expectation that the application would respond by putting the focus on the tree and specifically on that cell, putting it in editing mode. But the click event returns the same exitcode regardless of where the tree was clicked. How can the application identify the specific cell in order to respond as the user expects? 

There are two solutions to this problem. the first is that the `XTR.TARGETROW/COL` fields will be set according to the clicked-on tree (i.e. the previously inactive one), while the `XTR.XROW/XCOL` fields will indicate the last context of the tree that was active. (This solution only applies when the control which initially had the focus was XTREE.) 

A more general solution is that each XTREE control remembers any click events that occur while the tree is not active. The remembered click event can then be automatically processed when the application calls that tree to activate it. In the example just given, the application responds to the click on a particular tree by calling XTREE to activate it (typically in XTROP_RESELECT mode). As soon as it becomes active, that control can then respond to the saved click event (in this case putting the focus on cell (3,5) and going into editing mode. This scheme is particularly useful for events that aren't completely described by the `XTR.TARGETROW/COL` information (such as a SelChgExit triggered by the fact that the click on the inactive tree moved the selection bar of that tree). 

Another example of where the saved/recalled click mechanism comes in handy would be in the case of a right-click on an inactive tree which has a context menu defined (see PopupMenu). Initially, rather than displaying the context menu, the click information is saved and instead the exitcode associated with the clicked-on tree is generated, causing the current controlhandling routine to exit. When the application calls XTREE to process the clicked-on tree, XTREE will start by processing the deferred right-click information, causing the context menu to appear. (Assuming no undue delays in the application, this behindthe-scenes processing will be invisible to the user, who will simply see the context menu appear in response to the right-click.) 

A-Shell Reference 

Page 3690 

Both of these mechanisms are automatic. But there may be cases where the application decides it does not want to proceed with the user's intent, i.e. does not want the deferred click action to take place. For example, if the click on the inactive XTREE control occurs while the user was editing a text field (in INFLD, or perhaps in another XTREE), the typical plan would be for the current subroutine to return with the clicked-on XTREE's exitcode, so the application could call XTREE to process that event. But maybe the current value of the field violates some application rule, in which case the application may decide to just ignore the XTREE click and instead display a data-entry error message and return to editing the field. At some later point, the application may decide to activate the previously-clicked XTREE, but by then you would no longer want to process the deferred click event. XTREE uses a timer to attempt to determine whether the deferred click event is still relevant, but as of 5.1.1195, a new flag was added, XTF2_CLRDEFER, to force it to ignore (clear) deferred click event information (eliminating any question about the whether the timer expired). 

A-Shell Reference 

Page 3691 

## **MULTIPLE EXITCODES** 

The general A-Shell scheme for handling events relies on a single exitcode for each event. Usually this is sufficient, but with XTREE, a single click might logically be associated with more than one exitcode. (This complication is somewhat independent of the multi-tree scenario, but it is particularly acute here.) For example, consider a dialog with two XTREEs. The first tree has the focus, and the user is editing (changing) a cell (which is coded for validation). Then the user clicks on an item in the second tree. What is the appropriate exitcode? The one indicating the click on the inactive tree, or the one indicating validation required (-48) for the cell just exited? If the former, how does the app know to validate the edited cell? And if the latter, how does it know to activate the clicked-on tree? 

To help simplify these kinds of issues, XTREE uses a few simple rules for determining which exitcode to return. First, whenever an XTREE session is terminated by a click on some other control (whether another XTREE or something else), the other control's click exitcode will take precedence. For example, if you click on a button or another XTREE whose click string is "VK_xF101", XTREE will exit with exitcode -101. In any other case, if multiple exitcodes are applicable (for example, cell validation and a custom exitcode from a PopupMenu), the cell validation exitcode (-48), if applicable, will take precedence. Finally, to receive information about multiple exitcodes, you may specify the _xinfo_ parameter, which will be returned with a list of exitcodes. For example, in the case of a PopupMenu exitcode that interrupts a cell editing operation, the main exitcode parameter will contain -48, but _xinfo_ may contain 0,-48,-200. The leading "0," indicates the nature of the information in the _xinfo_ string, in this case, a list of exitcodes. And the -48,-200 indicates that both -48 (cell validation) and -200 (from the hypothetical PopupMenu choice) are applicable. (The first exitcode in the list may duplicate the value in the main exitcode parameter.) 

A sophisticated application could then respond to both, i.e. validating the cell editing operation, and responding to the menu event associated with -200. 

A-Shell Reference 

Page 3692 

## **SYNC SCROLLING** 

_Written November 2024_ 

Since property sheets effectively have only one data item per header item, it is sometimes useful to place multiple property sheets side-by-side as a way of displaying additional attributes associated one-to-one with the original items. In such a case, you can synchronize the vertical scrolling between the trees by setting the XTR.SYNCCTLNO field (in the XTRCTL parameter) to connect the 'scroll master' tree to the 'scroll slave'. Note that the 'master' and 'slave' terms here only refer to the fact that vertical scrolling the 'master' causes the 'slave' to scoll.  In every other respect the trees are independent. 

To implement, plug the XTR.CTLNO (XTREE control number) of the slave tree, plus one, into the new XTR.SYNCCTLNO field in the XTRCTL structure. The +1 is required since zero is a valid control number, but it makes more sense to allow the default zero to indicate the feature is not being enabled. Assuming that you are using the typical auto-assignment technique for control numbers, by pre-initializing XTR.CTLNO to -1, this would require you to create the slave tree first (in order to get its assigned XTR.CTLNO) and then plug that in to the master tree's XTR.CTLNO. 

The mechanism can be extended to a third tree by plugging it's XTR.CTLNO (+1) into the second tree's XTR.SYNCCTLNO.  But do not create a circle by linking a slave back to its master (an infinite message loop will result). 

## **History** 

- November 2024, A Shell 7.0.1765.5:  Vertical scroll mechanism now supports the mouse wheel. 

- November 2024, A Shell 7.0.1765.3:  Scroll syncing is now automatically bidirectional. The first scrolling operation on the 'master' tree automatically links the 'slave' tree back to the 'master', unless it was already linked to a third tree. 

- November 2024, A Shell 7.0.1765.0:  Add ability to sync vertical scrolling. 

XTREE refinement: 

A-Shell Reference 

Page 3693 

## **XTREE SAMPLE PROGRAMS** 

Several sample programs, with source code, are available to help you understand and use XTREE controls. The best place to get these and other sample programs is from the A-Shell SOSLIB. 

|**Program**|**Description**|
|---|---|
|TABDLG|Sample Tab control in a dialog, with anXTREEon one of the Tab pages.|
|XTRARY|Simple three-column list, array mode, using theSimple Multi-Column Coldef Syntax<br>.|
|XTRA2|A more sophisticated array-based example, supporting multi-level and multi-select options, and using the<br>Advanced Coldef syntax<br>to define columns with different formats, colors (row,column,cell), popup menus, etc.<br>Also supports option to display theXTREEinside of a dialog frame.|
|XTRA2A|Variation of XTRA2 illustrating`XTR.expandall`options with a 4 level hierarchy, also merge-into and merge-out<br>of options, row fonts.|
|XTRA3|An even fancier example demonstrating modeless operation, with options for multi-level and multi-selection.<br>The program also illustratesINFLDcheckboxes, buttons, TPRINT, some other GUI features, including tool tips<br>and dialog boxes.|
|XTRA4|Simple example of using twoXTREEcontrols at the same time.|
|XTRA5|Demonstrates checkboxes and editable text and combo boxes.|
|XTRA5M|Variation of XTRA5 using multi-selection.|



A-Shell Reference 

Page 3694 

|**Program**|**Description**|
|---|---|
|||
|XTRA6|Illustrates radio buttons, multi-line editable cells, colors.|
|XTRA7|Images and multi-line editable text. (A simple application for associating comments with images.)|
|XTRFIL|File-based example. You supply the file, including the column definitions in the first row. Demonstrates both<br>single and multiple selection options, and also the XTF_FILANS flag.|



A-Shell Reference 

Page 3695 

## **DEVELOPMENT TOPICS** 

This section of the documentation is written and intended for A-Shell developers seeking to take advantage of A-Shell capabilities to create or enhance existing applications. Most of the topics in this section are what we call A-Shell "extensions," which are capabilities or functions or processes that "extend" A-Shell beyond its original roots. Although using these extensions may increase the difficulty of maintaining backward compatibility, there are at least three reasons why you might want to do so anyway. 

- Some of A-Shell’s extensions, such as the expanding library of subroutines written in BASIC, provide you the tools to be more 

- productive as a programmer. 

- Some extensions, like memory mapping, may help you significantly improve your application’s performance. 

• Probably the most powerful reason is that once applications have been moved to the Windows or Unix environments, they will encounter users who expect certain things out of applications that were not commonly available under the old operating system. This is especially true under Windows, where users expect applications to support the mouse, graphics, GDI printing, message boxes, etc. But is also true under Unix where applications are expected to be able to handle signals, spawn background tasks, interface with the web and other services using socket-based protocols or FIFOs, understand native directories, etc. 

To accommodate these needs and interests, A-Shell has built up a variety of tools and other capabilities over the years, and the list is constantly growing. Many of A-Shell's expanded capabilities are in the form of subroutines or system configuration parameters. The information in this section overlaps those topics, and frequently references them, but is organized differently and presented with an emphasis on discussion and examples. 

There is no perfect way to organize these topics, and it is doubtful that you would want to read it from beginning to end, so you may need to rely on a combination of the table of contents, the index, searching and general browsing to find what you are looking for. 

## **Subtopics** 

- Input Mechanisms 

- Debugging Techniques 

- Hooks 

A-Shell Reference 

Page 3696 

- Dynamic Structures 

- Spreadsheet Interface 

- A-Shell as a CGI Web Service 

- GUI Development 

- Environment Variables 

- ISAM-A 

- Performance 

- Socket Programming 

- SBX Subroutines 

- Miscellaneous Topics 

A-Shell Reference 

Page 3697 

## **INPUT MECHANISMS** 

## _Written November 2025_ 

A-Shell supports several mechanisms for obtaining keyboard, file or socket input, summarized below. Note that the apparent overlap between some of the mechanisms, particularly the single character XCALLs, is a historical artifact related to supporting third-party developers migrating to A-Shell. Also note due to the ease of creating external SBX subroutines, it's common for developers to create their own custom input routines that wrap one or more of the common routines below. 

|**Mechanism**|**Data Source**|**ASB Category **|**Description**|**GUI* Support?**|
|---|---|---|---|---|
|INPUT|Keyboard or File|Statement|Line, raw, fields, CSV||
|GETKEY()|Keyboard|Function|Single character, test for availability||
|TINKEY|Keyboard|Xcall|Single character if available||
|ACCEPT|Keyboard|Xcall|Single character, wait||
|ACCEPN|Keyboard|Xcall|Same as ACCEPT but without echo|Yes|
|GET|Keyboard or File|Xcall|1 to n characters, timeout option||
|TCPX|Socket|Xcall|General TCP input/output|n/a|
|READ|Random or ISAM file|Statement|Record-oriented input|n/a|
|XREAD|Random or ISAM file|Statement|Variation of READ|n/a|



A-Shell Reference 

Page 3698 

|**Mechanism**|**Data Source**|**ASB Category **|**Description**|**GUI* Support?**|
|---|---|---|---|---|
|GETBYT|File|Xcall|Simplified version of GET||
|INFLD|Keyboard|Xcall|Sophisticated single-field input; text or GUI|Yes|
|SBXINP|Keyboard|SBX|Extended GUI wrapper for INFLD|Yes|
|INMEMO|Keyboard|Xcall|Multi line text, pick lists, menus|Yes|
|XTEXT|Keyboard|Xcall|Embedded word processor (GUI)|Yes|
|XTREE|Keyboard|Xcall|Grid-style display and input|Yes|
|AUI|Keyboard|Xcall|Edit box and other Windows controls|Yes|
|GET,<br>GET'xxx|ISAM-A file|Statement|Indexed record input||
|GETx|Keyboard|Xcall|Same asACCEPNbut with function key support|Yes|



* GUI support indicates that the mechanism has explicit support for GUI—it is able to create a GUI control to perform the function. Note however that the single character input routines, particularly without echo, are perfectly functional in a GUI environment since they don't affect the display. 

A-Shell Reference 

Page 3699 

## **DEBUGGING TECHNIQUES** 

_Written August 2025_ 

This section provides a summary / overview of several of the various tools, techniques and methods available for debugging ASB code. 

## **Print Statements** 

The oldest and most generic / primitive approach to debugging code is to insert PRINT statements to display variables at specific points in the logic. This is simple but unsatisfactory for several reasons, including: 

- They may interfere with the rest of the display—i.e., making it harder to see what the program is doing. 

- They might appear and disappear too fast to be seen, depending on what else is happening. You may use STOP or some 

- form of input to force a pause. 

- They aren’t generally visible in the AUI environment, because PRINT statements appear in the main (text) window which is 

- generally covered up by any AUI windows. 

- It requires repeated editing and recompiling—and then you need to remove them all for the release. 

## **Print Trace Statements** 

These offer several advantages over the plain vanilla PRINT statements: 

- They can be activated and deactivated, based on keywords and/or numeric levels, without re-compilation. 

- The output can be directed to a variety of targets (main window, special message window, file, custom SBX, etc.) without 

- interfering with the main display and therefore allowing you to study all the debug messages at leisure. 

- The syntax options allow for additional meta information to be easily included in the traces (time, date, location, variable 

A-Shell Reference 

Page 3700 

## names), making them both faster/easier to enter and providing more detailed and standardized output. 

For example, the following statement... 

```
Trace.print (9, “foo,bar,ledger”) “$# $T $L Look Mom!”, amount, subtotal, name$
```

... would output to the target location something like the following, assuming that the session DEBUG level was 9 or above, and/or that one of the tag keys “foo”, “bar” or “ledger” has been declared via a SET DEBUG command: 

```
1 15:19:35 00044b Look Mom!  amount=[123], subtotal=[5999.3], name$=”Homer”
```

While the statement may look complicated, the real beauty is that you can leave them in the code and just enable them when the need arises. And as a practical matter, you're likely to create a text shortcut or macro containing the common elements... 

```
trace.print (9, "tags") "$# $T #L",
```

... and copy/insert it in many places, potentially changing just the "tags" and appending a list of variables. 

Note that while the $L (location) macro does indicate exactly where the trace appeared (useful when you have a lot of similar looking traces to read through), it requires cross-referencing the hex numeric location with an LSX file (generated by the COMPIL /LF switch). A less precise but much more readable alternative, particularly for traces inside of functions or small source modules - would be to add one of the Auto Defined Symbols to the list of variables, e.g. 

```
trace.print (9, "tags") "$# $T #L", ABC_CURRENT_ROUTINE$, amount, subtotal, name$
```

## See TRACE Statements for more details. 

## **Trace PRAGMAs** 

These add an additional layer of flexibility on the Trace.Print statements by allowing you to tell the compiler to auto-generate Trace.Print statements for all or selected variables within a block of code. 

## - - See TRACE BEGIN and TRACE END for details. 

A-Shell Reference 

Page 3701 

## **SET TRACE Options** 

A-Shell supports many internal trace options that can be enabled and disabled via the SET TRACE command which can be of tremendous help in debugging code. Although these traces cannot be as tightly focused on your specific concerns as some of the techniques listed above, the big advantage is that they involve no programming. 

For programs involving a lot of function and procedure calls, one particularly useful option is FUNCS, which traces the values being passed into and returned from all functions and procedures. 

Note that although some of the TRACE options may be quite verbose, you can further fine tune the process by enabling/disabling XS them within your program using MX_SETTRACE . 

## **Log Files** 

Although Trace.Print statements can output to log files as an option, there are other ways to generate log files with debug information: 

• OPEN, PRINT and CLOSE statements. The main problem here is that you cannot easily enable/disable the option without adding custom logic. 

• MX_ASHLOGXS to output messages to the main ashlog.log file. This is probably not an appropriate method for general debugging since you don’t want to unnecessarily clutter up the main log file. It might however be very good for errors and exceptions, since you get the benefits of context, log rollover, and a handy viewer utility (VIEWASHLOG, discussed below). 

• Functions from the SOSLIB, such as those in SYSLOG.BSI in SOSLIB:[907,12], can help you simplify and standardize your own custom log files. 

• Although this is more targeted at exception reporting than debugging per se, the SOSLIB routine AXFLOG.SBX in SOSLIB: [907,60] provides a flexible framework for organizing and reporting a wide variety of events, including perhaps debug messages. Also see Event Tracing. 

A-Shell Reference 

Page 3702 

## **VIEWASHLOG** 

VIEWASHLOG.LIT is a general purpose viewer for the ashlog.log files, with several options which can be particularly useful for debugging, such as: 

- The ability to filter on one program or pid or user 

- In conjunction with compiler-generated symbol files, the ability to translate locations recorded by SET TRACE FUNCS into 

- actual source labels, functions and procedure names. 

## **A-Shell Debugger ADB** 

ADB.LIT is probably the most powerful and complex of the debugging tools and techniques currently available for A-Shell. It allows real-time / interactive debugging of a program running in a separate process, with the ability to set breakpoints, single step, examine individual variables, stack trace, etc. 

A-Shell Reference 

Page 3703 

## **HOOKS** 

## _Added December 2022_ 

A-Shell supports a number of hooks, also known as Plug-Ins, allowing developers to customize certain operational aspects of A- Shell. Hooks are based on defined interfaces to which you can attach your own (or third-party) modules to add capabilities or modify what otherwise would be the standard behavior of the core logic. In A-Shell's case, the preferred interface is an SBX call. If the SBX in question doesn't exist or hasn't been enabled via some configuration option, then the interface is bypassed. Otherwise the SBX is called, with considerable latitude to perform additional operations or modify the environment, provided it returns to the hook interface in the prescribed manner and in a reasonable amount of time. 

## Available hook interfaces: 

|**Hook Type**|**SBX Name**|**Description**|
|---|---|---|
|File Operations|Configurable|Called before or after selected file operations. SeeEstablish File Hooks<br>.|
|Group Licensing|ASLICGRP|Called on A-Shell startup to configure group licensing. SeeOther License Matters<br>.|
|Execution|XRUNLOG|Called on A-Shell startup/exit and program RUN startup/exit.|
|Print Preprocessing|Configurable|Called prior to sending file to printer. SeePrinter Configuration COMMAND<br>.|
|Exit|ASEXIT|Called on A-Shell exit.|



Additional planned interfaces: 

A-Shell Reference 

Page 3704 

|**Hook Type**|**SBX Name**|**Description**|
|---|---|---|
|Message Box|Configurable|(not yet documented)|



A-Shell Reference 

Page 3705 

## **DYNAMIC STRUCTURES** 

A Dynamic Structure (aka "Dynstruct") is like a regular structure—i.e., one defined with DEFSTRUCT—except that the definition occurs at runtime rather than compile time. This allows general-purpose compiled routines to adapt at run-time to a wide variety of data structures or record layouts, including ones not known about in advance. Typical applications include: 

- Generic file or audit trail viewers. 

- Report generators. 

- Handlers for SQL query results or CSV imports. 

- Security hardening of existing code (by modifying record structures at runtime to remove unauthorized fields without 

- breaking code referencing the authorized fields). 

- Creating XTREE array layouts on the fly. 

- Decoupling field-level logic from the physical layout of the containing record, i.e. adopting a more SQL-like approach to data. 

Dynamic Structures in A-Shell are implemented with the MX_DYNSTRUCT subroutine, which see for additional and related information. 

## **Dynstruct's Four Steps** 

There are four steps to using dynamic structures: 

- **Declare** a Dynstruct variable  to contain the structure 

- **Define** the Dynstruct layout 

- **Bind** the Dynstruct to a Variable 

- **Reference** the Dynstruct structure  and members as you would traditional structures / members. 

## **Typographical Note** 

The term "Dynstruct" is used here loosely as a shorthand for "dynamic structure" or for the A-Shell dynamic structure implementation in general. There is also a data type of the same name. When referring to it specifically, we’ll use all upper case 

A-Shell Reference 

Page 3706 

(DYNSTRUCT), even though data type names in ASB source code are not case sensitive. Code examples may use `DYNSTRUCT` and `dynstruct` interchangeably. 

## **History** 

## 2022 February, A-Shell 6.5.1711: Add Structure Definition Embedding (see following topic) 

## **Subtopics** 

- Declare a Dynstruct Variable 

- Define the Dynstruct Layout 

- Bind the Dynstruct to a Variable 

- Reference / Usage 

- Dynstruct Limitations 

- Dynstruct Error Handling 

- Dynamic Structure Examples 

A-Shell Reference 

Page 3707 

## **DECLARE A DYNSTRUCT VARIABLE** 

To enable the structure to be defined at runtime, an empty dynamic structure variable must be declared at compile time, using the type DYNSTRUCT **:** 

```
MAP1 ds, dynstruct   ! scalar dynamic structure
```

```
MAP1 DS2, DYNSTRUCT  ! another
```

As with other built-in types, the type name is case insensitive. 

Dynstructs are similar to dynamic X variables (X,0), except that they may be associated with—i.e. bound to—a structure definition. Until then, the structure is considered "uninitialized". Once the dynstruct variable has been bound to a defined structure, it behaves like a fixed-length instance of that structure. See Reference / Usage. 

A-Shell Reference 

Page 3708 

## **DEFINE THE DYNSTRUCT LAYOUT** 

_Rewritten July 2022_ 

The dynamic structure must be defined (or _"compiled"_ ) in a particular way—retaining the symbolic field names and positions— before it can be usefully associated with a declared dynstruct variable. This can be accomplished via either of the following methods: 

- By re-processing the DEFSTRUCT source code at runtime, either from a program file or from a string built by the application, 

- using MX_DYNSTRUCT with the DYNOP_DEF opcode. 

- By directing the compiler to embed the expanded DEFSTRUCT information in the RUN file, using one of the methods described 

- in Structure Definition Embedding. 

## **History** 

2022 February, A-Shell 6.5.1711, compiler edit 965:  Support Structure Definition Embedding. 

A-Shell Reference 

Page 3709 

## **STRUCTURE DEFINITION EMBEDDING** 

_Rewritten February 2022_ 

In order to bind a Dynamic Structure, the structure definition (i.e. the DEFSTRUCT) must be known at run time. This can be accomplished in one of two ways: 

- Call MX_DYNSTRUCT (DYNOP_INFO) to reprocess the DEFSTRUCT source code. 

- Arrange for the compiler to embed the desired DEFSTRUCT definitions into the RUN at compile time. 

The first method is perhaps the most flexible, but has the disadvantage of requiring that the source code be available at run time. The second method increases the size of the RUN file somewhat, but has the advantage of eliminating the need for the source code at run time. 

Structure definitions to be embedded may be identified by one of the following methods: 

## **Specifying individual structure definitions to be embedded:** 

```
DEFSTRUCT st_foo
```

```
    ...
```

```
ENDSTRUCT
```

```
++pragma EMBED_DEFSTRUCT st_foo
```

Each EMBED_DEFSTRUCT pragma identifies a single DEFSTRUCT, which must already have been seen by the compiler, for embedding. 

## **Enclosing a series of DEFSTRUCTs in a pair of EMBED_DEFSTRUCT_BEGIN and _END pragmas:** 

```
++pragma EMBED_DEFSTRUCT_BEGIN
```

```
    ...
```

```
++pragma EMBED_DEFSTRUCT_END
```

A-Shell Reference 

Page 3710 

Any DEFSTRUCTs between the _BEGIN and _END pragmas will be embedded. You can have multiple such _BEGIN and _END blocks within a program. 

## **Implicit embedding:** 

The .BINDSTRUCT() statement will cause the definition of the referenced structure to be embedded. For example: 

```
DEFSTRUCT ST_FOO
```

```
    map2 tender,s,10
```

```
    ...
```

```
ENDSTRUCT
```

```
map1 ds, DYNSTRUCT
```

```
map1 bar, ST_FOO
```

```
.BINDSTRUCT ds, bar    ! ST_FOO definition will be embedded
```

In addition, any defined structure instance passed to a function which receives it as a DYNSTRUCT will be embedded.  Building on the above example, ... 

```
bar.tender = "Joe"
```

```
call Fn'Dive(ds=bar)   ! ST_FOO will be embedded (because of how fn'foo receives it)
```

```
...
```

```
function Fn'Dive(ds as DYNSTRUCT)
```

- `? "Hi , I'm "; ds.tender        !  ds'tender = "Joe" (implicit binding)` 

A-Shell Reference 

Page 3711 

```
endfunction
```

## **History** 

2022 February, A-Shell 6.5.1711, compiler edit 967:  Feature added to A-Shell. 

A-Shell Reference 

Page 3712 

## **BIND THE DYNSTRUCT TO A VARIABLE** 

_Updated March 2025_ 

The binding operation associates a dynamic structure definition with a DYNSTRUCT variable, accomplished via one of the following methods. 

```
map1 ds, DYNSTRUCT            ! sample dynamic struct  (used below)
```

```
map1 stvar, ST_SOME_STRUCT    ! sample defstruct          "   "
map1 bar, ST_ANOTHER_STRUCT   ! another sample defstruct  "   "
```

- Explicit binding via MX_DYNSTRUCT: 

```
xcall MIAMEX, MX_DYNSTRUCT, DYNOP_BIND, status, dsname$, ds
```

- Explicit binding via .BINDSTRUCT: 

```
.BINDSTRUCT ds, stvar
```

- Implicit DYNSTRUCT by passing an instance of a defined structure to a function which receives it as a DYNSTRUCT: 

```
call Fn'Dive(ds=bar)   ! ST_ANOTHER_STRUCT will be embedded (because of how Fn'Dive receives it))
```

```
...
```

```
function Fn'Dive(ds as DYNSTRUCT)
```

Implicit binding works even for parameters defined with the :OUTPUTONLY qualifier. The received DYNSTRUCT variable will be empty regardless of the default value, if any, but will be bound. For example: 

```
defstruct st_cust
```

```
    map2 id,b,4
```

A-Shell Reference 

Page 3713 

```
    map2 name,s,30
endstruct
```

```
map1 cust, st_cust
cust.id = 99
cust.name = "Jacob"
```

```
call fn'foo(ds=cust)
end
```

```
? cust.name                  ! will be "Finkleheimer"
```

```
function fn'foo(ds="" as dynstruct:outputonly)
```

```
    ? ds.name                ! will be "" because of :outputonly
    ds.name = "Finkleheimer" ! valid because ds auto-bound to st_cust
    xputarg @ds
```

```
endfunction
```

## **See Also** 

- Structure Definition Embedding 

## **History** 

A-Shell Reference 

Page 3714 

- 2025 March, A Shell 7.0.1770.0, compiler edit 1064:  The :OUTPUTONLY qualifier no longer disables implicit binding. Prior to this update, the references to ds.name inside the function would have generated error 70 (invalid dynstruct reference) because the :outputonly would have defeated the automatic binding. 

A-Shell Reference 

Page 3715 

## **REFERENCE / USAGE** 

Once a dynamic structure variable has been declared and bound to a structure definition it is ready to be referenced or used. The general idea and syntax are similar to that for regular fixed structure members, with the main difference being that the members are unknown to the compiler, and instead have to be resolved at runtime. 

## **Assignment to Dynstruct as a Whole** 

If the destination dynstruct has not been bound, then the only allowable assignment to it is from another bound dynstruct, in which case the operation starts by auto-binding the destination dynstruct to match the source, followed by the assignment as described below. Note that this logic also applies when the source is a function that returns a bound dynstruct, and also when the assignment is to a function parameter via an XPUTARG statement. 

If the destination dynstruct has been bound, then an assignment to it is a raw copy, essentially equivalent to an n assignment to an instance of a defstruct or any other fixed length unformatted (X) variable. There is no attempt to determine whether the source and destination layouts are compatible, and the number of bytes copied will be determined by the smaller of the source and destination. The only difference with the dynstruct destination is that if the source is smaller than the destination, the remaining bytes in the destination are set to nulls. Unlike the defstruct or fixed length X variable assignment, where extra bytes in the destination are untouched. 

Any other assignment to an un-bound dynstruct results in an error #70 (invalid dynstruct reference). See History below for evolution of this behavior. 

## **Assignment from a Dynstruct as a Whole** 

A bound dynstruct acts the same as an instance of a defstruct or a fixed length X variable when used as the source in an assignment statement. The one exception is where the destination is also a dynstruct as described previously. 

An attempt to use an unbound dynstruct as the source of an assignment statement will generate ASB error #70, invalid dynstruct reference. 

## **Simple Indirect** 

The syntax here is identical to that for a traditional structure, e.g. 

```
ds.id = "Dynamo"        ! member name is "id"
```

A-Shell Reference 

Page 3716 

```
ds.amount = 12.34       ! member name is "amount"
```

Although the above syntax is the same as for traditional structures, the semantics are different. Instead of using the compiled definition of the member, the run-time interpreter looks up the member by its textual name —e.g. "id" or "amount"—in the dynstruct definition bound to the dynstruct variable ( `ds` in this example) to get the member’s data type and offset within the structure. 

This scheme is probably most useful for repurposing code originally written to work on traditional structures and conforms to the "duck typing" paradigm. 

## **Indirect Deferred** 

In this variation, the specified member name is a string variable whose _contents_ contain the actual member name, which is then treated as in the Simple Indirect scheme described above. The syntax uses a dot followed by the "at" sign, i.e. ".@",hopefully reinforcing the idea that the target member requires two steps to resolve. 

```
ds.@id = "Dynamo"       ! member name is value of id var
```

```
ds.@amount = 12.34      ! member name is value of amount var
```

The indirect deferred method is more flexible than the simple indirect in that it doesn’t require you to have code written in advance with any knowledge of the structure members. But most likely you would want to use a string array to hold the field names, rather than individual scalar variables. For example: 

```
map1 ds,dynstruct
```

```
dimx fnames$(0),s,64,auto_extend    ! array of potential member names
```

```
<load fnames$() array from some external source>
```

```
<define the dynamic structure and bind it to the variable ds>
```

```
for i = 1 to .extent(fnames$())     ! now cycle thru the members
```

```
    ds.@fnames$(i) = <value>
```

A-Shell Reference 

Page 3717 

```
next i
```

## **Array Dynstruct Members** 

Array dynstruct members present a potential syntactic ambiguity in that it isn’t obvious from the source code whether `ds.@fname$(i)` refers to a scalar member whose name is the value of `fname$(i)` , or an array member whose name is the value of `fname$` , in which case the subscript `(i)` applies to the dynstruct array member. 

To avoid this ambiguity, the compiler will treat `fname$(i)` as a normal array variable (as we would expect), i.e. as the container holding the name of the scalar dynstruct member. The only way to access an array member using the indirect deferred syntax is to use an array variable to hold the member name, which will result in two sets of subscripts, one for the array holding the member name, and one for the target dynstruct member array. For example, consider the structure: 

```
Defstruct ST_FOO
```

```
    map2 sku,s,10
```

```
    map2 price(3),f
```

```
Endstruct
```

If the structure is defined and bound to a dynstruct variable `ds` , and `fname$(1) = "sku"` and `fname$(2) = "price("` , then: 

- `? ds.@fname$(1)    ! refers to sku member` 

- `? ds.@fname$(2)(1) ! refers to ds.price(1)` 

- `? ds.@fname$(2)(2) ! refers to ds.price(2)` 

- `? ds.@fname$(2)(3) ! refers to ds.price(3)` 

A-Shell Reference 

Page 3718 

ASB  has no variable syntax with adjacent pairs of parenthesized terms, so there is no ambiguity for the compiler in recognizing that `fname$(2)(3)` can be compiled as two separate components: `fname$(2),` resolved at runtime `as "price("` , and `(3),` resolved separately at runtime and then combined with `"price("` to get the member name `"price(3)"` . 

Note that when referring to the name of a dynstruct array member, it must contain at least the open parenthesis, i.e. `"price("` rather than simply `"price".` 

## **History** 

- 2023 June, A Shell 6.5.1733:  Assignments from an initialized (bound) DYNSTRUCT to an uninitialized (un-bound) DYNSTRUCT now allowed. Previously, this condition generated an ASB error #70, invalid dynstruct reference. Conversely, assignment from an uninitialized DYNSTRUCT now generates ASB error #70; it previously acted like an uninitialized X,0 variable. 

- 2022 December, A Shell 6.5.1724:  Assignments to an uninitialized DYNSTRUCT now generate ASB error #67 (invalid reference to structure). Previously they acted as an assignment to X,0 variable. 

- 2022 December, A Shell 6.5.1723:  Assignments to a bound DYNSTRUCT now act as if to a fixed sized structure. Previously they acted as if the DYNSTRUCT variable was like an X,0 variable, expanding or contracting to match the size of the source. 

A-Shell Reference 

Page 3719 

## **DYNSTRUCT LIMITATIONS** 

In addition to the array syntax limitation described above, this section discusses some of the other complications and limitations in the syntax, capabilities and usage of dynstructs. 

## **Subtopics** 

- Numeric Members 

- Indirect Deferred Syntax Limitations 

A-Shell Reference 

Page 3720 

## **NUMERIC MEMBERS** 

The ability to mix string and numeric variables within expressions, which is a common feature of ASB, depends largely on the ability of the compiler to determine when a string-to-numeric or number-to-string conversion is required. For example, the following statement… 

```
If X = Y then P = Q
```

… could result in multiple compilation variations, depending on the types of the variables involved.  If `X` is a numeric variable and `Y` is a string variable, then the compiler will insert a `val(y)` to convert y to a number so that it can be compared directly with `X` . Similarly, if `P` is a string variable and `Q` is a numeric variable or expression, the compiler will insert a `str(Q)` to convert `Q` from a number to a string to be able to assign it to the string variable `P` . So, the statement gets compiled as: 

```
If X = val(Y) then P = str(Q)
```

In the case of dynamic structures, there is no way for the compiler to determine the member data types since they won’t have been defined yet. In order to avoid paralysis by indecision, it simply assumes that all structure members are of type string. This can lead to misunderstandings when doing arithmetic on numeric members of dynstructs. To avoid such misunderstandings, you have to keep reminding yourself that whenever a dynstruct member appears in an expression, it will be treated like a string, i.e. as if there was a str() function around it in the case of numeric variables. 

The main case where this is likely to give you the unintended result is when making assignments to a numeric dynstruct variable from an expression involving the "+" operator, which acts as concatenation when it occurs within a string expression.  For example, assuming `ds.qty` is a numeric variable, consider: 

```
ds.qty = 1 + 2     ! sets ds.qty to 12 ("1" + "2"), not 3
```

The problem is that since the compiler thinks that `ds.qty` is a string variable, it compiles the expression 1 + 2 as a string expression—i.e. string concatenation. At runtime that value "12" gets converted to numeric form to match the `ds.qty` type. 

A workaround is to just use a temporary variable that the compiler knows is numeric, e.g. 

```
MAP1 value,f
```

```
value = 1 + 2
```

```
ds.qty = value
```

A-Shell Reference 

Page 3721 

Another workaround is to use one of the Explicit Plus Operators, e.g. 

```
ds.qty = 1 #+ 2          ! force 1 + 2 to be treated as addition (3)
```

Yet another is to use the NUMEXPR() system function, e.g. 

```
ds.qty = NUMEXPR(1 + 2)  ! for expression to be numeric (3)
```

A variation of the problem occurs in a PRINT statement, since the compiler determines the type of each expression by the first term in the expression.  Consider… 

```
ds.qty = 3
```

```
? ds.qty + 1    ! prints 31 ("3" + "1")
```

Note that there is no problem with mixing numeric and string variables or expressions in a PRINT statement, as long as they are in separate terms. The problem above is caused by the fact that `ds.qty + 1` is a single term. 

Aside from using a temporary variable, another workaround is possible in this kind of situation, using a numeric function, e.g. 

```
Function Fn’Val(value as f8:inputonly) as f8
```

```
    Fn’Val = value
```

```
EndFunction
```

```
? Fn’Val(ds.qty) + 1
```

In the above case, the compiler knows that Fn’Val() is numeric, and it doesn’t need to make any assumptions about the types of the parameters—whether function or subroutine—since the parameter passing mechanism provides all of the necessary information for the receiver to do all of the necessary conversions. The compiler recognizes that `Fn’Val` is a numeric function, by the lack of a $ suffix, so it treats the expression Fn’Val(ds.qty) + 1 as numeric and performs addition instead of concatenation. 

A-Shell Reference 

Page 3722 

But beware: this trick doesn’t work for assignment statements, since in that context, the destination variable type determines the type of the expression on the right side of the assignment operator. 

Other than the string concatenation vs addition problem, for the most part the runtime system will be able to resolve the confusion left by the compiler incorrectly assuming that all dynstruct members are strings. 

## **Also See** 

- Explicit Plus Operators 

- NUMEXPR() 

A-Shell Reference 

Page 3723 

## **INDIRECT DEFERRED SYNTAX LIMITATIONS** 

As noted above, in the indirect deferred method, dynstruct members are referenced by the combination of the dynstruct variable, `.@` , and then a string variable containing the actual name of the dynamic member. If that member is an array, the name should have a `"("` appended to it. 

The variable containing the member name can only be a standard scalar or array string variable, e.g. 

```
ds.@fname$               ! scalar variable referencing scalar member
```

```
ds.@fname$(x)            ! array variable referencing scalar member
```

```
ds.@fname$(x+y)(a*b)     ! array variable referencing array member
```

What you can NOT do is use other kinds of string variables or expressions, such as literal strings, ordmaps, structure members, dot variables, etc. None of the following are legal: 

```
ds.@"price"              ! illegal syntax
ds.@a(b).c               ! illegal syntax
ds.@$map(a$)             ! illegal syntax
```

Note that in order to use indirect deferred syntax to reference an array element within the dynstruct, you must also use an array to reference to the field name, as in the "array variable referencing array member" example above. Refer back to the section on Array Dynstruct Members in the Reference / Usage Dynamic topic for further explanation. 

A-Shell Reference 

Page 3724 

## **DYNSTRUCT ERROR HANDLING** 

There are two general categories of errors that can occur in the course of working with dynstructs: 

- Status-type errors returned from the MX_DYNSTRUCT operations: define, bind, get layout, etc. These you need to explicitly 

- check the applicable return parameters for. 

- Run-time ASB errors: 

- Error 70, Invalid dynstruct reference, typically means that you are attempting to reference a member of a dynstruct variable 

- that has not been bound to a defined dynstruct. This is most likely a simple programming error, i.e. failure to follow the ' 

- necessary steps; see Dynstruct s Four Steps. 

- Error 71, Undefined dynstruct member, occurs when the member name you are trying to write to does not actually exist in 

- currently bound dynstruct definition. Attempts to read from an undefined member will act as if the member value is `.NULL` (displays as "<null>"). Any attempt to access an array member without specifying the subscripts will generate the error as well (reads and writes). See below for further comments. 

The undefined dynstruct member error (71) could be a simple programming error, or it could be something harder to avoid due to the nature of dynamically-defined structures whose members can change from one execution to the next. Although you can handle it like all other ASB errors—i.e. via the error-trapping mechanism, you may wonder how to anticipate the possibility so that your run-time code can avoid it. 

For the indirect deferred access method, where the member name is obtained from the run-time value of the variable used to hold it, e.g. `ds.@fname$` , the way to avoid the problem is to always retrieve the layout information—see Retrieve Layout of a Dynstruct—before using it. That information will always be up to date. 

That technique won’t help for the simple indirect access method ( `ds.fname` ) where the member name is essentially hard-coded into the program, even if it isn’t evaluated until run-time. If, for example, you decide to employ the indirect access dynstruct mechanism as a means of bottom-up security hardening, by removing unauthorized fields from the structures returned by data access functions, any rogue attempts to _update_ those removed members will generate the error 71. But attempts to merely _read_ them value will return `.NULL` , which is probably ideal in most cases. 

Note that if you are undefining structure members to prevent unauthorized access to them, if you also want to retain the original structure size, perhaps to allow writing the record back to the file with authorized updates, then you would need preserve the member definitions (i.e. preserve the layout) but change their names to prevent them from being used. That might be a less 

A-Shell Reference 

Page 3725 

than perfect means of protecting those fields, since they would still be visible by retrieving the layout information, but the assumption here is that the access is still limited by the existing application logic. The objective of bottom-up hardening of this type not being to prevent all programmer access but to prevent accidental user access from existing parts of the application. 

A-Shell Reference 

Page 3726 

## **DYNAMIC STRUCTURE EXAMPLES** 

The following examples are excerpted from the modules fndynst.bp in SOSLIB:[907,11] _,_ fndynst.bsi in SOSLIB:[907,10] _,_ and the sample program dynst1.bp in EXLIB:[908,79]. While the explanations and annotations below may be helpful, you should experiment with the modules themselves. 

## **Subtopics** 

- Define From String 

- Define From Source File 

- Bind a Definition to a Variable 

- Retrieve Layout of a Dynstruct 

- Accessing Members in the Dynstruct 

- Arrays of Dynstructs 

- Passing Dynstructs as Parameters 

A-Shell Reference 

Page 3727 

## **DEFINE FROM STRING** 

Here we create DEFSTRUCT in a string variable, including a couple of dependent DEFSTRUCTs, DEFTYPEs, and DEFINEs, and use it to define a dynstruct. 

```
map1 dsdef$,s,0             ! string to hold definition source
```

```
map1 fields,i,2             ! # fields (signed to allow error codes)
```

```
map1 stsize,b,4             ! size of the structure
```

```
map1 errmsg$,s,100          ! error messages
```

```
map1 lf,s,1,chr(10)         ! line terminator for structure lines
```

- `! Start with some preliminary definitions…` 

```
    dsdef$ = "deftype T_SKU = s,10" + lf &
```

```
       + "define LEN_NOTES = 30" + lf
```

- `! now define structures on which our Dynstruct will depend` 

```
    dsdef$ += "defstruct ST_PRICE" + lf &
```

```
        + "map2 cost,f,6" + lf &
        + "map2 wholesale,f,6" + lf &
        + "map2 retail,f,6" + lf &
        + "endstruct" + lf
```

```
    dsdef$ += "defstruct ST_DUMMY" + lf &
```

A-Shell Reference 

Page 3728 

```
        + "map2 manny,f,6" + lf &
        + "map2 moe,f,6" + lf &
        + "map2 jack,f,6" + lf &
        + "endstruct" + lf
```

```
! finally the Dynstruct we are defining...
    dsdef$ += "defstruct ST_TEST" + lf &
        + "map2 qty,b,2" + lf &
        + "map2 sku,T_SKU" + lf &
        + "map2 price,ST_PRICE" + lf &
        + "map2 notes(4),s,LEN_NOTES" + lf &
        + "endstruct" + lf
```

```
    fields = Fn'Dynst'Define(dsdef$,stsize,"ST_TEST",errmsg$)
```

```
    ? "    status: ";fields
```

```
    if fields < 0 then
```

```
        ? " status (fields): ";fields;" ("+errmsg$+")"
```

```
    else
```

```
        ?
```

```
        ? "    structsize: ";stsize
```

A-Shell Reference 

Page 3729 

```
        ? "    # fields:     ";fields;" (including overall structure)"
```

```
    endif
```

The above example uses a convenience wrapper function from fndynst.bsi in SOSLIB:[907,10] to handle the actual MX_DYNSTRUCT to define the dynstruct, the source of which is here: 

```
Function Fn'Dynst'Define(dsdef$ as s0:inputonly, &
```

```
                         stsize as i4:outputonly, &
```

```
                         dsname$ as T_DYN_NAME:inputonly, &
```

```
                         errmsg$ as s0:outputonly) as i4
```

```
    map1 locals
        map2 status,i,4
        map2 fields,i,4
```

```
    xcall MIAMEX, MX_DYNSTRUCT, DYNOP_DEF, status, dsdef$, fields, stsize, dsname$, errmsg$
```

```
    if status >= 0 then
        Fn'Dynst'Define = fields
```

```
    else
```

```
        Fn'Dynst'Define = status
    endif
    xputarg @stsize
```

A-Shell Reference 

Page 3730 

```
    xputarg @errmsg$
```

```
EndFunction
```

The function doesn’t add much value but does isolate the application somewhat from the technical details of the dynstruct definition process, which could be subject to change in the future. 

Note that at this point we’ve defined the dynstruct ST_TEST and can refer to it by its name ("ST_TEST") at any pointer later in this program, i.e. to bind it to a dynstruct variable, retrieve layout information about it, etc. 

A-Shell Reference 

Page 3731 

## **DEFINE FROM SOURCE FILE** 

As an alternative to building a string variable containing the DEFSTRUCT and all the dependent definitions needed for your dynstruct, you can also extract it from a standard program source file. This might not help in situations where the structure information does not become available until runtime, but it is extremely useful in situations where you are using the dynstruct mechanism to work on a range of data layouts whose structures already exist. For example, a generic file viewer, or report generator for a particular application with a large, but finite set of file layouts. Note that the source file does not have to be limited to containing just the DEFSTRUCTS of interest; it can be an entire program, with many nested ++INCLUDEs, somewhere among which the target DEFSTRUCT is buried. Here we define a dynstruct corresponding to the DEFSTRUCT named ST_FLDDEF which is found in the file dynstruct.def, which is included by fndynst.bsi, which is included by fndynst.bp. 

```
map1 dsname$,T_DYN_NAME     ! name of the Dynstruct/DEFSTRUCT
map1 dsdef$,s,0             ! @name of source file containing struct definition
```

```
map1 fields,i,2             ! # fields (signed to allow error codes)
map1 stsize,b,4             ! size of the structure
map1 errmsg$,s,100          ! error messages
```

```
dsname$ = "ST_FLDDEF"       ! name of DEFSTRUCT to create dynstruct from
```

```
dsdef$ = "@soslib:fndynst.bp[907,11]   ! note @ prefix signals file name
```

```
fields = Fn'Dynst'Define(dsdef$,stsize,dsname$,errmsg$)
```

```
? "fields: ";fields; ifelse$(fields >= 0, " [ok]"," Error: "+errmsg$)
```

A-Shell Reference 

Page 3732 

## **BIND A DEFINITION TO A VARIABLE** 

Binding a dynstruct definition to a dynstruct variable is a one-line operation, once the dynstruct has been defined and the variable declared… 

```
map1 status,i,4      ! status variable
```

```
map1 ds, dynstruct   ! dynstruct variable
```

```
status = Fn'Dynst'Bind("ST_TEST", ds)
```

```
if status < 0 then <error>
```

_As in the previous example, instead of using the_ MX_DYNSTRUCT _call directly, here we used a wrapper function from_ fndynst.bsi in SOSLIB:[907,10] _, mainly to isolate us from possible changes in the implementation of the underlying mechanism. Using the_ MX_DYNSTRUCT _directly would look like this:_ 

```
map1 status,i,4      ! status variable
map1 ds, dynstruct   ! dynstruct variable
```

```
xcall MIAMEX, MX_DYNSTRUCT, DYNOP_BIND, status, "ST_TEST", ds
```

```
if status < 0 then <error>
```

Once the dynstruct definition has been bound to the dynstruct variable ds, the variable will have same size as the defined structure (ST_TEST) and can be copied to/from traditional structure variables of the same type, or X,0 variables. The following assumes that ds was defined and bound as show above. 

```
map1 test1, ST_TEST  ! traditional structure
```

A-Shell Reference 

Page 3733 

```
test1 = ds           ! copy from DYNSTRUCT var to traditional structure
```

```
ds = test1           ! or vice versa
```

To copy a bound dynstruct variable and its bound definition to another dynstruct variable that has not yet been bound, use the MX_DYNSTRUCT DYNOP_COPY or its wrapper function. 

A-Shell Reference 

Page 3734 

## **RETRIEVE LAYOUT OF A DYNSTRUCT** 

Typically, to access the dynstruct effectively, you need to get the information about the fields organized in way to facilitate easy systematic access. The MX_DYNSTRUCT DYNOP_INFO call returns the layout information for a previously defined dynstruct. You can reference it by its name, or via a dynstruct variable which has been bound to the dynstruct definition. The layout is returned to you in an array of structures containing all the relevant attributes for each field. The array is of type ST_FLDDEF. Note that since the subroutine is not able to auto-extend the array, either you must make two calls—the first to get the number of fields, the second to get the actual array after re-dimensioning it to the necessary size—or use the fndynst.bsi wrapper function which takes care of those details. Here we get the layout of the previously defined ST_TEST dynstruct, from the first example, and from that we’ll create a simple array of field names to be used later for accessing the members by name. 

```
map1 fields,i,4
```

```
map1 i,i,4
```

```
dimx flddefs(10),ST_FLDDEF                 ! array of field definitions
```

```
dimx fnames$(0), T_DYN_NAME, auto_extend   ! array of field names
```

```
fields = Fn'Dynst'Get'Def'By'Name("ST_TEST",flddefs())
```

```
? "fields: ";fields; ifelse$(fields >= 0, " [ok]"," [Error]")
```

```
if fields > 0 then
```

```
    for i = 1 to fields
```

```
        fnames$(i) = flddefs(i).name
```

```
    next i
```

```
endif
```

A-Shell Reference 

Page 3735 

It may seem pointless to copy the field names from the `flddefs()` array of ST_FLDDEF structures into the simple array `fnames$ ()` , but we need a simple array, i.e. an array of strings rather than structures for syntactic reasons when actually referencing the dynstruct members. See Indirect Deferred Syntax Limitations. 

Also note that while in most cases, all we need in order to access the structure members are the field names, if any of the structure members are arrays, we’ll need to get that information from the flddefs() array and use it to form alternate syntax for accessing the array members. The syntax for referencing an array variable is necessarily different from that for scalar variables. 

A-Shell Reference 

Page 3736 

## **ACCESSING MEMBERS IN THE DYNSTRUCT** 

This example continues from the previous one in which we retrieved the layout of the dynstruct ST_TEST into a `flddefs()` array, and then created a simple array, `fnames$(),` of member names. Here we’ll bind the defined dynstruct to a dynstruct variable, make assignments to members via the Simple Indirect syntax, and then retrieve members using the Indirect Deferred syntax with the help of the `fnames$()` array. 

```
map1 status,i,4              ! status variable
map1 dstest, dynstruct       ! dynstruct variable
map1 fields,i,4              ! # fields (see previous example)
map1 i,i,2                   ! loop variable
```

```
dimx flddefs(10),ST_FLDDEF   ! array of field info (see prev example)
```

```
dimx fnames$(0), T_MAX_DYNAME, auto_extend ! array of field names (see prev)
```

```
<define ST_TEST, retrieve flddefs(), create fnames$() per above examples>
```

```
status = Fn'Dynst'Bind("ST_TEST", dstest)   ! bind ST_TEST Dynstruct to dstest
```

```
if status = 0 then          ! success
```

```
    ! samples assignments using simple indirect syntax
```

```
    dstest.sku = "SKU12345"
```

```
    dstest.qty = 2
    dstest.price.retail = 1.99
    dstest.notes(1) = "steal this product"
    dstest.notes(2) = "and live in infamy"
```

A-Shell Reference 

Page 3737 

- `! sample retrieval/display using indirect deferred syntax` 

```
    for i = 1 to fields
```

```
        ? dstest.@fnames$(i)    ! warning: see notes below
```

```
    next i
```

```
endif
```

Although the indirect deferred system is very convenient and indeed essential if the goal is to write totally generic code without any hard-coded references to specific dynamic structure members, there are a couple of complications which need to be considered when iterating through the fields by name; see the subtopics noted below. 

## **Subtopics** 

- Multi-level field structures 

- Array members 

A-Shell Reference 

Page 3738 

## **- MULTI LEVEL FIELD STRUCTURES** 

The ST_TEST structure contains members which are unformatted headers or containers for the actual lower-level fields. In fact, every structure has this issue with the first member, being the name of the overall structure rather than a proper member. So in the for/next loop, the print statement to print dstest.@fnames$(1) is equivalent to trying to print dstest itself, most like resulting in unintelligible garbage due to the mixture of field types, embedded raw binary bytes, etc. So, in general when iterating through the fields of a dynstruct, you probably want to skip the first one. In addition, the ST_TEST structure has a member (price) which itself a structure (ST_PRICE). It would make little sense to try print that structure as if it were a single printable entity.  One way to avoid this kind of problem is to refer back to the field attributes in the flddefs() array and avoid attempts to print members that are themselves structures or perhaps any member of type X. The following improved version of the for/next loop printing the fields illustrates a couple of approaches to that test: 

```
! sample retrieval/display using indirect deferred syntax
```

```
! (with logic to avoid printing members of type X or with sub-members)
```

```
for i = 1 to fields
```

```
    if (flddefs(i).vartyp and VARTYP_MASK) = VARTYP_X then
```

```
        repeat   ! skip X vars
```

```
    elseif (i < fields) and flddefs(i+1).pos = flddefs(i).pos then
```

```
        repeat   ! skip vars with sub-layouts
```

```
    else
```

```
        ? dstest.@fnames$(i)    ! print only non-X, non-multilevel
```

```
    endif
```

```
next i
```

Note that the test above for two adjacent fields with the same starting position, while a perfectly valid way to detect when a field is actually just a header for a collection of subfields, probably won’t come into play because in virtually all cases, those top-level 

A-Shell Reference 

Page 3739 

fields would be of type X (covered by the first test). The exception would be an overlay, but in that case, the overlaid members may not be adjacent. 

A-Shell Reference 

Page 3740 

## **ARRAY MEMBERS** 

Array members of the dynstruct present a special problem in that the syntax to reference an array is necessarily distinct from the syntax to reference a scalar. One has a parenthesized list of subscripts at the end, the other does not. Worse, there’s no current way to avoid writing different template statements for each array with a different number of dimensions. For example, the following statements show the indirect deferred syntax for a scalar member and for a series of array members of 1, 2, and 3 dimensions: 

```
ds.fnames$(i)          ! scalar member
ds.fnames$(i)(x)       ! 1-dimension array member
ds.fnames$(i)(x,y)     ! 2-dimension array member
ds.fnames$(i)(x,y,z)   ! 3-dimension array member
```

The compiler has no way to enforce agreement between the subscripts specified at compile time and the number actually needed for the target member at run-time, because it doesn’t know which dynstruct member  fnames$(i) will evaluate to. The runtime system can detect the most common error, where you use the first syntax above for an array member, i.e. you forget to supply any subscripts for the array member. That will produce an undefined member error; see Dynstruct Error Handling. But it cannot detect the case where the target array needs 3 subscripts, but you only supplied 2, or vice versa. That might cause a stack overflow or underflow, but it might just cause another part of the current expression (waiting its turn on the stack) to be misused as an array subscript, which in turn will almost certainly lead to another runtime error like illegal syntax code or undefined function. 

One take-away is to avoid using arrays in dynstructs. If that’s not possible, the other is that is you must then be careful to add logic like the following to detect the various array cases and to use the appropriate template statements depending on the dimensionality of each array member. 

- `! sample retrieval/display using indirect deferred syntax` 

- `! (with logic to avoid printing members of type X or with sub-members,` 

- `! and logic to handle array members)` 

```
for i = 1 to fields
```

A-Shell Reference 

Page 3741 

```
    if (flddefs(i).vartyp and VARTYP_MASK) = VARTYP_X then
```

```
        repeat                              ! skip X vars
```

```
    elseif (i < fields) and flddefs(i+1).pos = flddefs(i).pos then
```

```
        repeat                              ! skip vars with sub-layouts
    elseif flddefs(i).subs = 0 then         ! scalar member
        ? dstest.@fnames$(i)    ! print only non-X, non-multilevel
    else
```

```
        switch flddefs(i).subs
            case 1                          ! 1 dimension array
                for x = 1 to flddefs(i).subext(1)
                    ? dstest.@fnames$(i)(x)
                next x
                exit
```

```
            case 2                          ! 2 dimension array
                for x = 1 to flddefs(i).subext(1)
                    for y = 1 to flddefs(i).subext(2)
                        ? dstest.@fnames$(i)(x,y)
                    next y
                next x
                exit
```

```
            case 3                          ! 3 dimension array
```

A-Shell Reference 

Page 3742 

```
                for x = 1 to flddefs(i).subext(1)
                    for y = 1 to flddefs(i).subext(2)
                        for z = 1 to flddefs(i).subext(3)
                            ? dstest.@fnames$(i)(x,y,z)
                        next z
                    next y
                next x
                exit
         endswitch
    endif
next i
```

A-Shell Reference 

Page 3743 

## **ARRAYS OF DYNSTRUCTS** 

As noted above in Declare a DYNSTRUCT Variable, the dynstruct type currently only supports mapped scalar variables; no arrays, mapped or dimx. However, as also noted, you can work around this limitation by copying freely between dynstructs and arrays of traditional structures or X variables. In this example, we retrieve instances of ST_TEST structures—defined in the example Define a Dynstruct from a String—from a function, copying each to an array of type X that was previously dimensioned to match the size of ST_TEST. Then we reverse the operation, copying elements out of the array back into the scalar dynstruct variable to print the members. 

```
map1 dsdef$,s,0             ! string to hold definition source
```

```
map1 fields,i,2             ! # fields (signed to allow error codes)
```

```
map1 stsize,b,4             ! size of the structure
map1 errmsg$,s,100          ! error messages
```

```
map1 ds, DYNSTRUCT          ! var to contain the dynstruct ST_TEST
```

```
! assume dsdef$ string already built to define ST_TEST (see first example)
```

```
! now define it and get the size
```

```
fields = Fn'Dynst'Define(dsdef$,stsize,"ST_TEST",errmsg$)
```

```
if fields > 0 then
```

```
    dimx testarray(0), X, stsize, auto_extend   ! array to match dynstruct size
```

```
    do while <some condition>
```

```
        ds = Fn’Get’Structure’Data$("ST_TEST")  ! get data into the ds from somewhere
```

```
        i += 1
```

A-Shell Reference 

Page 3744 

```
        testarray(i) = ds             ! copy it into our unformatted array
```

```
    loop
```

```
    ! now reverse process, copying from the X array to our ds var
```

```
    do while i > 0
```

```
        ds = testarray(i)
     ? ds.sku
     ? ds.price.retail
     ? ds.notes(1)
```

```
    Loop
```

```
Endif
```

A-Shell Reference 

Page 3745 

## **PASSING DYNSTRUCTS AS PARAMETERS** 

As noted previously, the DYNSTRUCT data type acts essentially the same as X0, and so can be passed as a parameter or returned as the value of a function in all the same ways. The example above referenced a hypothetical function Fn’Get’Structure’Data$() which returned an instance of the specified DYNSTRUCT type. That function could be implemented something like the following: 

```
Function Fn’Get’Structure’Data$(dyntype$ as T_DYN_NAME) as DYNSTRUCT
```

```
    If Fn'Dynst'Bind(dyntype$, Fn’Get’Structure’Data$) = 0 then
```

```
        <populate the Fn’Get’Structure’Data$ structure members>
```

```
    Endif
```

```
EndFunction
```

In the above case, the function assumes that the specified dynstruct name (dyntype$) has been defined, and it binds it to the function’s local, previously uninitialized dynstruct variable—i.e. the name of the function and its return value. 

Note that to be realistic, the function would probably need to retrieve the structure layout information in order to determine how to populate the returned structure. See the previous example Retrieve Layout of a Dynstruct for details on that operation. 

In another variation on the same theme, we could implement a similar function which receives an already-bound dynstruct variable, updating and returning it in place. In this case the return value of the function could be a status value… 

```
Function Fn’Get’Structure’Data(dsx as DYNSTRUCT) as i2
```

```
    map1 dsname$,s,T_DYN_NAME
```

```
    dsname$ = Fn’Dynst’Name’From’Instance$(dsx)  ! get the Dynstruct name from instance
```

```
    if dsname$ = "" then
```

```
        ? "dsx not bound to a Dynstruct definition!"
```

```
    else
```

A-Shell Reference 

Page 3746 

```
        <update fields of dsx>
```

```
        Xputarg @dsx              ! return updated dynstruct
```

```
    Endif
```

```
EndFunction
```

As in the previous case, the example has left to your imagination the details of how it will update or populate the structure about which the compiler and programmer may have known nothing in advance. But it would presumably involve retrieving the layout information for the dynstruct, and then using the structure name and member names and types to match the fields up with some other data. 

A-Shell Reference 

Page 3747 

## **SPREADSHEET INTERFACE** 

In A-Shell 6.3.1500, the module AXL ("axle") was added to A-Shell. AXL ("A" from A-Shell and "XL" from Excel or XLS{X}* file format) is the licensing and incorporatation of a third-party library of spreadsheet functions called "LibXL." The purpose of including this library and its extensive tools for spreadsheet generation and manipulation is to make it easier—and in some cases, possible at all—for A-Shell developers to produce user-friendly spreadsheets for use outside of A-Shell. Spreadsheets may be created by two different means: 

CSV2XL:  This is a modestly capable implementation of LibXL which allows developers to take existing CSV files—i.e., those they have already been creating with A-Shell—and convert them into full-blown spreadsheets using fonts, colors, headings, number formats, etc. Since probably 90% of users and 90% of spreadsheets use a fairly small set of spreadsheet functions and capabilities, CSV2XL presents a simple means to generate basic spreadsheets. It incorporates the several most useful functions and ignores the rest of the library. The idea behind CSV2XL is to provide a tool that is limited in scope—i.e., simple to use and master—which meets most of the needs of most of the users most of the time. 

AXL:  This is the full function library, packaged appropriately and incorporated into A-Shell. Developers can use LibXL to build spreadsheets with virtually any degree of complexity and using any/all of Excel's vast functionality, and can also read and modify existing spreadsheets. It consists of approximately 125 functions with which developers can specify or change every aspect of a spreadsheet. 

*  AXL, including CSV2XL, supports both the old Excel file format XLS and the new file format XLSX. All references in this 

documentation to one or the other file formats should be understood to apply equally to the other format, unless explicitly stated otherwise. 

## u **Installation Notes** 

The main requirement for use of the LibXL spreadsheet interface is that the LibXL library be present so that it can be dynamically loaded when needed. The easiest and preferred way to accomplish this is to put the dynamic library in the same directory as the A-Shell executable. Typically this will be handled by the installer, but if you are installing it manually or piecemeal, or trying to debug it, here are the details for each platform: 

- Windows and ATE: The library file is libxl.dll, which just has to be present in A-Shell's bin directory. No registration or other 

- explicit initialization or configuration required. 

A-Shell Reference 

Page 3748 

• Unix: The library file name is libxl.so.1, but this is typically a link to the real library file, which is named libxl.so.w.x.y-zzz _,_ where w, x and y identify the library version, e.g. 3.6.5, and -zzz identifies the minimum Unix kernel version for compatibility, e.g. -el4 indicates that it will work with CentOS/RHEL 4 and above. A typical ls -l listing of your libxl files will look something like this: 

```
$ ls -l libxl*
```

```
lrwxrwxrwx 1 jack ashell       18 Feb 17 11:20 libxl.so.1 -> libxl.so.3.6.5.el4
```

**==> picture [430 x 10] intentionally omitted <==**

Note that the x (executable) flag must be set. If you have only the libxl.so.w.x.y-zzz file, you can create the libxl.so.1 link as follows: 

```
$ ln -s libxl.so.3.6.5.el4 libxl.so.1
```

For unrestricted operation, you may also need to update your A-Shell license to add the APEX or LIBXL options. 

A-Shell Reference 

Page 3749 

## **CSV2XL** 

CSV2XL converts CSV files to file in the XLS{X} format. It is written in ASB and compiled as a subroutine (CSV2XL.SBX). It is structured as a print filter, which means that it can be called automatically via the printer ini file COMMAND=SBX:CSV2XL interface, but, like all print filters, can also be called directly from an application. A convenient System Command version is also provided. 

In addition to the calling parameters specified below, the operation of CSV2XL is controlled by series of directives. Some of these directives apply to all spreadsheets all of the time, while other directives apply only to the current spreadsheet. Accordingly, they are divided into INI File Directives and CSV File Directives, which see for full information. 

Print filter syntax (within a printer ini file): 

## **COMMAND=SBX:CSV2XL{,inifile}** 

System Command syntax: 

## **CSV2XL fspec {,inifile}** 

Subroutine syntax: 

## **xcall CSV2XL, sts, fspec {, printer, switches, copies, form, inifile }** 

## **Parameters** 

|**Paramete**<br>**r**|**Type**|**I/O**|**Description**|
|---|---|---|---|
|sts|B,1|Out|Normally used to signal to the caller whether to it should print the file after<br>processing by the filter. Currently not used since XLS{X} files are generally<br>not printed directly.|
|fspec|String|In|The source file spec, e.g. xxx.csv|
|printer|String|In|Not applicable here.|



A-Shell Reference 

Page 3750 

|**Paramete**<br>**r**|**Type**|**Type**|**I/O**|**Description**|
|---|---|---|---|---|
|switches||Num|In|Not applicable here.|
|copies||Num|In|Not applicable here.|
|form|String||In|Not applicable here.|
|inifile|String||In|Specifies the ini file to use; default isBAS:CSV2XL.INI.|



## **See Also** 

- Notes on Syntax 

- All of the other topics in the "Other CSV2XL Topics" section 

A-Shell Reference 

Page 3751 

## **INI FILE DIRECTIVES** 

Listed below are the CSV2XL directives that are placed within the CSV2XL initialization file and apply to all spreadsheets generated with CSV2XL. Following this topic is a sample ini file and, following that, the CSV File Directives that may be inserted into and apply only to specific spreadsheets. 

|**Name and Example**|**Description if Needed**|**Possible Values (and default)**|
|---|---|---|
|**FORMAT section of ini file**|||
|OutputFormat=XLS||XLS, (XLSX)|
|HeadersFG=COLOR_BLACK|Headers text color|See Specifying Colors<br>; (COLOR_BLACK)|
|HeadersBG=COLOR_GRAY25|Headers background color|See Specifying Colors<br>; (COLOR_GRAY25)|
|HeadersBold=0||(1 for Yes), 0 for No|
|TotalsBG=COLOR_GRAY25|Totals background color|See Specifying Colors<br>; (COLOR_GRAY25)|
|FootnoteSubscripts=1||1 for Yes, (0 for No)|
|NumFormat|Defines the default format for<br>numeric columns|numfmtid|



A-Shell Reference 

Page 3752 

|**Name and Example**|**Description if Needed**|**Possible Values (and default)**|
|---|---|---|
|ColTitleTextRegex|Identify columns to format as<br>text by title pattern|See link at left|
|ColTitleFormatRegex|Associate specific formats with<br>columns by title pattern|See link at left|
|SplitCol=#|Freeze columns|See CSV File DirectiveSplitCol<br>for details (default 0)|
|SplitRow=#|Freeze rows|See CSV File DirectiveSplitRow<br> for details (default 0)|
|**DATA section of ini file**|||
|AddTotals=1|Add line and auto-total any<br>numeric column|1 for Yes, 0 for No|
|Headers=1|Treat first line as header|1 for header/yes, 0 for data/no|
|**POST section of ini file**|||
|SaveToDir=||Directory name , or blank for same as directory as CSV|
|SendToPC=0||0 for No, 1 for FTP, 2 for ATEAPX non-FTP|



A-Shell Reference 

Page 3753 

|**Name and Example**|**Description if Needed**|**Possible Values (and default)**|
|---|---|---|
|SendToDir=%TEMP%||PC folder name like c:\docs\sheets or %Environment<br>Variable%|
|Overwrite=0||2 for Yes, 1 for Warn, 0 for No|
|AppendSeqno=1||1 for Yes, 0 for No. Add a sequential number suffix to the<br>filename to avoid overwriting a prior version. For help<br>determining the filename created, see theSOSLIB function<br>Fn'FileAgeLatest$())<br>.|
|Launch=1||(1 for Yes), 0 for No|
|**XL section of ini file**|||
|The [XL] section may contain up to 9 directives that will act as if inserted at the top of the CSV source file. Note that the //XL prefix<br>is dropped, and that each line must start with a unique single-digit number.|||
|1,SetDefaultFont,fontname="Calibri",fontsize=12|||
|SetRGBMode<br>=0||1 for Yes, (0 for no)|



A-Shell Reference 

Page 3754 

## **NUMFORMAT** 

_New May 2025_ 

## **NumFormat=NUMFMT_xxx** 

## **NumFormat=mask** 

Specified in the [FORMAT] section of the CSV2XL.INI file, NumFormat defines the default format to use for columns that are purely numeric (instead of NUMFMT_GENERAL) and are not otherwise defined via SetCol directives. 

The first variation above uses the pre-defined NUMFMT_xxx symbols. For example: 

```
NumFormat=NUMFMT_NUMBER_SEP_D2
```

The second variation specifies a mask according to the specification for the mask parameter of the SetCol directive. For example: 

```
NumFormat=##,###,###.00;[Red]##,###,###.00
```

Note that for columns that are purely numeric, but which you want to leave unformatted such as account numbers, zip codes, etc., you can use the ColTitleTextRegex directive to exclude them from the NumFormat format based on the column title. 

## **History** 

- 2025 May, A Shell 7.0.1772, CSV2XL.SBX 2.2(304):  Directive added to CSV2XL.SBX. 

A-Shell Reference 

Page 3755 

## **FORMAT BY COLUMN TITLE** 

_Written June 2025_ 

CSV2XL provides two mechanisms whereby the format applied to a column of data can be specified by identifying the pattern of the column title. Regular expressions (regex) are used for the pattern recognition. 

## **Format Column As Text** 

A common problem in Excel conversions is that Excel treats all numeric-looking data as numbers. That is fine most of the time, but not when the numeric-looking data are part numbers, or postal codes, or other "text data that just happens to be numbers." Using the ColTitleTextRegex directive, CSV2XL basically says "If the column title looks like the specified regular expression, then the data in the column should be treated as text rather than numbers." 

## **Example1** 

```
ColTitleTextRegex=zip|(part *(no|num|#))|phone|sku
```

This expression would identify any column title containing "zip", "phone", or "part" followed by optional space and then "no","num", or "#." The data in the column would therefore be treated as text. 

Matching is case insensitive, not anchored. Use ^ and $ for start/end anchoring. 

## **Example2** 

ColTitleTextRegex supports directives from 1 to 9 to make it easier to edit a long pattern list in the ini file. The maximum combined length is 500 characters, but you can break it up, e.g. 

```
ColTitleTextRegex=zip|(part *(no|num|#))|phone|sku|invno|wo|code|po
```

```
ColTitleTextRegex2=acct *(no|num|#)|status|icd|
```

```
ColTitleTextRegex3=diag|m\d|diag\d
```

```
ColTitleTextRegex4=street #|house #
```

```
ColTitleTextRegex5=Dept#|^id|^prov|^loc|^pos
```

```
...
```

A-Shell Reference 

Page 3756 

```
ColTitleTextRegex9=Numero|Cantidad
```

Note that it doesn't matter whether each line ends with a pipe (|) or not; they will be concatenated with pipe separators as required.here. 

## **Format Column As Anything** 

The directive described above, ColTitleTextRegex, was created near the beginning of CSV2XL development. As time went by, it became clear that CSV2XL needed a more general and comprehensive "format by recognition" directive. Users liked the "recognize" part but wanted more flexibility with the "format" part. This led to the creation of the ColTitleFormatRegex directive, which works exactly as above but provides the ability to format the column as text or any other supported Excel format. Note that "text" is simply one of the available number formats, making the original ColTitleTextRegex directive completely redundant; it continues to work only for backward compatibility. 

CSV2XL supports up to four format directives to associate formats with column titles. Unlike the otherwise similar ColTitleTextRegex directives, these are each independent, associating a pattern with a number format: 

```
ColTitleFormatRegex1=format,pattern
```

```
ColTitleFormatRegex2=format,pattern
```

```
ColTitleFormatRegex3=format,pattern
```

```
ColTitleFormatRegex4=format,pattern
```

As with the NumFormat directive, the format may be either a predefined NUMFMT_xxx symbol or a mask; see the //XL,SetCol directive for details. Note that unlike most other directives, these take two arguments, separated by a comma. If either the format or the pattern contains commas, you must enclose it in quotes, e.g.: 

```
ColTitleFormatRegex1="##,###.00[red]##,###.00",Amount|Total|Price|Value
```

A-Shell Reference 

Page 3757 

## **SAMPLE INI FILE** 

Many of CSV2XL's options are configurable via an initialization file, either the default bas:csv2xl.ini or another file specified in the calling interface. The options are mostly either self-explanatory or explained by way of comments in the sample csv2xl.ini file included with the release and reproduced below. 

_Note: the blank lines below do not exist in the actual file. They are inserted here to make the text more readable. Likewise, the section headers are in bold underline below, but of course not in the ini file._ 

```
;CSV2XL.INI - Configuration file for CSV2XL.SBX
```

## **`[FORMAT]`** 

```
;OutputFormat choices: XLS (default), XLSX
```

```
OutputFormat=XLS
```

```
;Headers Text color (Use COLOR_xxx from libxl:libxl.def; default=COLOR_BLACK)
```

```
HeadersFG=COLOR_BLACK
```

```
;Headers background color (default=COLOR_GRAY25, may use &hxxxxxx hex notation for RGB)
```

```
;HeadersBG=COLOR_GRAY25
```

```
HeadersBG=&hd0e0f0
```

A-Shell Reference 

Page 3758 

```
;Headers bold option (default=1)
```

```
HeadersBold=0
```

```
TotalsBG=COLOR_GRAY25
```

```
;regex pattern applied to col titles to force the column to be treated as text (zip, part #, etc.)
```

```
;Example: zip|(part *(no|num|#))|phone
```

```
; matches any title containing "zip", "phone", or "part" followed by optional space and then "no","num", or
"#"
```

- `; matching is case insensitive, not anchored (use ^ and $ for start/end anchoring)` 

```
ColTitleTextRegex=zip|(part *(no|num|#))|phone|sku
```

```
;Headers bold option (default=1)
```

```
HeadersBold=0
```

```
;SplitRow specifies first row after split (after fixed rows); 0=no, 1=based on headers (default); n = n-1
fixed rows at top
```

```
SplitRow=1
```

- `;SplitCol specifies first column after fixed columns (default 0); 0/1 = no split, n = n-1 fixed cols at left` 

```
SplitCol=0
```

A-Shell Reference 

Page 3759 

## **`[DATA]`** 

```
;AddTotals: 1=yes (add line and auto-total any numeric col)
AddTotals=1
```

```
;Headers=0 (treat first line as data); =1 (treat as headers) (default=1)
Headers=1
```

## **`[POST]`** 

```
;Directory to which output should be saved (blank for same as CSV)
SaveToDir=
```

```
;Send output to PC client (1=FTP, 2=ATEAPX non-FTP)
SendToPC=0
```

```
;If sending to PC, use this directory
SendToDir=%TEMP%
```

```
;Allow replacement of existing XLS{X} output file
```

```
Overwrite=0
```

A-Shell Reference 

Page 3760 

```
;Append a sequence number suffix to output file to make it unique
```

```
AppendSeqno=1
```

```
;Launch spreadsheet application (e.g. Excel) to view output
```

```
Launch=1
```

```
;The [XL] section may contain up to 9 directives that will act as if inserted at the top of the CSV source
file.
```

```
;Note that the //XL prefix is dropped, and that each line must start with #, where # is a unique digit from
1-9.
```

## **`[XL]`** 

- `1,SetDefaultFont,fontname="Calibri",fontsize=12` 

```
;2,SetRGBMode
```

A-Shell Reference 

Page 3761 

## **CSV FILE DIRECTIVES** 

## _Updated May 2023_ 

To assert greater control over details of the output file formatting, you may optionally insert //XL directives into the CSV file. These should be at the top, before any data lines, except in the case of the //XL,SetRow directive, which may be inserted anywhere above the affected row(s). 

The syntax for the //XL directives is a bit tricky, and differs from normal A-Shell conventions. See Notes on Syntax. 

|**Directive**|**Operation**|
|---|---|
|AddComment|Add a cell comment.|
|AddFootnote|Add explanatory note at bottom of sheet.|
|AddLink|Create link from specified cell to footnotes.|
|AddSheet|Add or rename sheet.|
|AddTotals|Override Totals directive in ini file.|
|DefineFont|Define a font and give it an identifier.|
|DefineFormat|Define a format and give it an identifier.|
|MergeCells|Merge cells.|



A-Shell Reference 

Page 3762 

|**Directive**|**Operation**|
|---|---|
|SetAppendSeqno|Override AppendSeqno directive in ini file.|
|SetBanner|Add text and special formatting to line one.|
|SetCol|Set attributes for one or more columns.|
|SetDefaultFont|Set default font.|
|SetGroup|Create a row group.|
|SetIni|Override default ini file name.|
|SetLaunch|Override Launch directive in ini file.|
|SetOutputFormat|Override OutputFormat directive in ini file.|
|SetPageBreak|Force page break at specified location.|
|SetPrint|Set various print features.|
|SetRGBmode|Enable RGB color specifications.|
|SetRow|Set attributes for a row.|



A-Shell Reference 

Page 3763 

|**Directive**|**Operation**|
|---|---|
|||
|SplitRow|Freeze one or more rows at top of sheet.|
|SplitCol|Freeze one or more columns at left of sheet.|



A-Shell Reference 

Page 3764 

## **ADDCOMMENT** 

## **AddComment** 

## **//XL, AddComment, row=##, col=##, text=text {,width=pixels} {,height=pixels}** 

As of A-Shell 6.5.1668, this directive is ignored for XLSX format—i.e. is only supported for XLS format. 

## **DefineFont** 

## **//XL, DefineFont, {fontid=}<fontid>, {name=<name>} {,size=<pointsize>} {,color=COLOR_xxx}** 

**{,** Common //XL Parameters **}** 

Defines a font and gives it an identifier which can then be used in a subsequent DefineFormat directive. This is only necessary when you want to use the same font in multiple formats, columns or rows. Otherwise, you can specify the font attributes directly when defining the format or setting the column or row attributes. 

## **Examples** 

```
//;Define bold green font, assign fontid “bold_green”
```

```
//XL,DefineFont,fontid=bold_green,bold,COLOR_GREEN
```

```
//;Define 14 Courier font, name it “courier14”
```

```
//XL,DefineFont,fontid=courier14,fontsize=14, fontname=Courier New
```

A-Shell Reference 

Page 3765 

## **DefineFormat** 

## **//XL, DefineFormat, {formatid=}<formatid> {,** Common //XL Parameters **}** 

Defines a format and gives it an identifier which can then be used in a subsequent SetCol and SetRow directives. This is only necessary when you want to use the same format in multiple columns or rows. Otherwise, you can specify the format attributes directly in the SetCol and/or SetRow directives. 

## **Examples** 

```
//;Define format named “fmtx” using bold_green font
```

```
//XL,DefineFormat,formatid=fmtx,fontid=bold_green,ALIGNH_CENTER
```

```
//;Define format named “fmtpink” with pink bg, bold violet text
```

```
//XL,DefineFont,formatid=fmtpink, FILLPATTERN_SOLID, patternfgc=COLOR_PINK, bold, fontcolor=COLOR_VIOLET
```

## **MergeCells** 

## **//XL,MergeCells,colfirst=#,collast=#{,rowfirst=#}{,rowlast=#}** 

Merges the specified cells into one. The row parameters default to the next data row following the directive, so it can be inserted just before the data in question. For example: 

```
//XL,MergeCells,colfirst=3,collast=5
```

```
data1,data2,data3,,,data6
```

In the above example, columns 3-5 would be merged and would contain "data3". Note that you don't normally try to put anything into the cells that otherwise disappear as part of the merge. 

A-Shell Reference 

Page 3766 

## **History** 

- 2025 February, A Shell 7.0.1769: Directive added to CSV2XL.SBX. 

## **SetAppendSeqno** 

## **//XL,SetLaunch,#** 

## **//XL,SetAppendSeqno,#** 

Overrides the AppendSeqno options from the ini file. 0 disables, 1 enables. Must be placed after any SetIni directive. 

## **SetDefaultFont** 

## **//XL, SetDefaultFont {,fontname=<fontface>} {,fontsize=<pointsize>}** 

Establishes the default font face and size to be used by the spreadsheet app. 

## **Example** 

```
//XL,SetDefaultFont,fontname=Courier New,fontsize=12
```

## **SetIni** 

## **//XL, SetIni, <inifile>** 

Establishes the name of the ini file, overriding the one specified in the printer initialization file or subroutine. This directive can only appear once in a source file, and must appear at the top, before any data lines. 

## **Example** 

A-Shell Reference 

Page 3767 

```
//XL,SetIni,BAS:CUSXLS.INI
```

## **SetLaunch** 

## **//XL,SetLaunch,#** 

Overrides the Launch option from the ini file. 0 disables, 1 enables. Must be placed after any SetIni directive. 

## **SetOutputFormat** 

## **//XL,SetOutputFormat,<format>** 

Overrides the OutputFormat directive in the ini file. The two <format> options in either case are XLS and XLSX. As with the SetIni directive, it has to appear in the CSV source file prior to any lines that do not start with //XL. 

## **SetPageBreak** 

## **//XL,SetPageBreak{row=#}{,col=#}** 

Forces a break to occur after the specified row and/or column when the spreadsheet is printed. The default row is the current position. To set a column page break without a row pagebreak, set row=-1. Note that page breaks may be seen in Excel by activating Page Break Preview from the View menu, or by using the Print Preview. 

## **History** 

- 2025 February, A Shell 7.0.1769: Directive added to CSV2XL.SBX. 

## **SetRow** 

A-Shell Reference 

Page 3768 

## **//XL, SetRow, {row = #} {,rowfirst=#} {,rowlast=#} {,height = #} {,Common //XL Parameters}** 

Sets attributes for a row or group of rows. The first row is considered row 1, whether it contains headings or data. It should be specified before the affected data rows. If the none of the row* parameters are specified, the directive affects the next row to be output. To specify all rows, set rowlast to a number greater than the actual number of rows (e.g. 999999).  Height is set in typographical points. The directive also supports setting attributes (such as colors) for the next row or a specified set of rows yet to be output. 

## **SplitRow, SplitCol** 

## **//XL, SplitRow, row** 

## **//XL, SplitCol, column** 

Note that these are good examples of directives that may be in either the ini file or the CSV file. 

The Split options might also be thought of as "freeze" as they control the number of rows and/or columns that remain in position while the others are allowed to scroll vertically and/or horizontally. The default for SplitRow is 1, which freezes the top 1 or 2 rows, depending on whether a banner was defined. Setting it to a larger number freezes the rows less than the specified number (e.g. SplitRow,4 freezes 3 rows.) SplitCol defaults to 0; both 0 and 1 result in no columns frozen. To freeze N columns, set SplitCol to N+1. 

Also note that the Excel user interface refers to this same concept as "Freeze Panes". Here, the "split" is a reference to "split scrolling", i.e. the division between the rows or columns that are frozen in place at the top/left, and the ones that are subject to scrolling. 

The row and column "number of" parameters specifies the first row (from top) or column (from left) subject to scrolling, or one more than the frozen row or column. For example: 

```
//XL,SplitRow,3
```

```
//XL,SplitCol,2
```

would cause the first two rows and first column to be frozen (not scroll). 

A-Shell Reference 

Page 3769 

## **ADDFOOTNOTE** 

_Written November 2019_ 

## **//XL, AddFootnote, {text=} text {,title=text}** 

AddFootnote provides a convenient way to create footnotes in your spreadsheet. Footnotes are useful for providing explanatory details about how the data in the spreadsheet was compiled. 

AddFootnote can appear multiple times anywhere in the file. Each instance of adds a footnote to the bottom of the current sheet. If no title is specified, the default title "Footnotes:" will be used. For example, 

```
//XL,AddFootnote,1) This is footnote #1
```

- `//XL,AddFootnote,"2) Data source: Manny, Moe and Jack"` 

The above pair of directives would cause the following to be added to the bottom of the current sheet, below any totals: 

## + Footnotes: 

The actual footnotes are collapsed within the group; clicking the "+" will expand them to show: 

Footnotes: 

- 1) This is footnote #1 

- 2) Data source: Manny, Moe and Jack 

## **Notes** 

- Footnotes will appear in the order the corresponding directives appear. 

- There is no automatic formatting or numbering; you will need to supply your own. 

- Make sure to quote the footnote in the directive if it contains commas. 

## **History** 

A-Shell Reference 

Page 3770 

- 2019 November, CSV2XL.SBX edit 241, first included with A Shell 6.5.1671: Function added to A-Shell. 

A-Shell Reference 

Page 3771 

## **ADDLINK** 

_Added May 2023_ 

## **//XL, AddLink, row=<#>, col=<#>, text=<display text> {,linkto=<link target>} {,** Common //XL Parameters **}** 

Addlink creates a link in the specified cell, with the specified display text, that jumps to the specified link target. Links are particularly useful for drawing the user's attention to explanatory footnotes (see AddFootnote) which might otherwise go unnoticed at the bottom of the sheet. But they can also be useful for creating a free-form table of contents to sections in a very large spreadsheet, or to jump from one sheet to an associated part of another. 

The _row_ and _col_ parameters should be numeric, starting at 1 for the first row / column. Note that the link occupies only a single cell. If the link is to share row 1 with a banner (see SetBanner), then the banner size will be adjusted accordingly. For example, if the link is to occupy the cell A,1 then the banner will start in column B. Or, if there are ten columns in the spreadsheet and the link is positioned in row 1, column 10, then the banner will occupy row 1 columns 1 thru 9. 

The _text_ parameter determines what will display in the cell; blue and underlined like typical links, unless overridden via the Common //XL Parameters. It should probably be kept short since they occupy only a single cell and Excel does not always know how to properly wrap them. 

The _linkto_ parameter can be in one of the following forms: 

- A standard Excel cell address on the current sheet, e.g. 

```
linkto=A99
```

## `linkto=$Q$2` 

• A special alias link to the start of the footnotes; see AddFootnote. This is useful when you don't know what row the Footnotes will appear on when you are outputting the AddLink directive. 

## `linkto=@footnotes` 

- To link to a cell on another worksheet, prefix the cell address with the worksheet name and an exclamation point, e.g. 

```
linkto=Detail!A1
```

A-Shell Reference 

Page 3772 

- To link to a URL, just specify the URL, including the scheme prefix: 

```
linkto=https://www.microsabio.com
```

AddLink directives can appear anywhere in the source document; before or after the row in question has been populated. The one exception is that if the link location is sharing row 1 with SetBanner, the AddLink directive must come between the SetBanner and the headers. 

See SetBanner for an example. 

## **History** 

- 2023 May, A Shell 6.5.1731, CSV2XL.SBX edit 279: Function added to A-Shell. 

A-Shell Reference 

Page 3773 

## **ADDSHEET** 

_Updated May 2019; see History_ 

## **//XL, AddSheet {,srcbook=xxx.xls} {,dstbook=yyy.xls} {,sheetname=zzz}{,index=1} {,deletefirst} {,color=COLOR_xxx} {,protect} {,password=<password>}** 

AddSheet allows you to define the name of the sheet, and/or add it to an existing workbook, and/or change the name of the output workbook. Subsequent instances of the directive create new pages. By not including the file extension in the specification, the extension (XLXL or XLS) will be automatically selected based on the current output format. All four parameters are optional, but you need at least one to make any sense: 

|**Parameter**|**Description**|
|---|---|
|srcbook=|Specifies the source workbook to which you are appending the sheet, e.g.<br>`srcbook=mybook.xls`.<br>Default is to create a new book. Must be a native filespec.|
|dstbook=|Specifies the destination workbook to save the result as. Can be same as_srcbook_. Default is the original<br>CSV file with .xls extension, and optionally with a -# sequence number appended to the name; see<br>AppendSeqno in [Post] section of the ini file. Must be a native filespec. See History.|
|sheetname=|Optionally (see History) specifies the name you want to assign to the sheet. Default is "sheet1". Note:<br>must be unique within the workbook!|
|index=#|Causes the new sheet to be inserted at position #. Default is to append to the end.|
|deletefirst|If the_deletefirst_parameter is specified and the specified sheet already exists, it will first be deleted<br>before being re-added. Otherwise, the default is to just overwrite the existing sheet with the new data.<br>This could result in a mixture of new and old data if the CSV data contains fewer rows or columns than<br>the existing sheet data.|
|color=|COLOR_xxx sets the tab color.|
|protect|Sets the default protection option for the sheet.|
|password|Set the password needed to unprotect the sheet.  Implies protect.|



A-Shell Reference 

Page 3774 

Subsequent AddSheet directives cause the current sheet to be finished and a new sheet started. This also includes triggering any automatic totals per the ini file settings, and re-initializing the number and formats of the columns per the data lines following the AddSheet directive. In other words, each sheet is effectively independent. 

For example, the following creates a workbook with two sheets, the first named "English" with three columns, and the second named "Spanish" with two columns... 

```
//XL,AddSheet,Sheetname=English
```

```
One,Two,Three
```

```
1,two,3
```

```
11,twenty-two,33
```

```
111,two-twenty-two,333
```

```
//XL,AddSheet,Sheetname=Spanish
```

```
Uno,Dos
```

```
Un perro,2
```

```
Unos hombres,22
```

Assuming the ini file enables automatic totals, the two sheets of the resulting workbook would look something like this: 

Note that the two sheets have completely different column structures. 

## **History** 

- 2025 February, A Shell 7.0.1769, CSV2XL.SBX edit 2303: 

- The _sheetname_ attribute is now optional, defaulting to "Data". Previously, the operation may have failed entirely. 

A-Shell Reference 

Page 3775 

• The target directory (extracted from the _dstbook_ attribute) will now be created if it doesn't already exist. Note that this only works at the bottom level, i.e. the parent directory must exist. If the directory creation fails, the spreadsheet will be saved in the current directory.Add support for protect and password options. 

- 2020 September, A Shell 6.5.1691, CSV2XL.SBX edit 255: Add support for protect and password options. 

- 2019 September, A Shell 6.5.1668, CSV2XL.SBX edit 236: Extension may now be eliminated from the directive in order to allow the current output format to set the standard extension. Previously you had to specify either xls or xlsx which would then cause problems if the actual format didn't match. 

- 2019 May, A Shell 6.5.1661, CSV2XL.SBX edit 230: Add support for: //XL,AddSheet now supports an optional parameter COLOR=COLOR_xxx to set the tab color; and set wrap attribute for column headers. 

- 2019 Feburary, A Shell 6.5.1656, CSV2XL.SBX edit 222: Support multiple sheets within a single source file. 

- 2018 January, A Shell 6.4.1556:  Add _deletefirst_ parameter to AddSheet directive 

A-Shell Reference 

Page 3776 

## **ADDTOTALS** 

_Added March 2025_ 

## **//XL,AddTotals,#** 

These override the ini file options of the same names, provided they are placed after all SetCol, SetIni, and SetBanner directives. Set # to 0 to disable, > 0 to enable and/or set to a specific value. 

Setting AddTotals to 0 disables all totals, overriding the SetCol directives. Setting it to 1 enables totals, but does NOT override the SetCol "total" and "nototal" options, nor the built-in rules for deciding which columns are suitable for totalling—i.e. not text, dates, etc. 

## **History** 

- 2025 February, A Shell 7.0.1769, CSV2XL 2.2(302):  Directives added to A-Shell. 

A-Shell Reference 

Page 3777 

## **SETBANNER** 

_Updated May 2023_ 

## **//XL, SetBanner, text=<banner text> {,** Common //XL Parameters **}** 

SetBanner causes the banner to occupy the first row of the spreadsheet, above the headers, with the text centered in a bold 12 point font. All of the columns are merged so at to make a single wide column for the banner. This is a good way of displaying a spreadsheet title or other identifying information about the spreadsheet, such as dates, selection criteria, etc. 

The SetBanner directive, if used, must appear after any AddSheet directive and before the headers. For example: 

```
//XL,AddSheet,sheetname=Taxes
```

```
//XL,SetBanner,text="Property Taxes, 2023"
```

```
Parcel ID,Net Tax,Net Penalty,Owner Name
```

```
2712_00490004, 20874 , 2087 ,"MICROSABIO INTERNATIONAL"
2713_00523002, 9234 , 1423 ,"A-SHELL ENTERPRISES, LLC"
```

```
...
```

## **Notes** 

- As with all other directives, remember to put quotes around any argument containing commas, e.g.: 

## `//XL SetBanner,text="The Bad, the Good, and the Beautiful"` 

- The banner carries automatically over to subsequent sheets in the same workbook. To prevent that, set the text argument 

- to an empty string, e.g. 

```
//XL SetBanner,text=
```

A-Shell Reference 

Page 3778 

- Unlike header columns, the banner does not wrap and increase in height automatically. But you can insert "^M" to create 

- explicit line breaks, which will increase the banner height accordingly. See _History_ for details. 

- For a short banner on a very wide spreadsheet, you may want to override the default horizontal centering by adding the 

- ALIGNH_LEFT parameter, e.g. 

```
//XL SetBanner,text="Important Stuff",ALIGNH_CENTER
```

- Beginning with A-Shell 1739, SetBanner supports the _fontname_ and _fontsize_ attributes, e.g.: 

- `//XL,SetBanner,text="This is a Banner",fontheight=20,fontname=Broadway` 

- The AddLink directive may be used to place a link in the first or last cell of the banner (top) row with the banner width 

- adjusting itself accordingly. For example, adding the following directive to the Property Taxes example above... 

```
//XL,AddLink,row=1,col=1,text=Legend,linkto=Legend!A1
```

- ... would result in the banner being shifted over like this: 

## **History** 

- 2023 August, A Shell 1739, CSV2XL 2.1(286):  Add support for _fontname_ and _fontsize_ attributes. 

- 2023 May, A Shell 6.5.1730, CSV2XL.SBX 2.1.(281):  Support multiple ^M line breaks; support additional common //XL parameters; support sharing of banner row with a hyperlink. 

- 2019 December, A Shell 6.5.1672, CSV2XL.SBX 2.1(244):  Add ^M for line break. 

- 2019 September, A Shell 6.5.1668, CSV2XL.SBX edit 234: Function added to A-Shell. 

A-Shell Reference 

Page 3779 

## **SETCOL** 

## **//XL, SetCol, {colfirst=}<##>, {,collast=<##>} {,width=##} {,total|nototal} {,** Common //XL Parameters **}** 

Use SetCol to set attributes for a column or set of columns. Note that you have the option of referencing a previously defined format via the _formatid_ =<formatid> parameter, in which case you should not specify any of the other font or format-related parameters. (A format includes a font.) Otherwise, you can specify any of the individual font and/or format parameters to effectively define the font and format on the fly. 

Note that if the _collast_ parameter is omitted, it is assumed to be the same as _colfirst_ . If the first parameter is not named, it is assumed to be colfirst. 

The SetCol directive(s) should be specified at the top of the file, before any data. 

In the case of a multi-sheet workbook, any SetCol directives apply only to current sheet, and are reset by the next AddSheet directive. In the case, new SetCol directives can appear after each AddSheet directives but before any data lines but before any subsequent data lines. 

Parameter _total_ forces the column to be totaled, _nototal_ disables totals for the column. These override the ColTitleTextRegex directive in the CSV2XL.INI file, as well as the default rules, which are to total numeric columns. 

## **Examples** 

```
//;Set column 3 to bold
```

```
//XL,SetCol,3,bold
```

```
//;Set columns 4-6 to have yellow background
```

```
//XL,SetCol,colfirst=4,collast=6,FILLPATTERN_SOLID, patternfgc=COLOR_YELLOW
```

```
//;Set column 7 to use predefined format name fmtspecial
```

A-Shell Reference 

Page 3780 

```
//XL,SetCol,colfirst=7,formatid=fmtspecial
```

## **History** 

- 2019 September, A Shell 6.5.1668, CSV2XL.SBX edit 234: Parameters total | nototal added. 

A-Shell Reference 

Page 3781 

## **SETGROUP** 

_Updated May 2020_ 

## **//XL, SetGroup, rowfirst=##, rowlast=## {,collapsed} {,summary {=#}}** 

SetGroup creates a row group that can be collapsed or expanded. If the collapsed argument is specified, the group will be initially collapsed when viewed in the spreadsheet application; else expanded. The summary option determines whether the spreadsheet app should allow for a summary line and where, above or below. Specifying the summary argument by itself, or summary=1, puts the summary below the group; summary=-1 puts it above. Note that you have to create the summary line yourself and insert it in the proper order. For example: 

```
Conference,Team,Wins,Payroll($M)
```

```
AFC,Ravens,10,87
```

```
AFC,Patriots,10,79
```

```
AFC,Bills,9,82
```

```
//XL,SetGroup,rowfirst=2,rowlast=4,collapsed,summary
```

```
AFC,"",=SUM(C2:C4),=SUM(D2:D4)
```

```
NFC,49ers,10,93
NFC,Saints,8,75
```

```
NFC,Bears,7,74
```

```
//XL,SetGroup,rowfirst=6,rowlast=8,collapsed,summary
```

```
NFC,"",=SUM(C6:C8),=SUM(D6:D8)
```

In the above example we have column titles and two groups of three data rows with a summary line below it. Note that group has its own SetGroup directive below the data items, with the summary line below that. It would look like this in Excel: 

A-Shell Reference 

Page 3782 

(Collapsed) 

(Expanded) 

When the group summary line follows the data, the expand/contract buttons appear on the line above the group summary, which may seem a bit odd. The other option is to put the summaries above the data lines, which is more difficult to program (since you need to output the summary information before the details and thus can't calculate the summary while outputting the data), but may look cleaner in the resulting spreadsheet, particularly when collapsed: 

```
Conference,Team,Wins,Payroll($M)
```

```
//XL,SetGroup,rowfirst=3,rowlast=5,collapsed,summary=-1
```

```
AFC,"",=SUM(C3:C5),=SUM(D3:D5)
```

```
AFC,Ravens,10,87
```

```
AFC,Patriots,10,79
AFC,Bills,9,82
```

```
//XL,SetGroup,rowfirst=7,rowlast=9,collapsed,summary=-1
```

```
NFC,"",=SUM(C7:C9),=SUM(D7:D9)
```

```
NFC,49ers,10,93
NFC,Saints,8,75
```

```
NFC,Bears,7,74
```

A-Shell Reference 

Page 3783 

## **History** 

- 2019 December, CSV2XL.SBX edit 243, first included with A Shell 6.5.1671:  Function added to A-Shell. 

A-Shell Reference 

Page 3784 

## **SETPRINT** 

_Updated June 2019; see History_ 

## **//XL, SetPrint, attribute=value, attribute=value,...** 

SetPrint allows you to set various print features, where the possible attributes and values are: 

|**Attribute**|**Value**|**Description/Comment**|
|---|---|---|
|orientation|landscape, portrait|Set initial orientation when printing|
|header|<text>|Set print header/footer text. May contain macros.|
|footer|||
|hmargin|<number of inches>|Set margin for header, footer, left, top, right, bottom|
|fmargin|||
|lmargin|||
|tmargin|||
|rmargin|||
|bmargin|||



A-Shell Reference 

Page 3785 

|**Attribute**|**Value**|**Description/Comment**|
|---|---|---|
||||
|repeatrows|<number>|Set number of rows to repeat at top of each page|
|repeatcols|<number>|Set number of columns to repeat at left edge of each page|
|vcenter,<br>hcenter|1,0|Values (1 for on, 0 for off) are optional|
|vfitpages<br>hfitpages||Set the print scaling to fit the spreadsheet on the specified number of print pages,<br>vertically and horizontally, respectively. For example, to force the output to be scaled<br>so that all the columns fit across a single page width, use: //XL,SetPrint,hfitpages=1|



Note that all of the above attributes affect the current page, and thus should be specified after the page is initiated. For example, they might come after the first row data on the page. 

## **Macros** 

The following macros may be used with the header and footer attributes. 

|**Macro**|**Action**||**Macro**|**Action**|
|---|---|---|---|---|
|&L|Start of left-justified section||&E|Set double-underline text attribute|



A-Shell Reference 

Page 3786 

|**Macro**|**Action**||**Macro**|**Action**|
|---|---|---|---|---|
|&P|Current page #||&R|Start of the right-justified section|
|&N|Total # of pages||&Z|Workbook file path|
|&##|Specify font size (## points), e.g. &14||&F|Workbook file name|
|&S|Set strikethrough text attribute||&A|Current sheet name|
|&Y|Set subscript text style||&"font"|Font, e.g. &"Times New Roman"|
|&C|Start of the center-justified section||&B|Set bold text attribute|
|&D|Current date||&I|Set italic text attribute|
|&T|Current time||&&|Literal ampersand|
|&U|Set underline text attribute||||



## **History** 

2025 February, CSV2XL.SBX edit 299, first included with A-Shell 7.0.1769: Add attributes _vfitpages_ and _hfitpages_ . 

2019 June, CSV2XL.SBX edit 232, first included with A-Shell 6.5.1661: Add attributes _vcenter_ and _hcenter_ . 

A-Shell Reference 

Page 3787 

- 2019 May, A Shell 6.5.1660, CSV2XL.SBX edit 22: Function added to A-Shell. 

A-Shell Reference 

Page 3788 

## **SETRGBMODE** 

## **//XL, SetRGBMode {,rgbmode=boolean}** 

SetRBGmode provides support for RGB colors. The AXL library always starts out in color index mode (rgbmode=false), meaning that colors must be specified via the COLOR_xxx index names. Using this directive, with rgbmode=true (or omitting the parameter entirely), switches the library over to RGB mode, in which colors are specified using the hex format &hbbggrr. For example: 

```
hello,"<fontcolor=&hff99cc,bold/>Bonjour",Hola
```

You can continue to use COLOR_xxx indices in RGB mode, as they can be converted unambiguously by the AXL library functions. But the reverse is not supported, i.e. you cannot specify RGB values when not in RGB mode. 

## **Comments** 

- RGB mode is only supported with XLSX format, not XLS. 

- If using the AXL library functions directly, you must recompile with libxl.bsi [138] or higher and libxl2.bsi [103] or higher. 

- Attempts to specify colors that are incompatible with the mode will result in a warning message in the System Messages 

- window. 

- RGB mode is now (see History) automatically activated if any color parameter in the ini file is specified in terms of a hex 

- value, e.g. 

```
HeadersBG=&hd0e0f0
```

## **History** 

## - 2019 June, A Shell 6.5.1682, CSV2XL.SBX edit 249: Function added to A-Shell. 

A-Shell Reference 

Page 3789 

## **OTHER CSV2XL TOPICS** 

A-Shell Reference 

Page 3790 

## **NOTES ON SYNTAX** 

Here are some notes on the somewhat exotic argument syntax of the //XL directives in CSV2XL. 

- To insert a comment in the CSV file, start the line with //; (two slashes followed by a semicolon). This is consistent with the 

- syntax for comments with normal GDI directives, e.g.: 

## `//; This is a comment` 

- Because there are so many potential parameters and most of them are optional, they have been assigned names. This allows 

- you to specify only the ones you are interested in setting, and in any order. So for example, here we define a font by specifying the fontname and color, but not the size or any other attributes: 

```
//XL,DefineFont,fontid=myfont,fontname=Courier New,fontcolor=COLOR_BLUE
```

- Because some of the attribute values have symbolic names (e.g. COLOR_BLUE) which are more descriptive than the numeric 

- values, you can use the symbolic names—as in the example above—or the corresponding numeric values (defined in libxl.def). 

- Because many of those attribute value symbolic names only apply to a single attribute type, e.g. NUMFMT_xxx only applies to 

- the format parameter _numfmtid_ , you can leave off the name= part of the name=value pair, e.g. 

- `//XL,DefineFormat,formatid=fmt_pct,NUMFMT_PERCENT,fontid=myfont` 

## is equivalent to 

```
//XL,DefineFormat,formatid=fmt_pct,numfmtid=NUMFMT_PERCENT,fontid=myfont
```

- In order to accommodate lengthy footnotes and banners, all parameters can be up to 512 characters long. 

- Parameters with Boolean attributes like bold, italic, etc., are all assumed FALSE (0) unless specified. Also, so there is no real 

- need to say "wrap=1". Just say "wrap". 

• Fonts and formats both have internal identifiers or handles, which can be shared between cells. To be more precise, fonts may be shared by formats, and formats may be shared by columns or rows. Thus the DefineFont directive assigns the resulting font to the fontid specified in the fontid= clause, which may then be referenced in a subsequent DefineFormat statement (as in the above example). The DefineFormat directive assigns the resulting format handle to the formatid specified in the formatid= clause (fmt_pct in the above example), which can then be used to assign it to one or more columns, e.g. 

A-Shell Reference 

Page 3791 

• The three part process described in the previous point—define a font, define a format using the font, then associate the format with columns—is logical but tedious and verbose in the simple case where you just want to apply some kind of formatting to a single column, or different formatting to different columns, where there is little or no opportunity to share formats or fonts. In that case, you can just do it all in the SetCol (or SetRow) directive, e.g.: 

## `//XL,SetCol,9,mask="###,###.00",fontcolor=COLOR_VIOLET,italic` 

The above example creates a numeric format using the specified mask and assigns column 9 to use it and to also use violet colored italic text. Internally this generates DefineFont and DefineFormat directives, but the handles are lost, so you can't re-use them in subsequent directives. But there is nothing stopping you from specifying the same attributes in additional SetCol or SetRow directives. 

• Some directives have an obvious or natural first parameter whose name can therefore be omitted. For example, the obvious/natural first parameter to the Setrow directive is the row number. The obvious/natural first parameter to the DefineFont and DefineFormat directives are the fontid and formatid to be assigned. In the case of the SetIni directive, the only parameter is the ini file spec, so there is no point in even defining a name for that parameter. For example: 

```
//; following two are equivalent
```

```
//XL,DefineFont,fontid=hdrfont,name=Broadway
```

```
//XL,DefineFont,hdrfont,name=Broadway
```

```
//; following two are equivalent
```

```
//XL,SetCol,6,formatid=fmt_pct
```

```
//XL,SetCol,colfirst=6,formatid=fmt_pct
```

A-Shell Reference 

Page 3792 

## **COMMON //XL PARAMETERS** 

The following table lists the parameters that can be used with several of the //XL directives. Note that: 

- You must list only the parameters you want to use. Simply omit those you don't wish to set. 

- See Notes on Syntax. 

- Some of the links below connect to external webpages that contain definitions for multiple parameters. Scroll down the page 

- as needed. 

- Numbers in parentheses (3) refer to the notes which immediately follow the table. 

|||**Available For Use In...**|**Available For Use In...**|**Available For Use In...**|**Available For Use In...**|
|---|---|---|---|---|---|
|**Name**|**Value**|**Set**<br>**Row**|**Set**<br>**Col**|**Define**<br>**Format**|**Define**<br>**Font**|
|alignh (1)|ALIGNH_xxx|x|x|x||
|alignv (1)|ALIGNV_xxx|x|x|x||
|bold|Boolean|x|x|x|x|
|bordercolor|COLOR_xxx|x|x|x||
|borderstyle (1)|BORDERSTYLE_xxx|x|x|x||



A-Shell Reference 

Page 3793 

|||**Available For Use In...**|**Available For Use In...**|**Available For Use In...**|**Available For Use In...**|
|---|---|---|---|---|---|
|**Name**|**Value**|**Set**<br>**Row**|**Set**<br>**Col**|**Define**<br>**Format**|**Define**<br>**Font**|
|fillpattern (1)|FILLPATTERN_xxx|x|x|x||
|fontid|Alphanumeric name you assign*|x|x|x|x|
|fontcolor|COLOR_xxx|x|x|x|x|
|fontname|Font name; eg "Arial", "Courier New"|x|x|x|x|
|fontsize|Integer number of points|x|x|x|x|
|formatid|Alphanumeric name you assign*|x|x|x||
|hidden|Boolean|x|x|x||
|indent|Integer 0 - 15|x|x|x||
|italic|Boolean (3)|x|x|x|x|
|locked|Boolean (3)|x|x|x||



A-Shell Reference 

Page 3794 

|||**Available For Use In...**|**Available For Use In...**|**Available For Use In...**|**Available For Use In...**|
|---|---|---|---|---|---|
|**Name**|**Value**|**Set**<br>**Row**|**Set**<br>**Col**|**Define**<br>**Format**|**Define**<br>**Font**|
|mask|mask|x|x|x||
|numfmtid (1)|NUMFMT_xxx|x|x|x||
|patternbgc (2)|COLOR_xxx|x|x|x||
|patternfgc (2)|COLOR_xxx|x|x|x||
|rotation|degrees (4)|x|x|x||
|shrinkfit|Boolean (3)|x|x|x||
|strikeout|Boolean (3)|x|x|x|x|
|underline|Boolean (3)|x|x|x|x|
|wrap|Boolean (3)|x|x|x||



* so you can refer to it later 

A-Shell Reference 

Page 3795 

## **Notes** 

- 1 Because the values for these parameters are uniquely associated with a specific parameter ("ALIGNH_LEFT" or 

- "BORDERSTYLE_THICK" or "FILLPATTERN_GRAY25"), it is not necessary to name the parameter. In other words, ALIGNH_LEFT by itself on the syntax line is equivalent to ALIGNH=ALIGNH_LEFT. 

- 2 Counter-intuitive setting: To set the "normal" background color of a cell, set _fillpattern_ to FILLPATTERN_SOLID and _patternfgc_ to the color. The _patternbgc_ parameter applies only to complex (non-solid) fill patterns. 

- 3 All parameters Boolean values (a) default to no and therefore (b) do not need to be mentioned except to turn on, and (c) do not require a value (Y or 1) to turn on; just naming the parameter on the syntax line ("Italic") turns it on. 

4. Rotation values 0-90 specify counterclockwise rotation in degrees.  Values 91-180 specify 1-90 degree rotation clockwise. 255 indicates vertical. 

A-Shell Reference 

Page 3796 

## **- CELL LEVEL ATTRIBUTES** 

_Added June 2020_ 

CSV2XL provides support for cell-level attributes using the syntax: 

## **"<attr=value,...,attr=value/>field data", ...** 

The attribute clause must begin with "<" and end with "/>", and there needs to be quotes around the entire combination of the attribute clause and the field data. (WRITECD will take care of the quoting.) The attribute list may contain any of the Common XL Parameters, except _mask_ and _formatid_ . Any attributes specified at the cell level are combined with the attributes previously defined by the SetCol directive for that column. 

For example, in the following data line, all fields will output using the attributes previously set, but the middle field font will be changed to lavender and bold. 

```
hello,"<fontcolor=COLOR_LAVENDER,bold/>Bonjour",Hola
```

Also, a new shorthand attribute _bgc_ has been defined to set the background color, which otherwise requires setting the fillpattern to FILLPATTERN_SOLID and the patternbgc to the desired color. For example: 

```
Breakfast,"<bgc=&h30c5a7/>burrito",4.99
```

## **History** 

- 2020 June, A Shell 6.5.1682, CSV2XL :  Function added to A-Shell 

A-Shell Reference 

Page 3797 

## **MASKS** 

## **Custom format string guidelines** 

Up to four sections of format codes can be specified. The format codes, separated by semicolons, define the formats for positive numbers, negative numbers, zero values, and text, in that order. If only two sections are specified, the first is used for positive numbers and zeros, and the second is used for negative numbers. If only one section is specified, it is used for all numbers. Four sections example: 

## `#,###.00_);[Red](#,###.00);0.00;"sales "@` 

The following table describes the different symbols that are available for use in custom number formats. 

|**Symbol**|**Description and result**|
|---|---|
|0|Digit placeholder. For example, if the value 8.9 is to be displayed as 8.90, use the format #.00|
|#|Digit placeholder. This symbol follows the same rules as the 0 symbol. However, the application shall not<br>display extra zeros when the number typed has fewer digits on either side of the decimal than there are #<br>symbols in the format. For example, if the custom format is #.##, and 8.9 is in the cell, the number 8.9 is<br>displayed.|
|?|Digit placeholder. This symbol follows the same rules as the 0 symbol. However, the application shall put a<br>space for insignificant zeros on either side of the decimal point so that decimal points are aligned in the<br>column. For example, the custom format 0.0? aligns the decimal points for the numbers 8.9 and 88.99 in a<br>column.|
|. (period)|Decimal point.|
|%|Percentage. If the cell contains a number between 0 and 1, and the custom format 0% is used, the<br>application shall multiply the number by 100 and adds the percentage symbol in the cell.|
|, (comma)|Thousands separator. The application shall separate thousands by commas if the format contains a comma<br>that is enclosed by number signs (#) or by zeros. A comma that follows a placeholder scales the number<br>by one thousand. For example, if the format is #.0,, and the cell value is 12,200,000 then the number 12.2<br>is displayed.|
|E- E+ e- e+|Scientific format. The application shall display a number to the right of the "E" symbol that corresponds to<br>the number of places that the decimal point was moved. For example, if the format is 0.00E+00, and the|



A-Shell Reference 

Page 3798 

|**Symbol**|**Description and result**|
|---|---|
||value 12,200,000 is in the cell, the number 1.22E+07 is displayed. If the number format is #0.0E+0, then<br>the number 12.2E+6 is displayed.|
|$-+/():space|Displays the symbol. If it is desired to display a character that differs from one of these symbols, precede<br>the character with a backslash (\). Alternatively, enclose the character in quotation marks. For example, if<br>the number format is (000), and the value 12 is in the cell, the number (012) is displayed.|
|\|Display the next character in the format. The application shall not display the backslash. For example, if<br>the number format is 0\!, and the value 3 is in the cell, the value 3! is displayed.|
|*|Repeat the next character in the format enough times to fill the column to its current width. There shall not<br>be more than one asterisk in one section of the format. If more than one asterisk appears in one section of<br>the format, all but the last asterisk shall be ignored. For example, if the number format is 0*x, and the<br>value 3 is in the cell, the value 3xxxxxx is displayed. The number of x characters that are displayed in the<br>cell varies based on the width of the column.|
|_ (underline)|Skip the width of the next character. This is useful for lining up negative and positive values in different<br>cells of the same column. For example, the number format _(0.0_);(0.0) aligns the numbers 2.3 and -4.5<br>in the column even though the negative number is enclosed by parentheses.|
|"text"|Display whatever text is inside the quotation marks. For example, the format 0.00 "dollars" displays 1.23<br>dollars when the value 1.23 is in the cell.|
|@|Text placeholder. If text is typed in the cell, the text from the cell is placed in the format where the at<br>symbol (@) appears. For example, if the number format is "Bob "@" Smith" (including quotation marks),<br>and the value "John" is in the cell, the value Bob John Smith is displayed.|
|0|Digit placeholder. For example, if the value 8.9 is to be displayed as 8.90, use the format #.00|



## **Specify colors** 

To set the text color for a section of the format, type the name of one of the following eight colors in square brackets in the section. The color code must be the first item in the section. 

[Black] 

[Green] [White] [Blue] 

A-Shell Reference 

Page 3799 

[Magenta] [Yellow] [Cyan] [Red] 

Instead of using the name of the color, the color index can be used, like this [Color3] for Red. Valid numeric indexes for color range from 1 to 56, which reference by index to the legacy color palette. 

## **Specify conditions** 

To set number formats that will be applied only if a number meets a specified condition, enclose the condition in square brackets. The condition consists of a comparison operator and a value. Comparison operators include: = Equal to; > Greater than; < Less than; >= Greater than or equal to, <= Less than or equal to, and <> Not equal to. For example, the following format displays numbers that are less than or equal to 100 in a red font and numbers that are greater than 100 in a blue font. `[Red][<=100];[Blue][>100]` 

If the cell value does not meet any of the criteria, then number signs ("#") are displayed across the width of the cell. 

## **Dates and times** 

|**To Display**|**As**|**Use This Code**|
|---|---|---|
|Months|1-12|m|
|Months|01-12|mm|
|Months|Jan-Dec|mmm|
|Months|January-<br>December|mmmm|
|Months|J-D|mmmmm|



A-Shell Reference 

Page 3800 

|**To Display**|**As**|**Use This Code**|
|---|---|---|
|Days|1-31|d|
|Days|01-31|dd|
|Days|Sun-Sat|ddd|
|Days|Sunday-<br>Saturday|dddd|
|Years|00-99|yy|
|Years|1900-9999|yyyy|
|Hours|0-23|h|
|Hours|00-23|hh|
|Minutes|0-59|m|
|Minutes|00-59|mm|
|Seconds|0-59|s|
|Seconds|00-59|ss|
|Time|4 AM|h AM/PM|
|Time|4:36 PM|h:mm AM/PM|
|Time|4:36:03 P|h:mm:ss A/P|
|Time|4:36:03.75|h:mm:ss.00|
|Elapsed time|1:02|[h]:mm|
|Elapsed time|62:16|[mm]:ss|
|Elapsed time|3735.80|[ss].00|



**Examples** 

A-Shell Reference 

Page 3801 

|**To Display**|**As**|**Use This Code**|
|---|---|---|
|1234.59|1234.6|####.#|
|8.9|8.900|#.000|
|.631|0.6|0.#|
|12<br>1234.568|12.0<br>1234.57|#.0#|
|44.398<br>102.65<br>2.8|44.398<br>102.65<br>2.8|???.???|
|5.25<br>5.3|5 1/4<br>5 3/10|# ??/??|
|12000|12,000|#,###|
|12000|12|#,|
|12400000|12.4|0.0,,|



A-Shell Reference 

Page 3802 

## **CSV2XL EXAMPLES** 

## **AddSheet** 

Assume these two files: 

File1.csv: 

```
//XL,AddSheet,dstbook=test.xls,sheetname=test sheet1
```

```
Name,Age,Sex,...
```

```
<data>
```

File2.csv: 

```
//XL,AddSheet,srcbook=test.xlsx,dstbook=test.xlsx,sheetname=test sheet2
```

```
Account#,Address,Amount...
```

```
<data>
```

## Execution: 

```
.PRINT CSV2XL=FILE1.CSV    ! creates TEST.XLS with sheet named "test sheet1"
.PRINT CSV2XL=FILE2.CSV    ! loads TEST.XLSX, adds new sheet "test sheet2", saves it as TEST.XLSX
```

The specified new sheet will be appended to the end of the workbook, and the existing file will be overwritten. 

A-Shell Reference 

Page 3803 

## **BENEFITS OF CSV2XL** 

Although most spreadsheet applications can open CSV files directly, there are a number of advantages to using CSV2XL to create an XLS{X} file. These include: 

- XLS{X} is easier to use for the file recipient. By creating the XLS{X} file under application control, you eliminate the 

- uncertainties and the possible need to answer questions that may arise when the recipient of the file imports it into a spreadsheet application. 

- CSV files cannot contain any formatting whereas XLS{X} files can, and the CSV2XL routine provides various options for 

- automatic and manual formatting to be applied. 

- CSV2XL can automatically highlight the column headers and add column totals. 

- CSV2XL can scroll-lock (aka split) the top line (headers) and/or first column so that they don’t scroll along with the rest of the 

- rows and columns. 

- CSV2XL has logic to properly identify columns that should be treated as strings (left justified, leading zeros retained, e.g. zip 

- codes) whereas the typical CSV importer would treat them as numbers. 

- CSV2XL recognizes dates and converts them to XLS{X} internal date format. 

- CSV2XL automatically sets the column widths appropriately for the data. 

- CSV2XL allows you to specify a default font. 

- The output file name may be serialized with a numeric suffix (eg. abc-1.xls, abc-2.xlsx, etc.) 

- For more advanced formatting, you can insert //XL directives at the top of the file to specify formats to be applied to 

- individual columns and/or rows. 

- Options are provided for post-processing of the XLS{X} file, such as transferring to the local workstation or launching the 

- spreadsheet application. 

A-Shell Reference 

Page 3804 

## **NUMBER FORMATS** 

|**Symbol**|**Value**|**Description**|**Example**|
|---|---|---|---|
|NUMFMT_GENERAL|0|general format||
|NUMFMT_NUMBER|1|general number|12345.6789|
|NUMFMT_NUMBER_D2|2|number with decimal point|12345.67|
|NUMFMT_NUMBER_SEP|3|number with thousands separator|12,345|
|NUMFMT_NUMBER_SEP_D2|4|number with decimal point and thousands separator|12,345.67|
|NUMFMT_CURRENCY_NEGBRA|5|monetary value, negative in brackets|(1000$)|
|NUMFMT_CURRENCY_NEGBRARED|6|monetary value, negative red in brackets|(1000$)|
|NUMFMT_CURRENCY_D2_NEGBRA|7|monetary value with decimal point, negative in brackets|($1,000.00)|
|NUMFMT_CURRENCY_D2_NEGBRAR<br>ED|8|monetary value with decimal point, negative ed in<br>brackets|($1,000.00)|
|NUMFMT_PERCENT|9|percent value, multiply the cell value by 100|75%|
|NUMFMT_PERCENT_D2|10|percent value with decimal point, multiply the cell value<br>by 100|75.00%|
|NUMFMT_SCIENTIFIC_D2|11|scientific value with E character and decimal point|1.00E+02|
|NUMFMT_FRACTION_ONEDIG|12|fraction value, one digit|10 1/2|
|NUMFMT_FRACTION_TWODIG|13|fraction value, two digits|10 23/95|
|NUMFMT_DATE|14|date value, depends on OS settings|3/11/2024|
|NUMFMT_CUSTOM_D_MON_YY|15|custom date value|11-Mar-24|
|NUMFMT_CUSTOM_D_MON|16|custom date value|11-Mar|
|NUMFMT_CUSTOM_MON_YY|17|custom date value|9-Mar|
|NUMFMT_CUSTOM_HMM_AM|18|custom date value|8:30 AM|
|NUMFMT_CUSTOM_HMMSS_AM|19|custom date value|8:30:00 AM|
|NUMFMT_CUSTOM_HMM|20|custom date value|8:30|



A-Shell Reference 

Page 3805 

|**Symbol**|**Value**|**Description**|**Example**|
|---|---|---|---|
|NUMFMT_CUSTOM_HMMSS|21|custom date value|8:30:00|
|NUMFMT_CUSTOM_MDYYYY_HMM|22|custom datetime value|3/11/2024 8:30|
|NUMFMT_NUMBER_SEP_NEGBRA|37|number with thousands separator, negative in brackets|-4,000|
|NUMFMT_NUMBER_SEP_NEGBRARE<br>D|38|number with thousands separator, negative red in<br>brackets|-4,000|
|NUMFMT_NUMBER_D2_SEP_NEGBR<br>A|39|number with thousands separator & decimal point,<br>negative in brackets|-4,000.00|
|NUMFMT_NUMBER_D2_SEP_NEGBR<br>ARED|40|number with thousands separator & decimal point,<br>negative red in brackets|-4,000.00|
|NUMFMT_ACCOUNT|41|account value|5,000|
|NUMFMT_ACCOUNTCUR|42|account value with currency symbol|AA$ 5,000|
|NUMFMT_ACCOUNT_D2|43|account value with decimal point|5,000.00|
|NUMFMT_ACCOUNT_D2_CUR|44|account value with currency symbol and decimal point|AA$ 5,000.00|
|NUMFMT_CUSTOM_MMSS|45|custom time value|30:55:00|
|NUMFMT_CUSTOM_H0MMSS|46|custom time value|20:30:55|
|NUMFMT_CUSTOM_MMSS0|47|custom time value|30:55.0|
|NUMFMT_CUSTOM_000P0E_PLUS0|48|custom value|1.52E+04|
|NUMFMT_TEXT|49|text value|any text|
|NUMFMTX_IMAGE|60|Image filespec (host format PNG, JPG, BMP, or TIF. For<br>example: c:\images\girl.jpg.|any image|



A-Shell Reference 

Page 3806 

## **CSV2XL NOTES AND TIPS** 

• CSV2XL supports both the old Excel file format XLS and the current  file format XLSX. All references in this documentation to one or the other file formats should be understood to apply equally to the other format, unless explicitly stated otherwise 

• An "^m" or "^M" can be inserted into data cells, as well as column headers and banners, to force line breaks and increase the row height accordingly. 

• CSV files can use comma, tab, or pipe delimiters, but //XL directives must use comma delimiters, and therefore any parameters containing commas must be quoted. 

• The following macros may be used as attribute values in //XL statements, referencing the ini attribute value of the same name: 

$HEADERSFG $HEADERSBG $TOTALSFG $DEFAULTFONT 

$DEFAUULTFONTSIZE $DATEFORMAT $TIMEFORMAT $DATETIMEFORMAT 

For example, to specify the ini-defined headers background color as the background for a particular column ... 

```
//XL,SetCol,colfirst=7,width=2,bgc=$HEADERSBG
```

• CSV2XL assigns the format NUMFMT_TEXT to columns with no data in the first 20 rows unless explicitly set via a SetCol directive. Previously they got the NUMFMT_GENERAL format which may have resulted in meaningless subtotals. 

## **History** 

- 2025 May, A Shell 1772, CSV2XL.SBX 2.2(306):  Added NUMFMT_TEXT formating as described above. 

- 2025 February, A Shell 1769.0, CSV2XL 2.2(300):  Added macro support as described above. 

- 2025 January, A Shell 1768.4, CSV2XL 2.2(296): updated to support the latest LIBXL.DLL 4.5.0. 

A-Shell Reference 

Page 3807 

- 2023 October, A Shell 1750.2, CSV2XL 2.2(291):  add support for 64 LibXL library, which is required when running on 64 bit versions of A-Shell. 

- 2023 February, A Shell 6.5.1724, CSV2XL.SBX 2.1(268):  A literal "^m" inside a data field now makes the expected adjustments to the spreadsheet configuration—i.e., activating the wrap option and increasing the row height. This was previously supported in the column headers only. 

A-Shell Reference 

Page 3808 

## **SPECIFYING COLORS** 

Various of the CSV2XL directives allow you to specify colors for text and background. You may so specify by using one of the two methods described below. 

## **Color Index** 

CSV2XL's native color reference system is a list of colors with associated common names. You can see the colors and their names here. 

Using the native scheme to set the headers background color, for example, you would write: 

```
HeadersBG=COLOR_GRAY25
```

This index is the default color definition scheme, and will be used and expected unless you change it to RGB. 

## **RBG Mode** 

If you prefer to use RGB color terminology, for example: 

```
HeadersBG=&hff99cc
```

...you can do so by shifting CSV2CL into RGB mode. 

## **Comments** 

- RGB mode is only supported with XLSX format, not XLS. 

- If using the AXL library functions directly, you must recompile with libxl.bsi [138] or higher and libxl2.bsi [103] or higher. 

- Attempts to specify colors that are incompatible with the mode will result in a warning message in the System Messages 

- window. 

- RGB mode is automatically activated if any color parameter in the ini file is specified in terms of a hex value, e.g. 

```
HeadersBG=&hd0e0f0
```

A-Shell Reference 

Page 3809 

• If you are in RGB mode, you can specify colors with the index designations; they will be recognized by the AXL library functions. However, the reverse is not true; you cannot specify RGB values when not in RGB mode. 

## **Entering / Exiting RGB Mode** 

As mentioned above, the native color selection mode is the CSV2XL color index. To use RGB colors, you need to go into RGB mode, which you can do in two ways. 

From within the ini file: 

## **SetRGBMode={boolean}** 

From within the csv file: 

## **//XL, SetRGBMode {,rgbmode=boolean}** 

To exit RGB mode and return to the index method: 

```
//XL, SetRGBMode 0
```

## **History** 

- 2019 June, A Shell 6.5.1682, CSV2XL.SBX edit 249: RGB mode added to CSV2XL. 

A-Shell Reference 

Page 3810 

## **AXL** 

Introduced in A-Shell 6.3, AXL provides a fully-featured application interface for reading and writing Excel spreadsheet (XLS) files. It is packaged as a collection of ASB functions and procedures built around a third-party library called LibXL. Although the individual functions are all relatively straightforward and intuitive,  there are quite a few of them—over 125. Rather than redundantly documenting all of them here, therefore, the following notes focus on providing an overview, tutorial, index, examples, etc., and rely on API source code (libxl.bsi) for the function-level documentation. 

## **Subtopics** 

- Library Class Overview 

- Hello World 

- AXL Installation 

- Progamming Notes 

- AXL Examples 

- Utilities 

A-Shell Reference 

Page 3811 

## **LIBRARY CLASS OVERVIEW** 

The underlying library is object-oriented, consisting of four classes: 

|**Class**|**Description**|
|---|---|
|Book|Each instance represents a workbook; methods including creating a workbook, loading one from a<br>file, saving it to file, adding sheets, defining fonts and formats, etc.|
|Sheet|Each instance represents a worksheet; methods and properties relating to rows, columns, cells.|
|Font|Each instance defines an individual font; a font instance may be shared by multiple instances of<br>the Format class.|
|Format|Each instance defines a combination of all the non-data attributes associated with cells—color,<br>alignment, borders, font, etc.|



ASB is not object-oriented per se, but generally follows the class orientation of the underlying library. You create instances of the various classes, which are identified by handles, which are then passed to the method functions to identify the instance of the class being operated on. Module-level (libxl.bsi) private data is used to keep track internally of the handles and various associated properties. 

Creating a spreadsheet from scratch typically involves the following: 

- ++INCLUDE libxl:libxl.bsi 

- Map variables for the various Book, Sheet, Format and Font objects you’ll be needing (using the special types BookHandle, 

- SheetHandle, FormatHandle and FontHandle), e.g. 

A-Shell Reference 

Page 3812 

```
Map1 handles
```

```
Map2 book1,BookHandle,
```

```
Map2 sheet1,SheetHandle
```

```
Map2 fmt’header,FormatHandle
```

```
Map2 fmt’total,FormatHandle
```

```
Map2 font’bold,FontHandle
```

- Load the library, e.g.: 

```
Call Fn’LibXL’Load(dlflags)
```

- Create an instance of the Book class, e.g.: 

```
book1 = Fn’LibXL’CreateBook()
```

- Create one or more Sheet instances, e.g.: 

```
sheet1 = Fn’LibXL’AddSheet(“Sheet1”, hbook=book1)
```

- Create zero or more Font instances, assigning attributes such as facename, size, color, e.g. 

```
font’bold = Fn’LibXL’AddFont’SetAttributes(size=16, bold=1)
```

- Create zero or more Format instances, assigning attributes such as borders, alignment, font, e.g. 

```
fmt’header = Fn’LibXL’AddFormat’SetAttributes(hfont=font’bold, alignh=ALIGNH_CENTER,…)
```

- Use functions in the Sheet class to set column/row dimensions, add pictures, and write cells. (Formats may be associated 

- with the cells when writing the data or by separate operations.) 

```
Call Fn’LibXL’SheetSetCol(hsheet=sheet1, colfirst=1, width=20)
```

```
Call Fn’LibXL’SheetWrite(row=1,col=2,”Hello World”, hformat=fmt’header)
```

A-Shell Reference 

Page 3813 

- Save the Book instance as a file, e.g. 

```
Call Fn’LibXL’SaveBook(“hello.xls”, hbook=book1)
```

- Release the book (frees resources) 

```
call LibXL'ReleaseBook()
```

- Unload the library 

```
call Fn'LibXL'Unload()
```

A-Shell Reference 

Page 3814 

## **HELLO WORLD** 

Here is spreadsheet version of the venerable Hello World program illustrating an extremely simple but working example. Note that since the example uses only one workbook and one sheet, there is no need to deal with handles for them. And to maximize simplicity, we use the default font and format, so there is no need for any of those handles either. 

```
Program hello,1.0(100)  ! hello world spreadsheet example
```

```
++include ashinc:ashell.def
```

```
++include libxl:libxl.bsi
```

```
call Fn'LibXL'Load(dlflags=DLF_STATUS_BASERR or DLF_SYSERR_BASERR)
```

```
if Fn'LibXL'CreateBook() then
```

```
if Fn'LibXL'AddSheet("Sheet1") then
```

```
call Fn'LibXL'Write(1, 1, “Hello World”)
```

```
endif
```

```
call Fn'LibXL'SaveBook(“hello.xls”)
```

```
call LibXL'ReleaseBook()
```

```
endif
```

```
call Fn'LibXL'Unload()
```

The program loads the LibXL library, creates an empty book, adds a sheet to it, writes “Hello World” into the first column of the second row (using 0 based counting), then saves the book to the file hello.xls. Finally it cleans up by releasing the resources 

A-Shell Reference 

Page 3815 

associated with the book and unloading the library. It doesn’t launch the spreadsheet application but you could do so with MX_SHELLEX or Fn’Shell’Exec() from sosfunc:fnshellex.bsi. 

A-Shell Reference 

Page 3816 

## **AXL INSTALLATION** 

The complete package consists of the following parts, some or all of which may need to be downloaded/installed manually: 

**External library:** The low-level code is packaged as a single external library file, which can be downloaded manually from the MicroSabio LibXL download directory. 

For Windows, the file is libxl.dll, and can be just dropping in the A-Shell bin directory (where the ashw32.exe file is). 

For Unix, the file is libxl.so.#.#.#.xxx, which can also be dropped into the A-Shell bin directory (where the ashell executable is). Then you must create a symbolic link to it named /usr/lib/libxl.so.1, e.g.: 

```
$ sudo ln -s /vm/miame/bin/libxl.so.3.7.2.lnx /usr/lib/libxl.so.1
```

You can test that the library itself has all of its prerequisites with the ldd command: 

```
$ ldd /usr/lib/libxl.so.1
linux-gate.so.1 =>  (0x00818000)
```

```
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00279000)
```

```
libm.so.6 => /lib/libm.so.6 (0x00161000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x003c3000)
libc.so.6 => /lib/libc.so.6 (0x00506000)
```

```
/lib/ld-linux.so.2 (0x004e9000)
```

**LIBXL: ersatz directory:** define an ersatz device LIBXL: which points to the directory where you install the LIBXL API files. This directory is typically [908,68], and is included (as [908,68]) in the MicroSabio EXLIB Repository. You might as well just download the entire library, updating the existing one you may already have installed. 

**SOSFUNC: and ASHINC:** Several files in these standard ersatz directories, typically [907,10] and [907,16] are used by the LibXL module and almost certainly require updating. Since they are both part of the MicroSabio SOSLIB Repository, the easiest way to satisfy this requirement is to download/update the entire set of [907,xxx] directories. 

A-Shell Reference 

Page 3817 

**A-Shell 6.3.15xx:** LibXL absolutely requires 6.3 as a minimum. 

**Compiler edit 793:** If using APN, you should ideally have the 793 (or later) version of the standalone compiler. You’ll also need to update your compil command line in APN to include the -p or -px switch (see next section for details). 

Having completed the above, you should be able to compile and run one of the sample programs, e.g. 

```
.LOG LIBXL:
```

```
.COMPIL TSTACB/X:2/M/P
```

```
.RUN TSTACB
```

A-Shell Reference 

Page 3818 

## **PROGAMMING NOTES** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Compiling 

- Return Status 

- Error Handling 

- Strings and Special Characters 

- Handles 

- Function Naming 

- Other Usage Notes 

- Function Index 

A-Shell Reference 

Page 3819 

## **COMPILING** 

The LibXL API wrapper module, libxl.bsi, uses named parameters and thus requires the compiler /P switch. Since it contains many functions that may not be used in any particular program, your RUN modules will be much smaller if you use the extended version of the /P switch, /PX. For APN and the standalone external compiler (compil.exe), use the -p or -px switch. Examples: 

From the dot prompt: 

```
.COMPIL TSTACB/X:2/M/PX
```

## From within APN: 

```
"c:\vm\APN\compil.exe" -ini c:\vm\miame\miame.ini -w:4000 -x:2 -m -px -lf -lsm -so "C:
\vm\miame\exlib63\908068\tstacb.bp"
```

A-Shell Reference 

Page 3820 

## **RETURN STATUS** 

Consistent with the underlying LibXL library, most of the functions return non-zero for success. For functions that return object handles, e.g. book, sheet, etc., the return value is the handle. For "get property" or "get value" functions, the return value is the property or value. For other "set property" or other functions with no inherent return value, the return value is a boolean, i.e.True for success. The actual error/status codes associated with a failed call may be retrieved with Fn'LibXL'Get'Status(), although this is usually not necessary; see ERROR HANDLING. 

A-Shell Reference 

Page 3821 

## **ERROR HANDLING** 

Three general classes of errors are possible (all of which will result in the function call returning zero) : 

- ERRORS WITHIN THE DYNLIB INTERFACE MECHANISM, such as failure to load the target library, find the target function, 

- parameter errors, etc. These are recorded in the dlCtl.status member using DYNLIBE_xx values (arbitrary/specific to DYNLIB). Use Fn'libXL'Get'Status() to retrieve/dispay. 

- OS-LEVEL ERRORS within the target function or library. For example, invalid path, or file protection errors. These errors are 

- defined by the OS/platform (Windows system error codes for Windows, errno values for Unix). Use Fn'LibXL'Get'Syserr() to retrieve/display. 

- LIBRARY/LOGIC ERRORS, i.e. functions that fail for reasons that neither DYNLIB nor the OS can detect. These are indicated by 

- returning 0 for the function value (matching the underlying LibXL library behavior). You can use Fn'LibXL'GetErrorMessage() following one of these errors to get further details. 

This LibXL library wrapper provides various services/options to simplify error handling to make application level code simpler. These are all set via flags passed to the Fn'LibXL'Load() function, which are defined in ashinc:dynlib.def. 

|**LibXL’Load flags**|**Description**|
|---|---|
|DLF_STATUS_BASERR|Generate ASB error 65 on abnormal status conditions within<br>dynamic library interface|
|DLF_SYSERR_BASERR|Generate ASB error 65 on OS-related system errors|
|DLF_LOG_ERRORS|Write status/syserr errors to ashlog|
|DLF_PRINT_ERRORS|Print status/syserr errors to screen|
|DLF_MSGBOX_ERRORS|Report status/syserr errors via MSGBOX|



A-Shell Reference 

Page 3822 

**LibXL’Load flags Description** 

The first two options (triggering a ASB error 65) are ideal when errors are not expected, since you only have to put your error logic in one place in the error trap. The others relate to how errors are reported, also sparing the application from having to manage that aspect of error reporting. 

A-Shell Reference 

Page 3823 

## **STRINGS AND SPECIAL CHARACTERS** 

A-Shell programs normally use ANSI strings (one byte per character), with the lower 128 characters using the standard ASCII encoding, and the upper 128 characters using the Latin1 encoding. The Excel file format, on the other hand, internally uses the Windows Wide character format (two bytes per character, aka U16). So it has no trouble supporting the accented and other special characters, but they do have to be converted from ANSI format to wide (or U16). The LibXL API will accomplish this for you, but there are variations of how this can work depending on the platform and flags you can set. 

In the Windows environment the LibXL API converts the strings you pass it to wide / U16 format and then passes them to the external library using the « W » functions. The conversion is reversed for any return strings. 

In the Unix environment, it is more common for applications requiring special characters to use UTF8 representation (one to five bytes per character), even though the spreadsheet internal file format still uses the U16 format. Depending on the DLF_xxx options you set, the LibXL API will either leave your strings alone, passing them as-is, or it will first convert them to UTF8 before passing them to the LibXL library. 

In order for these conversions to work properly in each environment, and to allow your compiled programs to run in either environment without recompiling, you must set the DLF_ASCII or DLF_ANSI flag before calling the Fn’Load’LibXL function. (For simplicity, DLF_ANSI is defined as zero and thus is the default.) 

|**LibXL’Load**<br>**flags**|**Description**|
|---|---|
|DLF_ANSI|Application strings assumed to be in ANSI format (i.e. Latin1, one byte per<br>character). They will be converted to/from wide format for Windows, and UTF8<br>for Unix. (Requires A-Shell 6.3.1542+ for Unix.)|
|DLF_ASCII|Application strings are assumed to use only the ASCII values 0-127, and thus<br>require no conversion for special characters. They will still be converted to wide<br>format for Windows, but will be passed as-is in Unix.|
|DLF_UTF8|Application strings are assumed to already be in UTF8 format.  They will be|



A-Shell Reference 

Page 3824 

|**LibXL’Load**<br>**flags**|**Description**|
|---|---|
||converted from UTF8 to wide for Windows, and passed as is for Unix.|



For example: 

```
dlflags = DLF_STATUS_BASERR or DLF_STATUS_BASERR
```

```
dlflags = dlflags or DLF_PRINT_ERRORS
dlflags = dlflags or DLF_ASCII    ! app uses only ASCII chars
call Fn'LibXL'Load(dlflags=dlflags)
```

A-Shell Reference 

Page 3825 

## **HANDLES** 

The underlying library is divided into these four classes, and for each class instance there is a corresponding handle that must be passed to the class functions. The handles are 32 bit raw address values (B,4 with deftype aliases defined in libxl.def) which must be treated with care, i.e. should never be manipulated directly in BASIC. Although nearly all the functions internally require the corresponding handle to the instance of the class, in many cases it is implicit and the library can supply the handle without the application's help. For example, once you create a workbook, from that point forward that book will be the default for any further operations that require a book handle, so the application doesn't need to redundantly specify it. But if you are working with two books, then you will need to specify the proper book handle whenever switching the context from one to the other. Likewise for sheets, formats, and fonts. For all functions that take optional handle parameters, the handle parameter will come after the mandatory parameters, and may be specified by name using the standard handle parameter names " _hbook_ ", " _hsheet_ ", " _hformat_ ", " _hfont_ ", " _hinitsheet_ ", etc. So for example: 

```
hBook1 = Fn'LibXL'CreateBook(type)! 1st book instance
hBook2 = Fn'LibXL'CreateBook(type)! 2nd book instance
```

```
! add sheet to 2nd book (default)
```

```
hSheet2A = Fn'LibXL'AddSheet("sheet1")
```

```
! add sheet to 1st book (explicit)
```

```
hSheet1A = Fn'LibXL'AddSheet("sheet1",hbook=hBook1)
```

When the handle is mandatory, it will be the first parameter. 

A-Shell Reference 

Page 3826 

## **FUNCTION NAMING** 

All the routines meant for application use are either functions with Fn'LibXL' prefixes or procedures with LibXL' prefixes. (Hard to type, but in APN, just use the Ctl+Space auto-complete feature, e.g. "SetAttr" followed by Ctrl+space.) Consistent with the underlying library, the functions are divided into Book, Sheet, Format, and Font classes, with the requirements of the object/class orientation of the library satisfied by supplying a handle to the instance of the class whose method/function is being called. The general function naming convention is Fn'LibXL'<class><verb><objects>, e.g. "Fn'LibXL'FontSetAttributes()". 

Functions named this way (with one of the class names immediately following the LibXL' prefix) expect the first argument to be the handle to the corresponding class instance, e.g. 

```
Fn'LibXL'FontSetAttributes(hfont, size=16)
```

HOWEVER, since 90%+ of the applications using this library are likely to use only one book (or one book at a time), it seems excessive to include "Book" in the name of each book function, as well as require that the first argument passed be a handle to that same book object. Instead, we've dropped the leading "Book" from the book class functions and made the book handle be an optional parameter that can be supplied as a trailing named parameter in cases where you have more than one book context at a time. Examples: 

- `! no need to save book handle if dealing with only one book…` 

```
call Fn'LibXL'CreateBook(booktype)
```

- `! and no need to supply it when referencing the default book…` 

```
hSheet1 = Fn'LibXL'GetSheet(idx)
```

But if you are working with multiple books, then you should save the handle coming back from the CreateBook() function and pass it via the named parameter _hbook_ to the other functions, e.g. 

```
hbook1 = Fn'LibXL'CreateBook()
```

```
hbook2 = Fn'LibXL'CreateBook()
```

- `! add sheet to 1st book (specifying book handle by named parameter)` 

```
hsheetx = Fn'LibXL'AddSheet("sheetname",hbook=hbook1)
```

A-Shell Reference 

Page 3827 

```
! add a format to 2nd book
```

```
hformat = Fn'LibXL'AddFormat(hbook=hbook2)
```

Remember that named parameters have to follow any unnamed (positional) parameters. 

In the case of sheets, probably a slight majority of applications will be working on one sheet at a time, but for those that aren’t, most of the Sheet functions take the sheet handle as the first parameter (signaled by the function name starting with "Sheet" after the prefix). A few of the Sheet functions rely on the default (i.e. last accessed) sheet rather than requiring an explicit sheet handle, and thus they drop the "Sheet" from the name. For example: 

```
! requires explicit sheet handle
```

```
call Fn'LibXL'SheetWriteNum(hsheet1,row,col,num)
```

```
! uses implicit (current) sheet handle
```

```
call Fn'LibXL'WriteNum(row,col,num)
```

Format and Font class functions are normally only needed in the setup of the workbook. The handles to the created objects are then used to associate Fonts with Formats and Formats with cells. So these functions mostly all require the explicit handle. Since Fonts and Formats belong to Books, you typically use Book class functions to create the class instances (e.g. Fn'LibXL'AddFont()) and then Font and Format class functions to assign attributes to them. To simplify coding, there are also some combined functions that combine the separate operations of adding the object and assigning the attributes. These combined functions typically have two parts to the main function name, e.g. "AddFormat'SetAttributes". For example: 

```
! Separate:
```

- `! Create empty format object and add it to the default book` 

```
hformat = Fn'LibXL'AddFormat()
```

- `! Then use the object handle to set attributes to it call LibXL'FormatSetAttributes(hformat,...)` 

```
! Combined:
```

A-Shell Reference 

Page 3828 

```
hformat = Fn'LibXL'AddFormat'SetAttributes(...)
```

To minimize confusion between the word "format" when referring to the class, and the word "format" when referring to a numeric format specification, we abbreviate all references to the latter as "Fmt", e.g. 

LibXL'FormatSetNumFmt( _hformat,numfmtid_ ) sets the numeric format (fmt) identified by _numfmtid_ for the Format class instance whose handle is hformat. (The underlying libxl library uses "format" for both, which is confusing.) 

A-Shell Reference 

Page 3829 

## **OTHER USAGE NOTES** 

Formats are associated with cell data at the time the cell is written. Either you specify an explicit format handle at that time, or a default format will be used. The SetCol and SetRow functions establish default formats, but will not change the formats for data already written. The only way to change the format of a cell already written is with the SheetSetCellFormat() function, or by rewriting it. 

Since the format information is associated with each cell by means of a handle, changing the attributes of the format itself will affect the cells already written using that format handle. 

Setting column widths to automatic (width = -1) appears to work best if done after all the data is written. (It seems to calculate the size at the time of the SetCol function based on the data available.) So you may want to use SetCol to assign a default column format prior to writing column data, and then use it again to set auto-width after writing all the data. 

When setting cell colors, note that the text color is an attribute of the font (not of the format), and that a solid background color is set via fillpattern=FILLPATTERN_SOLID and patternfgc=COLOR_XXX. Yes, that's the pattern FOREGROUND color. (Pattennbgc values only apply to striped patterns.) 

To add a format attribute, such as a background color, to an existing cell of unknown attributes, use SheetGetCellFormat() to retrieve the existing format, then use AddFormat'SetAttrbutes() to create a new format, specifying the existing format as the _hinitformat_ param, along with any new attributes. Then use SheetSetCellFormat() to update the cell with the new format, e.g.: 

```
hformat = Fn'LibXL'SheetGetCellFormat(sheet1,row,col)
```

```
hnewformat = Fn'LibXL'AddFormat'SetAttributes(alignh=ALIGHN_CENTER, hinitformat=hformat)
```

```
call LibXL'SheetSetCellFormat(sheet1,row,col,hnewformat)
```

A-Shell Reference 

Page 3830 

## **FUNCTION INDEX** 

The following tables list and briefly describe all the functions, organized by class. Refer to the libxl.bsi source code for details on the parameters of each function. Refer to Function Naming Convention for notes on why the functions are named as they are. 

## **Subtopics** 

- Book Class 

- Sheet Class 

- Other Classes 

A-Shell Reference 

Page 3831 

## **BOOK CLASS** 

Except for Fn’LibXL’CreateBook, which returns a handle to an instance of the Book class, all the other functions take a Book handle. (However, if the handle is not specified, it defaults to the current workbook, so in the typical single workbook situation, you can effectively ignore the workbook handle and just let the libxl.bsi class wrapper handle it.) 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'CreateBook|Create an instance of the Book class|
|Fn'LibXL'LoadBook|Load workbook from file|
|Fn'LibXL'SaveBook|Save workbook to file|
|Fn'LibXL'AddSheet|Add a sheet to workbook|
|Fn'LibXL'DelSheet|Delete sheet from workbook|
|Fn'LibXL'InsertSheet|Insert a sheet|
|Fn'LibXL'GetSheet|Return handle to sheet by index #|
|Fn'LibXL'GetActiveSheet|Return handle to active sheet|
|LibXL'SetActiveSheet|Set active sheet|



A-Shell Reference 

Page 3832 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'AddFormat|Add a format instance to the workbook|
|Fn'LibXL'GetFormatCount|Return number of formats defined|
|Fn'LibXL'GetFormat|Return handle to format by index #|
|Fn'LibXL'AddCustomNumFmt|Add a custom format|
|Fn'LibXL'GetCustomNumFmt$|Return format handle for custom format by index #|
|Fn'LibXL'AddFont|Add a font instance to the workbook|
|Fn'LibXL'GetFontCount|Return number of font instances in workbook|
|Fn'LibXL'GetFont|Return font handle by index #|
|Fn'LibXL'GetDefaultFont$|Return attributes of default font (name, size, …)|
|LibXL'SetDefaultFont|Establish default font|
|Fn'LibXL'DatePack|Pack separate date/time fields into internal date format|



A-Shell Reference 

Page 3833 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'DateUnpack|Unpack internal date format into separated date/time fields|
|Fn'LibXL'AddPicture|Add a picture to the workbook|
|Fn'LibXL'GetPictureCount|Return count of pictures in the workbook|
|Fn'LibXL'GetErrorMessage$|Get message associated with error #|
|Fn'LibXL'GetBiffVersion|Get BIFF version of binary XLS file|
|Fn'LibXL'GetRC1RefMode|Return TRUE if R1C1 reference mode set|
|LibXL'SetR1C1RefMode|Set or reset R1C1 reference mode|



A-Shell Reference 

Page 3834 

## **SHEET CLASS** 

These functions all return or require a handle to an instance of the Sheet class. Those whose name contains “LibXL’Sheet” expect the sheet handle as the first parameter, but it can be ignored (in order to use the current default sheet) if you name all of the other parameters. Those whose name does not contain “LibXL’Sheet” move the optional sheet handle to the end of the parameter list, making it easier to omit (without requiring naming of all the other parameters). 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'SheetGetName$|Return name of sheet by index #|
|LibXL'SheetSetName|Set sheet name|
|Fn'LibXL'SheetGetFirstRow|Return first non-blank row index|
|Fn'LibXL'SheetGetLastRow|Return last non-blank row index|
|Fn'LibXL'SheetGetFirstCol|Return first non-blank column index|
|Fn'LibXL'SheetGetLastCol|Return last non-blank column index|
|Fn'LibXL'SheetGetCellType|Return cell type (CELLTYPE_xxx) of cell|
|Fn'LibXL'SheetIsFormula|Return TRUE if cell contains a formula|
|Fn'LibXL'SheetIsDate|Return TRUE if cell contains a date|



A-Shell Reference 

Page 3835 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'SheetGetCellFormat|Return handle to format instance for cell|
|LibXL'SheetSetCellFormat|Set format of cell|
|Fn'LibXL'SheetWrite|Generic cell write (based on type of value passed)|
|Fn'LibXL'Write|Variation of SheetWrite which assumes current sheet|
|Fn'LibXL'SheetWriteNum|Write numeric value to cell|
|Fn'LibXL'SheetWriteFormula|Write formula to cell|
|Fn'LibXL'WriteFormula|Variation of SheetWriteFormula which assumes current sheet|
|Fn'LibXL'SheetWriteComment|Write comment to cell|
|Fn'LibXL'SheetReadComment$|Read comment from cell|
|Fn'LibXL'SheetReadValue$|Read value from specified sheet, cell|
|Fn'LibXL'ReadValue$|Variation of SheetReadValue$ which assumes current sheet|



A-Shell Reference 

Page 3836 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'SheetReadStr$|Read string contents from specified sheet, cell|
|Fn'LibXL'SheetReadNum|Read numeric contents from specified sheet, cell|
|Fn'LibXL'SheetReadFormula$|Read formula from specified sheet, cell|
|Fn'LibXL'SheetReadBlank|Read blank from specified sheet, cell|
|Fn'LibXL'SheetReadBool|Read Boolean from specified sheet, cell|
|Fn'LibXL'SheetSetCol|Set attributes for specified sheet, column|
|Fn'LibXL'SheetGetColWidth|Get width of specified sheet, column|
|Fn'LibXL'SheetGetRowHeight|Get row height of specified sheet, row|
|Fn'LibXL'SheetSetRow|Set row attributes|
|Fn'LibXL'SheetSetPicture|Set picture on specified sheet, cell|
|Fn'LibXL'SheetGetPicture|Get picture from specified sheet, cell|



A-Shell Reference 

Page 3837 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'SheetSetProtect|Protect sheet|
|Fn'LibXL'SheetGetProtect|Return TRUE if sheet is protected|
|Fn'LibXL'SheetGetHidden|Get hidden attribute from specified sheet|
|LibXL'SheetSetHidden|Hide sheet|
|Fn'LibXL'SheetGetMergeCount|Return number of merged cells on sheet|
|Fn'LibXL'SheetGetMergeIdx|Get merged cells by index|
|Fn’LibXL’SheetGetMergeXY|Get merged cells at row, col|
|Fn'LibXL'SheetSetMerge|Merge specified cells|
|Fn'LibXL'SheetDelMergeXY|Remove specified cell merge at row,col|
|Fn'LibXL'SheetDelMergeIdx|Remove cell merge by index|
|LibXL'SheetSetDisplayGridlines|Set gridlines display option|



A-Shell Reference 

Page 3838 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'SheetGetDisplayGridlines|Get gridlines display option|
|LibXL'SheetSetPrintGridlines|Set gridlines print option|
|Fn'LibXL'SheetGetPrintGridlines|Get gridlines print option|
|Fn'LibXL'SheetGroupRows|Group rows|
|Fn'LibXL'SheetGroupCols|Group columns|
|Fn'LibXL'SheetGetSplitInfo|Get vertical and horizontal split locations|
|LibXL'SheetSetSplit|Set vertical and horizontal split locations|
|Fn'LibXL'SheetCopyCell|Copy a cell (data and format) to another cell on same sheet|
|Fn'LibXL'SheetGetHyperlinkCount|Return # of hyperlinks on sheet|
|Fn'LibXL'SheetGetHyperlink$|Get hyperlink info by index|
|LibXL'SheetAddHyperlink|Add hyperlink|



A-Shell Reference 

Page 3839 

|**Function / Procedure**|**Description**|
|---|---|
|LibXL'SheetAddrToRowCol|Convert A1 or $A$1 type address to row,col|
|Fn'LibXL'SheetRowColToAddr$|Convert row,col to A1 or $A$1 type address|
|||
|**Printing-Related routines**||
|LibXL'SetLandscape|Set orientation for printing (TRUE=landscape, FALSE=portrait)|
|Fn'LibXL'GetLandscape|Get orientation for printing|
|LibXL'SetPrintFit|Fit sheet to x pages wide by y pages high|
|Fn'LibXL'GetPrintFit|Get fit info|
|Fn'LibXL'SetHeader|Set header and margin|
|Fn'LibXL'GetHeader$|Get header and margin|
|Fn'LibXL'SetFooter|Set footer and margin|



A-Shell Reference 

Page 3840 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'GetFooter$|Get footer and margin|



A-Shell Reference 

Page 3841 

## **OTHER CLASSES** 

**Font Class.** Font instances belong to the workbook (see Fn'LibXL'GetFontCount and Fn'LibXL'GetFont in the Book Class functions). Each Font instance may be shared by any number of Format instances (which is how they get associated with cells). So the standard procedure for defining fonts involves using the Book class function Fn’LibXL’AddFont to create a font instance and add it to the book, then using the Font class function LibXL’FontSetAttributes to assign attributes to it. Or, you can combine these two steps using the Fn’LibXL’AddFont’SetAttributes function. 

|**Function / Procedure**|**Description**|
|---|---|
|LibXL'FontSetAttributes|Set attributes for specified instance of font class|
|Fn'LibXL'AddFont’SetAttributes|Create font instance, add to book, set attributes for it|
|Fn'LibXL'FontGetAttributes|Get attributes of specified font instance|



**Format Class.** Each cell (individually, or in rows or columns) is associated with a single instance of the Format class, which determines the non-data attributes for the cell (alignment, color, font, numeric format or mask, etc.). As with Fonts, the Format instances belong to the Book class, so the standard procedure for defining a Format would be to use the Book class function Fn’LibXL’AddFormat, and then pass the returned Format instance handle to the Format class procedure 

LibXL’FormatSetAttributes to assign the attributes of the format. Or, you can combine those two steps with the Fn’LibXL’AddFormat’SetAttributes function. 

Also note the overuse of the word “format” to refer both to the Format class, as well as to number formats, either the standard built-in ones identified by NUMFMT_xxx identifiers, or custom ones you define via a mask. (We try to minimize the confusion by using the abbreviation “Fmt” when referring to the number formats, reserving “Format” to refer to the Format class.) 

Custom numeric formats are also owned by the Book, and have to be created and added to the book before they can be associated with an instance of the Format class. Again you can perform those steps separately, starting with the Book class 

A-Shell Reference 

Page 3842 

function Fn'LibXL'AddCustomNumFmt and Format class function Fn’LibXL’FormatSetNumFmt, or use the combined function Fn’LibXL’Format’AddSetCustomNumFmt. 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'FormatGetFont|Return handle of font associated with specified format instance|
|Fn'LibXL'FormatSetFont|Set font for specified format instance|
|Fn'LibXL'FormatGetNumFmtId|Return numeric format id for specified format instance|
|LibXL'FormatSetNumFmt|Set numeric format for specified instance of format class|
|Fn'LibXL'AddFormat'SetNumFmt|Create format instance, add to book set numeric format for it|
|Fn'LibXL'Format'AddSetCustomNumFmt|Create custom numeric format, add to book, set specified  instance to use it|
|LibXL'FormatSetAttributes|Set attributes of specified format instance|
|Fn'LibXL'AddFormat'SetAttributes|Create format instance, add to book, set attributes for it|
|LibXL'FormatGetAttributes|Get attributes of specified format instance|
|Fn'LibXL'FormatSetBorders|Set borders for specified format instance|



A-Shell Reference 

Page 3843 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'FormatGetBorders|Get borders for specified format instance|



## **Misc Routines** (not associated with a class): 

|**Function / Procedure**|**Description**|
|---|---|
|Fn'LibXL'Load|Load the LibXL library|
|Fn'LibXL'Unload|Unload the library|
|Fn'LibXL'Handle'DynLib'Errors|Handle library errors related to the Dynamic library interface|
|LibXL'Error|Force/report a library logic error|
|Fn'LibXL'Get'DLCTL$|Return the dynamic library control structure|
|Fn'LibXL'Set'Flags|Set overall library interface flags|



A-Shell Reference 

Page 3844 

## **AXL EXAMPLES** 

This section contains a set of complete example programs illustrating different features. The program source code for each program is included in the LIBXL: ersatz directory, and a link to the online source code is also provided. Note that most of these are direct translations from C++ to ASB of the example programs packaged with the LibXL library. In many cases, the original C++ code is shown as comments. 

## **Subtopics** 

- Sample Invoice 

- Alignment, Colors, Borders 

- Formulas 

- Groups 

- Numeric Formats, Masks 

A-Shell Reference 

Page 3845 

## **SAMPLE INVOICE** 

The sample program SAMXLINV (source online here) illustrates inserting a graphic, merging two cells, and several fonts and formats. 

A-Shell Reference 

Page 3846 

## **ALIGNMENT, COLORS, BORDERS** 

The sample program TSTACB (source online here) illustrates the various permutations of cell alignment, plus border styles, fill and font colors. 

A-Shell Reference 

Page 3847 

## **FORMULAS** 

The sample program TSTFORMULA (source online here)illustrates the use of formulas, with the formula showing in the first column and the result in the second. 

A-Shell Reference 

Page 3848 

## **GROUPS** 

Sample program TSTGROUP (source online here) illustrates the row grouping. Note the plus and minus buttons in the left margin. Rows 3-7 are in a collapsed group, as 14-17 and 19-22. Rows 11-26 are in a group shown expanded. 

A-Shell Reference 

Page 3849 

## **NUMERIC FORMATS, MASKS** 

Sample program TSTNUMFOR (source online here) illustrates the use of built-in numeric formats (NUMFMT_xxx) and also custom masks. The raw value is shown in the first column, the format code or mask in the center, and the formatted value on the right. 

A-Shell Reference 

Page 3850 

## **UTILITIES** 

This section contains a set of utility programs which may be helpful during development. They may also serve as samples of LibXL interface programming, but unlike the samples in the previous section, these programs are more interesting for their output than for their source code. 

## **Subtopics** 

- Format Viewer 

- Interactive Read Utility 

A-Shell Reference 

Page 3851 

## **FORMAT VIEWER** 

Utility program LIBXLVIEW (source online here) reads an existing XLS file and creates a new one illustrating the use of fonts and formats within the original. This may be useful when trying to match the structure of an existing model spreadsheet file. To illustrate, here is the output of RUN LIBXLVIEW on the Sample Invoice shown in the previous section: 

It creates a new XLS file illustrating the use of fonts and formats in the first sheet of the source XLS file: 

The first sheet (above) lists all the fonts defined in the original. One anomaly you will note is that XLS files often contain many fonts that either aren't used or which are effectively duplicates. (This is particularly noticeable when creating an empty 

spreadsheet file using Excel.) In the example above, the samxlinv.bp program explicitly created only the last three fonts; the others were created by default (and can probably be ignored for our purposes.) 

The second sheet (above) lists all the formats defined in the original. As with the fonts, you may find that there are many formats defined by default. In this example, only the last 8 were explicitly defined by the samxlinv.bp program. 

The final sheet (above) represents the first sheet of the original/source XLS file, with each cell's contents replaced by the handle of the associated format. The colors are simply added to make it easier to identify cells with the same format. For comparison, here is the original again: 

A-Shell Reference 

Page 3852 

Column A of the diagnostic sheet shows that all of the cells in column A of the original have the same format. This includes the cell containing the image. (The image is independent of the cell's format.) 

Looking at the original invoice sheet, if you are wondering about the format used for row 7 (the Description and Amount header), you can look in the corresponding cells of the diagnostic sheet (colored yellow in this case), which indicates the format handle 650A180. For details on that format, you can then go back to the Format sheet and locate that handle in column A. 

The matching row (26) is show below (wrapped): 

The above indicates, for example, that the tan background color is achieved by setting the FillPattern to FILLPATTERN_SOLID, the PatternFGC to COLOR_TAN, and the PatternBGC to the default. 

A-Shell Reference 

Page 3853 

## **INTERACTIVE READ UTILITY** 

Utility program LIBXLIAR (source online here) prompts you to load an XLS and then queries it, displaying various details about the workbook such as the number of sheets, rows, cols, pictures, etc. It then prompts you for individual cells to query. You may find it useful both in the same vein as the previous utility—i.e. for examining the contents of spreadsheets that you created or received from others—as well as an example of the use of several LibXL functions related to querying. 

As an example, using the same sample invoice referenced previously, here is a query of the contents of cell 7,2 … 

A-Shell Reference 

Page 3854 

## **- A SHELL AS A CGI WEB SERVICE** 

A-Shell supports the CGI (Common Gateway Interface), including the FastCGI variation, allowing it to act as a CGI script to deliver dynamic web content.  Web programming is an involved topic and exceeds the scope of this guide, but perhaps the following overview of how this can work may help you get started. 

## The basic CGI framework is as follows: 

- A client, which may be a browser, possibly JavaScript code within a web page, or any program capable of 

- sending/receiving HTTP requests/responses, sends a request to the web server such as Apache, IIS, NginX, etc. 

• The web server (based on configuration options) executes the CGI script, passing it information from the request via the standard input ( _stdin_ ) channel, possibly along with some environment variables. In the A-Shell case, the CGI script will actually be a bat or shell script that launches an A-Shell session with the -cgi or -cgifast switches and an appropriate startup command to process the request. 

- The A-Shell program receives the requested information, processes it, and sends back a response; this typically involving 

- multiple CGIUTL calls.  Depending on the type of request, the response might consist of a new web page (HTML document) to be displayed on the browser, or perhaps a JSON or XML document to be handled by a web service client. Depending on whether the web server interface is standard CGI or FastCGI, the A-Shell session will either terminate or loop back to wait for the next request. 

- The response is picked up by the web server and forwarded to the client. In the simplest browser case, the response is a 

- new web page that the browser displays. In the JavaScript or generic cases, the response could be just about anything that both sides agree on. 

See the following subtopics for more details and examples. 

## **Subtopics** 

- Web Form Example 

- Linux Version 

A-Shell Reference 

Page 3855 

- Windows Version 

- A-Shell CGI Command Line 

- FastCGI 

- Testing / Debugging CGI 

- Web Servers 

A-Shell Reference 

Page 3856 

## **WEB FORM EXAMPLE** 

One common scenario is the typical web form, where the user fills in some fields and then clicks a button to 'submit' it to the server. For example: 

```
<HTML>
```

```
<HEAD>
```

```
<TITLE> Sample Form Using A-Shell as a CGI Engine </TITLE>
```

```
</HEAD>
```

```
<BODY>
```

```
<CENTER>
```

```
<H1> Sample HTML Form Using A-Shell as a CGI Engine </H1>
```

```
</CENTER>
```

```
<P>
```

```
<H2> Welcome to our sample form </H2>
```

```
This is an example of a typical form that asks some questions, then passes them to a CGI program for some
kind of processing, and then displays a new page with the results.
```

```
<p>
```

```
<FORM ACTION="/cgi-bin/cgitst" METHOD="POST">
```

```
<PRE>
```

```
Enter your name:<INPUT TYPE="text" NAME="name" SIZE=40>
```

```
zip:<INPUT TYPE="text" NAME="zip" SIZE=6>
```

```
<HR>
```

```
What is your age?
```

A-Shell Reference 

Page 3857 

```
<INPUT TYPE="radio" NAME="age" VALUE="1-10">1-10
```

```
<INPUT TYPE="radio" NAME="age" VALUE="11-30">11-30
<INPUT TYPE="radio" NAME="age" VALUE="31-60">31-60
```

```
<INPUT TYPE="radio" NAME="age" VALUE="61-112">61=112
```

```
<P>
```

```
<TEXTAREA NAME="comments" ROWS=5 COLS=60>
```

```
This comment will appear in the comment box, but you can erase it or add to it.
```

```
</TEXTAREA>
```

## `</PRE>` 

## `<HR>` 

```
<INPUT TYPE="submit" VALUE="SEND FORM"><BR>
```

```
<INPUT TYPE="reset" VALUE="Clear form">
```

```
</FORM>
```

## `</BODY>` 

The above HTML displays a simple form that looks like this: 

The most important line in the HTML for the purposes of this example is the one starting with "<FORM ACTION". The form of this, and the contents of the referenced script will be slightly different between Unix and Windows, so they are discussed separately in the following topics. 

A-Shell Reference 

Page 3858 

## **LINUX VERSION** 

The Linux version of the FORM ACTION command will most likely reference a Linux shell script, using syntax similar to this: 

## `<FORM ACTION="/cgi-bin/cgitst" METHOD="POST">` 

This causes the command /cgi-bin/cgitst to be executed, using the "POST" method of parameter passing, when the "SUBMIT" or "SEND FORM" button is pressed. Depending on the web server and environment it might be possible to specify some form of A- Shell executable in the FORM ACTION tag, but normally it will be a shell script that in turn launches A-Shell with the appropriate parameters to service the request. In this example, our cgitst shell script contains the following: 

## `#!/bin/bash` 

```
exec /vm/miame/bin/ashell -i /vm/miame/miame.ini –cgi –e cgicmd 2>/tmp/cgi.err
```

The script starts by specifying that it is to run under the bash shell. It makes little or no difference which shell it runs under, since the task is simply to execute an A-Shell command line, but most web servers require this initial line so it knows how to handle launch the script. The actual A-Shell  command line must include the -cgi switch, a startup command (cgicmd in this case, i.e. cmd:cgicmd.cmd), and typically redirects the _stderr_ channel to a file. In -cgi mode, regular PRINT statements are redirected to _stderr_ while the response to the web server uses _stdout_ . 

Note: in the FastCGI case, the web server would normally be configured to use a different directory for the scripts. such as /fcgibin/ instead of /cgi-bin/, and the scripts would need to launch A-Shell with -cgifast instead of -cgi. If you are using both CGI and FastCGI, you might also want to add extensions to the scripts to more easily distinguish them—e.g. script1.cgi vs. script1.fcgi— in which case the extension would need to be included in the FORM ACTION statement, and probably be registered in the web server's configuration file. 

## **See Also** 

- CGI Command Line for more discussion. 

A-Shell Reference 

Page 3859 

## **WINDOWS VERSION** 

The Windows version of the FORM ACTION command is nearly identical to the Linux version, except that it will most likely refer to a BAT file, using syntax similar to this: 

```
<FORM ACTION="/cgi-bin/cgitst.bat" METHOD="POST">
```

The referenced cgitst.bat, if equivalent to the Linux shell script described in the Linux Version topic, would be: 

```
@c:\vm\miame\bin\ashw32.exe -i c:\vm\miame\miame.ini –cgi –e –z cgitst
```

## **See Also** 

- CGI Command Line for more discussion. 

A-Shell Reference 

Page 3860 

## **- A SHELL CGI COMMAND LINE** 

This topic provides further details on the command line within the CGI script used to launch A-Shell so that it can respond to the request.  Examples of the Linux and Windows variations from the prior two topics are repeated here for easier reference: 

Linux: 

## `#!/bin/bash` 

```
exec /vm/miame/bin/ashell -i /vm/miame/miame.ini –cgi –e cgicmd \ 2>/tmp/cgi.err
```

## Windows: 

```
@c:\vm\miame\bin\ashw32.exe -i c:\vm\miame\miame.ini –cgi –e –z cgicmd
```

The main action of the shell script or BAT file is to launch A-Shell with a specific set of command line arguments. (The main reason we couldn’t do this directly from the HTML page is that the FORM ACTION statement doesn’t permit command line arguments.) The –cgi switch tells A-Shell to operate in "CGI mode". The –e switch tells A-Shell to exit as soon as it returns to the dot prompt after executing the command. (This would not be necessary if we make sure to execute HOST.LIT after completing the CGI process.) Without -e or an explicit HOST command to exit, CGI sessions will be aborted automatically after about 7 seconds of inactivity. 

In the Windows version of the command line, we also need the –z switch to prevent A-Shell from displaying a window on the web-server (where no one could see it, and where it might cause the process to abort with an error). After the switches we pass the startup command cgicmd which in this case refers to a CMD file (cmd:cgicmd.cmd). 

The windows version of the command requires the @ in front to prevent the BAT file processor from echoing the command line to _stdout_ , which would cause it to appear in the web page (or cause the web page to be rejected). 

Under Linux, we recommend redirecting _stderr_ (built-in file descriptor 2) to a file, which is accomplished via the 2>/tmp/cgi.err Since the –cgi switch causes ordinary PRINT statements to be sent to _stderr_ instead of _stdout_ , this will not only allow for easy debugging but also prevent inadvertent PRINT statements from corrupting the web page that the CGI process is supposed to create on the _stdout_ stream. 

A-Shell Reference 

Page 3861 

Under Windows, the redirection of _stderr_ to a file is harmless, but also useless and unnecessary, since in Windows, PRINT statements do not generate stream output. Instead, they get rendered graphically in the window, which was made invisible by the –z switch. If you want to output debugging messages, you will have to explicitly write them to a file. 

## **Subtopics** 

- A-Shell CMD / RUN 

A-Shell Reference 

Page 3862 

## **- A SHELL CMD / RUN** 

The CGI script launching A-Shell must provide a command file to log the session in and run a program capable of retrieving the request and responding to it.  The Linux and Windows examples in the prior topics used a command file CGITST (e.g. CMD:CGITST.CMD or CMD:CGITST.DO) that might contain something like the following: 

```
:R
```

```
log bas:
```

```
run cgitst
```

## Finally, our program CGITST.BAS might look something like this: 

```
program CGITST,1.0(100)
```

- `!---------------------------------------------------------------------` 

- `! Sample program used within a CGI script` 

- `! Note that we are expecting the form parameters to have been passed` 

- `! to us in stdin (using the POST method). We'll pick them up with` 

- `! cgiutl. The output page templateis stored in cgitst.htm in the` 

- `! current directory; it contains "variables" for the form parameters,` 

- `! which we substitute in using cgiutl.` 

- `!---------------------------------------------------------------------` 

```
++include ashinc:ashell.def
```

```
map1 PARAMETERS               ! parameters we expect to be passed by form
```

A-Shell Reference 

Page 3863 

```
map2 NAME,S,60
```

```
map2 ZIP,S,5
```

```
map2 AGE,S,10            ! e.g. "11-30"
map2 COMMENTS,S,500
```

```
map1 CGIUTL'PARMS
```

```
map2 STATUS,F
```

- `! test if we are in cgi mode (-cgi switch used)` 

```
xcall CGIUTL,CGIOP_STATUS,STATUS
```

```
if STATUS = 0 print "Not running in CGI mode" : end
```

- `! retrieve parameters` 

```
xcall CGIUTL,CGIOP_GETPAR,"name",NAME,STATUS
```

```
xcall CGIUTL,CGIOP_GETPAR,"zip",ZIP,STATUS
```

```
xcall CGIUTL,CGIOP_GETPA2,"age",AGE,STATUS
```

```
xcall CGIUTL,CGIOP_GETPA2,"comments",COMMENTS,STATUS
```

- `! now build new web page just displaying these parameters` 

- `! (using the template file CGITST.HTM)` 

```
xcall CGIUTL,CGIOP_MRGOUT,"cgitst.htm", STATUS, &
```

- `"$NAME="+NAME, &` 

- `"$ZIP="+ZIP, &` 

- `"$AGE="+AGE, &` 

A-Shell Reference 

Page 3864 

```
"$COMMENTS="+COMMENTS
```

```
! finally, just end
```

```
end
```

The template file for the output web page might look like the following. Note that we don’t have to use this template approach. We can also use the CGIUTL opcode CGIOP_STDOUT (4) to build the web page from scratch. But this approach allows you to design your web page in another tool, then just modify it to specify suitable fill-in variable names for the data you want to merge in. 

```
content-type: text/html
```

```
<HTML>
```

```
<HEAD>
```

```
<TITLE> Sample CGI-generated web page </TITLE>
```

```
</HEAD>
```

```
<BODY>
```

```
<H1> Here is the information you passed in the previous form: </H1>
```

```
<P></P>
```

```
<P>Name = $NAME</P>
<P>Zip = $ZIP</P>
<P>Age = $AGE</P>
```

```
<P>Comments = $COMMENTS</P>
```

```
</BODY>
```

A-Shell Reference 

Page 3865 

## `</HTML>` 

The above sample program doesn’t do anything useful, other than just read in the data input into the form, parse it out, and then display that data on a new web page. However, it should be easy to extend this technique to do something useful. 

See FastCGI for details about ASB support for the fast variation. 

A-Shell Reference 

Page 3866 

## **FASTCGI** 

_Updated November 2025; see History_ 

FastCGI is an optimized variation of the normal CGI protocol, which differs primarily in that the application server instances persist across many requests, rather than having to be launched and terminated for each request. FastCGI thus vastly reduces the overhead of servicing web requests, particularly for relatively large/complex application servers (like A-Shell). 

FastCGI is widely available on common web servers such as Apache and IIS, but almost certainly requires some configuration to enable. As of this writing, is has only been tested with Apache 2.4. 

To enable support for FastCGI protocol in A-Shell, change the **-cgi** command line switch to **-cgifast** . A-Shell will then determine whether the server is using FastCGI or normal CGI protocol, and will act accordingly—i.e. support either protocol. 

Existing A-Shell CGI applications require a minor modification after which they can support either mode as well, without having to be aware of the difference. Since the main objective of FastCGI is to avoid the need to launch a new instance of the application server for each request, you need to introduce a loop into your application so that after servicing a request, instead of exiting, it loops back to wait for another request. In other words, you must convert this: 

```
<process request>
```

```
<send response>
```

```
end
```

to this: 

```
do
```

```
    xcall CGIUTL, CGIOP_GETREQ, status
```

```
    if status < 0 exit
```

```
    <process request>
```

```
    <send response>
```

A-Shell Reference 

Page 3867 

```
loop
```

```
end
```

The CGIUTL opcode CGIOP_GETREQ waits until the request has been received and is ready to process in the normal way. For the first request after the instance has been launched, it will return immediately (be essentially a NOP). For subsequent requests, it waits until another client submits a request, or perhaps the server shuts us down. In the case of normal CGI mode, the second request will return -1, telling the app to shut down, as it would normally do for CGI. 

Note that FastCGI does not eliminate the standard CGI problem of having to reestablish the client context for each request. Consecutive requests received by the server instance of your application can easily be from different clients, so you need to design some means of identifying the client and saving/restoring the context of that client's browser session—using parameters passed with each request or cookies, saved context files on the server, etc. 

## **History** 

- 2025 November, A Shell 7.0.1781 (Linux): Beginning with A-Shell 7.0.1781 of November 2025, FastCGI supports on-demand linking of libfcgi.so rather than static linking. This reduces the size of the ashell executable for the vast majority of cases not using FastCGI, as well as providing more flexibility in the field to choose among FastCGI implementations. 

There are two tests you can use to determine whether and how FastCGI is supported: 

a) You can detect whether the library is static-linked (embedded) in the ashell executable with the following Linux command: 

```
$ nm ashell | FCGI
```

If it lists several matches, then the library was static-linked. 

b) For then non-static-linked case, you can test the ability to dynamically load the libfcgi.so library using the test program FCGITEST.BP and its companion FCTITEST.CMD from the 908062 directory in the EXLIB repository. Read the notes at the top of the source for instructions on setting up and running the test. 

A-Shell Reference 

Page 3868 

## **TESTING / DEBUGGING CGI** 

One way to test whether your ASB program and A-Shell are performing properly is to create a file that contains the expected _stdin_ string, then just open a Command Prompt window and execute a command line which launches A-Shell with the redirected _stdin_ file, and redirects output to another file. You can then examine the output file to see if it looks like a valid web page. 

For testing purposes, _stdin_ format input format can be simplified to a list of "VARNAME=value&" pairs, e.g.: 

```
NAME=Bertrand Russsel&GAME=philosophy&
```

(The above example simulates a form with two variables, NAME and GAME.) Assuming this meets the requirements of your CGI program, and you stored it in a file called cgitst.in, you could test it with something like the following: 

```
c:\vm\miame\bin\ashw32.exe -z -cgi -i c:\vm\miame\miame.ini cgicmd < ./cgitst.in > ./cgitst.out
```

Naturally you would adjust the paths, startup command name, and names of the input and output files as per your situation. If the process works, you should see no action whatsoever, but when you TYPE the cgitst.out file you should see a valid web page. Better yet, try to load it with a browser to verify that it is in a valid format. If this test works, then the only remaining issues would relate to the configuration of the web server. 

A-Shell Reference 

Page 3869 

## **WEB SERVERS** 

_Rewritten November 2025_ 

Although virtually all modern web servers support CGI, and most support FastCGI as well, the most popular servers are probably Apache, IIS (Windows only) and NginX.  In all cases, it will probably be necessary to adjust the web server configuration options to deal with CGI and or FastCGI as required for your environment.  You'll probably have to consult the web server documentation and/or the Internet for help on that, but for what it's worth, here is an example of changes that might be made to the Apache configuration under Windows (in http.conf) : 

For CGI: 

```
LoadModule cgi_module modules/mod_cgi.so
```

```
...
```

```
<IfModule alias_module>
```

```
    ScriptAlias /cgi-bin/ "c:/Apache24/cgi-bin/"
```

```
</IfModule>
```

```
...
```

```
<Directory "c:/Apache24/cgi-bin">
```

```
    SetHandler cgi-script
```

```
    AllowOverride None
```

```
    Options +ExecCGI
```

```
    Require all granted
```

```
</Directory>
```

For FastCGI: 

A-Shell Reference 

Page 3870 

```
LoadModule fcgid_module modules/mod_fcgid.so
```

```
...
```

```
<IfModule alias_module>
    ScriptAlias /fcgi-bin/ "c:/Apache24/fcgi-bin/"
</IfModule>
...
<IfModule fcgid_module>
    FcgidMaxRequestsPerProcess 50000
    FcgidMinProcessesPerClass 1
    FcgidMaxProcesses 2
    FcgidBusyTimeout 60
    FcgidBusyScanInterval 5
    FcgidIOTimeout 60
    FcgidIdleTimeout 0
    FcgidIdleScanInterval 100
    FcgidProcessLifeTime 0
<Directory "c:/Apache24/fcgi-bin">
    SetHandler fcgid-script
    AllowOverride None
    Options +ExecCGI
    Require all granted
```

A-Shell Reference 

Page 3871 

```
</Directory>
```

```
</IfModule>
```

A-Shell Reference 

Page 3872 

## **GUI DEVELOPMENT** 

A-Shell Reference 

Page 3873 

## **INTRODUCTION** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Definition 

- Overview 

A-Shell Reference 

Page 3874 

## **DEFINITION** 

The A-Shell User Interface (AUI) toolkit encapsulates A-Shell’s user interface functions within a framework that simplifies the addition of a graphic user interface (GUI) to legacy text applications and promotes the separation of business and presentation logic. The functions are accessed from ASB via subroutine, XFUNC, and/or AG_xxx statements, but may be conceptually thought of as a series of object classes and methods which can be extended by application programmers through creation of higher level SBX routines. 

AUI supports many of the standard GUI objects that Windows programmers are familiar with (buttons, dialogs, list boxes, etc.), but is designed to help bridge the two major gaps that divide legacy programs from their modern Windows counterparts: 

• Fixed pitch, 24 row by 80/132 column screen vs. proportional font, pixel-level, variable sized windows. AUI deals with this by maintaining two display layers: a text layer (for traditional fixed pitch text) and a GUI layer (for controls), which share a common row/column coordinate system. The GUI layer is transparent, except where controls are placed, and acts as an overlay to the text layer, allowing text and GUI objects to appear to coexist on one screen. 

• Procedural vs. event-driven programming model. AUI converts keyboard and mouse events into special keyboard strings that INFLD, AUI_EVENTWAIT and any other input routines can interpret. By selectively defining keyboard strings for individual objects, and choosing which codes your input routine(s) will respond to, you can determine the degree to which each program assumes a traditional linear or more modern event-driven behavior. 

Since the AUI toolkit is primarily just a repackaging of existing functions and intrinsic language functions within one or more "wrapper" subroutines, one might wonder what is the point. Although it is true that repackaging doesn’t provide any new functionality, it does provide the following advantages: 

- It helps organize the documentation, especially for the GUI functions, since they are logically grouped together (rather than 

- being all over). This is especially true for people just getting started. 

- It helps organize any changes to your programs by making it obvious which parts are specifically related to the user interface 

- logic. 

- The natural architecture of subroutines is the closest thing to object orientation we have in ASB. The are truly modular, they 

- encapsulate details within an explicit interface, they do not support any global variables (which is one of .NET’s requirements), they are extensible (via the SBX mechanism) and they can be substituted (via the ALIAS[SP] or VXCALL mechanisms), all of which contributes to good program design. 

A-Shell Reference 

Page 3875 

• By submitting to the discipline of implementing all of your user interface code within a manageable set of routines, you will create a better logical separation between your business logic and interface logic, and will be better positioned to adapt to new interface environments in the future. (Or, for that matter, to support the legacy text interface as a variation of a more objectoriented graphic user interface.) 

Although not (yet) fully realized, one of the goals of the AUI concept is to shelter the business logic of applications from the lowlevel details of the capabilities of the display device. Before adopting any of the functions described herein, check the documentation to determine the extent to which the function requires or assumes particular display environment characteristics. 

A-Shell Reference 

Page 3876 

## **OVERVIEW** 

The A-Shell User Interface typically takes one of the following forms (generally organized from least to most graphical): 

- Dumb monochrome ("green screen") terminals, supporting XY positioning, little or no other features. 

- Smarter monochrome terminals or emulators, supporting Wyse50 or AM6x with a range of visual features and attributes 

- accessed through Tab(-1,x) interface, e.g. status lines, box operations, reverse, underline, dim/bright. 

- Color terminals and emulators; can select foreground/background colors from a small palette; often color is only used to map 

- onto monochrome attributes) 

- Enhanced emulators (ZTERM, AlphaLAN, ATE) which add the ability to access limited Windows functionality via ESC 

- sequences, while still being fundamentally confined to the fixed pitch display environment. (The InSight package extended that somewhat, by replacing certain higher-level display functions with Windows equivalents.) 

• ATE provides capabilities which overlap both those of the enhanced emulators and the full Windows environment. At the low end, it provides some tricks for improving the look of text mode applications while remaining a text-mode display device (e.g. beveling effects, mouse support, the ability to tie the colors to Windows colors, access to GDI printing, FTP, etc.) At the high end, it provides nearly all the capabilities of a local Windows GUI environment; the main limitation being that data has to travel between the server and the client display device, sometimes limiting the practicality of certain functions, or at least imposing some constraints on the server in order to achieve good performance. 

- Full Windows GUI environment, which comes in various levels of sophistication depending on the version of Windows. 

A-Shell has always worked in all of these environments, more or less the same way, by sticking with a limited set of fixed-pitch text mode capabilities. While very practical for portability, this lowest-common-denominator approach has limited the ability to upgrade legacy applications to provide a more Windows-like user interface when in that environment. To partially address this desire, we have historically added miscellaneous Windows functions in a piecemeal fashion so that ASB programmers committed to the Windows environment can access isolated GUI features (such as a message box, or image display) to what remained fundamentally text-mode applications. 

The piecemeal approach has provided only limited satisfaction to programmers trying to compete against true Windows applications, so beginning with 4.9 and continuing through the 5.1 development cycles, we have extended and rounded out the GUI capabilities of ASB to the extent that you can create applications which have a true Windows look-and-feel, and can compete head-to-head with "native Windows" applications created in other languages. While there will always be features that some other 

A-Shell Reference 

Page 3877 

language has that are not (yet?) in ASB, we are realistically at the point where no one should be able to use that as an excuse for not being able to write or sell a modern, competitive application. 

The goal of the AUI Toolkit is to not just to provide modern Windows GUI capabilities, but to do so in a framework that maintains at least some degree of compatibility with the existing legacy text and procedural architecture of ASB. Ideally, all of the AUI functions would (or will?) work in a purely text environment as well, but that hasn’t been achieved. What has been achieved is a viable means to migrate in an incremental, evolutionary manner from the legacy text environment to the GUI environment, improving the modularity of your programs in the process. 

A-Shell Reference 

Page 3878 

## **PLANNING FOR GUI** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Text Message Tokenization 

- Spacious Screen Layouts 

- Use of INFLD 

- Upper and Lower Case 

- Parameterized Templates 

- Catalog Your Fields 

- Decide on Environments 

- Analyze, Organize Display Logic 

A-Shell Reference 

Page 3879 

## **TEXT MESSAGE TOKENIZATION** 

One of the most obvious differences between traditional legacy text applications and Windows GUI applications is the use of fixed pitch vs. proportional fonts. The obvious problem with proportional fonts is that they take up variable amounts of space depending on the individual character widths. In order for a screen layout to translate easily from fixed pitch to proportional (and back again), the most important factor is the degree to which the text messages are "tokenized". If each text message (field prompt, column header, advisory tip, etc.) is individually positioned by a Tab(x,y), without relying on spaces for positioning, this will make the conversion much easier. Any use of spaces for positioning (relying on the fact that a space occupies one column just like any other character in a fixed pitch font) will not translate well to proportional fonts (where spaces are about half the width of a typical character.) For example: 

```
PRINT TAB(5,5);"Customer Name"; TAB(5,45);"Home Phone";
```

```
PRINT TAB(6,5);"Address";      TAB(6,45);"Bus. Phone";
```

```
PRINT TAB(7,5);"City";         TAB(7,45);"Fax";
```

The example above works well with both fixed pitch and proportional fonts. However, the example below will not work well at all, because the prompts in the right hand column which line up in a fixed pitch will not work at all in a proportional font. Not only won’t the column line up, but it will appear much closer to the first column because proportional font spaces are much slimmer than fixed pitch spaces. 

```
PRINT TAB(5,5);"Customer Name                       Home Phone";
```

```
PRINT TAB(6,5);"Address                             Bus. Phone";
```

```
PRINT TAB(7,5);"City                                Fax";
```

With a proportional font, the above statements will appear something like this: 

Customer Name                              Home Phone 

Address                                    Bus. Phone 

City                                       Fax 

Aside from examining your source code, a quick way of sizing up how serious a problem you have in this area would be to use the SET AUTOTPRINT feature, which causes all subsequent PRINT statement output to be rendered in a proportional font. 

A-Shell Reference 

Page 3880 

## **Subtopics** 

- = 

- Using OPTIONS GUI_SPC_IND 

A-Shell Reference 

Page 3881 

## **USING OPTIONS=GUI_SPC_IND** 

Turning on OPTIONS=GUI_SPC_IND causes PRINT statements to be "tokenized" so that each token is positioned at the place where it would have been positioned if using fixed pitch. It also converts tokens made of hyphens (---------) or equals signs (=========) to graphic horizontal lines. This is best illustrated with the following examples. 

A-Shell Reference 

Page 3882 

## **SPACIOUS SCREEN LAYOUTS** 

Another characteristic of legacy text programs that tends to differ from Windows-style programs is that the former have a tendency to jam a lot more information on the screen. 24 rows by 80 columns doesn’t sound like much compared to 1024 x 768 pixels, but you will not find many Windows program which have more than a dozen or so rows of edit fields on a form. (You may see a lot of rows displayed in a spreadsheet-style grid, but rarely do they try to do normal data entry in such a small space.) 

A-Shell/Windows offers a number of configuration adjustments (see the Misc. Settings dialog) to help deal with overcrowded screens, but as a general rule, the more crowded your screens, the more difficult it will be to get a pleasing effect on any but the largest, highest resolution displays. In the worst cases, you might need to consider the use of a Modal Dialog Box or a Tab Control to reduce the number of data entry fields on the screen at one time. 

A-Shell Reference 

Page 3883 

## **USE OF INFLD** 

INFLD does a lot of the heavy lifting when converting from text to GUI, much of it without any program changes at all. But this only helps if you actually use INFLD for data entry. The more consistent and systematic use you make of INFLD, the easier the conversion will be. In particular, using INFLD for displaying data as well as just inputting is a big help. Also, the more you have centralized your calls to INFLD and standardized your TYPE codes, the better off you will be. This applies just as well to the text environment as to the GUI environment, and is a good example of how the effort to convert to a GUI might actually improve the text version of your application. 

Note that not all is lost if you use some other input routine, if you do so consistently, because INFLD is able to act as a wrapper for most other input routines. But the reverse is most definitely not true in the GUI world, so you will want to look at converting to INFLD first. 

A-Shell Reference 

Page 3884 

## **UPPER AND LOWER CASE** 

Proportional fonts generally do not look right when used to display words in all upper case. If your application tends to use all upper case for prompts and data entry, you might want to look at doing a conversion to standard upper and lower case first. (Again, as with some of the other changes recommended above, this will undoubtedly improve the look of your application even in text mode.) If you have a lot of text messages to convert, you might want to write a conversion utility to process all of your source programs, rather than doing them by hand. The XFOLD subroutine could be very useful for such a project, as it provides a way to deal systematically with exceptions. 

A-Shell Reference 

Page 3885 

## **PARAMETERIZED TEMPLATES** 

If you have developed a parameterized model for data entry (or other types of) programs, or have a generator, then obviously you have a big advantage in any kind of conversion, since you can make adjustments to the template or the generator and then replicate the changes through many programs. Even if you haven’t done so before, this might be an opportunity to look at the similarities and commonalities among your hundreds (thousands?) of programs and think about how you can reduce the redundancies using SBX modules, program parameterization, etc. Again, as with other changes suggested above, this will provide as much long term benefit on the text side as on the GUI side. 

A-Shell Reference 

Page 3886 

## **CATALOG YOUR FIELDS** 

This is related to the parameterization idea, but relates to your actual fields (data fields and the screen messages which accompany them) rather than to program structure per se. Having a catalog (simple data dictionary) of all your fields will be even more valuable when you get around to converting to a database, but it is also quite useful in the GUI conversion because it naturally leads towards better separation of business logic from user interface issues. As an example, if you had a catalog (database or maybe just a spreadsheet) of all the fields used in your application, you could have a non-programmer go through it to add tool tips, assign field id’s for documentation links, correct formatting and other inconsistencies, etc. Meanwhile, by getting these user interface details (like the actual text of the field prompts) out of the programs, you will automatically be that much closer to separating your business and interface logic, while encouraging a discipline of parameterization on your programming efforts. 

A-Shell can help you get started with such a field catalog by creating a spreadsheet on demand of all GUI controls currently on the screen, when you CTRL+SHIFT+DOUBLE-CLICK. By using SET AUTOTPRINT prior to running the program, then invoking the capture when you have a complete set of prompts and data on the screen, you’ll at least have all of the text messages and their positions and sizes. If you use INFLD for data display, you’ll also have the INFLD parameters associated with the data fields, which will get you well on your way. 

A-Shell Reference 

Page 3887 

## **DECIDE ON ENVIRONMENTS** 

This is a fairly important first step, since if affects which features you can rely on and the extent to which you need to include conditional logic to support different runtime (or even compile-time) environments. At one extreme, you may want to maintain both compile and runtime compatibility across AMOS, Unix (including dumb serial terminals), as well as Windows, taking advantage of GUI improvements only where appropriate. In this case you have to avoid using any language statements that won’t compile under AMOS, as well as including `IF TEXT THEN X ELSE Y` or similar conditional logic for runtime decisions on GUI versus text mode functions. You also have to avoid the use of SBX routines, unless you are willing to write AMOS equivalents in assembler. 

At the opposite extreme, you may decide you only care about the Windows environment, in which case you can use every GUI enhancement available (and can skip the rest of this topic). 

Somewhere in the middle are those that no longer care about AMOS compatibility, or who are willing to compile under A-Shell even run AMOS runtimes. If you don’t need AMOS compatibility even at runtime, then you should probably take advantage of SBX routines as much as possible to encapsulate the details of text vs. GUI methods. If you do need AMOS runtime compatibility, you can’t use SBX routines (unless you are willing to write them in AMOS assembler), but might use a scheme involving different sets of ++INCLUDE modules for different environments. If you don’t mind compiling under A-Shell and moving the RUN files to AMOS, then you can use TPRINT and DPRINT. The following table summarizes some of the compatibility relationships between features and environments. 

|**Technique**|**AMOS**<br>**Compile**|**AMOS**<br>**Runtime**|**Dumb**<br>**CRT**|**Notes**|
|---|---|---|---|---|
|SBX|Y|?|Y|Requires equivalent SBR written for AMOS for runtime<br>compatibility|
|Tab(-10,x)|Y|?|N|AMOS requires ATE client andam62cg.tdvterminal driver.|
|TPRINT<br>DPRINT|N|Y|Y|Can be compiled as if PRINT under A-Shell for AMOS<br>runtime compatibility; automatically treated as PRINT by A-<br>Shell if not a graphic-enabled TDV|
|INFLD|Y|Y||Global_type_<br>**|G**can activate GUI mode; auto-reverts to text<br>mode if no GUI avail.|



A-Shell Reference 

Page 3888 

|**Technique**|**AMOS**<br>**Compile**|**AMOS**<br>**Runtime**|**Dumb**<br>**CRT**|**Notes**|
|---|---|---|---|---|
|AUI<br>CONTROL<br>AUI IMAGE|Y|?|N|AMOS compatibility would require ATE client plus creation of<br>AUI. No chance for dumb CRT; better to use conditional<br>logic for text vs. GUI|
|AUI MENU|Y|?|N|<same as for AUI CONTROL>|
|XTREE|Y|?|N|AMOS requires ATE client,am62cg.tdvdriver,XTREE<br>(which supports a limited subset of XTREE functionality).<br>For very simple trees, you can use INMEMO instead.|
|AUI EN-<br>VIROMENT|Y|?|Y|Use other SBR (such as GETJTB) to determine AMOS<br>environment|
|AUI<br>CONTROL|Y|?|N|AMOS requires ATE client,am62cg.tdvdriver; use XCALL<br>MIAMEX,119 (MX_CONTROL) instead of AUI_CONTROL.|
|AUI IMAGE|Y|Y|N|AMOS requires ATE client,am62cg.tdvdriver; use XCALL<br>MIAMEX,119 (MX_CONTROL) instead of AUI_CONTROL.|
|MOUSE||||See the following section on "Using the Mouse."|



## **Subtopics** 

· Using the Mouse 

A-Shell Reference 

Page 3889 

## **USING THE MOUSE** 

The numbers in the following table refer to the notes following the table. 

|**Technique**|**AShell/ Windows**|**ATE > AShell**|**ZTERM > Ashell**|**ATE > AMOS**|**ZTERM > AMOS**|
|---|---|---|---|---|---|
|SmartMouse /<br>AutoMouse|1|1|1|1|1|
|Hot Spots:<br>Tab(-1,162)|2|3|5|4|5|
|Mouse Cursor<br>Reporting<br>Tab(-1,158)|6|7|8|7|9|
|Mouse Cursor<br>Shapes: Tab(-1,160),<br>AG_SETCURSOR; see<br>note 14|10|11|13|12|13|
|Mouse Cursor<br>Positioning|15|||||
|Clipboard|16,18|16,17,18|16,17|16,17|16,17|
|AUI|19|20||21||



**1.** SmartMouse (ZTERM) and AutoMouse (ATE/A-Shell) are similar, although the parsing logic may differ slightly between them. In both cases, they attempt to isolate the "token", strip off obvious formatting characters (like a period following a number), and transmit to the host. There is essentially nothing to configure and no need to modify your programs to support it (except perhaps to format your menu text to be compatible with the concept). Note that because they work entirely on the client side, host differences have no effect. 

**2.** Hot Spots originated with the AM72 terminal and InSight. They have been supported in A-Shell/Windows since 4.8. The application uses TAB(-1,162) to define up to 75 rectangular regions at a time, each which can associate a string of up to 16 characters with a single left-click on the area. Unlike SmartMouse / AutoMouse, or Mouse Cursor Reporting, it requires a fair amount of setup in order to define the hot spots for each screen. But, once defined, they are easy to support (since you can 

A-Shell Reference 

Page 3890 

define them to send any arbitrary strings you want, include those that generate exitcode values in INFLD). See the sample program AMOUSE in EXLIB:[908,36] for an example. 

**3.** Hot Spots were not implemented in the ATE environment until 5.1.1192.0 (both on the server and client side). On the server side, the main requirement is simply that the TDV support the TCRT codes 159, 160 and 162. (Support was added to the AM75* and AM62C* drivers in 5.1.1192.0.) You can hard-code the ESC sequences if using an older version of A-Shell or a TDV that doesn't support the codes. You can use XCALL WINFLG to test for support on the server side. 

**4.** The Hot Spot TCRT commands were only implemented under AMOS in am72.tdv (which virtually no one uses!) and in the am62cg.tdv distributed with ATE as of 5.1.1192. However, the ESC sequences can easily be added to any driver. 

**5.** ZTERM does not support Hot Spots. 

**6.** Mouse Cursor Reporting is a protocol whereby the client transmits an application-defined leadin followed by a standard byte sequence identifying the cursor position whenever the mouse is clicked. This is approximately equivalent to defining a separate Hot Spot for every row/col position on the screen, except that the click sequence has to be decoded. So it's easier to set up, but harder to support in your application once activated. Both A-Shell/Windows and ZTERM have supported it for many years. But in the case of ZTERM, you need a terminal driver on the server side that supports TAB(-1,158) and TAB(-1,159) commands; see notes 8 and 9. See the program MOUSEC in EXLIB:[908,36] for an example. 

**7.** Mouse Cursor Reporting didn't start working in ATE until 5.1.1192.0 

**8.** Mouse Cursor Reporting (TCRT 158 and 159) were added to most of the A-Shell server-side terminal drivers in 5.0. 

**9.** (AMOS support for Mouse Cursor Reporting) – The only drivers known to support this feature on the AMOS side are zterm*.tdv, am62cg.tdv and am72.tdv. (Not sure about AlphaLAN drivers.) However, adding support is easy (only two ESC sequences are required, and you can bypass the driver and just send the ESC sequences directly to the client if necessary.) 

**10.** Mouse cursor shapes – TAB(-1,160) - have been supported in A-Shell/Windows since at least 4.8. 

**11.** ATE has supported mouse cursor shapes since 5.0, but it required that the TDV on the server side support the TAB(-1,160), which was not always the case. As of 5.1.1192.0 it should be supported in all A-Shell server-side terminal drivers. Also see note 15. 

**12.** No standard AMOS TDVs support TAB(-1,160), except am72.tdv, and the ATE-supplied am62cg.tdv 

A-Shell Reference 

Page 3891 

**13.** ZTERM does not support mouse cursor shapes. 

**14.** A-Shell and ATE support an alternate TAB protocol, AG_SETCURSOR for changing the mouse cursor shape (which works with any version of a " G" driver, i.e. AM62CG, AM75G etc. under either AMOS or A-Shell servers.). 

**15.** A-Shell/Windows supports a primitive mechanism to position the cursor by clicking on an area of the screen. This only makes sense in an application that can move the cursor via arrow key commands (like VUE). Scrolling with the mouse wheel is similarly supported (translated into up/down arrow keys). 

**16.** A-Shell/Windows, ATE and ZTERM support the ability to mark a rectangular section of the screen and paste it into the clipboard. The also both support pasting text from the clipboard (although they have no control over how the application on the receiving end will handle it.) 

**17.** Both ATE and ZTERM support the ZTERM ESC sequence to paste clipboard text. 

**18.** A-Shell (both standalone Windows and server when the client is ATE) support the MX_CLIPBOARD function. 

**19.** The AUI (A-Shell User Interface) subsystem was added to A-Shell in 5.0, although there are on-going enhancements. 

**20.** Most AUI functions are supported in the ATE environment also, although there may be some limitations – see the documentation for the particular routines of interest. 

**21.** A limited subset of the AUI capabilities is available under AMOS when accessed via ATE. You must install the MIAMEX.SBR, 

XTREE.SBR, IMAGE.SBR subroutines and am62cg.tdv on the server (and use the AM62CG emulation). For INFLD GUI features, you need INFLD.SBR 7.0 or later. Only a subset of GUI features are supported, but programs should be mostly compatible across platforms and between INFLD/text and INFLD/GUI implementations. 

A-Shell Reference 

Page 3892 

## **ANALYZE, ORGANIZE DISPLAY LOGIC** 

The idea here is to get a good handle on the kinds of screen layouts you use, and how individual layouts break down into categories such as data fields, prompts or labels, headers, background, status messages, etc. You may find that most of your programs have a somewhat consistent 1 or 2 line header display (program title, date, operational mode, etc.). You may also have a status message area, perhaps occupying the bottom 2 lines of every screen. The more you can encapsulate these different display areas into common parameterized routines (ideally, SBX routines), the more flexibility you will have in adapting the design to a GUI environment. (And again, the more separation you will have between your logic and your data.) 

As an example, let’s assume you find that you do use a somewhat consistent two-line screen header, and most programs have a GOSUB HEADER to display it. While you can leave the header alone, or translate it directly into proportional fonts, you will probably find that the kinds of headers that look good in a green-screen layout don’t look so natural in a Window. As a first step in figuring out how to adapt your text screen headers to Windows, it would be very helpful to turn your internal HEADER routine into a HEADER.SBX, which takes parameters such as Program Title, Subtitle, Mode, etc. You will probably also need an Opcode parameter, to distinguish between clearing the entire header area and redrawing it entirely, vs. just updating the Mode or Subtitle field. Some parts of the header, such as the company name, date, time, user, etc., the HEADER.SBX (or BSI) routine can fetch for itself without needing to be passed those parameters. 

Once you have a feeling for the GUI environment, you can design a suitable equivalent version of the header. It might be very similar, perhaps just employing a larger font to make it stand out, or you might break it up, putting the title on the Window title bar, eliminating the date and time (already on the Windows task bar), etc. 

For the portion of your display devoted to data fields and associated prompts, a fundamental decision to be made is whether to treat the prompts which make up a screen layout as a single entity which must be displayed in its entirety in one operation. Or, you may decide that you can tie each prompt individually to a data field. In the former case, the goal would be to develop a generic "display background screen" routine which you passed a screen identifier to and it fetched the screen form from some external source. In the latter case, the ideal would be to include the prompts as part of your catalog of fields, and develop a generic routine that given a set of fields, is able to draw all the prompts, or all the data. Again, none of this is absolutely required for the GUI conversion, but thinking about it (or better yet doing it) in advance will both simplify the GUI conversion and improve your logic/presentation separation. 

A-Shell Reference 

Page 3893 

## **GUI EXTENSIONS** 

A desire commonly expressed by A-Shell developers, especially those deploying in Windows environments, is for tools to give existing applications more of a Windows-like user interface. This section provides a handy index to many of the currently available tools and extensions. The table below shows links to topics found elsewhere in the documentation, and following that are discussions on other relevant topics. 

|**Link**|**Description**|
|---|---|
|MX_GETOFD|Display a File Open / Save Dialog.|
|MX_CLIPBOARD|Cut-and paste operations by user, and a subroutine interface to allow applications to copy-to and<br>paste-from the clipboard under program control.|
|MX_REGISTRY|Saving information to and retrieving it from Windows' Registry.|
|MX_SHELLEX|Although you can useHOSTEXXSto launch any native application, it is sometimes useful to be able<br>to launch the application associated with a particular file type or URL, without knowing exactly what<br>the application is called or where it is. For example, when you click on a URL link inside of an email<br>message, the email application does not need to know which web browser you use or how to launch<br>it; it simply tells Windows to launch the application that goes with this URL.|
|MX_PLAYSOUND|Play a sound file.|
|AUI|A-Shell 4.9 introduced the ability to dynamically create real Windows controls in A-Shell. These<br>include dialogs, buttons, checkboxes, radio buttons, group boxes, listboxes, combo boxes, edit<br>controls, tab controls, static text controls, tree controls, etc. Using this technique, you can use<br>traditional A-BASIC screen drawing techniques (print commands, tab functions, and subroutines) to<br>create Windows "forms" and dialogs that are nearly indistinguishable from Windows programs<br>created in Visual Basic.|
|MX_WINPTR|Display Windows printer selection|
|MX_BROWSEFOLDER|Browse / select directories|
|MX_GETSHELLPATH|Retrieve a Windows directory by its alias/ID|
|MX_CHOOSECOLOR|Choose a color|
|MX_CHOOSEFONT|Choose a font|



A-Shell Reference 

Page 3894 

|**Link**|**Description**|
|---|---|
|MX_DEFTABXYZ|'3D' Tabs|
|MX_WINSETTINGS|Modify A-Shell GUI Settings|



## **Subtopics** 

- Mouse Interaction 

- Proportional Font Text Objects 

- Windows Themes 

- Beveling 

- Imaging 

- Adding Custom Menu Items 

A-Shell Reference 

Page 3895 

## **MOUSE INTERACTION** 

To change the screen icon/image of the cursor, see Set Mouse Cursor. 

## **Subtopics** 

- Mouse Hot Spots 

- Mouse Cursor Reporting1 

- AutoMouse Translations 

A-Shell Reference 

Page 3896 

## **MOUSE HOT SPOTS** 

The Mouse Hot Spot feature involves defining rectangular areas, that when clicked, send a particular keyboard sequence. The A- Shell implementation is compatible with the AMOS version, but its use is discouraged since the functionality has been largely superceded by the use of real GUI controls (such as buttons). 

A-Shell/Windows supports the extended mouse "hot spot" TCRT protocol introduced with the AM72 terminal and later promoted in conjunction with InSight. Briefly, this allows you to define arbitrary code strings and associate them with rectangular regions of the screen. When the mouse is clicked within one of these regions, the defined string of codes is transmitted into the keyboard buffer. Because the codes are routed into the keyboard buffer, it is almost trivial to add this capability to existing menu programs. (Just set the code string to the letter or number normally used to select that menu item.) Implementing traditional Windows-type data entry screens, where the mouse can be used to move the cursor to any field, is possible but considerably more difficult. (One approach involves extensive use of the EXITCODE feature within INFLD to define a separate code for each field. Upon exiting from any field, the program would check for one of these exit codes, and if appropriate, jump directly to the field indicated by the code.) 

All of the mouse hot spots which are active at one time must be specified in one large Tab(-1,162) sequence, which has the following general form: 

## **tab(-1,162); Count; Len1; Key1; Srow1; Scol1; Erow1; Ecol1; Len2; Key2; Srow2; Scol2; Erow2; Ecol2; Lenn; Keyn; Srown; Scoln; Erown; Ecoln;** 

The coding of the individual parameters is described in the table below: 

|**Parameter**|**Coding and Description**|
|---|---|
|Count|Code as CHR$(N+32) where N is the number of desired hot spots. (N=0 to clear all hot spots.)|
|Lenn|Code as CHR$(L+32) where L is the number of bytes in the following Keyn field. Maximum key length is 16.|
|Keyn|From 1 to 16 bytes to be transmitted into the keyboard buffer when the hot spot is clicked on.|
|Srown|Code as CHR$(R+31) where R is the starting row of the hot spot. Use R=0 for the top status line and R =|



A-Shell Reference 

Page 3897 

|**Parameter**|**Coding and Description**|
|---|---|
||<screen height+1> for the bottom status line.|
|Scoln|Column code. If columns is less than or equal to 96, then code as CHR$(C+31). Otherwise, code as<br>CHR$(25);CHR$(C-65) where C is the starting column of the hot spot.|
|Erown|Ending row of hot spot. Code same as for starting row|
|Ecoln|Ending column of hot spot. Code same as for starting column.|



There is a good general discussion of the technique of _Mouse Enabling Your Screens_ in a section under the same name in Chapter 6 of the _InSight Programmer's Reference Guide._ The A-Shell implementation of the feature is completely compatible with the InSight implementation, except that A-Shell allows you to create hot spots on the top and bottom status lines (by referring to them as row 0 and n+1, respectively, where n is the current height of the screen, typically 24.) For those of you eager to experiment with this technique but not eager to hunt down or read the documentation, A-Shell/Windows is supplied with a sample program, AMOUSE.BAS in EXLIB:[908,36], which adequately demonstrates the range of possibilities. 

ZTERM supports many of the InSight TCRT codes and ESC sequences. 

A-Shell Reference 

Page 3898 

## **MOUSE CURSOR REPORTING1** 

Like Mouse Hot Spots, Mouse Cursor Reporting has been largely superceded by the use of real GUI controls. 

Yet another protocol for sensing mouse clicks, also originating with InSight and currently supported by A-Shell/Windows, ZTERM, and AlphaLAN, is known as "mouse cursor reporting". It differs from the hot spot protocol in that once activated, it transmits control bytes into the keyboard buffer for every mouse click, no matter where it is on the screen. The control bytes indicate the position of the mouse and the button that was clicked (or double-clicked), leaving it to the application to decide how to respond. Unlike the hot spot protocol, this protocol requires that you use a single-byte-at-a-time input routine (such as the xcalls ACCEPT, TINKEY, GET, GETKEY, etc., and preferably one with a time-out feature) so that you can properly handle the variable-length sequences sent by the mouse and separate them from other keyboard activity. 

To activate mouse cursor reporting, use `TAB(-1,158)` , or the newer `TAB(-10,AG_TABWRAPPER` ), followed by a series of control bytes which define the way the reporting will work. The newer variation avoids complications between the cursor reporting and screen tracking in the ATE environment. See Mouse Cursor Reporting2 for details on the byte sequences for defining and detecting mouse cursor events, and sample programs MOUSEC.BAS, MOUSEC2.BP and MOUSEC3.BP in EXLIB:[908,36] for examples and details on the control bytes and how to parse the reporting sequences. 

Special thanks go to James Jarboe IV for the sample program MOUSEC and for his help in clarifying how mouse cursor reporting works. 

A-Shell Reference 

Page 3899 

## **AUTOMOUSE TRANSLATIONS** 

Like Mouse Hot Spots and Mouse Cursor Reporting, AutoMouse Programmable Translations have been largely superceded by GUI controls. 

AutoMouse is a variation on the "SmartMouse technology" used in ZTERM. The idea is that when activated, A-Shell will attempt to make sense of any left double-click it receives. The way it does this is by identify the text "token" that was clicked on. For example, if you double click on a number, then it transmits that number into the keyboard buffer. That aspect of AutoMouse is more of a user feature than a development topic, so we won’t pursue it further here. 

The AutoMouse Programmable Translations, on the other hand, relate to application development. The idea here is that your program may define its own special text tokens (arbitrary strings which may contains spaces and other delimiters) and associate them with specified keystrokes. This is similar in concept to the hot spots described previously, except that while hot spots are associated with specific positions on the screen, AutoMouse Programmable Translations are associated with specific text strings, wherever they may appear. AutoMouse Programmable Translations are maintained using a subroutine (MX_AMOUSEXLT) instead of via a Tab(-1,162) sequence as for hot spots. The flexibility of the subroutine interface offers the advantage of allowing the addition and deletion of individual translations (instead of having to do them all at once, as with hot spots). For a simple example, consider: 

```
xcall MIAMEX, MX_AMOUSEXLT, 0, STATUS, 0, &
```

```
"1. Add Transaction", "1"+chr(13),  &
```

```
"2. Change Transaction","2"+chr(13), &
```

```
"3. Delete Transaction","3"+chr(13), &
```

```
"4. Post","4"+chr(13), &
```

```
"ESC to Return to Menu",27
```

This might make sense in a menu program featuring those options. While the default AutoMouse translations would handle the numeric options in this menu automatically, you would have to click right on the numbers. After the above call, the user would be able to click anywhere, for example, on "1. Add Transaction" to transmit a "1" followed by a carriage return. Clicking anywhere on the string "ESC To Return to Menu" would send an ESC. (Note we can specify the chr(27) for ESC simply as 27, since it is a single byte value.) The multi-byte translations require a literal or mapped string, or a string expression. 

A-Shell Reference 

Page 3900 

When beveling is enabled and the screen background is a suitable mid-level color (not black or white), clicking on an AutoMouse token will briefly "buttonize" the token, giving it the impression of having been pushed slightly in. 

See the latest MIAMEX sample program for another example. 

A-Shell Reference 

Page 3901 

## **PROPORTIONAL FONT TEXT OBJECTS** 

You can convert ordinary PRINT statements, which output fixed pitch text to the screen, into proportional text objects using any of the following methods: 

TPRINT: If you compile with the /X:2 switch, you can use the TPRINT statement, which functions exactly like PRINT (to the screen) except that it uses the current default proportional GUI font. (You can override that font via Settings menu.) 

DPRINT: Nearly identical to TPRINT, except it creates a sunken panel for the output text, and thus is likely to be used for printing "Data" (whereas TPRINT is for "Text"). Note that the size of the sunken panel will be based on the size that would be needed if the standard fixed pitch font was being used. Also note that when INFLD is in GUI mode ( _type_ **|G** ), it displays the field (when not actively editing it) using the DPRINT style. 

EPRINT. Similar to DPRINT, except that it uses an EDIT control to display the string, rather than a sunken static text control. Note that EPRINT adds one to the width of the control if the width was otherwise going to be only one column; this should eliminate most of the cases where upper case text is truncated, without causing too much havoc with screen layouts. 

In a text-only environment (i.e. under Unix when the terminal driver name does not end in "G"), TPRINT, DPRINT and EPRINT will revert to acting just like PRINT. 

SET.LIT supports an AUTOTPRINT setting that causes existing PRINT statements to act as if they were TPRINT. This is the fastest way to convert your entire application from fixed to proportional text, and to size up the areas where you may have to make some formatting adjustments. 

The A-Shell compiler will compile TPRINT and DPRINT as if they were PRINT, if the /X:2 switch is not set. This might allow you to generate a RUN file compatible with AMOS even though your program uses TPRINT and DPRINT. 

Note that DPRINT applies "intelligent justfication" logic to decide whether the field should be right, left or center justified. If both the first and last character of a string expression are spaces, then it center justifies. If the first character is a space or monetary symbol and the last character is a non-space, then it right justifies. Otherwise it left justifies. This should result in the desired alignment for data fields in most cases, although you may have to adjust any fields in which you were intentionally counting on the fixed width of spaces. In the proportional font world, you cannot count on spaces for positioning of text; always use explicit Tab(x,y) statements for each output token to avoid confusion. 

A-Shell Reference 

Page 3902 

## **Subtopics** 

- Alignment Problems with Text 

A-Shell Reference 

Page 3903 

## **ALIGNMENT PROBLEMS WITH TEXT** 

When switching from fixed to proportional text, you are likely to run into problems with columns not aligning as they used to. This is due to the fact that with proportional fonts, character widths vary depending on the character. In particularly, the space character is very thin compared to most others, especially the capital letters (like W). However, because A-Shell continues to use the same row/col grid for Tab(x,y) commands, you can usually solve your alignment problems by following these guidelines: 

- Always use a Tab(x,y) prior to outputting a "token" of text. This will at least ensure that your text prompts and messages 

- always start in a consistent position. (In other words, don't use spaces to position your text.) 

- Avoid overwriting parts of existing messages. Instead, try to replace the entire message. (You cannot reliably determine the 

- X,Y coordinates of a particular character within a proportional text string.) 

- To overwrite an existing text object, you can simply Tab(X,Y) to the start of it and output a new text string. (You might want 

- to pad the string with sufficient spaces so that in the case of text mode, it would fully overwrite the string.) 

- Add a few extra spaces on the end of text tokens, to provide some "breathing room" for the proportional version of the 

- message to expand if it contains a lot of wide (or capital) letters. For example: 

```
TPRINT TAB(X,Y);"Vendor Name:  ";   TPRINT TAB(X,Y);MESSAGE$;"  ";
```

One situation you may run into is where you use a combination of Tab(x,y) with some spaces to align fields like this: 

`1.  Name:` 

```
    Addr:
```

`12. Parish:` 

```
    Postal code:
```

Assuming the last two items were variables (i.e. depending on some other flag, you might display "City", or "Borough" instead of "Parish", and "Zip Code" instead of "Postal Code"), then you might have created the above display with code like the following: `PRINT TAB(10,5);" 1. Name:"` 

```
PRINT TAB(11,5);"    Addr:"
PRINT TAB(12,5);"12. ";CITY$
```

A-Shell Reference 

Page 3904 

```
PRINT TAB(13,9);PHONE$
```

This works because the spaces occupy the same width as the numeric digits and the period, so in all cases the main part of the label starts in column 9. But if we convert these PRINT statements to TPRINT (or use SET AUTOTPRINT), they will no longer line up because spaces, digits, and periods all have different widths in the proportional font world. Following the guidelines give above, the ideal solution would be to recode this as: 

```
TPRINT TAB(10,5);" 1. ";TAB(10,9);"Name:"
TPRINT TAB(11,5);"    ";TAB(11,9);"Addr:"
TPRINT TAB(12,5);"12. ";TAB(12,9);CITY$
TPRINT TAB(13,5);"    ";TAB(13,9);PHONE$
```

But unfortunately that involves a lot of retyping. Slightly less retyping would be this solution: 

```
TPRINT TAB(10,5);" 1. ";"Name:"
TPRINT TAB(11,5);"    ";"Addr:"
TPRINT TAB(12,5);"12. ";CITY$
TPRINT TAB(13,5);"    ";PHONE$
```

The above solution works because each of the TPRINT statements has two arguments. The position of the second argument is calculated based on the number of characters in the first (which is 4 in each case), regardless of the fact that those characters will occupy different widths when rendered using a proportional font. So the result is equivalent to the previous example, where the Tab(x,9) was explicit. 

But even this may be a lot of work if you have a lot of screens like this. In the case, you may want to use the shortcut of adding OPTIONS=GUI_SPC_IND to miame.ini. This causes any string which contains leading spaces, or a combination of leading spaces, 

A-Shell Reference 

Page 3905 

numeric, digits, a period, and one or more spaces, to be output as if it was a separate print object from the rest of the string. In other words: 

```
PRINT TAB(10,5);" 1. Name:
```

Would be interpreted as if it had been coded as: 

```
PRINT TAB(10,5);" 1. ";"Name:"
```

This will generally result in the kind of alignment you were probably hoping for. (However, unless you know you have this problem, we don’t recommend just turning on this switch as a precautionary measure, because it increases screen complexity which may lead to some other undesirable side-effect.) 

A-Shell Reference 

Page 3906 

## **WINDOWS THEMES** 

Windows Themes are supported for any applicable GUI controls, provided that the file ashw32.exe.manifest is present in the same directory from which ashw32.exe was launched. Themes provide various visual enhancements, such as buttons which automatically highlight when the cursor passes over them. However, a downside of Themes is that you lose the ability to control the colors of most GUI objects. The one exception is that you can still control the foreground color of text objects, but you must add 64 to the foreground color parameter (fgc) of AUI "CONTROL", MX_WINCTL, or AG_CONTROL commands. 

A-Shell Reference 

Page 3907 

## **BEVELING** 

Beveling has been largely superceded by more powerful GUI enhancements, although is still of interest for traditional text mode programs. 

Beveling is the term we have given to a display enhancement that uses shading to give a three dimensional (or "beveled") appearance to certain display features. Currently this affects only line drawing characters (such as box borders) and input fields (processed with INFLD), but may potentially be expanded to other features as opportunities are recognized. It may be turned on (and saved with the other settings) via the Settings menu, or it may be turned on and off under program control, using AG_BEVEL. 

Most people prefer the beveled look, at it gives the application a more "Windows-like" appearance, but for best results you should follow the guidelines and tips described below. 

Since the effect is produced by drawing lines in lighter and darker shades of the background color (to simulate the effect of light and shadow), it requires that you use a "middle-range" background color. By "middle-range", we mean one whose R, G, and B values are somewhere in the middle between 0 and 255. The worst case is black (RGB=0,0,0) or white (RGB=255,255,255), since there is no way to make a darker version of black or a lighter version of white. But in fact, most of the standard colors are hardly any better, since they are typically made up of various combinations of 0 and 255. For example, the typical blue is made up of R=0,G=0,B=255; yellow is typically R=255,G=255,B=0. It is possible to simulate darker and lighter shades of such colors, but the effect is not as good as with colors whose RGB values are, say, between 50 and 200. The best results are probably achieved with the standard Windows gray background, which is R=192,G=192,B=192, although any pastel color will work well both in terms of making the beveling stand out and in terms of making the application appear at first glance to be more Windows-like than DOS-like. 

You can redefine the RGB values for the standard color numbers 0-15 either via the Custom Colors option in the _Settings...Colors_ dialog, or via AG_SETCOLOR. Also note that as an alternative to explicitly defining a suitable background color via RGB codes, you can use MX_SYSBCLR or SET TERM SYSBCOLOR to associate one of the standard numeric colors 0-7 with the current Windows background color, which is typically gray but changes according to the desktop color scheme selected in the Windows control panel. 

When drawing boxes or grids using line drawing characters, the beveling effect looks best if you make the background color of the lines (or box border, if using a routine such as MSBOXX[XS] ) match the background color of the surrounding screen area. 

A-Shell Reference 

Page 3908 

To maximize the Windows-like effect of the beveled (sunken) INFLD fields, you may want to experiment with the INFLD color parameters, for example, making the background of the field light gray while editing it and then returning it to the surrounding background color once the field is updated. (This has nothing to do with beveling but it is often nice to select a redisplay foreground color that is slightly different from the initial data foreground color to highlight those fields that have been edited.) The easiest way to experiment with INFLD color parameters is via the INI.CLR file or under MX_INICLR. 

A-Shell Reference 

Page 3909 

## **IMAGING** 

As of A-Shell / Windows Build 771, you can perform basic display and print operations on BMP, JPG, TIF and PCX format images. Display operations are handled by AUI_IMAGE, while printing operations are handled by the IMAGE embedded print file. TWAIN ACQUIRE (i.e. scanning or other image input) is also supported in IMAGE[XS] . 

Aside from the documentation for IMAGE[XS] and //IMAGE, you will find the sample program image.bp in SOSLIB:[908,32] and four sample image files (sample.jpg, sample.pcx, sample.tif, sample.bmp). There is also a sample GDI print file, image.txt, which prints a couple of the sample images. The image.bp program prompts you for opcodes, filenames, and other parameters needed by the IMAGE routine, allowing you to experiment with the various parameters. It also demonstrates one way to implement the ability to temporarily maximize the image via a function key, menu prompt, or mouse click. 

If you don’t have the sample programs, you can install just them from the standard A-Shell / Windows release package by selecting the Custom install method. 

IMAGE[XS] and the //IMAGE printing function are implemented with the help of an external library, vic32.dll, which due to licensing restrictions, is not included in the standard release of A-Shell. However, the licensing fee is rather nominal and activating the library can be accomplished without having to update the A-Shell executable. Contact MicroSabio for details on obtaining and distributing the library. 

Unisys Corp holds a patent on the LZW compression type used in nearly all GIF files found on the web. Although the imaging library we are using supports LZW decompression, it is not enabled until you obtain some kind of "certificate" from Unisys indicating that you have paid their license fee. In the absence of that, we suggest you stick with uncompressed images or other compression types (such as JPEG for color images and G3/G4 TIFF for bi-level document images.) 

A-Shell Reference 

Page 3910 

## **ADDING CUSTOM MENU ITEMS** 

One way to quickly make your applications more "Windows-like" is to use the Windows menu bar system as an alternative to traditional text-style application menus. AUI_MENU provides the necessary capabilities to accomplish this, and is adequately documented. Here we will instead go over a detailed example of adding Windows menu selections to a "typical" accounting application. 

Our example application uses two levels of main menus. The first level offers choices for the various accounting modules (GL, AR, AP) while the second level displays the individual programs or tasks within each module. Our plan is to add Windows menus for both levels to the menu bar of the top-level menu program so that the user can bypass the second level and go directly to any individual program/task. We will accomplish this by creating an MDF (Menu Definition File) listing all of the programs and organizing them into three drop-down menus. 

So far, this is very straightforward. The only complexities are deciding which of the menu action mechanisms to use, and how to integrate these actions with the existing main menu program. Briefly, the choices for each menu action are: 

- Execute a Windows command line 

- Call a custom DLL 

- Force a string of characters into the keyboard buffer 

- Specify a document or URL and let Windows decide how to launch the appropriate application to open it. 

## **Subtopics** 

- Keyboard String Menus 

- Command Line Menus 

- Registry (or Shell Execute) Menus 

A-Shell Reference 

Page 3911 

## **KEYBOARD STRING MENUS** 

Of the four types of menu items, probably the easiest to use is the type that transmits a string of keyboard characters when selected. These can be set up to transmit the same characters that a real user would type on the keyboard, and thus the program needs no special code to detect and process the selections (other than adding them to the menu in the first place and deleting them later.) This is possible even though a single Windows menu option in this case will span two separate menu programs. For example, to select the first choice on the top level menu and the third choice on the second level menu, we could just make the keyboard string be `"1"+chr(13)+"3"+chr(13)` . The first part of the string would be responded to by the top level menu program, and the second part would still be in the keyboard buffer, and thus responded to by the second level menu program. 

One complication to be overcome, though, is how to input the chr(13) (aka carriage return) control character into the MDF. Fortunately, there are two ways to do this. One is to use the Control-G lead-in, which tells the A-Shell/VUE editor to insert the next character into the file as-is, rather than treating it as a command. So the sequence Control-G Control-M would insert the carriage return character (i.e. chr(13) or Control-M) into the file, displaying it as a dim M. The only problem with this approach is that may create confusion when printing or typing the MDF on the screen or editing it with another editor. To avoid those problems, as of Build 828.2, you can also use the special notation of ^X to indicate Control-X (where X can be any character from A-Z, plus [, ], \, ^, and _.) For example, consider the following line: 

```
&G/L,"Account Maintenance",KBD,"1^M3^M"
```

This would create a menu item that transmitted the keyboard characters "1" followed by chr(13) (aka Control-M) followed by "3" followed by another Control-M. 

The other complication with this approach is to make sure you disable or remove the menu items as soon as we change to a context where there are no longer appropriate. Fortunately again, this is reasonably simply in a menu program. All we have to do is insert a call to disable or delete the menus immediately prior to chaining from or exiting the menu. 

To complete our example, here is the ashelp.mdf we’ll use: 

```
;Menu Definition File for GL, AR, AP, PR
```

```
;G/L is the first item on the main menu;
```

- `; its selections can be reached by entering 1 <CR>` 

A-Shell Reference 

Page 3912 

- `; (to get to the GLMENU program), then the appropriate` 

- `; # followed by another CR…` 

```
TOP,"&G/L",SUB
```

- `&G/L,"Account Maintenance", KBD,"1^M1^M"` 

- `&G/L,"Period Maintenance",KBD,"1^M2^M"` 

```
&G/L,"Transaction Entry", KBD,"1^M3^M"
```

```
&G/L,"Financial Statements", KBD,"1^M4^M"
```

```
;A/R is the second item on the main menu
```

```
TOP,"&A/R",SUB
```

- `&A/R,"Customer Maintenance", KBD,"2^M1^M"` 

- `&A/R,"Sales Transactions", KBD,"2^M2^M"` 

```
&A/R,"Cash Receipts",CMD, KBD,"2^M3^M"
```

```
&A/R,"A/R Reports",CMD, KBD,"2^M4^M"
```

```
;A/P is the third item on the main menu
TOP,"&A/P",SUB
```

- `&A/R,"Vendor Maintenance", KBD,"3^M1^M"` 

- `&A/R,"Expense Acct Maintenance", KBD,"3^M2^M"` 

- `&A/R,"Voucher Entry", KBD,"3^M3^M"` 

- `&A/R,"Payment Processing", KBD,"3^M4^M"` 

A-Shell Reference 

Page 3913 

```
&A/R,"A/P Reports", KBD,"3^M5^M"
```

```
;We'll also add a separator bar and then our application's
```

```
; documentation file to the Help menu
```

```
HELP,"h1",SEP
```

```
HELP,"Application Documentation",REG,"c:\vm\miame\doc\app.pdf"
```

Note that the "h1" in the first HELP menu line above doesn’t display but is needed in order to have a unique identifier for the separator bar, so that it can be deleted later. Also note that the second HELP menu line above use the menu type "REG" rather than "KBD". The "REG" type uses the Windows Registry to open the specified document with the application that has been previously registered to understand that type (Acrobat in the case of PDF.) 

Here’s an example of the code to reference the above MDF, adding it to the menu bar at the start of the main menu program and removing it before ending or chaining to another program: 

```
START:
```

```
OPCODE = 1 : STATE = 0   ! (add, enable)
```

```
call DO'WIN'MENU
```

```
DO'MAIN'MENU:
```

```
! Display and process main menu…
print tab(10,10);"1. General Ledger"
print tab(12,10);"2. Accounts Receivable"
```

```
print tab(14,10);"3. Accounts Payable"
print tab(18,10);"Enter Selection:"
```

```
input "",SELECT
```

A-Shell Reference 

Page 3914 

```
if (SELECT < 1 or SELECT > 3) goto EXIT'PROGRAM
```

```
CHAIN'TO'SELECTION:
```

```
OPCODE = 3  ! (delete)
call DO'WIN'MENU
chain PROGRAM$(SELECT)
```

```
EXIT'PROGRAM:
```

```
OPCODE = 3  ! (delete)
call DO'WIN'MENU
```

```
end
```

```
! add/delete/change Windows menu items
```

```
! Inputs: OPCODE (1=add, 2=change, 3=delete); STATE (0=enable, 1=disable)
```

```
DO'WIN'MENU:
```

```
! If MAIN.MDF exists, do it
```

```
LOOKUP "MAIN.MDF",X
```

```
if X # 0 then xcall MIAMEX, MX_WINMNU, OPCODE, "MAIN.MDF", STATE, STATUS
```

```
return
```

One "error" in the above program is that it removes the HELP menu selection (which presumably ought to be available from anywhere in the application) along with all of the rest of the menus when it chains out of the main menu. To treat one set of 

A-Shell Reference 

Page 3915 

menu items (in this case the HELP menu) differently from another set, you can use multiple MDFs. In this case, it would have made sense to have one MDF for the G/L, A/R and A/P menus, and one for the HELP menu. The HELP menu could then have been left in place while the others were deleted. We could also have just handled the HELP menu addition with the "traditional" form of MX_WINMNU, since there is little advantage to the MDF technique for adding just one item. 

When using multiple sets of menu items, the main limitation is that they be structurally independent from each other so that they can be added and deleted independently from each other. The simplest way to ensure this is to not mix groups of independent menu items on the same submenu. 

A-Shell Reference 

Page 3916 

## **COMMAND LINE MENUS** 

Let’s consider the pros and cons of using command line menus rather than keyboard string menus in the above example. The main two shortcomings of keyboard string menus are that you have to be careful to disable them as soon as the program’s input context changes, and you can only perform actions that can otherwise be performed with the keyboard. This latter comment may not seem like much of a "shortcoming" until we consider the benefits of being able to add functionality to programs via menus without otherwise modifying the programs. The help menu item in the previous example is a good illustration of this; it adds a capability (viewing documentation in Acrobat) to your program that may not have been previously implemented via keyboard commands. Furthermore, it can be added to the menu once and left there to be used from any of the programs in your application. 

The command line menu type overcomes both of the above shortcomings. First, the commands are executed independently of your program context and thus you don’t need to worry as much about changing the menu items as the program changes state. Second, you can execute any legal Windows command line, and thus you are not at all bound by the limitations of your 

application. For example, you can launch desktop utilities like the calculator (calc.exe), or entirely new applications, like a backup or email program. However, you might wonder what good this does when all you want to do (in the case of our simple accounting menu example) is select and run a program within A-Shell. It turns out you can use the command line approach for this case as well. The trick is to launch a new instance of A-Shell. Consider the following excerpt from our MDF, this time using the command line approach: 

```
TOP,"&G/L",SUB
```

```
&G/L,"Account Maintenance", CMD,"$ASHELL –e run glamnt"
```

```
&G/L,"Period Maintenance",CMD,"$ASHELL –e run actmnt"
```

```
&G/L,"Transaction Entry", CMD,"$ASHELL –e run trxedt"
```

```
&G/L,"Financial Statements", CMD,"$ASHELL –e run finstm"
```

```
TOP,"&Utilities",SUB
```

```
&Utilities,"Calculator", CMD,"calc.exe $"
```

A-Shell Reference 

Page 3917 

Here we used the special macro $ASHELL, which the MDF logic understands to mean _launch another instance of A-Shell using the same A-Shell executable and MIAME.INI file as the current instance._ The remainder of the command line simply runs the specified program, counting on the fact that the new instance of A-Shell will start out logged in to our current directory. If the programs were in another directory, we would either have to specify their location, or perhaps use a command file to first log us to the proper location and then run the program. The –e switch forces the instance to terminate when the specified program returns to the dot prompt. 

The new instance of A-Shell will be on top of the original instance, which will be suspended until the new instance terminates. At that point, you’ll be right back where you started. 

This approach has the potential advantage that it might be applicable anywhere in the application. For example, you might be in the A/P voucher entry program and want to look up an account in the G/L. Rather than exit the voucher program to switch to G/L, you might just select the G/L Account Maintenance option from the menu, launching a new instance for that program, then return to the original program when done. 

There are, however, some shortcomings to this approach as well. First, it requires that your programs can be run from the dot prompt without first going through some security logic in the main menu. (Many applications load some kind of security or other context information into memory within the main menu, which is needed by other programs in the application. In such a case, the above plan would not work.) Another potential problem might be confusion on the part of the user over how to get back to where they were. 

Note that you don’t have to suspend the original instance while the new instance is running. It might make more sense in this case to allow the user to operate as many independent sessions as they like, toggling between them at will. You can accomplish this by adding a " $" to the end of the command line string (e.g. " `$ASHELL –e run actmnt $` ".) (We chose to do this with the calculator item so that we wouldn’t have to close the calculator after each use.) 

A-Shell Reference 

Page 3918 

## **REGISTRY (OR SHELL EXECUTE) MENUS** 

The REG type of menu item (used in our original example above for the Application Help menu) is similar to the command line (CMD) type, in that it launches an independent application and thus has no particular connection to the context of the current application. The main advantage of the REG type over the CMD type is that you don’t have to worry about knowing the name or path of the executable needed. For example, if you want to open a CSV file as a spreadsheet, to use the CMD method, you would need to know the full pathname of the spreadsheet program. With the REG approach, you don’t even need to know what the program name is, much less its location. 

The main disadvantage of the REG type is that you can’t easily pass any command line arguments. Also, you can’t suspend the current A-Shell session while the new application runs. 

Since you can mix and match menu types, even within a single MDF, understanding the advantages and disadvantages of each type will allow you to use the best type for each circumstance. 

You can add up to 125 individual menu items. 

A-Shell Reference 

Page 3919 

## **STEPS TO GUI** 

The project to convert your text interface to a GUI may seem overwhelming, especially after reading the previous section. This section will attempt to serve as an antidote to the paralysis of where to start, by spelling out a series of relatively simple steps to get you started down the road, using as an example a rather old-fashioned AlphaACCOUNTING-style employee maintenance program, which looks like this: 

## **Subtopics** 

- Configure the Display 

- Activate INFLD GUI Mode 

- Activate GUI Version of PCKLST 

- Application Adjustments 

- Event-driven Programming 

A-Shell Reference 

Page 3920 

## **CONFIGURE THE DISPLAY** 

All of the GUI improvements we will be talking about here require, at least to some extent, the use of A-Shell/Windows, either directly in a Windows environment, or indirectly via ATE in a Unix or AMOS server environment. So the first step is just to configure the A-Shell/Windows display settings. 

## **Subtopics** 

- Define the Color Palette 

- Adjust Leading 

- Remove Status Lines 

- Adjust the Font 

A-Shell Reference 

Page 3921 

## **DEFINE THE COLOR PALETTE** 

_Reviewed July 2020_ 

Launch your application, then exit back to a dot prompt and use the SET TERM command to see what your standard foreground and background colors are: 

```
.SET TERM
```

```
Current terminal settings for TSKAAA are:
```

```
Terminal driver:  PCTDVG
Baud rate:        19200
Terminal width:   80
Terminal height:  24
Foreground color: 6
Background color: 0
Beveling:         Auto
Sys bg color      None
Win bg color      None
Win text color    None
```

In the above display, the foreground color is 6 (default is green) and the background is 0 (default is black). (If your screen is not green on black, then you have already redefined the meaning of the color palette entries for background 0 and/or foreground 6.) If your application never changes its basic color scheme, then you have two options for doing so yourself. One is for you to initialize the foreground and background color settings when you start the app, either via a CMD file with SET TERM FCOLOR and SET TERM BCOLOR commands, or preferably by adjusting the default or a custom CLR.INI file. The other method is to redefine 

A-Shell Reference 

Page 3922 

the palette so that that the default palette numbers foreground 6 and background 0 refer to something other than green on black. See the Colors Menu for details on color customization. 

Changing a monochrome green-on-black application to some other pair of colors is not a major improvement, and is not specifically related to GUI, but if you use the Custom Color option on the Color dialog to define some subtle or pastel colors rather than the primary DOS-style colors of the default palette can bring a psychological improvement. The following two shots give an idea of this. First, we have a traditional DOS-like color scheme: 

Then we improve things slightly by moving to a more pastel palette: 

If your intent is to move towards a Windows-like look, then you will have to start getting use to the Windows gray dialog background color. The particular shade of gray seems to change which each version of Windows and with the desktop theme, so it isn’t practical to try to define it manually. Instead, decide which of the 8 background palette numbers you want to dedicate to gray. (0 is probably a good bet, since that is the most common background number to use. Or, if you want to preserve your options, you might use 7, which is otherwise the least commonly used color number.) To define the palette number n as matching the current Windows gray background color, use one of the following commands: 

```
.SET TERM SYSBCOLOR n
```

```
xcall MIAMEX,MX_SYSBCLR,1,n
```

```
PRINT TAB(-10,AG_SYSBCLR);n;chr(127);
```

While you’re redefining your background color to match Windows, you might as well do the same with your standard foreground (text) color and editing window background colors. The standard text color in Windows is black, and the standard editing window background is white. Since these coincide with existing palette entries (although the particular shades of black and white may differ), it seems reasonable to link those palette numbers to the Windows color definitions of black text and white editing windows. Again you have your choice of the following methods: 

```
.SET TERM WINBCOLOR 1       ; (define fg 1 to match windows edit bg)
```

```
.SET TERM WINTXTCLR 0       ; (define bg 0 to match windows text clr)
```

or 

A-Shell Reference 

Page 3923 

```
FGTXT = 1    ! FG color # to use for text
BGSYS = 0    ! BG color # to use for main window
BGEDT = 1    ! BG color # to use for editing windows
xcall MIAMEX,MX_SYSBCLR,1,BGSYS,BGEDT,FGTXT
```

or 

```
PRINT TAB(-10,AG_SYSBCLR);BGSYS;",";BGEDT;",";FGTXT;chr(127);
```

After setting the above colors, you will probably want to save them in your current settings file (use menu File...Save), but note that this only saves the current Windows definitions for those colors. If the Windows colors have been changed by the next time you launch A-Shell, they will again be out of sync. So it is best to incorporate the above color initialization logic into your application startup so it is always current. 

A-Shell Reference 

Page 3924 

## **ADJUST LEADING** 

The next simple step is use the Misc. Settings dialog to add "leading," which is the vertical spacing between the rows, to relieve crowding. Windows GUI programs rarely pack fields as close together as a typical single-spaced text application, and short of redesigning your screen layout, adding leading is the simplest way to alleviate the crowding. Note that the font size will shrink as you increase the leading, so you probably will find the best compromise somewhere in the vicinity of 6. 

A-Shell Reference 

Page 3925 

## **REMOVE STATUS LINES** 

While we’re trying to get a more spacious feeling, we might want to get rid of the top and bottom status lines, which aren’t really being used in this application. The following show shows the effect of the Windows color scheme, increasing the leading to 6, and removing the status lines. See Enable / Disable Status Lines to accomplish this. 

A-Shell Reference 

Page 3926 

## **ADJUST THE FONT** 

If your application is fairly good at Text Message Tokenization then you may want to try converting it all to proportional font text. The simplest way to try this is to use the command: 

## `.SET AUTOTPRINT` 

before running your application. This will have the effect of making all your PRINT statements act like TPRINT, which is to say that rather than drawing fixed pitch text on the screen, they will create static text controls. If the effect is a disaster, then use SET NOAUTOTPRINT to restore the normal fixed pitch mode. In this case, you’ll may want to leave the fixed-to-proportional conversion to later. At this point, just make sure you have a good scalable font (Settings...Font...System Fixed); Lucida Console seems to the be a good choice. 

If your application looks somewhat reasonable with SET AUTOTPRINT on, then you can proceed to tinker with the proportional font options. First, check which font you have set; Settings...Fonts...GUI (Control). The default (and certainly the most Windows standard) is achieved if the font setting is blank. But you can always choose a specific font if you don’t like the Sans Serif default font. 

Here’s what our sample app looks like with SET AUTOTPRINT turned on: 

Because this application happens to use individually positioned print tokens for nearly every screen output, the switch to a proportional font actually works pretty well. 

With proportional fonts, you have the option to scale them to the window size or not. Most Windows programs do not scale the fonts (or the control sizes) when the window size changes. A-Shell/Windows will always scale row/column coordinate system to the window size (which will have the effect of making rectangular controls like buttons scale with it), but you can defeat the font scaling by setting the font scaling option in the Misc. Settings dialog to 0. In that case, you will probably want to adjust the Window size until you get a pleasing balance between the font size and the window size. If you set the font scaling option to a percentage (somewhere in the range of 80-110), then the fonts get bigger as the window gets bigger. Again, some experimentation will be needed to find a suitable balance between the scaling factor and the window size. 

Whether or not you scale the proportional fonts, they have to fit inside their (generally invisible) rectangular containers. When the font gets too big relative to the container size, the text gets clipped or may wrap. Again, since this effect is not always predictable, it is best to choose a size or scale factor that is small enough to leave some margin for expansion. 

A-Shell Reference 

Page 3927 

Most of the other options in the Misc Settings dialog will not apply until after we get into the GUI version of INFLD, so we’ll discuss those after INFLD in the next section. 

A-Shell Reference 

Page 3928 

## **ACTIVATE INFLD GUI MODE** 

Assuming your application uses INFLD, at least for input, you can activate the GUI version globally by adding SBR=INFDEF:|G to miame.ini. Without any changes to your application, this will cause INFLD to use Windows edit controls for field editing. In the case of date fields, it will use a date picker control. For fields with a list of possible choices defined in SETDEF, it will use a combo box. However, unless your application uses INFLD to display data (as well as to edit it), the enhancement will only affect the field that is being editing, and to some extent the fields that have been edited on the current screen. As each field is updated by INFLD, it will, by default, be converted to a sunken static text field. You can force it to redisplay the updated field using an edit box by adding **|E** to your SBR=INFDEF statement. To go one step further, you can use **||C** instead of **|E** , which will leave the date pickers and combo boxes in place also. If you don’t like the date pickers and combo boxes, use **|g** instead of **|G** . 

In our first attempt with **|G** active, our screen looks like this. The only thing which has changed so far is that the field we are actually editing, in this case, Social Security, is a Windows edit box, and the fields which have been edited and redisplayed by INFLD are displayed in sunken boxes. 

To get INFLD to redisplay updated fields using the same kind of edit box as when editing, you can add **||C** to the SBR=INFDEF specification, to get the result as shown below (after editing fields 3-7 and 10-11): 

The two dates in the example above have a dropdown button next to them, which brings up a date picker calendar control. If you don’t like this effect at all, and just want to use a regular edit box to edit dates, then replace **|G** with **|g** . If you want to us the date picker for editing, but don’t want it to display with the dropdown button, then use **|E** in place of **||C** . 

The display above is starting to look a lot like a regular Windows-style program, but there are still some deficiencies. One is that not all of the fields display the same way. This is because the program uses PRINT to display data, which produces the plain text version, and then when we edit a field, INFLD redisplays it using one of its formats (sunken gray box, white edit box, etc.). Furthermore, some fields even get redisplayed using PRINT immediately after editing, which means that even after editing them we don’t get the edit box or sunken rectangle. (In the above screen, this is the case with Marital Status, which gets input as a numeric code, then redisplayed as text. This is also the case with the fields 12-15.) 

Speaking of field numbers, the very idea of numbering fields on the screen is somewhat unusual in a Windows program. The idea of an "Any Change? " prompt asking you which field number to change is even more questionable. To deal with these and other differences between our legacy program and a modern Windows-style program, we’ll need to make some actual improvements 

A-Shell Reference 

Page 3929 

to the programs. But before getting into that, we’ll first finish up discussing some of the display adjustments and other GUI enhancements which can be done without any program changes. 

## **Subtopics** 

- INFLD-Related Display Settings 

A-Shell Reference 

Page 3930 

## **- INFLD RELATED DISPLAY SETTINGS** 

Once you have some edit controls (and possibly combo boxes) displayed, you can appreciate the checkbox options on the Misc. Settings dialog. 

## **Subtopics** 

- Fixed Pitch Font 

- Standard Colors In Edit Boxes 

- Edit Boxes Use Leading Space 

- Edit Box Height 

A-Shell Reference 

Page 3931 

## **FIXED PITCH FONT** 

When INFLD uses a Windows-style edit control, it normally uses a proportional font as well (the point is, after all, to act like Windows.) But proportional fonts do have the annoying feature of sometimes making it difficult to tell how many characters can be entered, based on the space available. The effect becomes more pronounced as the size of the field increases, to the point that for a 30 character address field, you might only be half way to the end when you run out of characters (if using lower case, spaces, periods, etc.). If using all capitals, the reverse could be true. One answer to this problem is to say "hey, that’s how it is in Windows applications." Another answer would be to set this fixed pitch font option, which will cause INFLD to use a fixed pitch font inside of any edit boxes it creates. The screen shot above was using the standard proportional font for editing, which is why the social security field, even though full with the maximum number of characters, appears as if it could support about 3 more digits. The following series shows the effect more dramatically, on an alphanumeric field. In each, case, the field as shown as the maximum allowed number of characters: 

The image above shows the address line being actively edited in a fixed pitch font, while the field below has been redisplayed in the standard proportional font. Note that even the fixed pitch font option does not always exactly fill the field ; in the example above, it looks like we should be able to fit one more character. This discrepancy is due to the lack of smoothness in scaling fixed pitch fonts. The two samples below give a good comparison between the fixed and proportional font. The first shows how the field above looks when redisplayed (since the standard redisplay uses a static text control and thus is not affected by the "fixed pitch font in edit box" option.) Some might find the huge discrepancy between what the field looks like while being editing and after (or before) editing to be an annoyance; others might like the way it makes it the active field stand out, and be easier to read, both of which may be appreciated by keypunch operators who might otherwise have difficulty seeing which field is active (by the tiny vertical bar caret) or what character they are about to insert or delete. 

The second example shows what the address line looks like when being actively edited in a proportional font. Note that although it looks nicer in general, it does suffer from the problem of being more compact, and thus the field looks half empty even after reaching the maximum number of characters: 

A-Shell Reference 

Page 3932 

## **STANDARD COLORS IN EDIT BOXES** 

INFLD has long supported the ability to define a set of colors which it would use, depending on the mode it was in. This can result in an interesting effect on a color text screen, but is of questionable value in a Windows GUI, (where it may just seem weird). This checkbox option provides a simple way to ignore your carefully selected INFLD colors and just use the Windows default (black text on a white box). Our examples above were already using standard colors so we’ll move on to the next option. 

A-Shell Reference 

Page 3933 

## **EDIT BOXES USE LEADING SPACE** 

Because an edit box uses up some space drawing its border, and due to the varying factors which affect font size, you may find that your edit boxes are too small to either fit the editing font, or to see the editing font if it does fit. The example below illustrates a borderline case, where the characters are not being clipped, but we are still getting little tick marks along the baseline of the edit box due to the cursor and/or tails of characters intersecting the edge of the box. 

To alleviate this slightly, we’ll set this option, which will cause the edit controls to use up to half of the leading space to make the control a bit taller. (This requires, of course, that you set your external leading to a non-zero value, preferably something like 6.) This provides a slight improvement: 

A-Shell Reference 

Page 3934 

## **EDIT BOX HEIGHT** 

This is a weird option. It arises because for some odd reason, Windows allows edit boxes to be independently scalable, but not combo boxes, whose size is based on the font associated with it. If you have a mixture of combo boxes and edit boxes on a screen, you may find that it looks bad for them to be different sizes, as in the following excerpt: 

If so, check this option, which will force the edit box height to conform to the combo box height as shown here: 

Note that this will defeat the ability to scale the combo box height by increasing the window height. But you should be able to adjust the height of these controls by changing your font scaling factor. 

A-Shell Reference 

Page 3935 

## **ACTIVATE GUI VERSION OF PCKLST** 

If your application uses pcklst.lst, you can convert it to use the GUI version (XTREE) by adding the following to miame.ini: 

```
SBR=PCKLST_GUI
```

This will convert the standard text implementation, which looks something like this... 

...into the XTREE version, which looks something like this: 

Note that in the above examples, the XTREE version shows more columns, because the default proportional font is smaller and thus allows more information to fit into the same screen area. It also supports horizontal and vertical scroll bars, but no bottom title bar. See the XTREE documentation for more details on its many features which go way beyond what the text version (PCKLST) supported. 

A-Shell Reference 

Page 3936 

## **APPLICATION ADJUSTMENTS** 

At this point, we are running out of GUI improvements that you can activate without making any changes to your programs. So now we begin to discuss some of the things you can do systematically and/or strategically to get the best results with the least effort. These are mostly in the form of ideas, rather than step-by-step instructions. 

## **Subtopics** 

- Buttons 

- Yes/No Fields and Checkboxes 

- Groupboxes 

- Anachronisms 

- INFLD 

- Subroutines for Each Field 

- Parameterized Field Attributes 

- Main Menu 

- Printing With GDI 

- Dialogs 

A-Shell Reference 

Page 3937 

## **BUTTONS** 

Many programs display lists of short keyboard (possibly function key) commands that are available in a particular context. It is generally simple to convert these to self documenting buttons which perform the same actions as the original commands and thus do not affect anything but the code that displays them. This is also a good way to document special keys that may be used from any field, like F1 for help, F2 for previous screen, etc. See the table of Virtual Key Symbolic Names for information on how to code a button to act like a function key. Note that buttons don’t have to be any more than one row high, so they don’t take any more room than a single line of text. 

A-Shell Reference 

Page 3938 

## **YES/NO FIELDS AND CHECKBOXES** 

A simple type code addition of **||c** to an existing Yes/No INFLD field will turn it into a checkbox. This is particularly effective if you have many Y/N fields, such as in a configuration screen. Displaying it as a checkbox does not change the way the field interacts with the application, so it is a very simple change. 

A-Shell Reference 

Page 3939 

## **GROUPBOXES** 

Organize groups of fields by combining them into a Groupbox Control. This can be a nearly one-to-one substitution for existing MSBOXX boxes, but then you have the option of making the fields be children to the groupbox, which means that their coordinates are relative to it. This allows them to be moved around together, and also deleted as a unit. 

A-Shell Reference 

Page 3940 

## **ANACHRONISMS** 

Your application may use some display features that are out of place in a modern GUI. For example, many legacy programs display a standard header on every screen which includes the program title, time, date, etc. This may make sense on a dumb terminal, but makes little sense on a PC, where the time and date is available on the status bar. You can move the program title to the title bar of the window, or, after eliminating the superfluous bits, make it stand out by putting it in a large font. 

Another example is the traditional AlphaACCOUNTING-style Add/Change/Delete/Print menu which takes a ridiculous amount of display space just to set a mode switch. Better to move right to the editing screen, and if it is necessary to establish an Add/Change/Delete mode, display a row of buttons for that purpose. 

After replacing the header and installing a button menu along the bottom, here’s what our screen looks like (OK, the banner isn’t quite right for the application, but you get the idea): 

A-Shell Reference 

Page 3941 

## **INFLD** 

The advantage of using INFLD for displaying fields is that you can use one set of field parameters for both input and display, letting INFLD do the formatting work as well as adapting to the capabilities of the display environment. But rather than convert your PRINT FIELD’1 statements to INFLD, you might as well go one short step further and just use the same code that you use for editing the fields to display it. For example, if your program has separate routines for displaying and editing your data, e.g.: 

```
DISPLAY'FIELDS:
```

```
PRINT TAB(8,10);FIELD1
PRINT TAB(9,10);FIELD2 USING "#####.##"
```

```
etc.
```

```
INPUT'FIELDS:
```

```
CALL INPUT'FIELD1
```

```
CALL INPUT'FIELD2
```

```
etc.
```

Assuming the INPUT’FIELDS routines use INFLD already, just make sure they use a common global variable for the OPCODE parameter (1=edit, 2=display), in which case you can reorganize it as follows: 

```
DISPLAY'FIELDS:
```

```
OPCODE = INFOP_DISPLAY   ! display
```

```
CALL DO'FIELDS
```

```
RETURN
```

```
INPUT'FIELDS:
```

```
OPCODE = INFOP_PRELOAD   ! input
```

```
CALL DO'FIELDS
```

A-Shell Reference 

Page 3942 

```
RETURN
```

```
DO'FIELDS:   ! caller sets OPCODE=1 for input, 2 for display
```

```
CALL FIELD1
CALL FIELD2
```

```
etc.
```

With INFLD doing the output, our screen now looks like this: 

Now we are getting pretty close, at least visually, but we still have the text INMEMO display of comments. To complete the visual makeover, we’ll change that to a multi-line edit control: 

At this point, the only obvious trace of text mode aesthetics visible is the use of numbers with the field labels. Aside from that, we still have some work to do on the operational side to implement the ability to click on any field. 

A-Shell Reference 

Page 3943 

## **SUBROUTINES FOR EACH FIELD** 

Adopt a common subroutine model for each field, which uses parameters to set the field location, and returns an exitcode. This allows the special details of the field to be kept together with the field, while still allowing you to adjust the inter-field behavior at the level above, or even to use the same field editing/display code in different contexts. For example, rather than the traditional AlphaACCOUNTING model: 

```
FIELD1:
```

```
<set INFLD parameters>
```

```
xcall INFLD, ...
```

```
IF INXCTL OR CNGCTL GOTO ANYCNG
```

```
FIELD2:
```

```
<set INFLD parameters>
```

```
xcall INFLD, ...
```

```
IF INXCTL OR CNGCTL GOTO ANYCNG
```

```
etc.
```

Break the above monolith into individual fields and move the interfield logic to a higher level, i.e.: 

```
DO'FIELDS:   ! caller sets OPCODE=1 for input, 2 for display
```

```
ON FNO CALL FIELD1,FIELD2,FIELD3,...
```

```
<check exitcodes, set next FNO accordingly>
```

```
IF NOT DONE GOTO DO'FIELDS
```

```
ANYCNG:
```

```
<confirm record update>
```

```
FIELD1:
```

A-Shell Reference 

Page 3944 

```
<set INFLD parameters>
xcall INFLD, ...
```

```
RETURN
```

```
FIELD2:
```

```
<set INFLD parameters>
xcall INFLD, ...
RETURN
```

A-Shell Reference 

Page 3945 

## **PARAMETERIZED FIELD ATTRIBUTES** 

Changing from hard-coded to variable field parameters won’t immediately improve the interface to your programs, but it will further the cause of separating your business and display logic, and make it much easier to implement more comprehensive application improvements, such as the switch to Event-Driven control. 

One way to quickly extract the existing hard-coded field parameters and coordinates is to add the SBR=INFDEF:|G|E global switches and then bring up your main display and step through all of the fields so that they get processed by INFLD. Then hit Control-Right-Double-Click to capture the field data in a spreadsheet, then rearrange the columns to get it down to just the information you need for each field (row, column, _type_ codes, etc.) Save your field parameters in a file for each screen, and use a standard MAP layout and import routine to load the parameters at the start of each program. 

Among the many advantages of having your field parameters separated from the programs, it allows a non-programmer to do a lot of useful but otherwise tedious cleanup and improvement, for example, adding tooltips and help keys. It will also allow you to centralize your field editing logic in a single routine, used throughout your application, which you can then update once to add global features like field-level help. 

A-Shell Reference 

Page 3946 

## **MAIN MENU** 

It might well be time to re-design your main menu, especially if it was designed for terminals, complete with graphic characters to make a logo. Since this is the part of the application that people see the most, it makes sense to give it a little design effort. One thing to consider is consolidating all of the submenus into a single Tab Control (with separate tabs for the submenus, and the items themselves being clickable.) Another thing to do is display a large graphic, logo or banner. If you don’t have one already developed, hire a designer to make you one. A third suggestion is to use the remaining space to provide shortcuts (via buttons or clickable text, or maybe even a list box) to the most common functions, making it even quick for the user to get where they want to go. This is much more effective if the user can customize their own shortcuts. Once you put all your menu options in a file, with security levels and other related attributes for each choice, it will be relatively easy to tinker with the menu design. 

A-Shell Reference 

Page 3947 

## **PRINTING WITH GDI** 

The GDI printing commands provide an easy way to upgrade plain text output to incorporate fonts and other graphics. And ATE makes this available even to Unix. Furthermore, unless you had a heavy investment in embedding your own ESC sequences (or PCL code) in your reports, you can insert GDI directives into existing printouts, so it isn’t necessary to do a major redesign of your reports to give them a facelift. 

A-Shell Reference 

Page 3948 

## **DIALOGS** 

The Model Dialog Box control makes it easy to create pop-up windows for displaying and editing information that doesn’t fit neatly into the existing screen. Because they don’t overwrite the existing window, can be moved around by the user, and force the user to exit the dialog before returning to the original screen, they are particularly easy to integrate into existing code: 

A-Shell Reference 

Page 3949 

## **- EVENT DRIVEN PROGRAMMING** 

A major difference in the architecture of modern programming languages designed for point-and-click user interfaces, and traditional programming languages like A-BASIC, is in how the program maintains control. In the point-and-click world, programs are "Event Driven", meaning that external events (like mouse clicks) are able to interrupt the program, forcing it to execute a "handler" for the event, whereas in the procedural model, the program decides for itself what statement to execute next. 

This may sound like a drastic and un-bridgeable difference, making it next to impossible to provide a point-and-click interface from a procedural language. But like so many other so-called new technologies in the computer world, the innovations are more in the terminology or way of looking at things than in the way they actually work. Just as you don’t need C++ or Java to implement object-oriented programming techniques, you don’t need VB or .Net to implement event-driven programming techniques. 

All operating systems of interest to this discussion, including AMOS, Unix, and Windows, support event interrupts for handling keyboard, network, disk, and other events which occur on their own timetables. Typically the operating system associates a driver which each type of event. The driver services the hardware, transferring data between it and memory buffers where it can be operated on by higher software levels. All these operating systems also maintain one or more run queues to schedule work to be done in time slices. 

The main thing that distinguishes event-driven programming from procedural programming is that in the former, the main body of the program is a loop that waits for event messages, calling routines to process the events of interest and passing the others on to a default event handler. In a procedural (sometimes called "linear" program) , the "main loop", if any, is typically related to waiting for the user to perform some keyboard action. However, there is nothing stopping you from implementing your own waitfor-event main loop and letting the AUI translate all the events of interest (mouse, keyboard, timer) into keyboard sequences which are reduced to exit codes by INFLD. As shown below, the two models then become very similar in appearance. 

In the standard event-driven model (top diagram), the operating system translates all of the events into coded messages. The main loop waits on these events, checks to see if they are of interest and passes them on to either its own hander or the default OS handler. 

In the procedural version (bottom diagram), A-Shell filters the events (using the standard event-driven model), handling the ones which don’t apply to the application itself, and translating the ones that do apply into keyboard sequences which are picked 

A-Shell Reference 

Page 3950 

up by whatever input routine is currently running (presumably INFLD). Depending on the event and or what the user types, the characteristics of the field, etc., the input routine will eventually exit, returning an exit code to the main loop. The main loop then determines from the exitcode what the next field or procedure will be, which eventually leads to another input operation and the process starts over again. 

You’ll note that neither of these flow charts makes at all clear where the "real work" of the program is done. In the top model, it is all buried within the "Process Event" routine. Typically a startup event will trigger the creation of the main window in the application, and then it will be up to the user to click on a button or something equivalent to trigger the event which starts a particular process within the program. While that particular process is running (for example, generating a report), subsequent events just queue up until the current subroutine returns back to the main loop. Similarly, in the procedural version, the same thing happens. While it is generating the report, if keystrokes will just queue up, waiting until it gets back to the next input routine. In either case, you can (and should) improve the event-responsiveness of long procedures by checking to see if there are any events waiting (but in both cases that can get tricky if the subsequent events contradict the current activity.) 

The main problem with the standard event-driven model, is that since there are so many possible events, you end up with myriad little event-handling routines which are difficult to keep track of and coordinate with each other. Along the same lines, any lengthy process must be broken up into event-sized chunks because suspending the event-handler for too long makes the program appear to have gone dead. 

The procedural version is actually easier to work with from the programmer standpoint, because the number of events is reduced to a manageable number, and because A-Shell itself takes care of the low-level events (like painting the window) independent of the application, the application doesn’t have to artificially break lengthy procedures down into tiny independent event-sized chunks. In a business application environment, all that is really needed in a lengthy procedure like a report is that it check for a single cancel event, which can be done within the context of the current procedure without returning to the main loop. 

Another advantage of the procedural model is that it allows the program to decide for itself when it is appropriate for the user to interrupt the flow of the procedure. For example, when filling out a certain type of form, there may be no reasonable need to jump around randomly from one field to another, and allowing it (which the standard event driven model is powerless to stop) may just complicate the ability of the program to both validate the data and assist the user in the data entry process by supplying appropriate defaults based on the context. In such a program, the procedural model can simply ignore misguided mouse-clicks and go from field-to-field in a logical manner until the form is filled out or the user aborts the operation. 

Still, it may far from trivial or even obvious how to convert a traditional procedural data entry model to this event-driven equivalent. To help analyze that question, here is a flow chart representing the traditional field-by-field (aka "AlphaACCOUNTING-style") data entry logic: 

A-Shell Reference 

Page 3951 

This flowchart is quite a long ways from either of the event-drive versions above. It does actually have logic after or between each field to decide whether to proceed to the next field or jump to the "Any Change?" prompt. In many cases, programmers have kept this model but added additional logic to process other exitcode conditions, perhaps to support moving backwards on up arrow, displaying help, etc. You can actually retain this model and still support the ability to click on any field to edit it, but it means that each of the test routines (shown above as "Abort or Change Mode?") has to be upgraded to support the ability to jump to any field. This will not be efficient from a programming standpoint. 

However, it would not be that difficult to change the model above to the model below: 

Essentially what we have done is converted each of the "Input Field #n" routines from the previous flowchart and turned them into individual subroutines, to be called based on the value of the Fno (field number) variable. (The box marked "Input routine for Field #Fno" would probably consist of a statement of the form " `on FNO call FIELD1, FIELD2, …` "etc.) The condition logic "Abort or Change Mode?" in between each field from the previous model is now centralized into a single routine which is represented here by the four shaded boxes. In practice, this routine might become quite complicated in the sense of having a lot of individual IF statements to deal with the various permutations of Exitcodes and field . But, it is all nicely contained, and if carefully parameterized, a single copy of this logic can be applied to all your data entry programs. (It really just needs to know the range of field numbers, but might also benefit from access to an array of field information allowing it to make advanced decisions based on the geometry of the field layout.) 

The only other step absolutely required to complete the conversion is to arrange for all of the applicable field objects to send identifiable keyboard strings that are turned into exitcodes when they are clicked. This will be a matter of displaying any fields you want clickable support for using the AUI CONTROL cmd parameter, or using the INFLD hlpidx parameter. 

The last box ("Done with fields, wait for event") could be no more than the traditional "Any Change?" prompt. But to achieve a more typical GUI style, you would probably replace the "Any Change?" prompt with two or more buttons (OK and CANCEL). Upon falling out of the last field, you could use Eventwait to put the focus on one of the two buttons and allow the user to select one via the keyboard, or to click on one of the fields to go back to edit it. 

## **Subtopics** 

· Further Improvements 

A-Shell Reference 

Page 3952 

## **FURTHER IMPROVEMENTS** 

There is always the "danger" that once you start on this conversion process, you’ll soon realize that with a little more up-front effort, you can create a generic data entry program or at least a template that can be used with an array of field data, a set of prompts (or screen layout), a set of field-entry routines, and some standardized file i/o logic to replace dozens of existing custom programs. The first one of these is hard to write, but after that, you may be able to convert significant chunks of your application quite easily. 

An added payback for the effort involved is that you will have achieved a high degree of separation between your user interface, data, and business logic. But it is important to note that the arguments for doing a more thorough overhaul of your software should be based on the merits of better structure, easier maintenance, etc., since it is not strictly needed just to achieve the GUI interface. 

A-Shell Reference 

Page 3953 

## **GUI TOOLS** 

|**Tool Name**|**Description**|
|---|---|
|APN|The A-Shell Programmers Notepad is a modern, Windows-based integrated development<br>environment (IDE) that makes A-Shell programming much more efficient than it can be with<br>VUE. It is recommended for all A-Shell programmers who do or can do their programming on<br>a PC.APNalso provides an environment that will be familiar to programmers migrating from<br>other languages.|
|LEO|A-Shell's most sophisticated AUI development tool is a program called LEO, developed by<br>Jorge Tavares. Contact MicroSabio for more information.|
|Text Attribute Manipulator|Tool to allow you to change the default text attributes.|
|Control Dump|Debugging and design tool.|
|Control Definition Snapshot|Related to tracing GUI events is the ability to get a snapshot of the definitions of all the<br>controls currently in existence. SeeControl Dump<br>.|



A-Shell Reference 

Page 3954 

## **TEXT ATTRIBUTE MANIPULATOR** 

At the opposite extreme from LEO is a very simple-minded tool built in to A-Shell which allows you to change the default text attributes as a way of experimenting with design changes to existing legacy screens. To access the tool, first issue the SET AUTOTPRINT command (see Adjust the Font) to convert plain text PRINT statements into static text control objects. Then, use Control+Shift+DoubleRightClick to bring up the _A-Shell Developer Control Operations_ popup dialog: 

Select the Change Text Attributes button to bring up this dialog: 

Changes here will affect the attributes of subsequently output text, without changing the attributes of text objects already on the screen. As an example of how you might use this in conjunction with a legacy text file maintenance program, just before displaying the main screen, you could set up some text attributes. Then, cause your program to actually output the background labels, which will now be in the color/font/style selected. Now, try changing the attributes again, perhaps using a different color and maybe DPRINT instead of TPRINT, and then cause the program to display data fields. If you end up with something pleasing, you can capture and record all the field data, with the attributes you applied, by generating and saving the control dump. 

A-Shell Reference 

Page 3955 

## **CONTROL DUMP** 

The control dump is a tool used both for debugging as well as for design. It outputs relevant details about each currently defined control to a CSV file and loads it into your local spreadsheet application. The spreadsheet data can later be fed back into the LEO design tool, or used to build your own repository of field layout definitions. To generate the dump, use CONTROL+SHIFT+DOUBLERIGHT-CLICK to display the _A-Shell Developer Control Operations_ popup dialog (see previous topic) and then click the button Dump the Control Info to Spreadsheet. 

A-Shell Reference 

Page 3956 

## **ENVIRONMENT VARIABLES** 

Several environment variables are created and/or used by A-Shell and ATE, and they are all described in the following sections. Note that: 

- In nearly every command context where you can specify a filespec, you can embed an environment variable reference by 

- surrounding the environment variable name by %, e.g. "%miame%\doc\ashelp.mdf". 

• A-Shell treats environment variable names as case insensitive (i.e. %MIAME% and %miame% are equivalent). This is consistent with Windows, which treats environment variables as case insensitive, but it might be confusing in the Unix environment, where environment variable names are case sensitive (and traditionally upper case.) 

• ATE environment variables (e.g. ATE, ATECACHE) are visible only to the ATE client process and any of its children, e.g. APEX, client-side SBX calls, AUXLOC: print file processing, AG_xxx functions, etc. The server can query these variables remotely using the AG_GETENV command. 

|**Variable**|**Platfor**<br>**m**|**Source**|**Description**|
|---|---|---|---|
|APEX|Win|M|Defines the location of the APEX work files and archived print files.|
|ASHCLIENTIP|||Optional definition of the client's IP address.|
|ASHFTPDEBUG|Win|M|Activates low level FTP debugging|
|ASHTMP|Unix|M|Directory to use for creation of temporary files used during spool processing.|
|ASQLTRACE|All|M|Set to 1 to activate detailed tracing ofSQLXSoperations.|



A-Shell Reference 

Page 3957 

|**Variable**|**Platfor**<br>**m**|**Source**|**Description**|
|---|---|---|---|
|ASWCACHE|Win P2P|M|Defines local directory for automatic image caching.|
|ATE|ATE|ATE|Same as %MIAME% but for ATE only|
|ATECACHE|ATE|ATE, CP|Temporary cache (cleared on exit)|
|ATEPERMCACHE|ATE|ATE, CP|Permanent cache (not cleared on exit)|
|ATEEXE|ATE|ATE|ATE or A-Shell/Windows executable filespec (Pseudo-environment variable)|
|ATELICMODE|ATE Svr|AS|Returns a value indicating ATE license method.|
|ATELOCALDIR|ATE|ATE, CP|Default Local Directory from the connection properties dialog.|
|ATEPROFILE|ATE|ATE, CP|ATE defines this variable to match the name of the current connection profile.|
|ATEVER|ATE|ATE|ATE or A-Shell/Windows version (pseudo-environment variable)|
|CURRENTDIRECTORY|All|A|Current directory (e.g. c:\vm\miame\dsk0\001004)|
|FORCEATE|ATE Svr|M|Use ATE protocol for some subroutine communications.|
|FTP2TIMEOUT|All|M|Overrides default timeout for FPT2 of 60 seconds.|



A-Shell Reference 

Page 3958 

|**Variable**|**Platfor**<br>**m**|**Source**|**Description**|
|---|---|---|---|
|||||
|HOME|Unix|U, M|Standard Unix variable defining the user's home directory.|
|MIAME|All|A|A-Shell base directory—i.e., the location ofmiame.ini.|
|MIAMEFILE|All|A|Complete filespec ofmiame.ini; is created automatically by A-Shell once it locates<br>miame.ini.|
|PERMCACHE|ATE|ATE, CP|Alias for ATEPERMCACHE|
|REMOTEHOST|Unix|U, M|Same as ASHCLIENTIP, but somewhat extended.|
|SYSTEMDIRECTORY|Win|A|Windows system directory (e.g. c:\Windows\System32)|
|TERM|Unix|U, M|Standard Unix variable defining terminal type|
|WINDOWSDIRECTORY|Win|A|Windows directory (e.g. c:\Windows)|
|XTREERAW|ATE Svr|M|Disable XTREE data transfer optimization.|



Meaning of codes in "Source" column above: 

A-Shell Reference 

Page 3959 

|**Cod**<br>**e**|**Meaning**|**Description**|
|---|---|---|
|M|Manual|Defined optionally and manually by user|
|ATE|ATE client|Defined automatically by ATE client|
|CP|ATE connection profile|Definition is based on parameter in connection profile|
|AS|A-Shell server|Defined automatically on server upon connection from ATE client|
|A|A-Shell|Defined automatically in all A-Shell environments|
|U|Unix|Typically defined automatically by Unix shell|



A-Shell Reference 

Page 3960 

## **ATELICMODE** 

The pseudo-environment variable ATELICMODE is supported in AG_GETENV to return a single decimal value containing flags indicating how the ATE workstation was licensed. 

The upper byte(s) contain one or more bit flags from the ATELF_xxx table below, and the bottom eight bits of the value will match one of the LICF_xxx values below. 

|**Symbol**|**Value**|**Description***|
|---|---|---|
|ATELF_PROTO|&h0100|ATE handshake was initiated, and also that the ATE client is at least 5.1.1164.0. (Prior to that,<br>command<br>`TAB(-10,AG_GETENV);"ATELICMODE";chr(127)`will return an empty string.|
|ATELF_PC|&h0200|ATE client has a local license.|
|ATELF_SRV1|&h0400|The server attempted to pass the ATE license via the new streamlined protocol (1162+)|
|ATELF_SRV2|&h0800|The server attempted to pass the ATE license via the LICENS/ATESRV mechanism. This also<br>implies that the server is less than 5.1.1162.0 and/or that the passed license wasn't valid (in<br>which case the lower byte should be <>0).|
|ATELF_AUX|&h1000|The server attempted to pass an auxiliary license to the client. (Will always be combined with<br>ATELF_SRV2.)|
|**Definition file: ashell.def**|||



A-Shell Reference 

Page 3961 

|**Symbol**|**Value**|**Description***|
|---|---|---|
|LICF_NORMAL|0|normal (licensed mode)|
|LICF_DEMO|1|demo mode|
|LICF_BADKEY|2|bad key|
|LICF_BADCO|3|bad company name|
|LICF_NONODE|4|no nodes|
|LICF_PSHELL|5|PolyShell not licensed|
|LICF_BADOS|6|license for other (wrong) operating system|
|LICF_EXPIRED|7|maintenance expiration|
|LICF_EXPEXE|8|run-time expiration|
|LICF_OLDKEY|9|old (and invalid) key format|
|LICF_ATSD|10|ATSD not licensed|



A-Shell Reference 

Page 3962 

|**Symbol**|**Value**|**Description***|
|---|---|---|
|LICF_SUPPORT|11|support use only|
|LICF_BADMAC|12|bad MAC address|
|LICF_SERIAL|13|invalid serial number|
|**Definition file: ashell.def**|||



A-Shell Reference 

Page 3963 

## **MIAME** 

This should specify the A-Shell base directory (i.e. the directory where miame.ini is found, and under which are various control directories such as doc, bin, dsk0, etc. Under Unix, this variable is usually predefined in a common login profile (such as /etc/profile or $HOME/bash_profile), so that the miame.ini specification does not have to be explicitly added to the A-Shell command line. Under Windows, the miame.ini specification is usually included in the command line associated with the shortcut/icon, eliminating the motivation for pre-defining it. Note that although A-Shell does not automatically define this variable, it will recognize and interpret %MIAME% as the directory where the current miame.ini is located. 

A-Shell Reference 

Page 3964 

## **- ISAM A** 

"ISAMA" is the name for A-Shell's implementation of ISAM PLUS file system. It is based on a commercial third-party ISAM product called D-ISAM, which in turn is an upward-compatible version of the Informix C-ISAM library. 

Using the third-party library meant that we could not provide compatibility with ISAM PLUS at the binary file level, although files can be easily converted using the ISMUTL dump and load operations. But it did allow us to maintain BASIC source and RUN compatibility with virtually all of the ISAM PLUS language statements. In addition, the commercial library is very fast and robust, and supports a number of additional features which give it several advantages over the AMOS version. The following several topics provide additional details about programming with ISAM-A, including differences between the AMOS (ISAM PLUS) and A- Shell (ISAM-A) versions, extensions, and a reference to the language statements. 

## **Subtopics** 

- Specifications & Features 

- ISAM-A Comparisons 

- General Topics 

- External Data Access Tools 

- ISAM-A Error Codes 

A-Shell Reference 

Page 3965 

## **SPECIFICATIONS & FEATURES** 

_Updated November 2018; see History_ 

The following table lists various sizes, capacities and limits for ISAM-A files and processing. Note, however, that some of these limits have been arbitrarily set just for efficiency. If you have legitimate need for larger limits, contact us. Also note that where the word "extension" appears in the table below, this indicates a feature that was not present in the AMOS version and which - may require some modification to your application; see A Shell Extensions for more details. 

|**Item**|**Size / Limit /**<br>**Capacity / Comment**|**Updated in A-Shell**<br>**build; old value**|
|---|---|---|
|Record size|16K|988 of Dec 07; 8K|
|Number of keys per record|20||
|DAT file size|2 terabytes|4.9.948; 2GB|
|IDX file size|2 terabytes (theoretical)|5.1.1134; 2GB|
|Records per file|2 ^ 31||
|Bytes per key|120||
|Parts (fields) per key|20||
|Duplicate keys|65536||



A-Shell Reference 

Page 3966 

|**Item**|**Size / Limit /**<br>**Capacity / Comment**|**Updated in A-Shell**<br>**build; old value**|
|---|---|---|
|Compressed keys|yes (optional, extension)||
|Compressed data records|yes (optional, extension)||
|Transaction support|yes Linux, no Windows||
|File recovery from log|yes Linux, no Windows||
|Audit trail|maybe; under review||
|Auto expansion of file|yes||
|Index rebuild utility|yes||
|Index verification utility|yes||
|Add/delete index without dump/reload|yes||
|ODBC / OLEDB / SQL access|yes via third party utilities||



**History** 

A-Shell Reference 

Page 3967 

## - November 2018, A Shell 6.5.1650: 

- Enable variable length records in the Windows version (matching Unix); 

• Increase the maximum number of key parts from 8 to 20, and the maximum key length from 80 to 120, in the Unix version (matching Windows). Note: the only outstanding difference between the two versions is that the Windows version doesn't support transaction logging. Also note: these changes update the ISAM-A version, as displayed by the ISMUTL header, to 6.11r. 

A-Shell Reference 

Page 3968 

## **- ISAM A COMPARISONS** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- ISAM-A vs. ISAM 

- ISAM-A vs. Other Indexing Schemes 

- A-Shell ISAM-A vs. AMOS ISAMPLUS 

A-Shell Reference 

Page 3969 

## **- ISAM A VS. ISAM** 

The following topics may be of interest to developers considering migration from ISAM (aka ISAM 1.x) to ISAM-A (aka ISAM 2.0). 

## **Subtopics** 

- ISAM-A Pros and Cons 

- Locking 

- File Structure 

- File Access Statement Ambiguity 

- File Administration Utilities 

- Converting Files to ISAM-A 

- Converting Programs to ISAM-A 

A-Shell Reference 

Page 3970 

## **- ISAM A PROS AND CONS** 

_Updated May 2021_ 

ISAM-A is an all-around better system than ISAM. It's faster, more robust, offers more features, and is easier to use. On the ease-of-use front, particularly noteworthy is the fact that all of the index maintenance is automatic. In other words, when you create or update a record, all keys are updated for you. It is even possible to add and delete indexes to existing files, without even recompiling the programs that access them (provided you don't delete an index that is being used to access the file). On a similar note, the ISAM-A ISMUTL utility allows you to verify and rebuild indexes without having to provide the index configuration specs or dump and reload the file. In ISAM 1.x, all index operations must be manually and explicitly handled by the program. 

The above mentioned advantages notwithstanding, ISAM-A does have a couple of limitations which can impede the easy migration from ISAM 1.x. The most significant is that ISAM-A does not allow synthetic keys. In other words, there will always be one key entry in each index for each record, and it will match the data in the record. In ISAM 1.x, it was possible to add multiple keys for a single record in a single index, or to have data records with no keys, or for keys to be formatted differently than in the data record. For example, for an alphabetic name index, in ISAM 1.x, you could have the data in upper and lower case but fold the keys to upper case. In general, these kinds of issues can be dealt with during conversion by a combination of adding fields to the data record to match the desired keys, and/or by creating additional files just to use the indexes (i.e. effectively ignoring the data). Note that in the latter case, although it is possible to store record numbers and to access ISAM-A files by record number, this should be highly discouraged. Instead, if you want to create a synthetic index, link it to the main file by means of field which is a unique key to the main file. 

One scenario in particular to be aware of is when a particular index only needs to contain keys for a small subset of the overall records. For example, consider a product file indexed by SKU, but a small subset of products also have an alternate product # that you want to index on. If you create a secondary index on the alternate #, you may end up with an index that has thousands of empty keys (for all the products that don't have an alternate #). That wouldn't be a problem for adds, lookups, or sequential reads, but it would be inefficient for updates and deletes (since locating the key would require scanning a very long chain of duplicates). You may be able to hack around the problem by populating the empty keys with dummy values that can be easily distinguished from real ones. But ISAM 1.x probably has the advantage in this kind of scenario, since you can add just the keys you need. 

The other limitation relates to non-standard manipulation of the data file. Although ISAM 1.x provides operations for adding and deleting records, some developers either bypassed them or extended them, taking advantage of the fact that the data files were accessible as ordinary random files. In such case, you may need to rethink your file design. It is worth noting, though, that these "limitations" of ISAM-A are essentially the same kinds of "limitations" you will find in any relational database, which are the 

A-Shell Reference 

Page 3971 

"price" for gaining access to many advantages, such as the ability to have a single, generic index verification/rebuild utility that works on all files (as opposed to a motley collection of specialized rebuild programs that would be needed to handle all these "tricks" under ISAM 1.x). 

A-Shell Reference 

Page 3972 

## **LOCKING** 

ISAM-A has integrated locking, independent of LOKSER. For ISAM 1.x, LOKSER was recommended, but not mandatory. If not use, then it was mandatory that you implement your own locking scheme, using something like XLOCK or FLOCK. 

A-Shell Reference 

Page 3973 

## **FILE STRUCTURE** 

Both versions use a single data file (.DAT for ISAM-A, .IDA for ISAM 1.x), and at least one index file, and both use a single OPEN statement to open the combination of the index and the data. However, while ISAM-A stores all the indexes in a single IDX (which are all opened at the same time), ISAM 1.x using a separate IDX file for each index, and required additional OPEN statements for each of the secondary indexes. 

ISAM 1.x data files used "blocking", meaning that individual records could not be split across 512 byte boundaries. Thus, if you had a record size of 128 bytes and wanted to add one more field, you might as well increase the record size to 170, because anything between 129 and 170 will result in only three records per 512 byte block (with wasted space at the end of the block). ISAM-A uses "span'blocks" mode, meaning that records are stacked end to end with no concern for block boundaries. This is much more efficient on a modern operating system, but does mean that the data file will probably not be a multiple of 512 bytes, and thus may "appear" as a sequential instead of random file (e.g. to the LOOKUP statement or DIR command). See OPTIONS=ABSLOOKUP. 

A-Shell Reference 

Page 3974 

## **FILE ACCESS STATEMENT AMBIGUITY** 

ISAM-A uses a different set of statements for accessing the file than ISAM 1.x, so for the most part there is no confusion at the source code level. They share the same CLOSE statement, but this is true with every other file type as well. The one ambiguity is in the OPEN statements, which are syntactically similar but semantically different: 

ISAM-A: 

## **OPEN #channel, filespec, mode, recnovar, fstatvar {,end'file} {, wait'record} {,wait'file} {,read'only}** 

ISAM 1.x: 

## **OPEN #channel, filespec, mode, recsize, recnovar {, wait'record} {,wait'file}** 

If the mode is INDEXED or INDEXED'EXCLUSIVE, the compiler cannot tell from the syntax alone which version of ISAM you are trying to open, and thus must rely on COMPIL switches and rules: 

- OCMPIL assumes ISAM 1.x, while COMPIL and COMPLP (or any version of the A-Shell compiler with /X:1 or /X:2) assume 

- ISAM-A 

- Adding the /I switch causes COMPIL and COMPLP to assume ISAM 1.x when ambiguous. 

- Under AMOS, ORUN only supported ISAM 1.x, while RUN and RUNP supported both. Under A-Shell, there is only one RUN and 

- it supports both versions of ISAM. (There is no ambiguity in the RUN file tokens.) 

- With COMPIL and COMPLP, you can use non-ambiguous forms of the Mode to force the compiler to recognize your intent, 

- regardless of the switches used. ISAMP'INDEXED and ISAMP'INDEXED'EXCLUSIVE indicate ISAM-A, while ISAM'INDEXED and ISAM'INDEXED'EXCLUSIVE indicate ISAM 1.x. 

- At runtime attempting to open an ISAM file using the wrong version will result in either a file not found (Error 17) or a file 

- type mismatch (Error 25). 

A-Shell Reference 

Page 3975 

## **FILE ADMINISTRATION UTILITIES** 

ISAM 1.x uses ISMBLD.LIT to create files and ISMDMP.LIT to dump or display their structure. ISAM-A uses ISMUTL.LIT to perform these operations as well as several others. A-Shell also provides a utility called ISMCHK which facilitates performing unattended verification of many files at a time (e.g. at night). 

A-Shell Reference 

Page 3976 

## **- CONVERTING FILES TO ISAM A** 

Although the ISAM and ISAM-A files have different structures, you can convert the data by dumping the ISAM 1.x file to a sequential file using ISMDMP, and then creating your ISAM-A file and loading it from that sequential file using ISMUTL. 

The AMOS and A-Shell versions of ISAM-A files are more similar, but still are not binary compatible so you have to perform some kind of conversion. The most straightforward is to dump the file on one system with ISMUTL, transfer the sequential file to the other system, then reload it using ISMUTL. If you have a lot of huge files to transfer, it may be more efficient to use the A-Shell ISMCVT utility (discussed in a separate topic later on in this document.) 

A-Shell Reference 

Page 3977 

## **- CONVERTING PROGRAMS TO ISAM A** 

There is no universal method for converting program written for ISAM 1.x to use ISAM-A, although in general, the conversion is fairly easy, and almost certainly presents an opportunity to simplify your code. From a logical standpoint, essentially all you have to do is get rid of all your extraneous locking and index maintenance operations that are simply unnecessary with ISAM-A. 

As a suggestion, it might be good to proceed by creating a set of template routines (open file, find a record, get next record, etc.) for both ISAM 1.x and ISAM-A access. Next, create a simple utility to replicate your template routines into file-specific versions (e.g. open CUST file, file CUST record, get next CUST, etc.) Then replace your embedded statements referencing ISAM statement with calls to your generic routines and confirm that the programs continue to work as before. Then you can start converting individual files from ISAM to ISAM-A by just substituting the template routines for ISAM with those for ISAM-A. 

A-Shell Reference 

Page 3978 

## **- ISAM A VS. OTHER INDEXING SCHEMES** 

Although it is impossible to offer many concrete details for comparing ISAM-A to other file indexing schemes, here are some general observations which you may find interesting enough to consider migrating from your custom indexing schemes to ISAMA. 

**Performance:** ISAM-A indexing uses an efficient B+ tree organization which generally means that you can access any record in 5 disk accesses or less, even in files containing millions of records. In comparison, a index based on binary searching (e.g. SERCH[XS] ) would require an average of 11 disk accesses to read a record in a file of only 1024 records. For a file of a million records, the number is more like 21 accesses. Since a random disk seek is by far the slowest operation in data processing (by orders of magnitude), this simple fact alone is likely to make a dramatic difference in your file throughput. 

**Simplicity:** Since ISAM-A takes care of so many details for you (like locking and index maintenance), it is generally much simpler to program with. Not only does this make development easier and faster, it also reduces bugs by eliminating all of the minute details (subroutine parameters, the need for synchronizing manual operations such as locking and index manipulation, etc.) And makes your programs easier to understand and maintain later. 

**Stable and Robust:** ISAM-A is a very mature system with a long track record, both in and outside of the A-Shell community. 

**Standard Utilities:** A single utility, ISMUTL, can handle all of your file administration (creation, rebuild, verification) needs. 

**Auto Expansion:** ISAM-A files automatically expand, eliminating the need for a lot of logic worrying about files filling up and needing to be rebuilt. 

**ODBC, SQL Access:** With ISAM-A files you have the option of accessing them from popular reporting and querying tools, such as Crystal Reports, via third-party ODBC and SQL drivers. 

A-Shell Reference 

Page 3979 

## **- - A SHELL ISAM A VS. AMOS ISAMPLUS** 

Although A-Shell's ISAM-A is mostly upward compatible (at a programming level) with AMOS ISAMPLUS, there are a couple of considerations that require attention in your code. 

**File names:** ISAMPLUS files contain a single data file and a single index file (which contains all of the individual logical indexes). Under AMOS (ISAMPLUS), the data file extension is IDA, whereas under A-Shell (ISAM-A) it is DAT. This is a minor inconvenience for programs which look for the IDA file, but this can be alleviated for the most part by means of the MAPIDA setting in miame.ini. In ISAM-A, files also contain a third physical file with an LCK extension which is used for locking (and which can generally be ignored by your application). 

**Data file layout:** Although the IDX files are completely different in format between AMOS and A-Shell, the data file layouts are quite similar, except for one important difference: the A-Shell version has an extra control byte on the end of each record which indicates whether the record is deleted or not. (Binary zero indicates deleted.) Thus, if your declared record size is 512, the actual physical record on disk will be 513. Records are stacked end to end with no consideration for "blocking". Under A-Shell, if you use the compressed data feature, only the fixed header portion of the data record will be stored in the DAT file; the compressed portion of the data record is actually stored in the IDX file. 

A-Shell Reference 

Page 3980 

## **GENERAL TOPICS** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- File Size Limits 

- Auto-Expansion 

- ISMUTL VERIFY 

- ISMCHK 

- CVTISM 

- Compressed Indexes 

- Compressed/variable length data 

- Transactions and Logging 

- Recovery 

A-Shell Reference 

Page 3981 

## **FILE SIZE LIMITS** 

Following is a reasonably complete answer to the question "What is the limit on ISAM file sizes?" Note that this discussion applies to both standard ISAM and ISAM-A. 

• **ISAM data file size limit:** Both ISAM and ISAM-A (aka ISAM-PLUS) use internal 32 bit record pointers. Although it might be possible, with care, to treat them as unsigned, by convention, these are signed and thus this imposes a limit of 2*31 (approximately 2 billion) **records** . If your record size was 512 bytes, that would impose a theoretical overall data file size of 2GB * 512 = 1TB. 

- **ISAM index file size limit:** Both ISAM and ISAM-A also use internal 32 bit index pointers, although the index block size is 

- different between the two. ISAM-A uses 1024 byte index blocks, imposing a theoretical IDX file size limit of 2TB. ISAM 1.0 used 512 byte index blocks, while ISAM 1.1 is configurable (see ISMBLD.LIT /B switch), supporting IDX block sizes from 512 to 16384 (1TB to 32TB theoretical limits). 

Note that the index size is dependent on the number of data records, key size(s), and amount of extra space to allow for performance and tree balancing reasons. So in practice this may lower the theoretical limit on the number of data records considerably. 

The above numbers are all theoretical limits. In practice, you will likely run into some severe performance issues long before you get to those sizes. Some of the factors to consider here are: 

- File system performance on large files. All file systems slow down  when dealing with very large files, because of the need to 

- employ some kind of hierarchical pointer structure in order to locate the physical disk block associated with a particular logical position in the file. The details may vary between file system types, but there doesn't seem to be a definitive reference to which file system(s) are the best for such large files. 

- Cache efficiency falls dramatically with such large files, because the nature of ISAM leads to random jumps all over the file. 

- Other than the first couple of levels of the index, the rest of the accesses in both the index and data files is likely to uniformly spread, meaning that the cache efficiency will not be much better than the raw ratio of the amount of cache memory available to the size of the files. 

- Because of the cache problem, you can run up against the raw random access performance of the disk drive. However, 

- modern disk drives—including SSDs—are very fast, and so hardware contraints are not as common as they used to be. Even the fastest drives cannot of course compete with the speed of the RAM cache. 

A-Shell Reference 

Page 3982 

Obviously you would want to go with the fastest possible drives and as much RAM as you can possibly get. Also, splitting the index and data across two drives would help considerably. 

But the biggest help would come from restructuring your data to reduce the size of any individual file. Within reason, you will get much better performance by having more, smaller files. 

For example, even though it might not be that elegant, if you had a transaction history file with 120 million records, you would probably get better performance by splitting it into 12 files of 10 million records each (one file per month). 

A-Shell Reference 

Page 3983 

## **- AUTO EXPANSION** 

One difference between the A-Shell ISAM-A and the AMOS ISAMPLUS is that ISAM-A files grow automatically as data is added to them. This can create a bit of confusion due to the fact that when the file is first created, regardless of how many records you asked for, the size of the DAT file will be zero, and the number of records allocated according to the stats will be 100 million (which is just a dummy number, intended to assure your application that it didn't need to worry about file expansion). The IDX file will start out with a few blocks to accommodate the index structure and the meta information about the index. 

Note that although the files will expand themselves as you add data to them, they will not automatically contract themselves as you delete records. Instead, deleted records are marked with a special control byte, and re-used for subsequent add operations. If you delete a large number of records at one time, you may want to compress the file by dumping it and reloading it. 

A-Shell Reference 

Page 3984 

## **ISMUTL VERIFY** 

ISAM-A supports an additional ISMUTL operation called VERIFY. It is equivalent to REBUILD, except it only checks the index without doing any updates on it. This is somewhat faster than REBUILD, and also lets you find out whether there was a problem in the first place. (REBUILD just rebuilds new indexes from scratch, so you have no idea whether the operation was necessary or not.) 

Beginning in A-Shell build 1164 of 2 Nov 09, ISMUTIL VERIFY operation outputs information to ashlog.log on errors. On the screen, it only shows the type of error without any helpful details. 

A-Shell Reference 

Page 3985 

## **ISMCHK** 

ISMCHK is a BASIC utility included with A-Shell which facilitates running unattended checks on your files and generating reported to be examined later or faxed/emailed to you. See the notes in the ismchk.bp source code for syntax and configurable options. 

A-Shell Reference 

Page 3986 

## **CVTISM** 

CVTISM.BP in EXLIB:[908,33] is a BASIC utility which allows you to convert DevPPN format ISAMPLUS files to A-Shell format ISAM-A files without dumping and reloading them. This can save a lot of time, especially if your files are large and your AMOS system is slow. See the notes in the source code for syntax and other instructions. 

A-Shell Reference 

Page 3987 

## **COMPRESSED INDEXES** 

As of A-Shell 4.9.948, compressed indexes are supported. These have no effect on your application code, and only serve to decrease the size of the IDX file on disk if they contain keys which are conducive to one or more of the following compression schemes: 

- Compress leading duplicate characters. Here, a single byte is used to represent the number of leading characters that have 

- been duplicated from the prior key. This is beneficial when the average number of leading duplicate characters is greater than one. (For example, an alphabetical name index.) 

- Compress trailing blanks. A single byte is added to the key to represent the number of blanks on the end. This is beneficial 

- when the average number of trailing blanks is greater than one. 

- Compress duplicate keys. This only makes sense when duplicate keys are allowed. A two byte duplicate key flag is used to 

- replace duplicate keys. 

Combining all three gives you "maximum" compression. 

To specify that you want a compressed index, you must rebuild the file using ISMUTL.LIT 1.4(129) or higher, which allows for a more detailed response to the "Allow Duplicate Keys" question: 

```
Are duplicate keys allowed for this index? (Y/N{+LTD})
```

```
   For compression, add L(eading), T(railing), D(duplicates) to Y/N
```

```
   Ex: YL (dupes allowed, compress leading dup chars)
```

```
   Ex: NLT (no dupes allowed, compress leading dup chars, trailing spaces)
```

For example, answering the question "Y/LT" will allow duplicate keys and activate compression of Leading and Trailing spaces. "N/T" will disallow duplicate keys and activate compression of trailing spaces only. "Y" or "N" by itself gives you a traditional noncompressed index. (OK, so it's a bit cryptic; the objective was to avoid breaking existing command files that execute ISMUTL.) 

Compressed indexes should only be used with indexes containing string keys, and generally only makes sense with keys longer than about 8 bytes. You pay for the disk savings with some CPU overhead, so you have to use your judgment to decide when the 

A-Shell Reference 

Page 3988 

payoff is in your favor. (In general, systems are much more disk bound than CPU bound, so if you can achieve a 25% or more reduction in the IDX size, compression will probably improve performance.) 

A-Shell Reference 

Page 3989 

## **COMPRESSED/VARIABLE LENGTH DATA** 

As of A-Shell 4.9.948, you have the option compressing the data records, which is essentially equivalent to supporting variable length records. The feature works by dividing the records into two parts: a fixed part (at the start of the record), followed by a variable (compressible) part which makes up the remainder of the record. The fixed part must contain all of the keys, and should probably contain most of the data, except for the parts which are likely to contain sequences of null bytes, spaces, or "0". The variable part gets compressed by collapsing contiguous sequences of those three special characters, and then the result is stored in the IDX file rather than in the DAT file. (The IDX file structure is already conducive to handling variable length chunks of information, and this allows the DAT file to continue to be made up of fixed length records). 

As an example of where this might be very useful, consider a customer master record of 512 bytes, to which you want to add some comments. You could use an external storage scheme, such as INMEMO, for the comments, but the simplest scheme might be just to add it to the end of the customer file by increasing the record size from 512 to 8192 (the current maximum record size), and declaring the last 7680 bytes of the record to be compressible. 

To specify compressed data records, you must build your file with ISMUTL 1.4(130) or higher. At the record size prompt, instead of specifying a single value as you would for normal fixed length records, you enter the maximum (uncompressed) size, followed by a slash, followed by the length of the fixed length header portion of the record. In the example just described, you would use "8192/512". (As with the cryptic format for specifying compressed indexes, the objective here was again to preserve compatibility with existing command files that execute ISMUTL.) 

A-Shell Reference 

Page 3990 

## **TRANSACTIONS AND LOGGING** 

In this context, the term "transaction" refers to a logical operation involving multiple physical operations on one or more files which should be performed as a single unit (all or nothing). For example, posting a payment to an account may involve updating a receipts file, an open items file, and also changing a balance in the customer master file. You don't want those to get out of sync, so if an error occurs somewhere in the middle of the transaction, you want to back it all out. Transactions support gives you just this capability via the TRANSACTION'BEGIN, TRANSACTION'COMMIT, and TRANSACTION'ROLLBACK statements (described separately above). 

Transactions require that all file updates be logged. The log makes is possible for the TRANSACTION'COMMIT and TRANSACTION'ROLLBACK commands to either make permanent or discard the changes since the TRANSACTION'BEGIN. So in order to use transactions, you must first open a log file (with TRANSACTION'LOG'OPEN). 

## Some additional notes about transactions: 

- All records involved in the transaction remain locked until either the TRANSACTION'ROLLBACK or TRANSACTION'COMMIT 

- statements. For this reason, you probably want to minimize the time spent in the transaction. 

- The log file keeps a record of every ISAM-A operation that alters data, whether a transaction is in progress or not. (See 

- discussion of the recovery feature following for an explanation why.) Thus, it can grow rather quickly, so you will need to develop a strategy for deleting it (preferably just after making a complete data backup). 

- If a transaction has started and the program ends without executing the TRANSACTION'COMMIT or 

TRANSACTION'ROLLBACK, then TRANSACTION'ROLLBACK will be executed automatically (on the assumption that your program aborted and you failed to trap the abort). This does not apply to SBXs; only to main programs (RUN and LIT modules). 

- In most cases, you would use a single log file for an entire application, although in some specialized circumstances it might 

- make sense to maintain separate log files for individual users. (The danger there is that actions by other users may affect the context of transactions, compromising the ability to replay them.) 

A-Shell Reference 

Page 3991 

## **RECOVERY** 

As a side benefit to transaction logging, the log file also makes it possible to "replay" (or "recover") all file updates (whether or not part of a "transaction"). 

As an example of the recovery feature, let's say you do nightly backups, after which you erase the log file. Half way through the day, somebody accidentally erases one of your ISAM-A data files. To recover it, you would restore all of the ISAM-A files from the previous night's backup (taking care not to overwrite today's log file). Then you would replay the transactions from the log using: 

```
.ISRCVR logfile
```

A-Shell Reference 

Page 3992 

## **EXTERNAL DATA ACCESS TOOLS** 

One of the benefits of using a third-party commercial library for implementing ISAM-A is that there are other third-party add-on tools available. Either of the products below will allow you to access your ISAM-A files from standard query and reporting tools such as Crystal Reports, Excel, Access, etc. If you are interested in this type of tool, please contact MicroSabio to check on latest developments. 

## **ConnX** 

ConnX Solutions, Inc. (http://www.connx.com) provides an ODBC/OLEDB driver for DISAM, along with an SQL query tool. It does not (yet) support F6, I4, and B5 data formats. If you intend to use this tool, you may want to convert your floating point fields to IEEE single (F4) or double (F8) formats. 

## **EasySoft** 

EasySoft Limited (http://www.easysoft.com) provides a similar interface, which does support all the standard field types, but is somewhat more expensive than the ConnX tool. 

A-Shell Reference 

Page 3993 

## **- ISAM A ERROR CODES** 

The error codes in the table below are all decimal values. 

|**Error #**|**Meaning**|
|---|---|
|201|Incompatible ISAM file|
|202|ISAM library not available, possibly not licensed|
|207|Index structure smashed|
|208|Duplicate key (not allowed)|
|210|Invalid number|
|213|Invalid record size|
|214|Too many concatenated keys|
|215|Primary key information missing|
|216|Maximum record size exceeded|
|217|Invalid key type|
|218|Maximum binary key size exceeded|
|219|Key range outside record|
|220|Overlap keys must be alphanumeric|
|222|Too many secondary indexes|
|223|No such secondary key number|
|224|This secondary key has been deleted|
|225|Number of records dumped don't match number in file|
|226|Key information missing|
|228|Cannot create existing file, file already exists|



A-Shell Reference 

Page 3994 

|**Error #**|**Meaning**|
|---|---|
|229|Data file smashed|
|230|System error|
|231|ISAM file must be rebuilt|



A-Shell Reference 

Page 3995 

## **PERFORMANCE** 

Performance issues and optimization under A-Shell are not generally a concern, since A-Shell systems tend to exceed users' performance expectations. We don't take all the credit for this; it is mostly due to the overwhelming power of the hardware, and in the case of Unix, to the operating systems' sophisticated I/O logic. However, there are some cases, particularly those involving Windows networks, where a performance improvement would be highly desirable. And in any case, it is human nature to want anything to go faster. With that goal in mind, the following topics present several performance enhancement suggestions that are relatively easy to implement, as well as some explanations that may lead you to solve performance-related problems. 

## **See Also** 

- Performance in Large Systems 

## **Subtopics** 

- Compare LAN, WAN, Cloud 

- Peer-to-Peer Issues 

- QFLOCK.SYS in Memory 

- Local Copies 

- Memory Mapping 

- Read-Only Mode 

- Accessing Files in the MEM: Device 

- Pre-load Frequently Used Programs 

- Temporary Files 

- Local Print Files (Windows) 

A-Shell Reference 

Page 3996 

- Number of Files per Directory 

- XCALL SERCH Optimization 

- Optimizing File Sorting 

- Use Span'Blocks 

- Use Larger Record Sizes 

- ISAM Performance 

A-Shell Reference 

Page 3997 

## **COMPARE LAN, WAN, CLOUD** 

" - " - In May 2018, the discussion Measuring Performance based on location of A Shell server took place on the A Shell forum. 

## **Question** 

My customer is asking for performance measurement comparisons before migrating A-Shell to a cloud. Specifically they want to know what difference there is (if any) when A-Shell is running on a LAN, the WAN, or in a Cloud. 

Since almost everything happens on the server (through AlphaLAN) wouldn't the main difference be how long it takes the user's PC to receive screen displays from the server? Does it make sense to measure that (and if so, how?) 

Also, much of the performance differences could be due to the speed of the cloud's processors versus the VM server's, not to mention the strength and bandwidth of the internet connection. 

We also use ATE, does that act as a true client or is it just another terminal emulator? If it's a client, does it bear its own type of measurement? Is there a way to time client to server transactions (and vice-versa)? 

Is this even a realistic thing to measure? If so, has anyone done this and can they share their solution? 

If not, what would make more sense to measure? 

For example, does it make more sense to measure the time to run a batch job (e.g., reading through a large ISAM file and displaying data on screen) using four variations: 

a) access the A-Shell VM from the VM server's location (LAN) 

b) access the same VM from a remote location (WAN) 

c) access cloud-based A-Shell from the VM server's location 

d) access the same cloud-based A-Shell from the above remote location 

Are c and d redundant? Should I test from multiple remote locations? 

With the batch job approach, should I do each type of run 10 times and then average the results? Is there a standard procedure for this kind of thing? 

A-Shell Reference 

Page 3998 

I'd appreciate any thoughts or suggestions. Thank you. 

(Later:) Another thought for the batch job, instead of reading an ISAM file, would it be sufficient to merely count to 100,000 and display the numbers on screen? The display would be stilted unless I only displayed every 100th number. Is this a test that would accurately provide metrics defining response time differences caused by accessing A-Shell from various locations? 

## **Answer** 

Trying to come up with a meaningful measure of performance—as opposed to MIPS, i.e. Meaningless Indicator of Performance, Stupid—is not easy. 

The first suggestion I would make is to assign relative degrees of importance to the various types of performance that are substantially independent of each other: 

- 1) CPU performance: calculations, ability to handle a lot of users active at once 

- 2) Data I/O performance: memory access, disk access (random or streaming), queue & cache efficiency, etc. 

- 3) Terminal I/O performance: both bandwidth and latency. 

One thing I can tell you is that parts 1 and 2 are pretty much independent of the network architecture. Your CPU and ISAM tests are going to perform the same regardless of whether the server and client are on the same machine, the same LAN, or on separate planets (assuming the same server capabilities). It's a little more difficult to make blanket statements about a physical vs a virtual server, but I think most of the industry is in agreement that VM technology puts very little extra overhead on the system, especially compared to the advantages it offers, so basically no one chooses physical vs virtual for performance reasons. In fact, it's quite the opposite. 

The only situation where the network architecture affects the Data I/O performance would be in the case of NAS or SAN disks, whereby the CPU and disks are separated by some kind of network. That can have a huge but extremely variable effect on performance. At one extreme would be shared directories across a LAN or WAN, which can be quite slow, at least when it comes to multi-user access, due to a combination of the network delay/bottleneck and the need for the file server to coordinate locking with multiple clients on remote machines. At the other would be a dedicated SAN, which might perform nearly as well as a disk local to the server. 

In your case, the choices are mainly going to differ in the area of Terminal I/O Performance. If your application is purely text based, and you're connecting via SSH or Telnet, you probably don't need much bandwidth, so that's not likely to be a problem. But the turnaround latency could become a slight annoyance. In a typical input environment, each character typed has to travel 

A-Shell Reference 

Page 3999 

to the server and back again before it shows up on the screen; when that delay starts to get up to a few hundred milliseconds, it starts to annoy some people. That's the one area where the cloud or WAN may be noticeably worse than the LAN. 

GUI would typically increase the demand on the bandwidth as there would be a lot more data transferred from the server to the client. But depending on the design, it might decrease the pressure on latency, since much of the UI activity can take place purely locally. 

Maybe that's an evasive answer, but I'm not sure what else I can say in general about the issue of how changing environments affects performance. If you have two actual environments that you can access, and want to come up with some metrics to quantify how they compare performance-wise, then we can get into the various kinds of tests that could be run. 

Your test of just counting up to 100,000 in a FOR/NEXT loop might give some indication of pure CPU performance if you didn't output the numbers. Otherwise it will be primarily a measure of terminal I/O performance, although you can achieve some compromise between the two by only outputting every nth value, like you suggest. As an example: 

```
program COUNT2,1.0(100)   ! measure for/next performance
```

```
SIGNIFICANCE 11
```

```
MAP1 MISC
```

```
    MAP2 USECS,B,4
    MAP2 I,F
    MAP2 N,B,4
```

```
    INPUT "Enter N for to output every Nth value: ",N
```

```
    IF N = 0 THEN N = 1
    XCALL TIMES, 3, USECS
    FOR I = 1 TO 100000
        IF (I MOD N) = 0 ? I
```

A-Shell Reference 

Page 4000 

```
    NEXT I
```

```
    XCALL TIMES, 3, USECS
    ? USECS;"us"
    end
```

Here is how that plays out on a Windows laptop (A-Shell/Windows) vs an ATE connection to a local Linux VM within the same laptop and an ATE connection to a remote Linux VM across the country via a VPN/WAN: 

```
N      Local Win    Local Linux  Remote Linux
-----  ----------   -----------  ------------
1      11 seconds   12 seconds   8 seconds
100    142 ms       136 ms       27 ms
1000   40 ms        36 ms        24 ms
```

At first glance the relative consistency of those values seems a bit surprising. How could the remote machine output 100,000 numbers to the screen faster than either of the local ones? The only answer I can come up with there is that in the ATE case, the server is responsible for computing and outputting the values, whereas in the local Windows case, the same instance of A-Shell is also responsible for displaying them. Plus, the total amount of I/O is still pretty small, less than 1 MB total, so we're not anywhere near pushing up against the limits of the network bandwidth even for the remote WAN. 

Another complication is that although the program reported 8 seconds for the remote connection (outputting each of the 100,000 numbers), in fact, the actual elapsed time as experienced by the user was over 12 seconds. In other words, due to buffering the program finished 5 seconds before all the buffered output was delivered to my workstation. And we should probably take into consideration the fact that a lot of that buffering may have been local to the server, and/or associated with the server's NICs. That's probably a 4th independent category of performance to be added to the 3 I listed at the top. And note that there are both hardware and OS-level components to the network interface performance; each major Linux release seems 

A-Shell Reference 

Page 4001 

to adjust the trade-offs between latency, bandwidth, and CPU efficiency in ways that may appear to favor overall server batch performance/throughput vs. individual responsiveness. 

So even this brain-dead simple test becomes complicated to interpret! Except for the last line (where we only output every 1000th value) - in that case it becomes more of a pure CPU test, with the results indicating that the remote server is quite a bit faster when it comes to raw CPU performance than my local machine, even though the remote physical machine has several VMs running on it, and this particular VM has 100+ users running on it. Which just goes to demonstrate that even though a modern PC with an i7 CPU is incredibly fast, real server hardware (in this case with a Xeon processor) can still run circles around it. That's not to say that a PC-grade machine can't perform admirably as a server, but it is to say that there is a real difference between PC-grade and server-grade hardware. 

A-Shell Reference 

Page 4002 

## **- - PEER TO PEER ISSUES** 

_Rewritten July 2020_ 

Peer-to-Peer (P2P) installations, where A-Shell clients share files with a "server" over a P2P network, are easy to set up for small networks, but are prone to performance issues due to the inherent weaknesses and overhead of the P2P architecture. With all the possible versions and sub-versions (Home, Professional, etc.) of Windows, hardware, anti-virus software, etc., it's impossible to say anything definitive that will address all performance problems. But here are some tips that might help: 

- Windows Professional vs Home versions: in a business environment, it's best to use the "Professional" version on all the 

- clients. 

- Try to get all the workstation clients on the same version of Windows. 

- Anti-virus: necessary perhaps, but also the number one cause of performance problems. Generally easy to rule out (by 

- disabling it on all the machines), if there is any reason to to suspect it, then you may need to configure it to be more selective about what it targets. It may be comforting to have the anti-virus scanning your data files constantly, but it's not likely to find anything there, while it could easily cut the performance substantially. 

- Privileges: obviously, each client will need full privileges on the shared files and directories. Don't try to rely on "Home 

- groups" for this. Instead, add all of the individual workstation users to the "server" as users, with their passwords. That will go a long way towards avoiding problems with Windows inexplicably denying access to one of the clients. On the "server" make sure to list all the users as having full privileges on the shared directories. 

- Limit the shared directory structure to just the \VM directory—i.e. not the entire C: drive. 

- Try the "C" version of A-Shell to see if it runs faster when there are multiple users with the same file open. Some sites report 

- this to have a huge effect; others little or none. 

- Don't try to extend your P2P network over a WAN. That might seem reasonable (using a VPN) for lightweight browsing and 

- file sharing, but is guaranteed to be terrible for typical applications performing multi-user record I/O. Instead, have the remote users connect via ATE, or RDP, or some similar technology that effectively allows the remote user to share the memory and CPU of the "server", with the only the screen updates traveling across the WAN. Note that if all the users connect with such a tool, you can turn off file sharing which will give you another boost. 

A-Shell Reference 

Page 4003 

## **QFLOCK.SYS IN MEMORY** 

(Unix only.) This is mainly only relevant if your application uses XLOCK, FLOCK, or a related locking subroutine, and/or you have a large number of jobs. If either is true, then make sure you use the MEM: (rather than DISK) option on the QUEUE statement in miame.ini. See the system parameter QUEUE and the next topic for more discussion of memory mapping. 

A-Shell Reference 

Page 4004 

## **LOCAL COPIES** 

Networked Windows environments are quite efficient at serving up entire files over the network from a fileserver (as in word processing applications), but they are relatively slow at serving up record-level operations. Here, the disk operation overhead is much higher than in the Unix world because of the need for machine-to-machine communication. Loading a file from the server may require only a couple of units of machine-to-machine communication, but reading the file via thousands of individual record operations (which is typical of AMOS-style report programs) requires thousands of units of machine-to-machine communications. This overhead typically becomes the limiting factor in Windows installations of A-Shell. 

Memory mapping doesn't really help here, since it doesn't eliminate the need for machine-to-machine communication, and in any case, it only works properly for read-only situations anyway. If we can limit ourselves to read-only access to a file in a particular program, then a better solution is to request that A-Shell give you a local copy of the file. In this case, when the file is opened, A-Shell copies the entire file (in one big transfer operation) from the server to the local workstation and then references the local copy until the file is closed (after which the local copy is deleted). This technique can significantly speed up report programs, or any other program that performs many read operations from a file, by eliminating that machine-to-machine communication overhead. As a side effect, it also reduces network traffic and the load on the fileserver, thus potentially speeding up other programs running across the network. 

Local copy mode is activated similarly to memory mapped mode, using `xcall ASFLAG,64` . 

A-Shell Reference 

Page 4005 

## **MEMORY MAPPING** 

Memory mapping is a file access technique that works very well under Unix. Under Windows, it only makes sense in read-only applications, and even there, the "local copy" option (covered in a subsequent topic) makes more sense. So it is for all practical purposes only of interest under Unix. The concept is to map a disk file onto a memory address space, such that it can be accessed via memory operations rather than disk operations. The file doesn't have to fit entirely in memory, because the demand paging system (otherwise associated with virtual memory) takes care of swapping pages in and out of memory as needed. 

It may appear that this is hardly different that ordinary disk caching, in which frequently accessed disk blocks are held in memory to minimize physical disk accesses. However, there is significant performance difference between accessing a cached disk record via a disk service call and accessing a memory record. Disk service calls require a context switch from user to supervisor mode, even if the data is in cache, whereas memory access calls do not. Such context switches are relatively expensive operations, being perhaps hundreds of times slower than ordinary instructions. So even though reading a disk record from cache and reading the equivalent data directory from memory may both appear to be "lightning fast", the difference can become significant when you have a lot of little disk accesses. 

If memory mapping is so wonderful, you might ask why we don't just use it all the time. The answer would be that it can cause memory to be used inefficiently, which can have an adverse impact on the system performance. The recommendation would be to only use memory mapping with reasonably small files that are heavily accessed in specific programs. Good candidates would be any custom (non-ISAM) index files, or any small file whose records are accessed multiple times in a particular program. (ISAM files are not generally good candidates except perhaps in certain individual programs and when the files are not too large, because there is no convenient way to map the index without the data.) 

The worst candidates examples are large files that are accessed sequentially or sporadically, with little repetitive access to the same records. For example, it would be a bad idea to memory map a customer master file probably in the customer maintenance program. Such a program is not likely to be disk-bound, and the amount of memory spent mapping the file would be better spent on other uses, like ordinary disk caching 

Memory mapping must be activated within individual programs, and applies only to files opened after the memory mapping option is turned on, so in addition to identifying heavily accessed files, you would need to identify specific programs that were disk-bound in order to benefit from it. 

Memory mapping is activated within a program using `xcall ASFLAG,16` . Once this call is made, any file subsequently opened within that program (other than for sequential access) will be memory mapped. The implementation therefore consists of 

A-Shell Reference 

Page 4006 

inserting a subroutine `ASFLAG,16` into selected programs just prior to opening the file(s) that you want to memory map. You can either rearrange the file opens to put the one(s) you want to memory map last, or you can insert a subsequent `XCALL ASFLAG,0` to clear the memory map flag after the intended files have been opened. No other changes are needed in the program; A-Shell will automatically convert the relevant disk operations to memory operations for you. 

It is safe to allow a mixture of simultaneous memory-mapped and traditional I/O to any given file under Unix. 

A-Shell Reference 

Page 4007 

## **- READ ONLY MODE** 

The benefits of read-only file access apply to all environments. The idea is that if you have no intention of updating a particular file, then there is no reason to pay all of the overhead that is associated with locking the file and coordinating your accesses with other users. The performance difference between reading records in a file opened for read-only access, and reading records from the same file opened for normal (read/write) access is relatively minor in a single-server Unix environment, but very substantial in networked environments such as NFS or Windows. 

In the Windows case, the decision to use read-only mode vs. local copy mode would be based on the size of the file relative to the number of accesses to be made to it. Local copy mode is more efficient (because you cut the network entirely out of the picture) but it does involve the initial overhead of copying the entire file across the network to the workstation. So you aren't going to read most of the records in the file during a particular instance of a program, then it probably is more efficient to leave the file on the server and use read-only mode. 

In the case of NFS under Unix, local copy is not an option, so read-only mode is the recommended approach for optimizing read access to a file. 

Your mileage will vary, but it is not uncommon for read-only access over a network to be twenty times faster than reading from a file that has been opened for read/write access by more than one person. (When only one process has the file open, it doesn't seem to have much effect.) 

Read-only access can be specified in one of two ways. One is to the "read'only" suffix to the open statement, for example: 

```
Open #1, "MYFILE.DAT", RANDOM'FORCED, RECSIZ, RECNOVAR, READ'ONLY
```

The READ'ONLY suffix is requires that you use the /V:1 switch or any of the /X switches when compiling the program. 

A second approach is to use `xcall ASFLAG,1` prior to opening the file. Like the other ASFLAG uses described above, all OPEN statements after the `xcall ASFAG,1` are affected. So you either need to rearrange your OPEN statements, or clear the read-only flag using `xcall ASFAG,0` . 

A-Shell Reference 

Page 4008 

## **ACCESSING FILES IN THE MEM: DEVICE** 

In some situations, it makes sense to load an entire file into your user memory partition and access it directly from memory. This can be accomplished using the MEM: device. Use the LOAD command to load the file into your user partition. Once loaded, you can open it and read/write to it just like any other random access file, simply by specifying MEM:<filename> in the OPEN statement. 

If you write to the file while it is in your memory partition, you will need to use SAVE.LIT or the equivalent MX_USRSAV function in order to write the updated file back to disk. 

Note that LOAD.LIT dynamically allocates additional memory for any files so loaded, so it is not necessary to worry about the size of your pre-allocated memory partition. 

Accessing a file using the MEM: device is naturally much faster than ordinary disk access (even when the file is cached). It is nearly as fast as memory map mode, and much faster than local copy or read-only modes. The biggest advantage that the MEM: approach has over the previous methods is that it can be used without making any program changes. The trick is to add 

OPTIONS=AUTO_MEMOPEN to miame.ini, which causes all BASIC file open operations to automatically check to see if the 

specified file is in memory before opening the disk copy. If it is already in memory, then it is accessed as if it had been using the MEM: device. This way, you can use MEM: access in specific programs merely by using LOAD.LIT to load the file prior to running the program. 

Be careful when using AUTO_MEMOPEN that you don't inadvertently leave the file in memory longer than intended, because subsequent programs will act as if running normally, but any changes to the file will only affect the memory copy. 

The MEM: device, as well as OPTIONS=AUTO_MEMOPEN, can  be used with sequential input files. For example: 

```
OPEN #1, "MEM:MYFILE.TXT", INPUT
```

The above statement would work if myfile.txt was loaded into the user memory (using `LOAD MYFILE.TXT` ). 

```
OPEN #1, "DSK1:MYFILE.TXT[123,456], INPUT
```

As with RANDOM files, if OPTIONS=AUTO_MEMOPEN, then the above OPEN statement will first check user memory to see if myfile.txt is loaded, and if so, will use that copy directly. 

A-Shell Reference 

Page 4009 

## **- PRE LOAD FREQUENTLY USED PROGRAMS** 

This advice mainly applies to Windows file server environments and where your application has a tendency to frequently chain to one or more particular programs. RUN and LIT programs are fetched from disk as needed and flushed after use (with the one exception being RUN.LIT). They are not cached in memory automatically (like SBX routines are) out of concern for the confusion that creates in development environments where you are frequently modifying and re-running programs. It is also very difficult to "guess" an optimum strategy for caching RUN files, since usage patterns vary spectacularly among applications. But it is easy enough to create a CMD file to LOAD your most commonly used RUN and LIT files before starting the application. 

Most modern systems are memory rich (or should be, given the low cost of memory), so you can probably afford to be "extravagant" (by traditional AMOS terms). However, there is obviously a point at which it becomes more efficient to allow the system more memory to use dynamically as it sees fit than to lock it up storing individual copies of RUN programs for each user. (There is currently no equivalent of loading a program in system memory, so each user needs to load their own copies.) 

A-Shell Reference 

Page 4010 

## **TEMPORARY FILES** 

A particularly good use of the MEM: device is for temporary files. Such files are typically only used by a single program anyway, so there is no point in having them on disk, except that we might not previously been able to afford the memory. Now that memory is cheap, and dynamically allocated as needed by the MEMORY and LOAD commands, there is little reason not to put any temporary files that are heavily accessed directly in memory. 

Unfortunately, there is currently no way to create a file directly in memory. The ALLOCATE statement does not support the MEM: statement. So you would have to first allocate the file on disk then load it in memory, as in this example: 

- `! Example of creating, loading, using a temp file in memory` 

- `! First, allocate the file on disk…  (we use the device TMP0:` 

- `! which, in the case of Windows, should point to a local` 

- `! workstation drive rather than the server` 

```
allocate "TMP0:MYTEMP.DAT", BLOCKS
```

- `! Next, load it into our user memory` 

```
xcall MIAMEX,108, IDX, "TMP0:MYTEMP.DAT"
```

- `! Remove it from disk (no longer needed there)` 

```
kill "TMP0:MYTEMP.DAT"
```

- `! Now open the file in memory…` 

```
open #1, "MEM:MYTEMP.DAT", RANDOM, RECSIZ, RECVAR
```

A-Shell Reference 

Page 4011 

- `! Read and write to the file just like any other file` 

```
read #1, REC
write #1, REC
```

```
<etc>
```

```
! Close file and delete it from memory
```

```
close #1
xcall MIAMEX, MX_USRDEL, IDX, "MYTEMP.DAT",
```

A-Shell Reference 

Page 4012 

## **LOCAL PRINT FILES (WINDOWS)** 

If you create large print files on a Windows network, you can improve performance by making sure they are written to the local workstation rather than to the server. As in the example above, the recommended practice is to define a special device (call it TMP0: or PRT0: or LOC0: ) which points to the local workstation (C: drive). This works best in applications that already have a configuration option to specify the logical device were particular classes of files, such as print files, get written. 

A-Shell Reference 

Page 4013 

## **NUMBER OF FILES PER DIRECTORY** 

This advice applies to all platforms: try to keep the number of files in any one directory down to a reasonable number (ideally no more than a few hundred). If you let the number of files creep up into the thousands, the overhead for performing operations on that directory (such as adding, deleting, or finding a file) grows at an alarming rate. Even worse, it can become impossible to perform Unix wildcard operations because the shell runs out of memory while attempting to enumerate the wildcard list. A large number of print files can also cause severe fragmentation of the file system, which further slows things down. 

This situation tends to occur in applications that create unique printfile names and which leave it to the users to delete print files periodically. Whereas under AMOS, with 32MB logical disks, they might have run out of space after accumulating several hundred print files, under Unix with a 20 GB logical disk, they may accumulate tens of thousands of print files and still not begin to notice the disk filling up. (They will notice the system slowing down, but will probably not recognize the cause.) 

There are several ways to avoid this problem. The simplest would be to just delete (or archive) the print files on a periodic basis. If you want to leave them on the hard drive for archival purposes, then at least move them to another directory which is not accessed constantly by A-Shell. Better yet, tar all of the print files for the period into one tar file (ideally a compressed one). If you ever need to get one, you can list the contents of the tar files and extract individual files as needed. 

Another approach would be to use the COMMAND=SBX: feature in the printer ini files, along with a custom SBX routine, to archive or relocate the print files as they are printed. 

Ideally, you would not only keep your print files and related output files in their own directories (outside of the directories holding the permanent data and program files), but you would even put them on a separate file system (or disk partition). That way, you insulate the more important part of the application from the potential dangers of large numbers of output files, such as filling up the file system, excessive fragmentation, etc. 

A-Shell Reference 

Page 4014 

## **XCALL SERCH OPTIMIZATION** 

The best way to optimize files using SERCH[XS] is to replace them with ISAM-A files. (At best, looking up a record in a file of 32K records would require on average 15 disk operations for SERCH[XS] , and about 3 for ISAM.) If that is not practical, then at consider one or both of the following suggestions: 

• Change your file reorganization threshold so that the index is kept sorted (i.e. so that the unsorted "overflow" area is kept small). On a machine where sorting took a relatively long time, you might have been tempted to delay sorting until the overflow area became quite large. But in the typical A-Shell case, it is much more likely that the accumulated delay in having to continually search the overflow area is much greater than the overhead in sorting the file. 

• If Unix, memory map the index file whenever possible. If Windows, use one of the other techniques (read-only, MEM:, local copy) in any program that does not need to update the file. 

A-Shell Reference 

Page 4015 

## **OPTIMIZING FILE SORTING** 

If you do a lot of sorting, or have very large files to sort, or would like more sorting capabilities, we recommend that you switch from BASORT and SORT to the OptTech sort routine, which was developed by third party specializing in sorting. It supports up to 100 sort keys, as well as complex operations like removing or exporting duplicate records, and is much faster than BASORT— particularly with files that do not fit in memory. It has some down sides as well, such as not being interface compatible with BASORT, not supporting files which have block padding, and there is a per-copy licensing fee. Contact us for more details if interested. Otherwise read on for tips on getting the best performance our of SORT and BASORT. 

The main trick to optimization of XCALL BASORT and SORT.LIT is to specify SBR=MALLOCSORT in miame.ini. This causes A-Shell to dynamically allocate a large chunk of memory to allow the file to be quick-sorted or tag-sorted directly in memory, instead of having to use the much slower, disk-based, polyphase merge sort. We recommend that you always specify SBR=MALLOCSORT. However, there is a limit to how much memory the sort routine will allocate. By default, this limit is 8MB. If you plan to sort larger files, you might want to increase this limit using the MALLOCLIMIT key in miame.ini. 

With modern Windows workstations (which typically have 256MB of memory), there is probably no harm in bumping MALLOCLIMIT up to 64MB. On Unix boxes, or in Windows Telnet or Terminal Server environments where many users are sharing the same memory, there is definitely a tradeoff between to be considered. If you allow one user to allocate too much memory, system performance may suffer, at least until that memory is fully returned to the system. 

In many operating systems environments where multiple users are sharing the same physical memory, even though a user frees up a temporary memory allocation, the system might not make the memory immediately available to others. This is due partly to historical experience suggesting that a process that allocates and then releases a chunk of memory is likely to re-allocate it again before it exits (and thus it is more efficient to "reserve" the freed memory for re-use by the user that freed it.) The other reason is there may be significant overhead in the "garbage cleanup" necessary to consolidate the freed memory with other available segments. The one guaranteed way to force the system to re-use freed memory is for the process to exit. (That is, if you have a single program that needs to sort a huge file, let's say 256MB, then you could launch an A-Shell session using MALLOCLIMIT of =260MB, sort the file, then exit that A-Shell session so that the memory will be immediately made available to the rest of the system.) 

Also note as an alternative to changing the MALLOCLIMIT, you can simply change your current memory partition size, dynamically, with the MEMORY.LIT command. (The BASORT subroutine will use your partition if there is sufficient memory available there for a quick sort or tag sort.) So in the case just described, it would be easier to just use a command file to set the 

A-Shell Reference 

Page 4016 

partition size for the process, rather than using a special version of miame.ini. The one potential downside of that approach is that if the requested amount of memory is not available, MEMORY.LIT will simply fail, whereas in the case of MALLOCLIMIT, BASORT will try for a smaller allocation if the original request fails. 

As of Build 833, BASORT contains some minor optimizations to the tag sort routine that come into play when the file being sorted is opened with the span'blocks modifier or when the record size divides evenly into 512 (or is larger than 512, in which case span'blocks is automatic). So when laying out a file to be sorted, it makes sense to use record sizes like 16, 32,64,128,256, etc., or to use span'blocks. 

A-Shell Reference 

Page 4017 

## **USE SPAN'BLOCKS** 

Historically under AMOS, all disk I/O was organized around 512 byte blocks. Because of this, logical records in a file were not split across block boundaries. Instead, filler bytes were simply added to the end of each block as needed. For example, if the record size were 170 bytes, three records would fit within a block (3 x 170 = 510) with two bytes left over. In this case, each block would have two wasted bytes at the end. Eventually, under AMOS 2.x, this requirement was lifted, but you had to specify the span'blocks modifier on the file open statement to force it to allow logical records to be split across blocks. For example: 

```
Open #1, "myfile.dat", random'forced, 170, recnovar, span'blocks
```

This method is certainly more efficient in terms of disk space, but possibly less efficient in terms of performance, so it never became very popular. However, under Unix and Windows, it is virtually always more efficient in all cases. In addition to eliminating wasted space, it also lends itself to optimization involving the reading and writing of arrays of records at a time. (The BASORT subroutine, for example, uses this technique with its temporary files.) Thus, thus the use of `span'blocks` is highly recommended under A-Shell. 

`Span'blocks` is automatic whenever the record size is greater than 512 and irrelevant if the record size divides evenly into 512. It is also automatic for ISAM-A files. However, note that for any given file, if you use `span'blocks` in one program, you need to use it in all the programs that access that file, since it does affect the way the data is organized on disk. 

A-Shell Reference 

Page 4018 

## **USE LARGER RECORD SIZES** 

This may sound like strange advice, especially for those of us that grew up squeezing our record sizes down to the absolute minimum possible. Surely, all else being equal a larger record is no more efficient than a smaller one, but it may not be any less efficient either. As was hopefully made clear in the discussion about memory mapping and local copies, the biggest bottleneck in disk I/O is not the transferring of the bytes or the network bandwidth but the various forms of overhead related to initiating the operation. Those forms of overhead are not related to the number of bytes transferred in an operation. In other words, the time required to read a 768-byte record is, for practical purposes, about the same as the time require to read a 16 byte record. 

Consequently, it doesn't make sense to try to squeeze bytes out of your records, especially if it requires you to go to extra trouble to pack data into compact formats. For example, whereas it might once have made sense to store dates in a compressed 2 byte format, packing and unpacking them as needed, it probably makes more sense to store them as 8 bytes, or even 10 (with slashes). 

The only reason to minimize record sizes is if, in doing so, you make the file easier to back up (i.e. it fits on a convenient medium) or you make it more practical to load into memory. But an increase of 25% in the size of the file is unlikely be significant in either case. 

Similarly, don't worry about 512 byte blocking or the 512 byte record limit. If you need to expand a record, just expand it to whatever size is convenient. A-Shell supports the `span'blocks` option on the OPEN statement (see previous topic), and invokes it automatically for record sizes larger than 512 bytes. You're much better off with a single record of 900 or 1600 bytes, than with two or three smaller records. (There might be a slight advantage to record sizes that are even divisors or multiples of 1024, but this is a minor factor.) 

As an example of where this logic might apply, let's say you are creating a file to store invoice history for each customer. Standard design principles would suggest creating a file with one record per invoice. That way, if a customer had 500 invoices, it would use 500 records, but if he had only one, then only 1 record would be needed. Let's say that the record size is 64 bytes. An alternative approach suggested by the "use larger record sizes" strategy would be to store the invoice history records in "superrecords", each holding several invoices. For example, we might go with a 1024 byte record that held up to 16 invoice items. It might take a bit more logic to access the file this way, and we would waste, on average, half a record (512 bytes) for each customer. On the other hand, we cut the number of file operations needed to fetch the invoice history for a customer by a factor of 16, making this design much faster, even allowing for the fact that we would be, on average, transferring twice as many bytes (due to the half-empty records). 

A-Shell Reference 

Page 4019 

You would have to decide for yourself if the performance advantage was worth the negative baggage (waste of space, extra logic required, etc.) Quite likely it is not. The point of this exercise was not to suggest a goofy database design, rather to make clear that the main disk bottleneck is in the number of records accessed, not in their sizes. If performance is important to you, then try to get more accomplished with fewer individual disk I/O operations. 

One more example of this principle is worth noting. Many applications have one or more utility programs, such as file rebuilds or reports, that read every record sequentially in a file. Although such programs will probably benefit from one of the methods described previously (e.g. memory mapping, local copy, read-only mode, etc.), yet another approach would simply be to read more than one record at a time. Let's assume again that we plan to read a sequential series of 64 byte records. Instead of reading them one at a time, we might do something like the following: 

```
map1 XREC
```

```
  map2 REC(16)                 ! array of 16 file records
```

```
map3 KEY,S,10
```

```
map3 DESCR,S,50
map3 CODE,B,4
```

```
OPEN #1, "MYFILE.DAT", RANDOM'FORCED, 1024, RECNO
```

```
LOOP:
```

```
RECNO = RECNO + 1
```

```
IF RECNO > MAXREC GOTO DONE
```

```
READ #1, XREC
```

```
! now process the 16 records individually….
FOR I = 1 TO 16
   <process REC(I)…>
```

```
NEXT I
```

A-Shell Reference 

Page 4020 

```
GOTO LOOP
```

The above technique needs some refinement. For example, it ought to deal with the case where the file doesn't contain an even multiple of 16 records. And it needs to be careful about whether reading multiple records at a time interferes with the 512 byte blocking logic. (This is another good reason why you should always use `span'blocks` mode, because it eliminates these pesky 512 byte blocking concerns.) The point, again, is that although this technique does not reduce the amount of data transferred, it reduces the overhead by reducing the number of individual disk operations, and thus will run faster and create less load on the server. 

A-Shell Reference 

Page 4021 

## **ISAM PERFORMANCE** 

Although ISAM-A is the preferred file structure for use in A-Shell, and has been for many years, ISAM 1.x continues to be fully supported. 

In August 2008, A-Shell build 1122, a major performance-related update of ISAM was undertaken to meet the needs of a new client. This "new ISAM" is known as ISAM 1.1. 

For large ISAM files, you can achieve much better performance by increasing the IDX block size and/or number of index levels from the previous fixed values of 512 and 3. The ISMBLD and ISMDMP utilities, updated to ISAM 1.1, allow access to this capability. 

To take advantage of the new capabilities, you must dump the file and build a new one with the ISMBLD switches /B:# and /L:#. 

Following are descriptions of how the ISMBLD.LIT switches may be used to improve performance. See the following topic for information on the very important /L:# switch, and ISMBLD.LIT for a full listing of the switches. 

## **IDX Blocks (/B:####)** 

Increasing the IDX block size helps by increasing the number of keys that can be scanned per disk operation, reducing the number of levels needed, and reducing the number of block splits during adding, all at the cost of more bytes being transferred to/from the disk per node accessed. For most modern disks and computers, the tradeoff works well, at least up to 2048. Our recommendation is to choose a block size 20-50 times larger than the key size. 

## **Memory Mapping (/MI and /MR)** 

Under Unix, memory mapping the IDX, either fully (/MI) or just the first few blocks at the top of the tree (/MR), affects only the ISMBLD loading operation. In general memory mapping results in a very significant performance increase, when the total file size is small compared to the available system memory (else it may adversely affect the cache efficiency). /MR only maps a handful of blocks, so there is no danger of it affecting cache efficiency, but on the other hand, the overall benefit is smaller. If you want to get this same effect in your application, you will need to use XCALL ASFLAG. 

Memory mapping does not have much, if any, benefit under Windows. 

## **Fast Load (/F)** 

A-Shell Reference 

Page 4022 

Like /MI and /MR, this also only affects the load operation. It speeds the process somewhat, by eliminating the initial key lookup operation that otherwise is performed to check whether the record being loaded is a duplicate. If you know that your load file is clean, this can shave about 20% off the load time. But the penalty is that if there is a duplicate key, instead of skipping the record (as in the normal case), the load will abort with an error. 

## **- Auto Expansion** 

Beginning with A-Shell 1344 of March 2013, the number of blocks added during auto-expansion is limited to 8 MB of data or 2000 index blocks. For very large files, this makes the auto-expansion process more seamless. 

## **- Real World Analysis** 

An A-Shell user asked a question about ISAM performance, and MicroSabio provided an in-depth answer that covers a lot of - " " ground. See the A Shell forum discussion ISAM performance after deletions. 

## **See Also** 

- ISMBLD.SBX 

- ISMDMP.LIT 

- ISMROKXS 

## **Subtopics** 

- IDX LEVELS (/L:#) 

A-Shell Reference 

Page 4023 

## **IDX LEVELS (/L:#)** 

Increasing the IDX levels helps balance the tree, avoiding the top-heavy situation where we have to sequentially scan many blocks at the top (root) of the tree in order to find the right branch. The optimum number of levels is that which results in only one block at the root of the tree, and is related to the number and size of keys, and inversely related to the size of the IDX blocks. ISMBLD (and ISMDMP) will work out the math for you and display a list of the projected IDX blocks at each level, e.g.: 

```
.ISMBLD TSTNEW
```

```
Key size: 50
```

```
Key position: 1
```

```
Size of data record: 64
```

```
Number of records to allocate: 500000
```

```
    62415 index blocks will be allocated
```

```
Empty index blocks to allocate: 62415
```

```
    Projected IDX blocks by level: 4000,20000,100000
```

```
    Warning: IDX is top heavy; consider adding levels or increasing block size.
```

The above example shows building a file with 500000 records each with a 50 byte key. Using the default values (512 byte IDX block and 3 levels) the estimated number of blocks at the top level is 4000 which is extremely top-heavy. (The top level must be scanned sequentially until we find our branch, sort of like turning the pages of the dictionary one by one to find the right page.) So in this case, each key lookup will take an average of 4000/2 or 2000 disk operations just for the top level, then typically one each for the remaining levels. 

(The numbers work out nicely in this example because assuming an average loading efficiency of 60%, that gives us 5 keys per 512 byte index block, hence the ratio of 5X between each level of the IDX.) 

Since 2000+ disk operations per key lookup is going to result in TERRIBLE performance, let's hit Control-C here (before the IDX is built) and try to optimize it. 

A-Shell Reference 

Page 4024 

To optimize this IDX, we can either increase the block size, the number of levels, or ideally both. Using our heuristic for the ideal block size of 20-50 times the key size, we could either go with 1024 or 2048; let's try 1024 and 6 levels: 

```
.ISMBLD TSTNEW/B:1024/L:6
Key size: 50
Key position: 1
Size of data record: 64
Number of records to allocate: 500000
    29415 index blocks will be allocated
Empty index blocks to allocate: 29415
    Projected IDX blocks by level: 1,5,50,500,5000,50000
```

As you can see, now we have a projected IDX tree with only 1 block at the top or root, 5 below that, and then a 10X factor between each of the rest. This is vastly better than the original default configuration, reducing the average number of disk operations per key lookup from over 2000 to about 7. 

If you have the time to experiment, you might want to try a block size of 2048 (/B:2048) and 5 levels, which produces an IDX level breakdown something like: 1,3,47,1034,22728. It is hard to predict whether the decrease of one level combined with the increase in block size will be a net gain or loss; it will probably depend on your hardware, but probably won't make a major difference. 

## **Projected vs. Actual IDX structure** 

The projected number of IDX blocks by level resulting from a particular combination of records, key size, block size and levels is just an estimate based on an average distribution of keys and the number of records specified. In a production environment, you might build the file with a small initial number of records and then rely on the auto-expand feature to increase the file size as needed. Unfortunately, unlike the case with ISAM-A, the auto-expand does not adjust the IDX structure, it only adds blocks to it. Thus what might be an ideal configuration for an initial file size of, say, 10,000 records, might turn out to be badly top-heavy if the file grows to 500,000 records. Thus, you may want to experiment using ISMBLD to specify the number of expected records 

A-Shell Reference 

Page 4025 

(i.e. the file size you'd like to optimize the IDX for), in order to figure out the best number of levels. (Just ^C before creating the actual file.) Then you can use the appropriate /B:### and /L:# values, and don't worry if the initial index appears to have more than the optimum number of levels (e.g. 1,1,3,30,3000). Keep in mind that the performance penalty for too many index levels is just one disk operation per level, while the penalty for too few levels is essentially unlimited. 

A-Shell Reference 

Page 4026 

## **SOCKET PROGRAMMING** 

Sockets (sometimes called "Berkeley sockets" because they were first introduced in Berkeley Unix) are almost certainly the most common mechanism for communicating between two computers across a network (especially the Internet). Some examples of common networking protocols that are built on sockets are: Telnet, FTP, HTTP, and SMTP. In terms of the TCP/IP protocol stack, sockets exist at the interface between the transport layer and the application layer, and are generally based on either of the two common transport protocols–TCP or UDP–approximately as illustrated here. 

**==> picture [292 x 314] intentionally omitted <==**

**----- Start of picture text -----**<br>
Telnet<br>FTP<br>Application Layer<br>A-Shell<br><sockets><br>Transport Layer UDP TCP<br>Network Layer (IPv4 or<br>Network Layer<br>IPv6)<br>Datalink (MAC) Layer Ethernet, Device Drivers<br>Physical Layer Hardware (e.g. 10BaseT)<br>**----- End of picture text -----**<br>


TCP/IP Protocol Stack 

A-Shell Reference 

Page 4027 

TCP (Transport Control Protocol) provides a reliable, stream-oriented "connection" analogous to a telephone call, while UDP (User Datagram Protocol) is a simpler, unreliable, datagram-oriented, "connectionless" protocol more analogous to a letter sent through the mail. (It is also possible for sockets to bypass the transport layer; these are called "raw" sockets.) 

When two computers communicate via sockets, one is considered the "server", and the other is the "client". The distinction relates solely to how the connection is established. The server "listens" (i.e. waits) for a client to "connect". In the case of TCP, once the connection is made, both sides can read and write (even at the same time, since the connection is "full duplex"), and either can initiate the close. 

In the context of socket programming, "clients" and "servers" are designations given to processes, not computers. (The two processes may exist on the same computer or on different computers thousands of miles apart.) This use of the terms should not be confused with the common notion of the "server" being a central computer and the "client" being a user device like a workstation. 

A socket is identified by the combination of an IP address and a 16-bit "port" number. Generally ports 1-1024 are reserved for "well-known" services (e.g. Telnet=23, SMTP=25, FTP=20,21, HTTP=80, etc.) while ports 1025-65535 are available for custom application use. A socket "connection" between two processes (typically but not necessarily on different machines) is defined by the two endpoints. Several connections can share the same endpoint at one end (for example, several Telnet sessions on the same server and all at port 23) but they would have to have unique endpoints at the other end, as shown here: 

## **Subtopics** 

- Listening vs. Connection Sockets 

- Socket Subroutines 

- Scenarios and Issues 

- Sample Programs 

- Interfacing to External Services 

A-Shell Reference 

Page 4028 

## **LISTENING VS. CONNECTION SOCKETS** 

When a client makes a socket connection, there is only one socket involved: the "connection socket". But on the server side, there are actually two sockets: a "listening socket" and a "connection socket". The server starts by creating a "listening socket" and "binding" it to a protocol, address and port number. Then it "listens" on this socket for a client connection. The act of accepting the connection creates a new "connection socket" used for the duration of the connection. The listening socket then may or may not be closed, depending on the design of the server. 

The A-Shell TCP subroutines encapsulate these details, making it appear as if there was only one socket. But in reality, it internally creates a listening socket, and then closes it after accepting a connection and returning the connection socket to the caller. Because it closes the listening socket, the port becomes available again for another process (or the same process) to again listen on the original port. 

A single program could actually support multiple socket connections, all on the same port. This is not of much practical significance, though, since the subroutine blocks while waiting to accept a connection (and thus would be unable to service the existing connections during that time.) To service multiple concurrent connections effectively, you generally need multiple server processes. 

A-Shell Reference 

Page 4029 

## **SOCKET SUBROUTINES** 

A-Shell includes three general-purpose socket routines, TCPCLI, TCPSRV, and TCPX. TCPCLI and TCPSRV were the original routines, designed specifically for the client and server ends of a connection, respectively. TCPX is the new version (as of Build 855), combining and extending the features, and is preferred for new programming. With these, you can create or interface to most kinds of TCP based socket services. Since the subroutines are already documented, we will instead go on to discuss higher level considerations. 

A-Shell Reference 

Page 4030 

## **SCENARIOS AND ISSUES** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Simple, Blocking, Iterative Server 

- Non-Blocking, Checking Without Waiting 

- Packet Fragmentation and Consolidation 

- Serving Multiple Connections 

A-Shell Reference 

Page 4031 

## **SIMPLE, BLOCKING, ITERATIVE SERVER** 

This scenario reflects one of the most common types of socket conversations, that of a server which fulfills a single request per client connection. An example might be an inventory lookup and pricing server. The client prepares a request (e.g. perhaps a list of part numbers and quantities.) It then connects to the server (which spends its time in waiting for such connections, except when it is actually busy servicing one.) If the connection fails, the client might wait and retry. Upon connection, the client passes the list of parts and quantities to the server, the server looks them up in the inventory and pricing databases, and then returns the list updated with the available quantities and current prices. The client then terminates the conversation and the server goes back to waiting for another client connection. 

There is nothing in this model requiring that the conversation be terminated after one request/reply cycle. 

A flow diagram representing this kind of conversation and indicating the actual TCPCLI[XS] and TCPSRV[XS] opcodes is given below. TCPX[XS] supports the same opcodes, so the references to TCPCLI and TCPSRV in the diagram apply equally to TCPX). 

A-Shell Reference 

Page 4032 

## **- NON BLOCKING, CHECKING WITHOUT WAITING** 

One possible shortcoming with the implementation just described is that both client and server are "hung" during the read operation (waiting for the other end to send something.) If the remote end malfunctions, the local side would become more or less incapacitated. (You could ^C out of the wait state, but that is of little benefit to an unattended process.) The danger of this happening is minimal in the simple server just described, but in some cases, it could perhaps be more of a concern. In that case, you may want to employ one of the following techniques. 

The first is simply to check for input (using Opcode 7) before invoking the read operation. Since you can set a timer on the check operation, you can be certain of not getting stuck. The main problem with Opcode 7 is that it can only tell you if there is data to read, not how much. Consequently, in order to achieve maximum robustness, you would need to program for the possibility of receiving a fragmented packet. (See the following discussion on packet fragmentation.) A better solution to that problem is Opcode 8, which will tell you how many characters are available. Perhaps better still would be to use the TIMER parameter to set the maximum time to a very short interval, and the FLAGS parameter to the number of characters you want to wait for. (This is a new capability added to TCPX that was not supported by the earlier routines.) 

An alternate approach is to open the socket with FLAGS=0 (i.e. to clear the blocking flag.) In that case, an attempt to read (or write) to a socket that is unable to supply (or receive) any data will return an error code rather than hanging the process. Under Windows the normal error code is -10035 (Operation Would Block.) Under Unix, it is typically –11 (Resource Unavailable.) When such an error occurred on a read or write call, the application would want to loop and retry after a short wait. 

Even in the non-blocking case, an active close at the remote end will be indicated by a return STATUS of 0 to a read call. An attempt to write to a socket that has been closed by the remote end may accept a few characters but will eventually return an error such as –32 (Broken Pipe). 

A-Shell Reference 

Page 4033 

## **PACKET FRAGMENTATION AND CONSOLIDATION** 

The TCP transport protocol guarantees that all bytes sent are delivered in the order sent. However, packets may be fragmented and/or consolidated at any point along the process. For example, if you send out several packets of 100 bytes in rapid succession, they may be consolidated and delivered as a single packet of several hundred bytes. Or conversely, a large packet of 4000 bytes may be broken up and delivered as two or more smaller packets. In fact, the very idea of a "packet" doesn’t really exist in TCP, which is a byte-stream protocol. "Packets" are used at the network and datalink layers to implement the TCP bytestream, but are essentially invisible to us as the TCP level. 

This is an important consideration when using TCPX (or TCPCLI / TCPSRV), since the fact that they can send or receive a logical packet of data at a time, may falsely give the impression of these logical packets being the same as physical packets, i.e. more like "messages" or "data records", when they are not. They are just groups of bytes, which may well be regrouped (but never reordered) during the transport process. It is up to the application to design a protocol that works with this paradigm. There are several possible approaches to doing this. 

One is to build your own two-level protocol on top of TCPX (TCPCLI / TCPSRV), with the lower level simply being responsible for accumulating (or transmitting) bytes, and the upper level mapping the buffered bytes into logical "packets" or "records". This is a bit awkward to do in BASIC, although it is certainly possible using unformatted variables with substring addressing, or arrays, along with the ability to map overlay structures in BASIC. 

Another is to make extensive use of Opcode 8 to always check that the number of bytes in your "packet" is available before reading, and to always specify the "packet" size in the FLAGS argument when reading, so that you don’t accidentally read more than one "packet" at a time. This, of course, works in conjunction with a protocol involving fixed length logical "packets". 

As discussed in the preceding topic, TCPX added the ability to combine a time-out with a blocking read operation. This simplifies the task of reading complete packets, but doesn’t completely eliminate the possibility that fragmentation and network delays will result in the timer expiring after receiving only a part of the desired logical packet. (This, however, would be pretty rare, and gets rarer still as the time out value is increased and the packet size is decreased. In fact, with packets less than about 1000 bytes, the chance of them being fragmented is practically nil, and even if there is fragmentation, the chance of there being a significant delay in arrival of the packets is another order of magnitude smaller. So it wouldn’t be unreasonable to forego the effort of reassembling physical packets into logical ones and instead just treat such a condition as a general protocol error, and reset the connection.) 

A third approach, which might be combined with either of the others, is to include mandatory "ACK/NAK" messages in your protocol. These allow you to synchronize the two processes, as well as providing a way to abort the connection at convenient 

A-Shell Reference 

Page 4034 

points where errors might be anticipated. For example, consider a simple file transfer protocol. The client sends a (fixed length) "request packet" to the server asking to retrieve a certain file, and the server responds first with a "header packet" giving details about the file (most importantly its size) and then sends a series of "data packets" containing the file. If the sender immediately followed the "header packet" with "data packets", they might arrive merged, requiring the receiver to separate them. But if the sender waits for the client to "ACK" the "header packet" before proceeding, the client can avoid excess manipulation of the incoming data, and if necessary, it can abort the transmission right here before it starts by sending a "NAK". The following code excerpt illustrates such a client: 

```
! Simple file transfer client
```

```
map1 CONTROL'PACKET                 ! arbitrary packet layout (must match server!)
```

```
     map1 CTL'OPCODE,B,1            ! 0=end, 1=request file, 2=ACK, 3=NAK
     map1 CTL'SIZE,B,4              ! # bytes in file (0=NA)
     map1 CTL'DATA,S,251            ! requested file name
map1 CTL'PAK'SIZ,F,6,256
```

```
map1 DATA'PACKET,X,1024
```

```
     FLAGS = 0                      ! (blocking connection)
```

```
     call CONNECT                   ! connect to server
     if STATUS <= 0 goto ERROR
     CTL'OPCODE = 1
     CTL'DATA = "MYDATA:SAMPLE.DAT"
```

```
     FLAGS = CTL'PAK'SIZ            ! send fixed length request packet
```

```
     call SEND'CONTROL'PACKET
```

A-Shell Reference 

Page 4035 

```
     if STATUS < CTL'PAK'SIZ goto ERROR
```

```
     call READ'CONTROL'PACKET       ! wait for response
```

```
     if STATUS < 1 goto ERROR       ! premature close (0) or other error (<0)
```

```
     if STATUS < CTL'PAK'SIZ then   ! (partial packet received – loop and get more)
```

```
          < get rest of control packet >
```

```
     endif
```

```
     open #CH, CTL'DATA, OUTPUT     ! open file ch to write received file
```

**==> picture [496 x 10] intentionally omitted <==**

**==> picture [496 x 10] intentionally omitted <==**

**==> picture [423 x 10] intentionally omitted <==**

```
     CTL'OPCODE = 2 : FLAGS = CTL'PAK'SIZ
```

```
     call SEND'CONTROL'PACKET       ! send ACK to server
```

```
     if STATUS < CTL'PAK'SIZ goto ERROR
```

```
RCV'LOOP:
```

```
     FLAGS = 0                      ! receive up to size of DATA'PACKET
```

```
     call READ'DATA'PACKET
```

```
     if STATUS <= 0 goto ERROR      ! premature close (0) or error (<0)
```

```
     PRINT #CH, DATA'PACKET[1,STATUS];     ! write received bytes to file
```

```
     TOT'RCVD = TOT'RCVD + STATUS
```

```
     if (TOT'RCVD < CTL'SIZE) goto RCV'LOOP
```

```
     close #CH
```

A-Shell Reference 

Page 4036 

```
     call CLOSE'CONNECTION
```

A-Shell Reference 

Page 4037 

## **SERVING MULTIPLE CONNECTIONS** 

A single server process can practically only serve one client process at a time. If another client tries to connect while the server is busy servicing another request, that client will receive an error during the connection attempt, such as "connection refused". If the duration of your typical server session is very short, and there are not too many clients competing to access it, then the easiest way to handle the possibility of a busy server is by having the clients retry their connection attempt after a short wait. However, if the average connection time is long, or the number of competing clients is sufficiently large, this will not give very good results, and a more powerful mechanism of supporting multiple clients is needed. 

The "normal" way to implement concurrent connection servers in the Unix world is by forking a new child process to handle each new connection. The typical Telnet daemon is an example of this. It listens on port 23 for a client connection, and as soon as it accepts one, it forks a child, which inherits (and takes over) the connection, while the original server closes its copy of the connection and goes back to listening for the next client connection. 

The TCP subroutines do not internally provide such a forking mechanism. There are, however, workarounds to this obstacle (including using SUBMIT to fork your own child-server). 

One such workaround would be to launch multiple servers, each listening on a different port. The clients would then need to be capable of iteratively trying to connect at each of the specified port numbers until a successful connection was established. A variation of this technique would be for the server, upon accepting a connection, to launch a child instance of A-Shell, passing it a command line which launched a new copy of the server at a new port number. At the same time, it would return to the client this port number so that the client could disconnect and then reconnect at the new port number. 

Multiple independent processes cannot all be listening on the same port, which is why the scheme just described requires separate port numbers. (Technically, there is a way around that restriction, but it involves opening a listening socket in one process, and then spawning multiple children that inherit and share the listening socket. This is beyond our scope at this point.) 

A more sophisticated workaround is for the server, after accepting a connection, to "hand it off" to a child process to be serviced, thus freeing the server to immediately accept another connection. You can do this using SUBMIT[XS] or ASHELL[XS] . You would need to pass to the child process (via command line arguments) the name of the program to service the connection and most importantly the socket number. 

Sockets are inherited by child processes launched via SUBMIT, but the child process needs to be told the socket number so it can pass it to TCPSRV[XS] . 

A-Shell Reference 

Page 4038 

## Such a server program would contain code something like this: 

```
LOOP:
```

```
   SOCKPORT = MY'PORT                         ! specified listening port
   call ACCEPT'CONNECTION                     ! wait for connection
```

```
   if STATUS <= 0 goto ERROR
```

```
   xcall ASHELL,"SUBMIT CHILD "+str(SOCKPORT)   ! launch CHILD.CTL
```

```
                                              ! (inherits our socket)
   call CLOSE'CONNECTION                      ! close our copy of socket
   goto LOOP                                  ! wait for another client
```

## The CHILD.CTL file might look something like this: 

```
;CHILD.CTL
RUN CHILD $0
```

A-Shell supports DO-file style arguments passed to CTL files via SUBMIT. 

The child.bas program might look something like this: 

```
SOCKPORT = str(CMDLIN)         ! (BASICPlus) pick up socket # from cmd line
```

```
   call READ'SOCKET            ! wait for client to send us something
```

```
   <process request>
```

```
   call WRITE'SOCKET           ! send client response
```

A-Shell Reference 

Page 4039 

```
   call CLOSE'CONNECTION       ! (or, we could loop back for more
```

```
END                            ! Terminate program and A-Shell session
```

A-Shell Reference 

Page 4040 

## **SAMPLE PROGRAMS** 

A-Shell comes with a number of sample programs that can help you experiment with (or develop) client/server socket programs. The most general is tcptst.bp in EXLIB:[908,25], which interactively prompts you for each operation, and supports both client and server modes. EMAILX.BAS (included with the EMAILX developer’s toolkit) contains a fully functioning example of a client program communicating with an SMTP server. And the pair of rxcall.bas and rpcutl.bas contain a fully functioning example of both ends of a client/server connection using a custom protocolm, designed to send subroutine parameter information between machines to implement remote subroutines. 

A-Shell Reference 

Page 4041 

## **INTERFACING TO EXTERNAL SERVICES** 

Although the TCP subroutines are quite useful for communicating between A-Shell processes, they are probably even more useful for communicating with the "outside world". As noted previously, most of the important services on the Internet are based on well-documented socket protocols. This means that you can use TCPX or TCPCLI to write client programs which can talk to Internet servers, and you can use TCPX or TCPSRV to write server programs that standard clients can use to talk to you. 

As a trivial but instructive example of talking to an Internet server, you can fetch raw web pages from any Internet web server using code similar to the following: 

```
map1 BUFFER,S,1024
```

```
map1 HOSTNAME,S,80
```

```
map1 SOCKPORT,F
map1 TIMER,F,6,5000      ! 5 second timeout
map1 FLAGS,F,6
```

```
HOSTNAME = "www.microsabio.com"         ! web site or IP addr (without http://)
SOCKPORT = 80                           ! standard http port
```

```
FLAGS = 1     ! blocking mode
```

```
xcall TCPX,9,STATUS,BUFFER,SOCKPORT,FLAGS,TIMER,HOSTNAME    ! connect to site
   if STATUS < 0 goto ERROR
```

```
BUFFER = "GET /index.html" + chr(13) + chr(10)              ! (must have CFLF!)
FLAGS = len(BUFFER)                                         ! # bytes to send
```

A-Shell Reference 

Page 4042 

```
xcall TCPX,2,STATUS,BUFFER,SOCKPORT,FLAGS,TIMER             ! send GET command
```

```
   if STATUS <= 0 goto ERROR
```

```
LOOP:                       ! retrieve the home page, one buffer at a time
```

```
   FLAGS = 0                ! retrieve one packet at a time (up to BUFFER size)
```

```
   xcall TCPX,4,STATUS,BUFFER,SOCKPORT, FLAGS,TIMER
```

```
   ! depending on how remote side closes socket, we may get STATUS 0 or -10054...
```

```
   if STATUS = 0 or STATUS = -10054 goto DONE               ! remote side closed
```

```
   if STATUS < 0 goto ERROR
```

```
      <process page text in BUFFER>
```

```
   goto LOOP
```

```
DONE:
```

```
   xcall TCPX,6,STATUS,BUFFER,SOCKPORT   ! close
```

```
END
```

A-Shell Reference 

Page 4043 

The GET command syntax above is an HTTP 1.0 "Simple Request", which is a generally deprecated form, although nearly all web servers will support it. Refer to the RFCs for HTTP (such as RFC 2616) for full specifications on the HTTP protocol. The point of the example is just to demonstrate how simple (and text-oriented) many of these Internet socket-based protocols can be. 

A slightly more complicated example can be seen by looking at the detailed log file created by the EMAILX.SBX routine, which will show the exchange between a mail client and an SMTP server. As with the HTTP protocol, SMTP is based on simple CRLFterminated text commands. 

If you need design a protocol for a server that will be accessed by "foreign" (non-A-Shell) clients, you may want to follow the model of protocols such as HTTP and SMTP and base them on CRLF-terminated text lines. Although human-readable text-based protocols may seem slightly less "efficient", this is really not much of a concern because of the substantial packet overhead suffered by small packets. For example, the smallest possible Ethernet IPv4 packet is 68 bytes, so there is little point in trying to compress your command lengths down to a few bytes, unless you can pack many of them together in a single packet. On the other hand, there are several significant advantages to text-oriented protocols, including: 

- They are easier to document. 

- They are easier to debug. (A simple text log of all data sent and received tells all.) 

- You can test the server side using Telnet as a client. 

A-Shell Reference 

Page 4044 

## **SBX SUBROUTINES** 

## **Short Description** 

An SBX Subroutine is a program with three distinguishing characteristics. It is: 

- Written in A-Shell BASIC like any other program. 

- Compiled with the /X:3 switch, resulting in an extension of .SBX rather than the normal .RUN. 

- Called with XCALL or XFUNC and in all other regards treated as an internal A-Shell subroutine. 

## **General Description** 

One of the most powerful features of A-BASIC is the ability to call external subroutines using the XCALL statement. Not only are such subroutines useful for modularizing application development, they also encourage code reuse, and perhaps most importantly, they encourage the development of high-quality utility routines that can be shared by a wide cross-section of developers. 

Under A-Shell, subroutines are supported, but up until Build 779, they had to be written in C and then linked into the A-Shell executable. Although we make available, on a somewhat customized basis, the tools for developing your own subroutines in C, most would-be subroutine developers have been put off by the technical obstacles and have chosen instead to have us write their routines and then include them in A-Shell. This has resulted in 200+ subroutines being included in the standard A-Shell release, but it has limited the development of new subroutines, especially those that might be useful to more than one developer. It has also created an annoying situation in which minor enhancements to a subroutine require a new version of the A-Shell executable to be linked. 

To remedy these shortcomings and to encourage the development of new routines, A-Shell Build 779 introduced the ability to create your own subroutines in BASIC. These subroutines can be fetched dynamically from disk when they are called, and offer most of the normal advantages of subroutines (modularity and true argument passing) plus the additional advantage of being dynamically loaded and thus able to be updated and distributed independent of the A-Shell executable. 

Nearly everything said here about writing subroutines also applies to external functions which are invoked via XFUNC. 

## **Subtopics** 

- BASIC or C? 

A-Shell Reference 

Page 4045 

- Subroutines vs. Programs 

- Development Steps 

- File Handling 

- Error Trapping 

- Persistent Variable Storage 

- Runtime Resolution of Subroutine Names 

- External (XFUNC) Functions 

- SBX Parameter Passing 

- Memory Usage 

- Loading and Cacheing 

- Named Parameters in Subroutines 

- Calling SBX Remotely on ATE Client 

- Subroutines vs. Functions/Procedures 

A-Shell Reference 

Page 4046 

## **BASIC OR C?** 

Subroutines written in BASIC are much easier to develop and deploy, and thus BASIC will most likely be the language of choice for most future subroutines development. However, there are a couple situations where BASIC may not be the best choice. One is where the subroutine performs some low-level, execution-intensive, performance-critical function. Obviously, subroutines written in C (and compiled to machine code and then linked directly into the A-Shell executable) will execute more efficiently, both in the calling overhead and in the instruction execution cycle. This is probably not a major issue, since A-Shell executes so fast. But if you were writing a routine to, say, convert from ASCII to EBCDIC or even to sort an array, it would probably be noticeably quicker in C. (Fortunately, we already offer subroutines written in C for both of those functions.) 

The second situation where BASIC is at a disadvantage in subroutine development is where the subroutine needs access to internal A-Shell data structures or functions. However, in most of those cases, specialized knowledge of the data structures or functions is needed anyway, and thus we would be the most logical one to develop such routines. So this probably isn’t much of a practical restriction for developers in the field either. 

There is another difference between the way the two types of subroutines execute, but it isn’t obvious whether it is an advantage or a disadvantage. In the case of subroutines written in C, they execute as "true" subroutines, meaning completely within the calling process. In fact, there is very little difference between a BASIC function, such as INSTR() and an equivalent subroutine written in C. They both consist of a single run-time opcode token followed by a list of parameters, and they are both implemented internally in C, and execute completely within the execution environment and stack of the calling program. 

Subroutines written in BASIC, on the other hand, are loaded from disk (unless already in memory) and executed in a separate, temporarily allocated memory space. They are still part of the original process and original job, but they have a separate stack and separate BASIC environment, which starts from scratch at the start of the subroutine, just like it does when you CHAIN to a new program. It is in fact very similar to what happens when you use `xcall ASHELL,"RUN xxxxx"` (provided the 

OPTIONS=ASHELL_RUNSBR setting is present in miame.ini). The most obvious consequence of this is that regardless of how badly the subroutine screws up, there are only two ways it can abort the calling program. One is by explicitly calling a particular MIAMEX function (discussed below under "Use End to Return to Calling Program..."). The other is by crashing A-Shell itself, since the subroutine is running in the same instance of the A-Shell executable as the calling program was. (But we’d like to think that crashing A-Shell is more or less impossible, so we don’t need to dwell on this possibility!) Otherwise, regardless of how the subroutine ends, either gracefully or otherwise, it will release its resources and the calling program will resume at the next statement. Be sure to read the following topic on Error Trapping, which relates closely to this topic. 

A-Shell Reference 

Page 4047 

## **SUBROUTINES VS. PROGRAMS** 

Subroutines written in ASB are written and compiled just like normal ASB programs, except for a few differences. The first is that after compiling (which you must do with the /X:2 option), you must change the extension from RUN to SBX; better yet, use the ++PRAGMA SBX which automatically creates an SBX instead of a RUN. The extension "SBX" was chosen, rather than SBR, to eliminate confusion between machine language SBRs or XBRs for AMOS and ASB SBXs for A-Shell, particularly for dealers that distribute their application on both AMOS and non-AMOS platforms. The search path for SBXs is the same as that for RUN programs (i.e. current [p,pn], [p,0], BAS:), unless the system parameter OPTIONS=SBX_RUNDIR is set, in which case the [p,0] part of the search path is replaced with the location whence the current RUN file was loaded. 

Because of the SBX extension used by subroutines written in ASB, these routines are often referred to, elsewhere in this document or in other documents, as SBX Modules or SBX Routines or simples SBXes. 

The biggest difference has to do with parameter passing. Standard RUN programs do not receive parameters, except via the command line or via some indirect method (such as COMMON or a shared file.) Subroutines, on the other hand, generally receive parameters from the calling program, often updating one or more of them for return to the calling program. Parameter passing to/from SBXs is similar in concept to that to/from Functions and Procedures; see Subroutines vs. Functions/Procedures for a more detailed comparison. From the standpoint of the calling program, there is no difference in the way parameters are passed between a traditional subroutine and one that was written in ASB. But from the standpoint of the subroutine itself, special techniques must be used to retrieve and return parameters. These steps are actually analogous to the procedure used in - subroutines written in assembler under AMOS to process the parameters. In this case, however, you use special statements (X ARGs) or MIAMEX functions rather than system library calls (as with AMOS subroutines) or direct binding (as with many other languages.) 

Some other differences between SBXs and programs 

- SBXs must have a PROGRAM statement statement. Programs should, but it is optional. 

- Files opened within an SBX are not automatically closed at the end of the SBX unless the AS_SBXASRUN flag is set; see 

- XCALL ASFLAG. 

These and other differences and details specific to SBXs are explored in the following sections. But first, let's address the question of whether a single compiled program can act as both a program (RUN) and a subroutine (SBX). 

A-Shell Reference 

Page 4048 

There is no difference in the internal structure of a RUN file versus an SBX, so any differences between the two arise solely from the file extension and the way they are called or executed. It is not possible to XCALL a RUN file (since the extension is not part of the XCALL statement syntax; see Calling External Routines), but it is possible to RUN an SBX directly by specifying the SBX extension on the RUN command line, e.g. : 

```
.RUN FOO.SBX
```

Alternatively, you can create a simple wrapper command to use in place of RUN.LIT when you want to 'run' an SBX ... 

## `.SBXRUN FOO` 

... where SBXRUN.LIT essentially consists of VXCALL CMDLIN, although it might include other configuration logic, such as converting command line arguments (CMDLIN) into XCALL parameters. Note that the compiler expects the XCALL statement to specify a literal SBX name; in order to use a single statement to call an SBX whose name is not resolved until runtime we need to use the VXCALL variant. 

RUN programs typically input parameters from the keyboard or files, not from the command line, so the SBX would probably use the .ARGCNT system variable to determine whether it should act like a program or a subroutine. 

Most programs though are not launched via a command line, rather via CHAIN, which is a bit more finicky about syntax. In order to CHAIN to an SBX, you would need to specify the complete command line, e.g. : 

## `CHAIN "SYS:RUN FOO.SBX"` 

So the answer the question is yes; an SBX file can act as both a subroutine and a program, depending on how it is called. But except in the simplest cases, it will require some conditional logic to adapt to how it is being run. 

A-Shell Reference 

Page 4049 

## **DEVELOPMENT STEPS** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- PROGRAM statement 

- include (++) xcall.bsi 

- Retrieve Individual Parameters 

- Return Individual Parameters 

- Ending / Returning from SBX 

- Return with Function Value 

- Compile, Rename to SBX 

- Memory Considerations 

- Nesting of Subroutines 

A-Shell Reference 

Page 4050 

## **PROGRAM STATEMENT** 

_Rewritten August 2015_ 

## **PROGRAM** _**progname**_ **,** _**vmajor**_ **.** _**vminor**_ **{** _**vsub**_ **} (** _**vedit**_ **) {,** _**flag**_ **}** 

The optional PROGRAM statement statement embeds a header in the compiled object code (RUN, LIT, SBX) containing the specified version and flag. The version information may be retrieved both within the running program and from external program files, and is obviously very useful in keeping track of which versions of each module that you have installed or running. 

## **Parameters** 

## _progname_ 

name of the program (1-10 RAD50-compatible characters). Note that it doesn't actually get embedded in the compiled code though, so it mainly servers as a source code documentation. 

## _vmajor_ 

major version (0-255). 

## _vminor_ 

minor version (0-15). 

## _vsub_ 

sub-version (A-O). 

## _vedit_ 

edit number (0-4095). 

## _flag_ 

optional flag, default is -1. The only allowed value other than -1 is -2, which causes the program to be allowed to run even if the job is not currently logged in. This is necessary for LOG.LIT, and is otherwise convenient for command programs which may be 

A-Shell Reference 

Page 4051 

specified directly on the ashell startup command line. Note however that such a program should then use XCALL LOG or some equivalent mechanism to establish a current directory before accessing files. 

## **Examples:** 

```
program MYPROG,1.0(100)
```

```
PROGRAM anotherprg,234.15B(4001),-2
```

## **Comments:** 

Given the fairly large range of _vedit_ values (0-4095), it's a useful convenience to treat it as unique identifier for source code changes, leaving the _vmajor_ , _vminor_ and _vsub_ values to be used for higher level purposes (marketing, general releases, etc.) Both of the program editors VUE and APN have macro functions to help streamline the process of associating changes in the edit number with source code comments which programmers should take advantage of. For VUE, the command is Control+_ E, which increments the _vedit_ number in the program statement, if found, or in a comment consisting of ";VEDIT=###", and inserts an edit history node. For APN, you can define your own macro via the Text Clip system. The standard release comes with two related macros, "prog" for creating a skeleton program header and "eh" for entering a new edit history item. 

## **See Also:** 

- DIR.LIT: /V switch to display program file versions 

- GETVER:  get version of current running program 

- SOSLIB:[907,10]:Fn'FileVer get version from file 

- VERSYS.LIT: additional version info 

A-Shell Reference 

Page 4052 

## **INCLUDE (++) XCALL.BSI** 

You should ++INCLUDE ashinc:xcall.bsi at the start of your subroutine. This file is included in the standard A-Shell release (see notes on ASHINC), and includes some symbols and MAP statements which are used by the parameter passing routines. It will set the variable `XCBCNT` to the number of parameters passed to the subroutine, and will set up the following array structure with the types and sizes of all the parameters: 

```
map1 XCBCNT,f,6                    ! # of parameters passed
```

```
map1 XCBSTRUCTX
```

```
   map2 XCBSTRUCT(30)              ! (max of 30 params to xcall)
```

```
      map3 XCB'PTYPE,b,2           ! (0=X, 2=S, 4=F, 6=B,+16=array)
```

Since this BSI includes code as well as MAP statements, you must position it so that comes before any executable code in your subroutine that deals with parameters. Note that it is not strictly necessary to ++INCLUDE xcall.bsi, unless you plan to use the MX_XCBDATAX routine for parameter passing, or you want to know the number and types of parameters that were passed. 

A-Shell Reference 

Page 4053 

## **RETRIEVE INDIVIDUAL PARAMETERS** 

Explicit statements or calls must be made to retrieve the parameters passed to the SBX routine. This may seem like an extra step compared to languages, like C, which handle the parameter passing more directly (by setting it up at compile time). But it is actually similar in concept to the higher level, runtime-adaptable interfaces like ActiveX/COM, which provide the flexibility for the modules to examine their own interfaces at runtime. This adds a little overhead and some complexity, but allows the external modules to be much more resilient to version changes in one side independent of the other. For example, a subroutine may be designed initially with 3 parameters, but later additional features may be added that require another parameter. The updated subroutine can still work with older programs since it can see that only 3 parameters were passed and act accordingly. In fact, the older version of the subroutine can even still work with newer programs, since the additional parameter can be ignored. Or, it can report to the caller that there seems to be a version mismatch. All this makes it much easier to develop reusable subroutines independent of the applications that use them. 

There are two different methods for retrieving parameters. The older method (deprecated as of Build 903 but still supported) uses the following subroutine: 

## **xcall MIAMEX, MX_XCBDATAX, xcbadr, xcbget, <parm#>, <variable>** 

`MX_XCBDATAX` is a constant, defined in ASHINC:XCALL.BSI, specifying the opcode to MIAMEX. The first `<parm#>` is 1 (not 0.) The `<variable>` you specify should be mapped in a way that is "reasonably compatible" with the actual type and size passed to the subroutine, although conversions and truncations will be applied automatically if necessary. `XCBADR` is a pointer to the parameter list, and is set up automatically by xcall.bsi. XCBGET is another constant, also set up by xcall.bsi, which indicates the operation (get vs. put.) 

The new method (Build 903+) uses one or both of these special Basic statements: 

## **XGETARGS ARG1{,ARG2,...ARGN}** 

## **XGETARG <arg#>,ARG** 

The first statement (XGETARGS) retrieves (some or all of) the subroutine arguments into the corresponding variables. (The first argument is returned in ARG1, the second in ARG2, etc.) If more args were passed than you specify variables for, the extra arguments are ignored. Conversely, if you specify more ARG variables in the XGETARGS statement then were passed by the caller, the excess ARG variables are ignored. In either case, the operation is non-destructive to the original argument list, so you 

A-Shell Reference 

Page 4054 

can later go back and retrieve (or re-retrieve) parameters using XGETARGS, XGETARG, or the original MX_XCBDATAX statements. `XGETARG <arg#>,ARG` performs the same function as XGETARGS except that it retrieves only the one argument (whose number is specified in <arg#>, with the first parameter being #1). 

As with the original MX_XCBDATAX operation, variable type and size conversions will be made as necessary, within the bounds of reason. 

If the subroutine supports different, incompatible parameter calling formats, it can examine the parameter count, type, and size information provided in the XCBCNT and XCBSTRUCT variables set up by ASHINC:XCALL.BSI and then use the appropriate XGETARG or XGETARGS statements. 

A-Shell Reference 

Page 4055 

## **RETURN INDIVIDUAL PARAMETERS** 

After you have done all of your processing, to return any individual parameters to the calling program, use one of the following.: 

## **xcall MIAMEX, MX_XCBDATAX, xcbadr, xcbput, <parm#>, <expression>** 

## **XPUTARG <parm#>,<expression>** 

Both methods are supported, but as of Build 903, the XPUTARG statement is preferred (and is more efficient). Note that unlike the retrieve parameter statements where you must specify actual variables to received the parameters), the "put" parameter statements allow you to specify a variable or an expression. 

A-Shell Reference 

Page 4056 

## **ENDING / RETURNING FROM SBX** 

The SBX routine will end and return to the calling program when it hits any of the following: 

- An END statement. 

- The physical end of the SBX. This is not very good form, but acts the same as END. 

• A RETURN (<EXPRESSION>) statement. This is a special form of the RETURN statement used to return from a GOSUB, which takes an expression argument in parentheses. If the SBX was called as a function, via XFUNC or XFUNC$, then the <expression> is returned as the value of the function, and should be a numeric or string expression according to the way the routine is intended to be used. See External (XFUNC) Functions for details on writing and using SBX routines as functions. If the SBX was called via XCALL or VXCALL, then the <expression> is discarded and the statement treated just like END. 

The only other option would be to abort directly to the dot prompt (without returning to the calling program), which you can do with the following statement: 

```
xcall MIAMEX, MX_EXIT
```

A-Shell Reference 

Page 4057 

## **RETURN WITH FUNCTION VALUE** 

As of Build 828, you may also return from an SBX routine using a special form of the RETURN statement: 

## `Return(<expression>)` 

This statement sets the return value of the function if the SBX was called via XFUNC. If the SBX was called via XCALL or VXCALL, then the <expression> is just discarded and the statement acts like the END statement (i.e. returning to the calling BASIC program). 

See the subsequent topic  for more details on external functions. This is an A-Shell extension and requires that you compile with the /X:2 switch. 

A-Shell Reference 

Page 4058 

## **COMPILE, RENAME TO SBX** 

Compile the subroutine as you would any other BASIC program, and then rename the RUN module to SBX. You may want to relocate it to the [p,0] or BAS: account if you want to be able to access it from other [p,pn]’s. 

You may want to create your own DO file, e.g. comsbx.do, which compiles your SBX modules and renames the resulting .RUN file to .SBX. 

You may also want to always compile with the /X:2 switch (for A-Shell extensions to A-BASIC.) This is mandatory if you use the XGETARG or XPUTARG statements, but even if you don’t, it clearly marks the resulting module as not being compatible with AMOS, eliminating any possibility of confusion by accidentally executing it under AMOS. 

It is also recommended that you use the /M switch (to enforce mapping of all variables.) This is good programming practice in general, but is particularly useful in subroutine programming where it will quickly point out two of the most common subroutine programming errors, forgetting to ++INCLUDE ASHINC:XCALL.BSI, and misspelling one of the constants such as XCBGET, XCBPUT, MX_XCBDATAX, and MX_EXIT. 

As an alternative to manually renaming the .RUN to .SBX, you can specify the following pragma: 

## `++PRAGMA SBX` 

Or, you can compile with the /X:3 switch, which is like /X:2 but automatically invokes the ++PRAGMA SBX feature. In either case, the output of the compilation will be an SBX rather than an SBR. 

Compiling a new SBX doesn’t necessarily replace one that is loaded into user memory! Always do a DEL * to force a fresh copy to be loaded from disk. 

A-Shell Reference 

Page 4059 

## **MEMORY CONSIDERATIONS** 

The default amount of memory available to these subroutines is 360K, but this figure may be changed using the MEMORY statement in the system configuration file. If the current memory partition has sufficient room, the SBX will use that memory like subroutines do under AMOS. Otherwise, a new, temporary partition will be allocated. 

Although memory allocation is fast, if you are concerned about minimizing SBX calling overhead, you would be advised to make the main memory partition large enough so that the SBX memory can be taken from it. For example, if your SBX routines can get by with 360K, and your largest RUN program requires 400K of working memory, then if you set your memory partition size to more than 760K, the SBX routine will be able to share the same memory allocation with the calling program. (Of course, nesting SBX calls would require successively larger partitions to avoid the automatic temporary memory allocations.) To determine how much free memory is available, use the mem(0) function within a running program. To trace memory allocations in the ashlog.log file, use SET TRACE MALLOC ON before running your program. 

A-Shell Reference 

Page 4060 

## **NESTING OF SUBROUTINES** 

As should be obvious from the fact that these subroutines themselves use MIAMEX for parameter passing, it is possible to nest subroutine calls, regardless of whether the subroutines are written in BASIC or C. Each level of nesting, though, does use up memory and stack space so it is not recommended that you get too carried away with nesting, particularly with highly recursive subroutine calls. 

If you are planning to nest subroutines, for maximum speed it is best to make sure the main memory partition has enough free space for the minimum SBX memory, plus the actual amount of SBX memory required for the number of levels of nesting. As long as there is sufficient free memory available in the partition for the minimum requirement (360K or as specified by the MEMORY statement), then it will actually only use as much as is needed. So for example, if you have 500K free in the main partition and your SBX minimum is 360K, the first SBX call will simply take over the 500K available. But if the subroutine is small, it might only use up, say, 30K of that 500K, leaving 470K free for the next level down. You could repeat that process severa levels deep before the original 500K was used up, after which separate system memory allocations would have to be made for subsequent levels. 

A-Shell Reference 

Page 4061 

## **FILE HANDLING** 

SBX modules can access files pretty much just like any other program. There are some subtleties, though, with respect to the relationship between the files opened within an SBX module and those opened by the calling program or module. This section discusses those issues. 

## **Subtopics** 

- Accessing Open Files 

- File Open Persistence 

- File Auto-Close Behavior 

- File Channel Conflicts 

A-Shell Reference 

Page 4062 

## **ACCESSING OPEN FILES** 

Although SBX routines start with a fresh memory partition, they inherit the table of open files from their parent. This allows the subroutine to read and write to files that have been opened by the calling program. However, because of this, if you want to open and close files within the subroutine independently from the calling program, then you must be careful to use different file channel numbers. 

It would probably be a good idea to adopt some systematic approach to the use of file channels, such as reserving file channels 60000-65000 for use within subroutines. 

For sequential files (opened for INPUT, OUTPUT, or APPEND) no special techniques are needed to access the files opened outside of the subroutine. You can use PRINT #CH and INPUT #CH statements just as if you had opened the specified file channel (#CH) within the subroutine. 

For random (contiguous) and ISAM files, however, the problem is that the file number variable, which was associated with the file when the file was opened, is only accessible from within the module that opened the file (i.e. the module that owns the record number variable.) So, in the case of random files, while you could access them, you could not change the record number (and thus would only be able to read and write whatever record was last accessed in the calling module). In the case of ISAM-A files, you would be able to move around in the file because this is based on key operations, but you would not be able to get the status back for each operation. To surmount that obstacle, you can call a special MIAMEX function to associate a new recordnumber variable (and in the case of ISAM, a status variable) with the file: 

## **xcall MIAMEX, MX_FLSET, ch, status, recvar'adr {,statvar'adr}** 

This function assigns a new (local) record number variable and optionally, ISAM-A status variable, with the file opened by the calling program on channel CH. Note that the parameters have to be mapped in a specific way; see MX_FLSET for details. 

Once you successfully execute the MX_FLSET operation, you can have full access to the RANDOM, ISAM, or ISAM-A file within the subroutine. 

## **Comments** 

See XREAD, XWRITE, XUNLOKR for an alternative which avoids the need for MX_FLSET. 

Don’t forget that the record number and ISAM status variables to be used within the subroutines are the ones whose address(es) you pass to the MX_FLSET subroutine, and not the ones that were originally used in the calling program. Otherwise, you may 

A-Shell Reference 

Page 4063 

appear to be reading and writing the file normally within the subroutine, but you will either be reading and writing the same record over and over again (i.e. the last one accessed by the calling program) or in the case of ISAM-A, you will be accessing the file but never getting any valid status results back. (Every key operation would return 0 for ISAM’EQ, since the real return value would be sent to the variable in the calling program.) 

Also, be careful of FILEBASE. You may safely ignore this for ISAM-A files where you may never explicitly use the record number, but for RANDOM files, you would ideally want to make sure that the subroutine was written to use the same FILEBASE as the calling program. But unfortunately there is no way to guarantee this. The effective FILEBASE is the one that was in effect when the file was opened; there is no way for the subroutine to override this other than closing and reopening the file. 

A-Shell automatically resets the record number and ISAM status variables to their original values on return from a subroutine call, so it is not necessary for the calling program (even if it is itself an SBX routine) to worry about what the subroutine may have done to its file control variables. 

A-Shell Reference 

Page 4064 

## **FILE OPEN PERSISTENCE** 

There are a few ramifications of the fact that files remain open across subroutine calls that you should be careful of. One is that it works both ways. That is, files that are opened within a subroutine remain open (unless explicitly closed or the AF_SBXASRUN flag in XCALL ASFLAG is set) when the subroutine returns to the calling program. So, for example, you could create an "open file" subroutine whose job was to figure out _which_ file to open and then returned the file channel number. Then, the _calling_ program would have to use MX_FLSET as described above to hook its control variables to the file. 

A second ramification is that a file opened by the main program and closed by the subroutine remains closed when the subroutine returns to the calling program. This would surely be a dubious programming technique, but is still worth watching out for. Of course this also works both ways: a file opened in the subroutine may be closed in the parent program. 

A third ramification derives directly from the previous one but is much more useful: a file opened in a subroutine may remain open across multiple calls to the subroutine. For example, if you have a subroutine that reads a single response from a serial port under Unix, rather than opening and closing the file on each subroutine call, or opening the file in main program even though it is only accessed in the subroutine, you may decide to open it the first time the subroutine is called, but just leave it open in case the subroutine is called multiple times. 

This raises the question of how to tell if a file is open on a specified channel. The answer is the `EOF()` function. `EOF(CH)` (where `CH` is the file channel number you are inquiring on) will return negative one if the file is not open. Otherwise, it will return 0, or possibly 1 (to indicate a sequential input file at EOF). 

Because these persistence issues are invitations to confusion, it is a good idea to think through your SBX-related file access strategy with an eye towards simplicity. 

If you open a RANDOM, ISAM, or ISAM-A file within an SBX routine and then wish to access it in a later call to that routine, you should repeat the MX_FLSET operation to reset the file’s control variables. This is not necessary for sequential files which don’t have control variables, but is essential otherwise, since the control variables are referenced by the file table via their address in memory, and that address is almost certain to change with each call to the subroutine. 

## **See Also** 

- File Auto-Close Behavior 

A-Shell Reference 

Page 4065 

## **- FILE AUTO CLOSE BEHAVIOR** 

_Created July 2015_ 

Revisions to file auto-close behavior with respect to SBXs: 

- ASQL connections are auto-disconnected using the same set of rules used for the auto-closing of normal files. 

- By default, files and ASQL connections are auto-closed only when a RUN file terminates—i.e. not on return from an SBX. 

- If the AF_SBXASRUN flag in XCALL ASFLAG is set at the time a file is opened within an SBX, that file will be auto-closed (or auto- 

- disconnected for ASQL) when the SBX returns. Note that while this behavior is intended as a convenience for unexpected aborts within an SBX, auto-disconnecting an ASQL connection does not auto-close the ASQL library itself. That probably won't matter to the application, but may prevent the library from being unloaded until the A-Shell process finally terminates. 

- In a nested SBX call (where an SBX calls another SBX), if the AF_SBXASRUN flag is clear when the file is opened, then it will be 

- auto-closed or auto-disconnected on return from the last SBX that was called with the flag set. For example, if A.RUN XCALLs B.SBX, which sets the AF_SBXASRUN flag and XCALLs C.SBX, which clears it, then any files subseuqently opened in C.SBX will be closed when B.SBX (not C.SBX) returns. 

## **History** 

- 2015 March, A Shell 6.1.1405:  Add feature to A-Shell 

A-Shell Reference 

Page 4066 

## **FILE CHANNEL CONFLICTS** 

When you want to open a file within an SBX that has nothing to do with the calling program, one concern is how to select a file channel that is guaranteed not to be in use already. The best way to do this is to start with a suitably high file channel (one not likely to be used by the calling programs), and then just to be safe, use the EOF() function to verify that the channel is free, incrementing the channel if necessary until a free one is found. For example: 

```
FCH = 50000                    ! start with a high file channel
```

```
    do while eof(FCH) = 0      ! keep looking until we find a free channel
```

```
    FCH = FCH + 1
```

```
loop
```

```
open #FCH, FSPEC, output
```

```
...
```

A-Shell Reference 

Page 4067 

## **ERROR TRAPPING** 

Since subroutines written in ASB have their own execution environment, they do not share the error status conditions or error trapping of the calling program. Thus if an ASB error aborts the execution of the subroutine, causing it to end, it will still return to the calling program, which will have no idea that the error occurred in the subroutine. Thus, it is nearly essential that you implement an ON ERROR GOTO in the subroutine, as well as some means of passing error conditions back to the calling program (such as with a "STATUS" parameter in the subroutine parameter list.) If you aren’t going to pass a status parameter back to the calling program, it may be best to use MX_EXIT to abort to the dot prompt. 

If you don’t trap errors within your subroutine and an error occurs, the standard ASB error message will be printed and the subroutine will return to the caller. However, since this is very likely to go unnoticed by the user, A-Shell will delay for a few seconds after displaying the error message, to give you at least some chance of being able to diagnose the condition. 

You can force the ^C condition to be passed back to the calling program using: 

```
xcall ASFLAG, AF_SETCTRLC      ! (128) set ^C on return from sbx
```

A-Shell Reference 

Page 4068 

## **PERSISTENT VARIABLE STORAGE** 

Sometimes it is useful for an instance of an SBX to be able to store some data for a subsequent instance of the SBX to be able to use. There are several ways to accomplish this: 

- Pass the data back to the caller in a parameter, and have the caller then pass it back to next invocation of the SBX. The 

- downside of this is that you burden the calling program with caring for data which it otherwise has no use for, reducing the degree of data encapsulation offered by the subroutine. 

- Store the data using COMMON[XS] . This can work for small amounts of data, but one problem here is that COMMON is subject to 

- various global configuration options, which will interfere with the ability to use your SBX in different environments (i.e. reduces portability). 

- Store the data in a file. This avoids both of the issues listed above, but introduces a couple of its own. A minor issue is that 

- storing data in a file is somewhat less efficient than memory based schemes, so might add significantly to the performance overhead of an SBX. A larger one is that in order to allow for each job to have its own inter-SBX storage facility, you’ll probably have to incorporate the job number or name into the storage filename, which means that you might end up creating a large number of files. And since the SBX can’t guarantee that the caller will give the SBX an opportunity to clean up after itself, you might end up littering the disk with files that have no meaning to the application (thus making it hard to know whether they can be deleted or not.) (You could reduce the file count by storing each job’s data as a record within a single file, but this introduces issues associated with maintaining the structure of the file.) 

- Store the data in user memory. This avoids all of the problems above. It doesn’t impose any responsibility on the calling 

- program, assume anything about the environment, or add any disk I/O overhead. And, it is self-cleaning, since user memory modules are automatically deleted when an instance of A-Shell exits. So this would be the recommended method for most cases, provided you can count on A-Shell build 916 or higher. The following excerpt of sample code illustrates the technique. 

```
map1 LOCAL'STORAGE             ! variables internal to SBX but needed between calls
```

```
   map2 VAR1,S,100             ! arbitrary variables used by the SBX
```

```
   map2 VAR2,F,6
```

A-Shell Reference 

Page 4069 

```
map1 MODNAME,S,14,"SBX99.MEM"  ! arbitrary module name
```

- `!  To save the data in LOCAL'STORAGE for a subsequent instance of this SBX...` 

```
      xcall MIAMEX, MX_USRLOD, idx, modname, usrmem'nofile, local'storage
```

```
      if IDX <= 0 then goto UNABLE'TO'STORE'USRMEM   ! (error)
```

- `!  To retrieve the data from user memory into LOCAL'STORAGE...` 

   - `xcall MIAMEX, MX_USRIO, status, modname, 0, local'storage` 

- `!  To update the data in the user memory module directly from LOCAL'STORAGE,` 

- `!  (without deleting / recreating the module as with MX_USRLOD)...` 

   - `xcall MIAMEX, MX_USRIO, status, modname, 1, local'storage` 

- `!  To delete the module explicitly...` 

   - `xcall MIAMEX, MX_USRDEL, idx, modname` 

Prior to build 916, you could still use this strategy but would have to first create a sequential disk file in order to load it into memory. Also note that if you want to protect the module from being deleted inadvertently, you can use FLAGS argument to the MX_USRLOD and MX_USRDEL routines to lock and explicitly unlock the module. 

A-Shell Reference 

Page 4070 

## **RUNTIME RESOLUTION OF SUBROUTINE NAMES** 

_Revised May 2023_ 

While XCALL requires a literal subroutine name, the otherwise-similar VXCALL statement accepts a string variable or expression, thus allowing the subroutine name to be resolved at runtime rather than compile time. For example: 

```
map1 SBRNAM$,S,6,"HELLO"
```

```
VXCALL SBRNAM$,ARG1,ARG2,...       ! (xcall HELLO,...)
VXCALL "HELLO",ARG1,ARG2,...       ! (xcall HELLO,...)
VXCALL SBRNAM$+"1",ARG1,ARG2,...   ! (xcall HELLO1,...)
```

As with other A-Shell extensions to Basic, you must compile your programs with the /X:2 switch to enable the use of the VXCALL statement. 

VXCALL can be used equally well with embedded subroutines (those written in C and linked into A-Shell) and external SBX routines. However, its usefulness is magnified in the case of SBX routines, providing an almost open-ended mechanism to customize application behavior at runtime. The following examples will help illustrate this. 

First, let’s consider an invoicing module installed in many businesses. Unfortunately, many businesses are particular about their invoices, perhaps requiring a special form, or wanting their own logo, or custom messages to be printed at the bottom, etc. Rather than having to include a bunch of "IF" conditions and a bunch of different routines within the invoice program (with only one being used at a particular site), you could just design your invoice program to assemble the necessary line items and header information into a standardized structure, and then pass it via RXCALL to an invoice formatting subroutine whose name was a function of the site or client ID. For example: 

```
map1 INV'DATA            ! (uniform structure with invoice data)
```

```
   map2 INV'HDR'DATA
```

```
      map3 ...
```

A-Shell Reference 

Page 4071 

```
      map3 ...
   map2 INV'LINE'ITEMS(500)
      map3 ITEM'NO,S,10
      map3 ...
<load up INV'DATA structure...>
```

```
VXCALL SITE'ID$,OPCODE'INV,INV'DATA    ! (format & print invoice)
```

In the above example, we are passing an "opcode" variable to the SITE’ID$ subroutine to allow for the possibility of combining several different customization functions within a single subroutine. The developer/distributor of the software could then release source code to a standard version of the customization module (renamed to match the SITE’ID$), and allow each site to customize it as they choose. The fact that the A-Shell runtime system contains the compiler, and that the linking and binding for such subroutines is all done at runtime, makes this particularly feasible. Naturally, there would be a training issue, but in some cases that might create an opportunity to engage the customer’s desire for customization and earn additional revenues at the same time. Even if the developer/distributor does all the customization on behalf of the client, this mechanism provides a very useful mechanism for modularization, isolating the code that is site-specific, from the core of the application. 

As a second example, consider the COMMAND=SBX:<sbxname> parameter in the A-Shell printer initialization files. Briefly, what this statement does is cause the print spooler interface to pass the print file to the specified subroutine for processing, either before or in lieu of sending it to a printer. Without the VXCALL mechanism for binding the subroutine name at runtime, this would be impossible. 

As a third and final example, VXCALL opens the possibility for the creation of a generic front-end subroutine that handled some kind of pre-processing or interfacing function that you wish to apply to a range of subroutines, some of which you may not have the ability to modifiy directly because they are embedded within A-Shell. Why would you want to do such a thing? One reason might be for security or licensing. Let’s say you have a series of data access or display subroutines, and then your industry (for example, the health care industry) decides to impose (or the government forcefully imposes on them) a regime of strict security requirements to protect the privacy of data. One way to deal with such a requirement would be to develop a single security package that could then be wrapped around a variety of subroutines that had anything to do with data access. For example, if 

A-Shell Reference 

Page 4072 

you called your wrapper routine SECURE, you might use it with existing subroutines such as SERCH (to lookup records) and DSPLY (to format/display data) as follows: 

```
xcall SECURE,"DSPLY",XMAX,ROW,COL,DECMAL,OPTION,1
```

```
xcall SECURE,"SERCH",CH,REC,KEY,...
```

The observant reader will note that we didn’t use VXCALL in the above statements, but the point is that our hypothetical SECURE.SBX module would need to use VXCALL to call the routine specified in the first argument. Otherwise, we would need a different version of SECURE.SBX for every other subroutine we wanted to apply it to. 

Naturally, this approach introduces another layer of overhead on the underlying subroutines, but virtually all other industrystandard approaches to creating security wrappers around data objects involve substantial overhead as well. It should also be noted that the approach doesn’t provide a very thorough level of data security, since the data itself can presumably be copied and accessed by rogue parties, without using the hypothetical SECURE routine. To protect against that kind of access, you would have to encrypt your data, and build the decryption logic into the SECURE routine itself. 

## **Notes** 

- As with other A-Shell extensions to Basic, you must compile your programs with the /X:2 switch to enable the use of the 

- VXCALL statement. 

- Since the VXCALL subroutine name can be a string expression, and string expressions may contain parentheses, VXCALL 

- (unlike XCALL) does not support the alternate procedure syntax—i.e. enclosing the argument list in parentheses. 

- Similarly, because the VXCALL subroutine name is not resolved until runtime, it doesn't support DEFXCALL, named 

- parameters, or the APN call tips feature. 

## **See Also:** 

- DYNFUNC regarding runtime resolution of function names 

- XFUNC 

A-Shell Reference 

Page 4073 

## **EXTERNAL (XFUNC) FUNCTIONS** 

XFUNC() and XFUNC$() provide a means of calling external subroutines as if they were functions. 

## **XFUNC(Sbxnam, Arg1, Arg2,..., Argn)** 

## **XFUNC$(Sbxnam, Arg1, Arg2,..., Argn)** 

XFUNC (without the $) is a numeric function (i.e. evaluates to a floating point value), while XFUNC$ is for string functions. _Sbxnam_ is a string expression that evaluates to the name of the SBX module containing the function code. _Arg1_ through _Argn_ are arbitrary arguments or parameters to the function, analogous to the parameters in a subroutine statement. 

From the standpoint of the calling program, XFUNC and XFUNC$ may be used within expressions just like any other numeric function or string function, for example: 

```
PRINT XFUNC$("CENTER",Name$,40);
```

```
TOTAL = QTY * XFUNC(PriceFunc$,Part$,Cust$,QTY)
```

The SBX implementation of the function must end with a special version of the RETURN statement which specifies the value to return: 

```
RETURN (<expression>)
```

The `<expression>` should be numeric for functions to called by XFUNC(), and string for those called by XFUNC$(). This form of the RETURN statement will be treated the same as `END—` i.e. terminate subroutine and return to calling program—if the SBX was called via a subroutine statement. 

External functions may also return updated parameter values just like subroutines do. In fact, a single SBX module may act as both an external function and a subroutine. The distinction is just in how it is called (via XCALL, XFUNC or XFUNC$). 

## **See Also** 

- XCALL 

- VXCALL 

A-Shell Reference 

Page 4074 

- AG_XFUNC 

A-Shell Reference 

Page 4075 

## **SBX PARAMETER PASSING** 

Parameters can be passed to and from SBX routines. In most cases the mechanism, techniques and capabilities are essentially the same, whether we are talking about SBX routines or functions/procedures, although there are some syntax differences and limitations that apply to SBXs. 

In all cases the caller passes the parameters in a comma-delimited list as part of the call, with the compiler identifying the parameter types automatically.  On the receiving end, the SBX must use XARG Statements to retrieve them. Functions can do the same, but normally receive the parameters automatically based on the function declaration. To send parameters back to the caller, both SBXs and functions use XPUTARG. For example: 

```
! (In caller)
```

```
xcall MYSBX, arg1, arg2, ... argN   ! arguments passed to SBX
```

```
! (in MYSBX.SBX)
xgetargs var1, var2, ... varN       ! receiving the passed arguments within SBX
```

```
...
```

```
xputarg @var1                       ! sending var1 back to arg1
xputarg @var2=xyz                   ! sending xyx back to arg2
```

The above example illustrates the most typical situation, which involves passing of ordinary scalar parameters by value. The following subtopics provide additional details about more advanced aspects of parameter passing such as passing arrays, using named parameters, etc.  Note that the topics may apply to both SBXs and functions, with differences between them noted accordingly. 

- Named Parameters in Subroutines 

- Passing DIMX Arrays 

- Parameter Passing (Collections): Passing Collection Elements, Passing Collections 

- MLIST Parameter Passing 

A-Shell Reference 

Page 4076 

- Collections Passing 

A-Shell Reference 

Page 4077 

## **MEMORY USAGE** 

When an SBX routine is called, A-Shell ensures that it has available to it, at a minimum, the amount of memory declared in the second argument to the MEMORY statement in miame.ini. (If not specified, the default value is 360K.) If the amount of free memory in the current partition (this is the amount that the function mem(0) would display) is sufficient, the SBX takes over all of that free memory in the parent job. Otherwise, a new, temporary partition is allocated using the minimum size. 

Note that when SBX calls are nested, the amount of memory used up in each level is only the amount actually needed, not the full minimum as specified by the MEMORY statement. So, for example, if miame.ini has `MEMORY=1000K,500K` and you call a series of small nested subroutines, you may be able to stack them many levels deep (as opposed to just 2 levels as implied by the ratio of 1000K to 500K). However, once the amount of free memory in the main partition falls below the minimum (500K in this case), then each nested SBX call after that will allocate a separate 500K temporary partition which is freed up when the SBX returns. 

A-Shell Reference 

Page 4078 

## **LOADING AND CACHEING** 

When the RUN interpreter encounters a subroutine statement, it first checks to see if it refers to an embedded subroutine. If not there, it checks to see if there is a matching SBX loaded into the user's memory, either due to an explicit LOAD operation, MX_USRLOD, or an implicit prior load of the same SBX. If not in memory, a general SBX search is performed and if found, the SBX is loaded into user memory. 

If the SBX is already in memory, it can be reused directly without reloading. And any SBX loaded into memory this way will remain in cached in memory for a time, based on available space and usage patterns to avoid the overhead of having to constantly reload it from disk. This cache feature essentially eliminates the need to pre-load subroutines into memory. However, one potential problem with the cache mechanism is that in order to use an updated version of an SBX (newly compiled or newly copied to the target system), the old copy of the SBX must first be removed from memory. COMPIL.LIT will automatically do a DEL * to avoid confusion over this detail. Otherwise, when an SBX is called, A-Shell checks to see if the version available on disk is newer than the one in memory, and if so, automatically reloads it from disk. To reduce the overhead of this check to a negligible amount, the test is never performed more often than once per fifteen seconds for any single SBX. In other words, within fifteen seconds of copying a new version of an SBX into the search path, all calls to the SBX will begin using the new version. 

Note that the test is not "directional", i.e. it will reload the version on disk if there is any difference in the time stamp (newer or older), so you can roll back to a prior version the same way you update to a newer version. 

**Warning:** The search path used to compare the disk version to the memory version is identical to that used to actually load the subroutine from disk. If you intend to roll out a new version of the SBX and take advantage of the AF_SBXAUTOUPDATE feature, make sure that your new version appears before any older versions in the search path. And if, for some hard-to-imagine reason, you don't want users to immediately being using an updated SBX, don't copy it into the search path. 

A-Shell Reference 

Page 4079 

## **NAMED PARAMETERS IN SUBROUTINES** 

_Added January 2014_ 

As described in Named Parameters, you may use named parameters in conjunction with A-Shell functions and procedures. Parameter passing to subroutines is nearly identical to that for procedures and functions, so the implementation details are nearly the same. The main difference is that since subroutines do not have definition statements like functions and procedures do, a new statement had been introduced to allow you to define their parameter names and default values: 

## **DEFXCALL xcallname{+|,}pname{|alias}{=defval},pname{|alias}{=defval}...** 

DEFXCALL works similarly to FUNCTION and PROCEDURE definition statements, defining the names of the parameters, their order, and optionally default values. But there are several subtle differences, noted below: 

- Unlike functions and procedures, subroutine names are not case sensitive, so neither is the DEFXCALL statement. This applies 

- to the subroutine name and the parameter names, but not to the default values. The following two statements are therefore equivalent: 

```
DEFXCALL MSGBOX,MSG,TITLE="Warning",FLAGS
```

```
defxcall msgbox,msg,title="Warning",flags
```

- Immediately following the xcall name, you can use a "+" instead of a "," to create a definition specific not just to the xcall 

- name but to the combination of the xcall name with a literal string or numeric first parameter. This is particularly useful with some built-in subroutines like AUI and MIAMEX which have completely different syntax and semantics depending on the first parameter. For example: 

```
DEFXCALL AUI+AUI_ENVIRONMENT,opcode,guiflags
```

```
DEFXCALL AUI+AUI_EVENTWAIT,parentid,ctlid,exitcode,opflags,timer
```

```
DEFXCALL MIAMEX+MX_FSPEC,spec,locpath,ext,flags,ddb,status
```

A-Shell Reference 

Page 4080 

- You may define a single alias (alternate name) for any of the parameters. This is useful in cases where documentation or 

- usage evolution has resulted in a parameter having more than one common name. For example, to allow the first parameter to AUI_ENVIRONMENT to be called either opcode or opflags, we could define it as: 

```
DEFXCALL AUI+AUI_EVIRONMENT,opcode|opflags,guiflags
```

• As with function and procedure definitions, you can define default values for any parameters, and doing so converts all of the other parameters (those without defaults) to mandatory status. However, there are many existing internal subroutines which have a large number of optional parameters, making both named parameters and defaults extremely useful, which may determine semantics based on the number of passed parameters. 

To better align the declarative capabilities of DEFXCALL with the ways in which existing subroutines may have been implemented (hidden from view in most cases), another difference is that DEFXCALL supports an option to separate the parameter list into an initial mandatory group and a trailing optional group by enclosing the trailing optional group in {squiggly brackets}. For example: 

```
DEFXCALL TEST1,one,two{,three,four,five}
```

## Note that the {brackets} cannot be nested. 

In the above example, we are indicating that the last three parameters are optional, which has these important semantic sideeffects: 

- it makes the first three parameters truly mandatory, even if no default values are defined 

- for the parameters in the optional section, even those with defaults defined will be ignored unless the caller specifies one or 

- more parameters beyond that one. 

## A few examples will help clarify this: 

```
DEFXCALL TEST1,one,two,three,four,five
```

```
DEFXCALL TEST2,one,two=2,three,four,five
```

```
DEFXCALL TEST3,one,two=2{,three=3,four,five=5}
```

A-Shell Reference 

Page 4081 

```
DEFXCALL TEST4,one,two{,three=3,four=4,five}
```

All four routines have five defined parameters, but the semantics and requirements are different in each case. 

TEST1's parameters are all optional, because no defaults were specified, nor were {brackets} used to identify an optional section. 

TEST2's parameters are all mandatory, because there is at least one default defined, yet no {brackets} to mark the optional parameters. 

TEST3 has two mandatory parameters (one and two), and three optional parameters. The default specified for parameter two has no effect, since the parameter being prior to the start of the {optional} parameters, must be explicitly specified by the caller. The caller can specify 2, 3, 4, or 5 parameters (or more), but if parameter five is specified by name, then parameter four must also must also be specified, since it has no default and gaps are not allowed, even within the optional set of parameters. The default value for parameter five has no effect, since the parameters within the {optional} list are only passed to the routine up to the highest numbered parameter that is actually specified in the call. 

TEST4 is a more logical version of TEST3 in that it eliminates the two default values that had no effect in TEST3 (two=2 and five=5), and adds one that might be useful (four=4). The following call: 

```
XCALL TEST4,100,200,FIVE=500
```

would be considered legal—the two skipped parameters have defined defaults—and would be converted the equivalent of: `XCALL TEST4,100,200,3,4,500` 

## **History** 

- 2014 January, A Shell 6.1.1373:  Named parameters implemented in A-Shell. 

A-Shell Reference 

Page 4082 

## **CALLING SBX REMOTELY ON ATE CLIENT** 

SBX routines can be called remotely on an ATE client by implementing them as functions; see Call SBX as a Function. This can be a very useful and powerful technique to extend application functionality from the server to the workstation—or vice versa, e.g. to allow the application to take advantage of some functionality existing on the Windows workstation but not the Unix server. The main limitation in this technique is that unlike a local SBX, the remote SBX can directly return only a single value, i.e. the value of the function. But there are ways around that limitation. For example, you can encode multiple values into a return string which are then parsed by the application. Or, the remote SBX can create a file and FTP it back. 

One obstacle to overcome with remote SBXs is getting them installed on the client workstation in advance. This can be made simple by use of the utility function SOSLIB:[907,10]Fn'ATE'SBX(). 

A-Shell Reference 

Page 4083 

## **SUBROUTINES VS. FUNCTIONS/PROCEDURES** 

Both SBXs and user-defined functions and procedures—hereafter referred to collectively as functions—provide the ability to create reusable, parameterized code modules, giving rise to the question of which approach is better. As with most questions of that type, the answer depends on a variety of considerations, including personal preference. The following factors and comments may help you decide which is better for your situations. 

## **- Re usability** 

The most significant different between the two is that SBXs are entirely separate modules, essentially separate programs, loaded on demand—see Subroutines vs. Programs—while functions and procedures are compiled directly into a program. Re-usability of SBXs comes from the fact that once compiled and placed in the search path of the directory system, they are available for use by any program at run time. SBXs can be compiled and then distributed to other systems, even while there are active users potentially using those SBXs, and they will automatically detect and use the new version on the next call. Re-usability of functions comes requires using the ++INCLUDE statement to load them into your program at compile time, so if you need to update a function and distribute it, you will need to recompile all the programs using that function and redistribute all those programs. So SBXs have a big edge here in flexibility. 

## **Performance** 

Although SBXs are cached in memory, greatly reducing disk overhead for repetitive calls, there is still a lot more CPU and memory overhead in the calling process, compared to functions. As an example, a comparison test on an i7 Core laptop of a simple routine with several parameters, coded both as an SBX and as a function, yielded about 10 microseconds per SBX call, vs. about 1.5 microseconds for each function call. That's a difference of about seven times, but it may not be meaningful unless you need to call the routine hundreds of thousands of times. 

## **Memory Overhead** 

Each SBX execution instance requires it's own memory partition—see the System Parameter MEMORY—which typically needs to be at least about 500K. In comparison, each instance of a Function call needs only enough memory for the parameters and stack, typically less than 5K. So that's a huge (~100X) difference, but with the amount of memory on modern systems, perhaps not that significant either. 

## **Parameter Passing** 

A-Shell Reference 

Page 4084 

Both SBXs and functions have similar parameter passing mechanisms, and in fact use the same X-Args statements within the called routine. 

## **Global Variables** 

SBXs are not able to share any global variables with the calling program, except through external means such as files, common memory modules, parameters, etc. Functions, on the other hand, are able to share any variables with the rest of the program. However, this isn't really much of an advantage, since the use of global variables undermines the ability of either type of routine to encapsulate its internals and separate itself from the rest of your logic. 

## **Persistent Variables** 

Functions have a big advantage here in their ability to declare STATIC local and PRIVATE module-level variables which persist across calls. SBXs have no such capability except through external storage. 

## **File Handling** 

SBXs and Functions are roughly the same in the fact that they share the file table with the calling program. Any files opened by the calling program are accessible, assuming the file channel is made available to the routine, and any files opened within the routine remain open on return, unless explicitly closed. SBXs do support a global XCALL ASFLAG option to adjust that behavior, possibly giving them an edge in flexibility. 

## **Remote Execution on ATE Client** 

SBXs, being independent files loaded at runtime, have the ability to be transferred at runtime to the ATE client for remote execution, a trick which Functions cannot duplicate. See the module FNATESBX.BSI in SOSLIB:[907,10] for an easy way to facilitate such remote calls. 

## **Recursion and Nesting** 

Both SBXs and functions support recursion and heterogeneous nesting—mixtures of nested SBX and function calls recursive and otherwise—but the memory overhead is significantly lower in the function case, making deep nesting more practical. 

A-Shell Reference 

Page 4085 

## **MISCELLANEOUS TOPICS** 

A-Shell Reference 

Page 4086 

## **CACHE** 

_Written August 2023_ 

The concept of caching, storing of local copies of files to speed up repeated references, occurs in a variety of places and flavors within A-Shell and ATE. Although the details vary, the common goal is to improve performance by storing local or memory copies of files previously retrieved from a more costly, time-consuming or distant resource. A common operational feature is that they are automatically checked prior to retrieving / opening a file, whether specified explicitly or implicitly. 

See the subtopics listed below for details on the various types, names and functions of the cacheing systems used within A-Shell. 

## **See Also** 

- Cacheing SBX Subroutines 

- WEBCACHE setting in SET.LIT 

## **Subtopics** 

- ATEPERMCACHE 

- ATECACHE 

- ASWCACHE 

- WEBCACHE 

A-Shell Reference 

Page 4087 

## **ATEPERMCACHE** 

This is similar to the ATECACHE directory except that it is neither loaded nor cleared automatically. Applications may use this directory to permanently store resources (such as icons and other images) that are required by the application, often using ATSYNC to refresh / sync the directory at the start of each session. As with ATECACHE, the location (typically %ATE% \PermCache), is defined via the ATE Connection Properties dialog. ATE creates an environment variable, %ATEPERMCACHE% pointing to the directory, but does not ever clear it. 

A-Shell Reference 

Page 4088 

## **ATECACHE** 

_Revised August 2023_ 

Whenever files are transferred from the server to the client within an ATE session (e.g. printing and GUI display resources such as icons, images, etc.), they are cached in this directory. The directory location, normally %ATE%\Cache, is defined via the ATE Connection Properties dialog. ATE creates an environment variable, %ATECACHE% pointing to the directory, and automatically clears the directory at the end of the last concurrent session—unless it is defined to be the same directory as ATEPERMCACHE. 

## **History** 

- 2023 August, A Shell 6.5.1740:  ATECACHE directory now retains files for 96 hours after the last access as an optimization to reduce excess cache transfers. Previously the entire directory was cleared after the last ATE session the local machine exited 

A-Shell Reference 

Page 4089 

## **ASWCACHE** 

_Added August 2015_ 

To help alleviate the performance overhead when many image files or icons are loaded from a network file server, images may be automatically cached on the local workstation provided the following: 

- The environment variable ASWCACHE is defined and points to a valid directory. The directory will be created if it doesn't 

- exist, provided the parent directory exists. It can be anywhere, but obviously should be on a local drive. 

- The operation of loading the image file into memory takes more than 10 ms. This has been determined by limited testing as a 

- reasonable threshhold between typical performance of local disks and that of network disks. 

- AUI_CONTROL will automatically check the cache first whenever it creates an image control, eliminating the overhead of 

- reloading the file over the network if it is cached locally. 

## **Comments** 

Since the images are auto-cached as used, and auto-removed from the cache on exit, there is no need for any special management on the application's part—i.e. for manually syncing from the file server to the local workstation. However, since the benefit of the cacheing occurs starting with the second load of each image, it is only useful in applications which repetitively load the same images or icons, from a file server, many times during a session. 

An easy way to set the environment variable is via the MX_SETENV function, or SETENV.LIT, e.g. 

```
.SETENV ASWCACHE=C:\VM\MIAME\CACHE
```

**Warning:** Since the cache directory is cleared on exit, you must be careful not to use a directory containing permanent files!!!!!!!!! 

You can trace the cache logic by activating the FOPENS trace option. It shows the search operations, and also records how long the image load operation takes; look for "loadandresizex" in the ashlog.log or System Messages window, e.g.in the following, the load takes just over 16 ms (16001 microseconds), and thus would be auto-cached if the cache is defined. 

```
loadandresizex (\\SERVER\icons\BETA\clock.png), rc=0, himg=78dfd0 [16001 us]
```

## **History** 

A-Shell Reference 

Page 4090 

- 2015 June, A Shell 6.1.1412:  Add new enviornment variable to A-Shell 

A-Shell Reference 

Page 4091 

## **WEBCACHE** 

_Revised and Updated August 2023_ 

WEBCACHE is an A-Shell module that auto caches/downloads files from a web directory if not found in the local search path. Downloaded files are cached in the directory %MIAME%/webcache, which is checked first—as in a web browser—to avoid the overhead of unnecessary web accesses. As a special case, DLLs will be downloaded into the current executable directory (if write access available) so that they will found in the OS library search path. 

The feature is referred to under the generic umbrella of "WEBCACHE" and may be enabled and configured via a SET.LIT option and/or a MIAMEX function, both described below. 

Option flags determine which types of files are subject to the feature. By default it applies to images and any other kind of file operation that currently supports automatic lookup in the cache and permcache directories. Additional file/type options: 

|**Option**|**Description**|
|---|---|
|PROG|programs (RUN, LIT, SBX)|
|OPENI|files being opened for sequential input|
|LOOKUP|files reference by LOOKUP statement orXCALL SIZE|
|DLL|Windows DLLs referenced indirectly via XCALLS (e.g. HTTP, FTP2)|



The webcache directory, like the ATEPERMCACHE directory, is not auto-cleared at the end of the session. But like a typical web browser cache, it can be cleared with a command (in this case, SET WEBCACHE CLEAR). Also, as with a typical web browser, the existence of a file in the cache short-circuits any web lookup for that file.  However, there is no automatic comparison of file sizes 

A-Shell Reference 

Page 4092 

or dates between the cached copy and the web copy (because this would undermine the performance benefit of the cache). So you have to clear the cache in order to get a refreshed copy from the web repository. 

## **See Also** 

- Search Paths 

- SET.LIT options for WEBCACHE 

- WEBRUN.LIT 

- MX_WEBCACHE 

- AG_WEBCACHE 

## **History** 

## - 2016 October, A Shell 6.3.1529 and 1531: WEBCACHE function added to A-Shell. 

A-Shell Reference 

Page 4093 

## **SUBROUTINE WRAPPERS** 

_Written August 2023_ 

A-Shell includes approximately thirty functions that are implemented as both subroutines and as print tab statements. The print tab statements are of the form AG_xxx, e.g. `PRINT TAB(-10,AG_xxx)` , and the subroutines are either MX_xxx ( `xcall MIAMEX, MX_xxx` ) or AUI_xxx ( `xcall AUI, AUI_xxx` ). 

This dichotomy parallels the fact that applications operate simultaneously in two contexts:  server, where the application runs, and client, where the user interface is.  In a Windows environment, the server and client can be on the same machine; in ATE environments they are separate and may even be different operating system types. The print tab implementations always communicate directly with the client, but depend on the client supporting A-Shell extensions which is either A-Shell/Windows or ATE.  By contrast, the subroutine implementations operate on the server side, but may internally act as wrappers, if appropriate, by forwarding the command to the client via the print tab command and the client's response, if any, back to the application. 

In some cases the determination of whether to forward the command is automatic, such as where the server is Linux and the command only makes sense in a Windows environment, or where the client doesn't support the function. In others, there is a parameter allowing the application to make the choice. In general, the subroutine version is preferable because because of the extra intelligence and flexibility it provides, and because it eliminates the complication of having to use a timed input function to retrieve the client response. The tab functions on the other hand have the advantage with non-A-Shell servers or where there is no subroutine version, and in some cases may eliminate confusion or complexity when you are certain you want the command sent directly to the client. 

In addition to the explicit pairs of AG_xxx / MX_xxx statements noted above, there is also MX_AGWRAPPER. This subroutine can be used as a sort of universal MIAMEX wrapper for ATE commands that don't have specifically dedicated ones. 

Another related function is AGCMD.LIT, which provides yet another kind of wrapper—let's say a "command prompt wrapper"—for the AG_xxx functions. 

A-Shell Reference 

Page 4094 

## **CREATE DIRECTORIES FROM APPS** 

There is often some confusion around the topic of creating directories, generally relating to one or more of the following: 

- DevPPN-style vs. native-style syntax (e.g. DSK9:[23,4] vs /vm/miame/dsk9/023004 or C:\vm\data\dsk9\023004). 

- Checking if the directory exists, vs. creating it. 

- SYSTAT.LIT vs. native OS commands vs. XCALLs 

It's not possible to answer every related and imaginable question, but here are a few notes that might fill in the blanks for those unsure about the best approach (particularly since the various components may be scattered all over the documentation): 

**SYSACT.LIT:** One option for creating a directory (using AMOS-style syntax) is just to use SYSTAT.LIT, either manually or via a command file. This is the only method that includes the option to create a password for the directory. The main downsides are that: a) it's dangerous, since you can too-easily delete directories this way; and b) if you wanted to do it under program control, you'd have to create a command file and then shell out to it, which introduces a fair amount of additional complexity. 

**Checking if the directory already exists:** If working with AMOS-style syntax, you can use MX_CHKPPN. Otherwise, if your directory spec is already in native form, you can use MX_FINDFIRST. However, in either case, it isn't clear that there is any performance advantage to checking first if the directory exists, vs. just trying to create it. (The operation to create it will internally determine if it exists and just return with an appropriate status code.) 

**MX_MKPATH:** this is the most straightforward approach, regardless of operating system, but does require that you convert your directory spec to native syntax. To do that, you can use MX_FSPEC, but it requires that you set up some map statements and pay attention to several details. A simpler approach is to use the function Fn'FQFS$ in SOSLIB:[907,10], which takes a full or partial AMOS-style filespec or relative native filespec (e.g. ".") and returns the corresponding Fully Qualified native File Spec. 

As with MK_FSPEC, it may require a dummy file.ext (typically one uses "z.z"), which you can then strip from the end if you just want the directory, as is the case here. So here is an example of using Fn'FQFS$() and MK_MKPATH to create the AMOS-style directory "TMZ0:[15,37]": 

```
++include sosfunc:fnfqfs.bsi
```

```
...
```

```
MAP1 NATIVEDIR$,S,260
```

A-Shell Reference 

Page 4095 

```
MAP1 STATUS,F
```

```
...
```

```
NATIVEDIR$ = Fn'FQFS$("TMZ0:Z.Z[15,37]")[1,-5]    ! cvt to native and chop off "/z.z"
XCALL MIAMEX, MX_MKPATH, LOCAL, STATUS
```

```
IF STATUS # 0 and STATUS # -1 and STATUS # 183 THEN
    <handle error - unable to create directory>
```

```
ENDIF
```

Note that for Unix, the "directory already exists" error will be -1, while for Windows it will 183. 

Use MX_RMPATH to delete a directory. 

**HOSTEX:** Another option (again requiring a native spec) is to use XCALL HOSTEX to access an operating system shell command to check for and/or create the directory. (This will definitely require determining which platform you are on first so you can use the appropriate commands, and thus is probably less sensible than one of the above methods which will handle most of that problem for you.) Here we check for the existence of the TMZ0:Z.Z[15,37] directory under Linux and then create it if necessary. (Assume that we have already converted it to the native syntax using a technique like the one shown above.) 

```
MAP1 STDOUT$,S,200
```

```
...
```

```
XCALL HOSTEX,"stat "+NATIVEDIR$+" >/dev/null 2>&1",STATUS
```

```
if STATUS # 0 then
```

```
    XCALL HOSTEX,"mkdir "+NATIVEDIR$+" >&1",STATUS,STDOUT$
```

```
    if STATUS # 0 then
```

```
        ? "Error: ";STDOUT$
```

A-Shell Reference 

Page 4096 

```
    endif
```

```
endif
```

In the above code, we captured the _stdout_ and _stderr_ from the MKDIR command into the parameter STDOUT$ so that we could display the error message if the command failed. 

**DEVICEs:** In all of the above cases, there is an assumption that for the directory to be created, the parent already exists. The parent of a PPN under AMOS terminology would be called a DEVICE. These DEVICEs (which are just directories from the host operating system's perspective) may be created like any other directory. But in order to then reference PPNs within that DEVICE using AMOS-style syntax, the DEVICE must be defined in miame.ini using a DEVICE statement, which see for details. 

A-Shell Reference 

Page 4097 

## **EVENT TRACING** 

Aside from traditional PRINT statements to output traces to the main screen, ASB provides two separate channels for outputting debug and trace messages: a dedicated message window and the main system log, each described in subtopics below. 

## **Subtopics** 

- Message Window 

- ASHLOG 

A-Shell Reference 

Page 4098 

## **MESSAGE WINDOW** 

## **Opening the Message Window** 

To manually open the message window, use CTRL+SHIFT+DOUBLE-CLICK somewhere on the A-Shell window, preferably not on a control that might respond to a click. This will pop up a _A-Shell Developer Control Operations_ dialog, on which you can click the _System Message Window_ button. 

## To programmatically open the message window, use one of the TRACE Statements. 

The xxxx.OPEN statements are optional and mainly server to allow you to set the title on the message window. The xxxx.PRINT and xxxx.PAUSE statements will automatically open the message window if necessary. 

The <msg> and <title> arguments are each limited to a single string expression (which may involve string operations and functions but must rely on concatenation to assemble a compound string of many parts, rather than commas or semicolons as you can do with PRINT). They may also start with zero or more of the following special control variables: 

```
$# (displays the running message count as a message id #)
```

```
$T (displays the time in HH:MM:SS format)
```

```
$P (displays the program name in brackets, e.g. <MYPROG>)
```

For example, the following statement 

```
DEBUG.PRINT "$T $P The value of X is: " + X
```

would appear something like: 

```
11:25:01 <MYPROG> The value of X is: 25
```

## **Using the Message Window** 

The message window consists of a popup-dialog, initially positioned in the upper right corner of the screen, and filled with a multi-line text control, scrollable in both directions. 

A-Shell Reference 

Page 4099 

The messages displaying in the System Messages window originate from three sources: 

- Internal traces generated automatically by A-Shell when activated by the various TRACE flags (see TRACE options, the TRACE 

- system parameter, and the subroutines MX_GETTRACE, MX_SETTRACE. 

- TRACE.PRINT statements in the application 

- DEBUG.PRINT statements in the application when the DEBUG flag is set, which can be accomplished with the SET DEBUG 

- command, MX_DEBUG subroutine, or by clicking on the Set Debug Mode option in the System Messages window context menu as seen above. (The latter method is particularly handy as it allows activating DEBUG mode externally while running a program.) 

The user can move, resize, minimize or close the dialog using the typical mouse operations, without affecting the application. A right-click context menu is also supported, as shown above. 

The message window lacks the more advanced capabilities found in text editors, such as search, edit, file operations, etc. If you find yourself needing these functions, the recommended procedure is: 

- select the parts of interest, by clicking on individual lines or using Select All on the context menu 

- use Copy, also on the context menu 

- launch Notepad or another editor, and paste the copied messages into it 

- use the editor for searching, editing, saving, etc. 

Or, from the dot prompt, use vue %miame%/ashlog.log to access the logged copies of the messages appearing in the window. 

## **See Also** 

- TRACE_BEGIN and _END 

- EVTWIN 

## **History** 

- 2023 January, A Shell 6.5.1724:  Add context menu option to send ^C to the application, primarily as an aid to developers who may face the need to abort in awkward situations during testing. Unlike hitting ^C on the keyboard, this method bypasses 

A-Shell Reference 

Page 4100 

restrictions on the keyboard mode—i.e. locked or local mode only. In the ATE case, it also discards any currently queued output, allowing the effect of the ^C to be seen more rapidly in the output. 

Note that sending a ^C doesn't necessarily always abort the application. Possible exceptions would be where the applicaton has disabled it, or is trapping and resuming from it, or is in the middle of a GUI wait state. 

Also note this may leave the terminal in an indeterminate state requiring you to use the Settings menu to manually clear the kbd lock and/or reset the terminal, but but helps to work around situations where a combination of rapid output and a keyboard lock makes it otherwise impossible to abort an out-of-control program. 

## **Subtopics** 

- Properties 

A-Shell Reference 

Page 4101 

## **PROPERTIES** 

The Properties option on the menu pops up another dialog containing checkboxes corresponding to the various TRACE options in miame.ini or the SET.LIT TRACE options. At the top of the dialog is a master checkbox which controls whether any of the system trace messages appear in the _System Message Window_ . When the dialog is launched manually, by default the system trace option is set, in which case the display can be considered just a slightly more convenient version of the information also being sent to the ashlog.log file. When the message window is opened under program control, the system trace option defaults to off, since the likelihood there is that the program is going to control the information sent to the message window. 

If the system trace option is set, the remaining checkboxes allow you to turn trace options on and off for immediate effect, rather than having to set them globally in miame.ini or from the dot prompt; this makes it easier to turn on a lot of traces for a very short period in order to investigate something within a complex program. Another advantage of the trace window versus the ashlog.log is that the trace window contains only messages for the current instance of A-Shell. 

Note that any traces activated in the message window properties will also be output to the ashlog.log file. Turning them on and off this way allows for greater control than would be possible with SET TRACE or adding TRACE statements to miame.ini. 

A-Shell Reference 

Page 4102 

## **ASHLOG** 

_Updated December 2019_ 

A-Shell maintains a log of significant events in the file ashlog.log, which can be an invaluable aid in monitoring a system and tracking down problems after they occur. By default it is found in the directory where the miame.ini is located, but the optional LOGDIR directory in miame.ini can be used to put it somewhere else. The log automatically resets and archives several prior copies of itself (using ashlog.001, ashlog.002, up to ashlog.005) when it reaches approximately 10 MB. The log will contain any critical or unusual error messages, plus any of a wide variety of information messages that can be configured using system trace options, which may be set by any of the following methods: 

- TRACE statement(s) in miame.ini. It is recommend that all A-Shell installations have TRACE=BASERR,SIGHUP,INOUT as a 

- minimum. 

- TRACE options in SET.LIT (SET TRACE xxxxx ON/OFF) 

- MX_GETTRACE, MX_SETTRACE 

## Applications can also output directly to the ashlog.log file using MX_ASHLOG. 

## **Comments** 

All trace messages start with a date/time stamp, followed by [ppppp-jjj]<xxxxx:yyyyy:zzz> where ppppp is either the server process ID or the Windows client machine id, jjj is the job #, xxxxx is the program or command file being executed, yyyyy is the current SBX routine (if applicable), and zzz is the location counter within the program or SBX. In the case of Windows, the client machine id may have a :## suffix indicating the instance ## of A-Shell on that machine—i.e. to distinguish multiple client instances launched on the same machine. Note that the first few traces will show a job # of 0 since they occur before the job number is assigned. 

Many other messages may appear indicating either errors, warnings, or debugging details activated by one of the other TRACE options. Some of those can be quite verbose, but you can enable and disable them temporarily from the dot prompt using the TRACE options in SET.LIT command. 

Reviewing the log periodically is a good way of identifying issues that can be addressed before they become more serious. 

## **See Also** 

A-Shell Reference 

Page 4103 

- LOGDIR[SP] 

- TRACESP 

- EVTWINXS 

- TRACE options in SET.LIT 

- Subtopics listed below for more detail on selected ashlog messages 

## **History** 

- 2019 June, A Shell 6.5.1662:  Increase maximum size of each generation of the ashlog log file to 10 MB. Previous maximum filesizes were 3MB (Windows) and 5MB (Unix). 

- 2011 September, A Shell 5.1.1231:  All program (RUN/SBX/LIT) load errors are now logged to ashlog.log, mainly to improve the prospects for detecting and tracking problems. 

## **Subtopics** 

- TRACE=INOUT 

- TRACE=BASERR 

- TRACE=SIGHUP 

A-Shell Reference 

Page 4104 

## **TRACE=INOUT** 

_Added December 2019_ 

This setting is recommended for all A-Shell sites under all conditions. It generates the messages shown below noting the startup and shutdown of each session. 

## **- A Shell/Unix/ATSD startup:** 

```
26-Dec-19 09:56:23 [p103032-0]<:0> ----------------
```

```
26-Dec-19 09:56:23 [p103032-0]<:0> A-Shell 6.4.1556.3 launched on pts/37:103032 by fulano
```

```
26-Dec-19 09:56:23 [p103032-0]<ASTART:0> (ATE client 6.4.1547.7, machine=HDL-WKS-001:01, user=EZapata, ack=0,
fg,bg=6,0)
```

```
26-Dec-19 09:56:23 [p103032-0]<ASTART:0> jcbrebuild #0
```

```
26-Dec-19 09:56:23 [p103032-37]<ASTART:0> In: Nodes=72/76/173 [P], ip=192.168.3.211 0:e0:c5:53:d7:5c,
(fulano) inodes: si=0,sm=0 ...
```

## **- A Shell/Windows Startup** 

```
27-Dec-19 09:15:15 [JACKT450:03-0]<:0> ----------------
```

```
27-Dec-19 09:15:15 [JACKT450:03-0]<:0> A-Shell 6.5.1669.0 launched on ZEUS:03 by joaquin (winver:10.0.17134
hwnd:4f0c4a v:1 pid:41016 )
```

```
27-Dec-19 09:15:15 [JACKT450:01-1]<ASTART:0> In: Nodes=1/2/5 [L], ip=10.172.0.10 0:5:9a:3c:7a:0, (joaquin)
sip=0, sm=1
```

## **Shutdown:** 

```
26-Dec-19 15:33:00 [tsk:103032-37]<MENUC:1a4e5> Out: Nodes Remaining = 63P/65L, 1199717 reads, 28 writes,
87740 kbd bytes
```

A-Shell Reference 

Page 4105 

## **Notes** 

- The initial "launched on" line indicates the version of A-Shell being launched, the connection device or client machine name, 

- and the user name (either the Unix login name, or the Windows client login name). 

- In the case of an ATE connection, the next line will show the ATE client version, ATE machine name, the Windows client login 

- name, and a few other minor details. 

- The "jcbrebuild #" messages are normal and simply indicate that the Job Table is being refreshed, with the # indicating the 

- triggering event. 

- The "In: Nodes=AA/BB/CC [P]" line indicates the number of A-Shell nodes calculated after the new session is counted. AA 

- indicates the number of nodes counting against the license; BB is the total number of jobs; CC is the licensed node limit (which applies to AA, not BB). This is followed by [P] indicating a "Physical node" (counts against the license limit, i.e. adds to the AA figure) or [L] for a "Logical node" (doesn't count; adds to the BB figure). This is followed by the IP and MAC address of the client and the login name on the client machine. The si{p} and sm values indicate the number of other sessions originating from the same IP address and client machine, respectively. 

- The "Out:" line indicates the number of remaining physical [P] and logical [L] nodes in use, along with a few usage indicators 

- for the session. 

A-Shell Reference 

Page 4106 

## **TRACE=BASERR** 

_Added December 2019_ 

This setting is recommended for most situations. It outputs messages for each ASB error, indicating whether or not it was trapped, along with other details. The only case where you may not want this trace is in an environment where it is normal to use ^C to terminate programs, since otherwise this will generate a lot of Error #1 traces. The typical trace looks like this: 

```
27-Dec-19 11:46:04 [p26428-16]<REGSC2:0x246d> Trapped ASB error #6 (RETURN without GOSUB) last line # 3380
(location 246D)
```

- `27-Dec-19 11:46:04 [p26428-16]<REGSC2:0x246d> Call stack trace, from program REGSC2 : ...` 

## **Notes:** 

- For programs without line #'s, the location counter will allow you to locate the exact source line, provided you have an LSX 

- file corresponding to to the compiled module. See COMPIL /LF switch for information on generating the LSX file and Call Stack Tracing for information on interpreting the stack trace details. 

- Some errors may log additional forensic details beyond what could otherwise be determined from the error code alone, so 

- even if your programs log their own errors, you may find the ashlog traces useful. For example, in the case of subscript out of range (error #8), the ashlog trace will indicate the array index being referenced, along with the dimensionality of the array. Or in the case of out-of-memory (error #3) it will likely note the context of the memory request and the amount being requested. 

A-Shell Reference 

Page 4107 

## **TRACE=SIGHUP** 

_Added December 2019_ 

This setting is recommended for most situations. It generates messages indicating when a session shutdown is triggered by a SIGHUP (disconnect) or SIGTERM (kill) signal. For example: 

```
26-Dec-19 10:02:58 [tsk:96643-53]<POS:CRTO:a4f> SIGHUP trapped on: TSKACA (fulano)
```

```
26-Dec-19 10:02:58 [tsk:96643-53]<POS:CRTO:a4f> (Waiting for kbd wait or tcki to generate error; tinstate=1,
rlock=0)
```

```
26-Dec-19 10:02:58 [tsk:96643-53]<POS:CRTO:a4f> (Now in kbd wait; setting ASB error #250)
```

```
26-Dec-19 10:02:58 [tsk:96643-53]<POS:CRTO:a4f> Trapped ASB error #250 (Hangup signal (SIGHUP) received) at
location counter A4F
```

```
26-Dec-19 10:02:58 [tsk:96643-53]<POS:CRTO:a4f> Call stack trace, from program LEDGER : ...
```

```
26-Dec-19 10:03:02 [tsk:96643-53]<POS:CRTO:bc9> SIGTERM trapped on: TSKACA (fulano)
```

```
26-Dec-19 10:03:02 [tsk:96643-53]<POS:CRTO:bc9> Out: Nodes Remaining = 74P/80L, 153230 reads, 84 writes,
39717 kbd bytes
```

```
26-Dec-19 10:03:02 [tsk:96643-53]<POS:CRTO:bc9> shut miame...
```

```
26-Dec-19 10:03:02 [tsk:96643-53]<POS:CRTO:bc9> Forced abort; qflock & miame shutdown complete.
```

## **Notes** 

- SIGHUP (SIGnal HangUP) only occurs with SSH or Telnet connections, indicating that the connection between the server and 

- client has been lost. The signal is typically trapped by A-Shell (see the various -h* switches in the Command Line Switches topic) in order to allow the program to complete any activity that it may be in the middle of. Since the session no longer has a client connection, it gets turned into a background process and may continue running that way until it stops for keyboard input or gets another error. Note during this period, the program is not aware of the change of status. Once it asks for keyboard input, A-Shell will generate error 250 to force the program to take some action to shut down, since it can't receive keyboard input without a connection. 

A-Shell Reference 

Page 4108 

- Assuming TRACE=BASERR was active, the error 250 will generate its own trace message with details about the call stack. 

- Finally, assuming the session shuts down, you will see the Out: line, possibly with a couple of confirming details as shown 

- above. 

- If the log contains the SIGHUP message but no Out: message, that suggests the session failed to shut down (either because 

- it went into a loop without any need for keyboard input), or due to some other malfunction deserving further investigation. 

A-Shell Reference 

Page 4109 

## **DEBUGGING RESOURCES** 

_Documentation in Progress_ 

For now, see Event Tracing. 

A-Shell Reference 

Page 4110 

## **BACKGROUND JOBS** 

Many applications make use of some kind of background jobs, which leads to the question of how to implement them under A- Shell. UNDER AMOS, you would typically have launched such jobs from the system INI when the system was booted, but under A-Shell/Windows/Unix there are a variety of possibilities and considerations, which are discussed below. 

## **Launch background job when the system boots** 

Start by coming up with the necessary command line which will start A-Shell and then the program (typically via a startup command file). You can test that from the shell prompt (under Unix) or from the Start>Run prompt under Windows. Once you have it perfected in interactive mode, to make it invisible, for Windows, add the -z (invisible) or perhaps -zi (system tray) switch to get it off the Task Bar; for Unix, add code to the end of the command line to redirect the output, i.e. " `>out.lst 2>1` " (to 

redirect both _stdout_ and _stderr_ to the file out.lst) or " `&gt/dev/null 2>err.lst` " (to discard _stdout_ but capture _stderr_ ). Under Unix, you will probably want to add "-td dumb" to set the terminal driver to "dumb" to eliminate emulation escape sequences from any captured output. 

Finally to launch your command at system startup, for Windows create a shortcut with the command line and add it to the Startup folder. For Unix, add it to rc.local (or the equivalent). 

## **Job dies and needs to be re-launched** 

The first thing your background application should do is check to see if it is already running. One simple way to do this is to use the -j <jobname> switch to force it to use a specific job name. If the job name already exists, the A-Shell launch will fail, so there would be no harm in just re-launching it as often as you like, either manually or automatically. (This assumes that if the job dies, it will close itself down entirely. You can help guarantee that by using the -e startup switch, adding HOST to the end of the command file which starts the app, adding XCALL MIAMEX, MX_EXIT to your error trap, etc.) 

Under Windows you can use the System Scheduler (aka "Scheduled Tasks") to force your shortcut to be launched every few minutes, so that if the background job does die, it will automatically get restarted. Same idea under Unix, except using crontab. 

Another possibility is that other jobs in your application can act as watchdogs, such that if they detect the background job is missing, they can relaunch it using XCALL HOSTEX, or, for Unix, you might prefer XCALL SUBMIT (but use the /NEXT:0-0-0 option 

A-Shell Reference 

Page 4111 

to make it run under control of the atd daemon rather than as a child of the job which launched it.) 

## **Detect new version and re-launch** 

You can use XCALL GETVER to get the version of the currently running program. You can also use MIAMEX,107 to get the version of a program that has been loaded into memory. 

To get the version of the program on disk, you could use `DIR/V` as you suggest, but it would be more efficient to read it directly from the file. Here is how DIR.LIT does it: 

```
map1 STRING'VERSION,s,13        ! Version string
```

```
map1 VERSION                    ! Version no.
   map2 VMAJOR,f,6             ! Major version
   map2 VMINOR,f,6             ! Minor version
   map2 VSUB,f,6               ! Sub version
   map2 VEDIT,f,6              ! Edit number
   map2 VWHO,f,6               ! Patch level
map1 VRECORD                    ! version record
   map2 VBINARY(8),b,1         ! Individual bytes
map1 VRETURN,f,6                ! No. bytes actually read
```

```
MAKE'VERSION:
```

```
   STRING'VERSION = ""
```

A-Shell Reference 

Page 4112 

```
   open #1,FILE$,input
```

```
   xcall GET,VRECORD,1,8,VRETURN
```

```
   if VRETURN = 8 and  VBINARY(1) >= 254 and VBINARY(2) = 255 then
```

```
      VMAJOR = VBINARY(4)
```

```
      VMINOR = VBINARY(3) and 15
```

```
      VSUB = int(VBINARY(6)/16)
```

```
      VEDIT = (VBINARY(6) and 15)*256+VBINARY(5)
```

```
      VWHO = int(VBINARY(3)/16)
```

```
      STRING'VERSION = str(VMAJOR)+"."+str(VMINOR)
```

```
      if VSUB then STRING'VERSION = STRING'VERSION+chr(64+VSUB)
```

```
      if VEDIT then STRING'VERSION = STRING'VERSION+"("+str(VEDIT)+")"
```

```
      if VWHO then STRING'VERSION = STRING'VERSION+"-"+str(VWHO)
```

```
   endif
```

```
   close #1
```

```
   return
```

Actually, there is a function in SOSFUNC: to extract the version from a RUN, LIT, or SBX file on disk: Fn'ProgVer$(progspec$) 

Note that while you could install a new RUN while the program is running, XCALL GETVER will continue to get the version of the program running in memory, ignoring the updated one on disk. But Fn'ProgVer$() (or the raw code from DIR shown above) will read the version from the disk file, ignoring the one in memory. So by comparing the two periodically, you could detect when the version had been updated. 

A-Shell Reference 

Page 4113 

## **Node count and licensing** 

Do background jobs count as nodes against the license? Yes and no. The first background job does count. Additional jobs do not count until you have as many background jobs as you have licensed nodes, and then they start counting. 

## **Keeping track of what background jobs are doing** 

The time-tested approach is for your background job to maintain a log file and/or status file that you can examine. You may find the SOSPROC: procedure SysLog() to be helpful. Also, keep in mind that if you want to be able to see the latest messages output to a sequential file, you either need to close it after each message (reopening for APPEND prior to each new message) or disable output buffering using MX_NOBUF. you will also want to make sure when you query the log file that you don't open it in a way that will interfere with the on-going output to it. 

Under Windows, if you run your background jobs from the system tray, you will be able to make them visible by double-clicking on their icons in the system tray. (Although in a multi-user system, you will have to do this from the PC which launched the job.) 

Note: This topic was originally written as a post on our support forum. You might want to check the original post to see if there have been any additional comments: "Background Job (tips)" 

A-Shell Reference 

Page 4114 

## **JOB TERMINATIONS** 

Most job termination issues are primarily issues under Unix and Linux with telnet connections, but kills apply to Windows as well. 

One problem with non-hardwired connections, such as network and modem connections, is that they can become disconnected unexpectedly. (Actually, under Unix, turning off a hardwired dumb terminal can also cause the session to be disconnected, but mainly this is an issue for telnet and modem connections.) Under Unix, such disconnects generally cause the process to be terminated, which may not be such a good thing, particularly if the process was doing some kind of posting. To make matters worse, since the session’s display is disconnected at the same time as the process is terminated, you typically get no message on the screen, making it difficult to track what, when, or even if anything happened. 

A closely related situation occurs when a process is killed using the Unix kill command or A-Shell KILL.LIT command (and this is independent of the hardware connection type). 

Under Unix, a process being killed or disconnected is sent a "signal" which in most cases can be trapped and responded to by a "handler", which is essentially like the error trap in a BASIC program. A-Shell contains handlers for a number of signals, but the two of interest to this discussion are SIGTERM and SIGHUP. SIGTERM is the standard kill signal and is sent by KILL.LIT/K, and by the operating system when it is preparing to shut down. (It can also be sent with the Unix kill utility, using the –TERM switch, as well as via MX_GETSIG.) SIGHUP is the signal sent when a process has been disconnected from its terminal device, such as due to a loss of network connection, or modem hangup. (It may also be sent manually with the Unix kill utility, using the –HUP switch, or via MX_GETSIG.) 

Windows does not support these signals per se, but A-Shell does emulate the SIGTERM signal (with KILL.LIT/K). 

When A-Shell receives a SIGHUP or SIGTERM signal, it generates ASB error (#250 for SIGHUP and #251 for SIGTERM), allowing your program a chance to do some kind of graceful shutdown instead of just being obliterated. In the case of SIGTERM the error #251 is raised immediately, while in the case of SIGHUP, the error #250 may or may not be delayed, depending on which command line options were specified when A-Shell was launched. 

The ASB error won’t do your application much good if you don’t trap it. Programmers may often neglect error trapping, both because no one likes to think about errors, and because there is a general sense that the errors you plan for are never the ones that occur. Some may also rationalize that the default handling of errors (in which the BASIC runtime system reports the error message and line number, if applicable) is as good, or better, than the typical custom error trap code. These were never great excuses, and they are even less so in the modern environment where ASB errors can be caused so easily by disconnects, both caused by careless user action (e.g. resetting the PC) as well as by network errors that are not anyone’s fault. 

A-Shell Reference 

Page 4115 

A simple error trap routine might look something like the following: 

```
on error goto TRAP:
```

```
......
```

```
TRAP:
```

- `! special handlers for errors 250-255` 

```
on err(0)-249 goto &
TRAP'HANGUP, TRAP'KILL, TRAP'QZAP, TRAP'SOCKERR, &
```

```
TRAP'TIMEOUT, TRAP'WINCLOSE
```

```
TRAP'SOCKERR:
```

- `! <This occurs only during socket comm. Sessions using` 

- `! TCPxxx; it can be handled like most other BASIC` 

- `! errors, and thus we just fall through…>` 

```
<Existing error trapping, which may display messages,
```

```
prompt user to acknowledge, chain to menu, etc., none
```

```
of which makes much sense in a disconnect situation.
```

```
See subroutines ERRMSG and FILNAM which may be very handy
```

```
in error trap routines.>
```

```
TRAP'HANGUP:
```

A-Shell Reference 

Page 4116 

```
TRAP'KILL:
```

```
TRAP'QZAP:
```

```
TRAP'TIMEOUT:
```

```
TRAP'WINCLOSE:
```

```
<close files, possibly log error, no input or display>
END                 ! terminate program
```

Errors 254 (timeout) and 255 (window close) are discussed in the next topic. Error 252 (queue zapped) occurs if your job table record is removed or corrupted. Although these are somewhat unrelated to the hangup and kill conditions, as a practical matter, the handling is probably the same. 

In addition to this method of trapping and logging disconnects, which is highly recommended, but which requires some modification to your programs, you can also have A-Shell at least create a log of these kinds of events by adding TRACE=SIGHUP to miame.ini (see the TRACE system parameter. 

A-Shell/Unix supports several Command Line Switches (see for details) which modify the way hang-ups are processed: –h (ignore hangup signal), –hd (delayed hangup response), –hp (hangup parent), –hetcki (hangup error on tcki), and –hei (hangup error immediate). 

## **Subtopics** 

- Disconnects and Program Terminations 

- Trapping Timeouts and Closed Windows 

A-Shell Reference 

Page 4117 

## **DISCONNECTS AND PROGRAM TERMINATIONS** 

In some cases, having a process terminate due to an unexpected Telnet disconnect can be very inconvenient, and you would prefer that the process continue to run anyway. This is automatic in A-Shell, provided that the process does not require any keyboard input, which is not practical with a process that has lost its terminal connection. When the hangup signal is detected, the A-Shell will convert the session into an independent background session and keep running. The process will continue running until it gets another error or until it stops to wait for keyboard input. At that point, it will get an error 250 as described earlier, allowing the program to perform any desired cleanup/shutdown procedures. When the program then goes back into another keyboard wait—i.e. returns to a menu, or drops to the dot prompt, or prompts within the error trap for some kind of user response—then it will be terminated and forcefully shut down. 

The –hetcki switch causes a TCKI (check for keyboard without waiting) operation to be treated like a regular keyboard request, which will then cause a disconnected session to be terminated. This is useful in programs like ASTAT, which might otherwise run forever after being disconnected. ASTAT in fact internally sets this flag using MX_CLFLAGS while it is running, and then restores the flags that were originally set as it exits. 

The –hei switch is needed to get the old hangup behavior, which was to immediately generate ASB error 250 and then wait for the program to shut down or to go into a keyboard wait. You might want to set this switch in a program that you specifically did not want to continue running if the session was terminated (possibly a large report that was intended to be output to the screen or workstation printer). 

A-Shell Reference 

Page 4118 

## **TRAPPING TIMEOUTS AND CLOSED WINDOWS** 

Note that an inactivity timeout may occur in any version of A-Shell, while a closed window event only applies to A-Shell/Windows. 

In addition to the external events described above, there are a number of internal events which can also interrupt an application. Most ASB errors fall into this category, but there are two special conditions for which there is no AMOS equivalent and thus deserve further discussion here: inactivity timeout and a manually closed window. 

Inactivity timeout is an optional feature of A-Shell that may be activated via the IATIMEOUT System Parameter. By default, it is disabled, but when enabled, a background timer is started that checks on the application periodically to see if it has been idle for the specified duration. If so, A-Shell generates an error #254. Note that although unlike the hangup signal (error #250) in the sense that the terminal connection is still live, as a practical matter, it probably indicates that the operator has left her station and thus there is little point in displaying a message and prompting for an acknowledgement (as you might do with most other errors). This is why it was handled like the hangup and kill errors in the sample error trap routine in the preceding section. (If you think that there is a possibility that the operator is there but just not paying attention to the screen, it might make sense to ring the terminal bell a few times and then use a timed keyboard operation to give her a last chance to resume before aborting.) 

Possibilities for detecting timeout conditions abound. At the individual field level, INFLD[XS] and GET[XS] both support time-limited keyboard entry. At the session level, in addition to the IATIMEOUT A-Shell system parameter, many telnet clients support an idle timeout. (In this case, the client would shut down the session and A-Shell would treat it like a disconnect.) 

The Closed Window event only applies to A-Shell/Windows when OPTIONS=XABORT is set in miame.ini. In this case, the user is allowed to abort a running application by clicking on the "X" in the upper right corner, or by hitting ALT-F4. Either action in this case will trigger ASB error #255, which should be handled, for all practical purposes, just like the kill signal (error #251). 

A-Shell Reference 

Page 4119 

## **- A SHELL FOR APPLE MACINTOSH** 

_Added October 2016_ 

So why is there not a version of A-Shell for the Mac? Since A-Shell is written in C, and there is a C compiler for the Mac, can't it run? Here is the reply from the horse's mouth, as it were. 

Yes, there is a C compiler for the Mac, and yes, A-Shell could be made to run on the Macintosh. The obstacles are: 

- The flavor of C has a number of quirks that would probably require some time to figure out. 

- The Mac environment, although based on Linux, has a number of peculiarities that would have to be worked through. 

- We don't know anything about the Mac P2P environment, whether Mac workstations can coexist and share files on a Windows 

- LAN, etc. Probably they can. 

- The GUI environment is totally different. Since A-Shell's GUI is based on the WIN32 API, that isn't an easy nut to crack. And 

my guess is that since the Mac is mostly of interest as a workstation, users would likely want some GUI capabilities. Rewriting the GUI to use some higher-level, more portable framework (perhaps more HTML based) might have a lot of benefits, but is obviously a big job. 

- In 25 years or so, MicroSabio have had about five inquiries about using the Mac. So while that may not be a good indicator, it 

- seems reasonable that the total possible sales of a Macintosh-based version of A-Shell would be a tiny sliver of the Windows sales. A-Shell business applications don't seem to overlap very much with the Apple world. 

In summary, we could probably get a plain text (Unix-like) A-Shell/ATE working in a hundred hours or so. Networking and coexistence with Windows PCs would probably double that. And GUI would be ten times that. Given that the sales income from such efforts would likely cover only tiny fraction of the costs, the Mac version of A-Shell is unlikely to ever get built. 

A-Shell Reference 

Page 4120 

## **- A SHELL/FAX** 

A-Shell/FAX is an application programming interface (API) which enables applications running under A-Shell/Windows to send faxes via the Windows Fax Service. While faxing has always been possible under A-Shell/Windows by the simple fact that most fax packages emulate a standard Windows printer, A-Shell/FAX allows the application to pass all of the necessary addressing information (fax number, to/from names, cover page info, etc.) directly to the Fax Service, eliminating the need for the user to respond to the dialog boxes which would otherwise pop up to request this information. 

Note that A-Shell/FAX can be made available to A-Shell/Unix via ATE and the GDIPRT printing subroutine. 

The mechanism for passing this information from the application to the Fax Service consists of a set of commands or directives that can be embedded at the start of the print file. The concept is identical to that used for embedding GDI directives for font selection, line drawing, image printing, etc. The actual set of directives overlaps that of the AlphaFAX package available under AMOS. That is to say, most (but not all) AlphaFAX commands are supported by A-Shell/FAX, yet A-Shell/FAX supports a number of additional commands designed to take advantage of features of the Windows Fax Service that do not exist in AlphaFAX. 

## **Subtopics** 

- Command Format 

- Command Listing 

- Supported AlphaFAX Commands 

- Additional Informational Commands 

- Cover Page Commands 

- Unsupported AlphaFAX Commands 

- Document Formatting Codes 

- Sample Document 

- Defining the Fax Printer 

A-Shell Reference 

Page 4121 

## **COMMAND FORMAT** 

All of the A-Shell/FAX commands start with " `@@` " which must appear in the first two columns of the line. As with the A-Shell GDI printing commands (which start with " `//` "), you may comment out a line by putting a semicolon in the third column. For example: 

```
@@;This is a comment and will not be printed.
```

The basic format of all the commands consists of the `@@` followed by a keyword. If the command takes any parameters, the keyword is followed immediately by an equal sign, followed by one or more comma-delimited parameters. For example: 

```
@@KEYWORD=param1{,param2}...{,paramN}
```

The commands are not case sensitive, but there should be no space before or after the equal sign. Since the comma is the parameter delimiter, if a single parameter contains any embedded commas you must enclose the entire parameter in quotes (e.g. "Mr. Scholar, PhD"). 

All @@commands must appear before any blank or printable lines in the print file. (Scanning for @@commands stops when the first line which does not start with "@@" or "//" is encountered.) 

A-Shell Reference 

Page 4122 

## **COMMAND LISTING** 

This table lists the A-Shell/FAX and AlphaFAX commands. The names of the table sections correspond to the documentation headings where you will find detailed descriptions of the commands. 

|**@@ Command**|**Description**|
|---|---|
|**Supported AlphaFAX Commands**||
|TELNO|"To" fax number|
|ID|Identifier for log file|
|NOTIFY|Email address for delivery report; see warning|
|PREVIEW|Ignore all other commands and send to printer|
|PRINTFAX|Printer name|
|**Additional Informational Commands**||
|TO|"To" person name|
|FROM|"From" person name|
|FROMCO|"From" company name|
|FROMDEPT|"From" department name|
|DOCNAME|Description of faxed document|
|**Cover Page Commands**||
|CPNAME|Filename of cover page|
|CPTO|"To" person|
|CPTOADDR|"To" physical address|
|CPFROM|"From" person|
|CPFROMADDR|"From" physical address|
|CPSUBJECT|Subject|



A-Shell Reference 

Page 4123 

|**@@ Command**|**Description**|
|---|---|
|CPTOTPAGES|Total pages|
|CPNOTE|Note|
|CPRFROMFAX|"From" fax number|
|**Unsupported AlphaFAX Commands**||
|DEFER|Defer until <time>|
|PRIORITY|Priority|
|FINE|Sending quality|
|INCLUDE|File to be included|
|DISTRIBUTE|Distribution list|
|NEWDOCUMENT|Begin new fax|



A-Shell Reference 

Page 4124 

## **SUPPORTED ALPHAFAX COMMANDS** 

_Reviewed July 2020_ 

This first set of commands consists of those that are also supported by AlphaFAX. The first of these, `@@TELNO` , is the only mandatory command. All the others are optional and mostly serve to provide additional information in the fax log which is kept by the Fax Service (see W2000 Event Viewer, Application Messages.) 

```
@@TELNO=<target fax number>
```

```
@@ID=<identifier for log file>
```

```
@@NOTIFY=<email address to send delivery report to>
```

The `@@NOTIFY` command in AlphaFAX took a jobname as its parameter and caused a screen message to be sent to that job’s terminal when the fax had been sent or aborted. In the A-Shell/FAX version, the Fax Service is requested to send an email delivery (or non-delivery) report to the specified address. However, in order for this to work, the Fax Server must have an email interface configured. This command can also be called `@@MAILDR` . 

**Warning:** Due to a bug in some versions of the Windows Fax Server, specifying the @@NOTIFY command may result in no output at all (no fax, no notification). 

```
@@PREVIEW
```

The `@@PREVIEW` command causes all of the other @@ commands to be ignored and instead of sending it to the fax printer, it is sent to the printer. If you don’t specify any printer, then the A-Shell default printer is used. Otherwise, you can specify a printer using the following syntax: 

```
@@PREVIEW=<printer name>
```

For example: 

```
@@PREVIEW=laser
```

As long as the printer specified is capable of raster graphics, the output should look essentially identically to what the fax would look like. Note that the only statement that is processed from the printer INI for the specified printer is the DEVICE statement. 

A-Shell Reference 

Page 4125 

All the other printing parameters of the preview printer’s INI are ignored, and those of the original fax printer INI are used instead. (The idea here is to make the output on the preview printer match that on the fax printer.) 

Although this is not specific to faxing, you may find it handy to have a printer called PROMPT whose INI specifies DEVICE = PROMPT: in which case @@PREVIEW=PROMPT would cause A-Shell to prompt you for the preview printer name. 

If you want to send the fax AND print it (for example, to keep a hardcopy for yourself) then you can use the following command: 

```
@@PRINTFAX=<printer name>
```

This is identical in concept to @@PREVIEW except the fax is also sent. 

`@@PRINTFAX` is not part of the AlphaFAX command set. 

A-Shell Reference 

Page 4126 

## **ADDITIONAL INFORMATIONAL COMMANDS** 

The following commands are A-Shell/FAX extensions (i.e. do not exist in AlphaFAX) and serve primarily to cause additional information to be written to the Fax Server log. 

```
@@TO=<recipient name>
```

```
@@FROM=<sender name>
```

```
@@FROMCO=<sender company>
```

```
@@FROMDEPT=<sender dept>
```

```
@@DOCNAME=<descriptive name of faxed document>
```

A-Shell Reference 

Page 4127 

## **COVER PAGE COMMANDS** 

The following A-Shell/FAX extensions (i.e. which do not exist in AlphaFAX) are solely for the purpose of passing information to a cover page which has been created by the Fax Service Cover Page Editor. The critical command here is `@@CPNAME` which specifies the name of the cover page. If the command is present, then an attempt will be made to create a cover page. Otherwise, all of the other cover page related commands are ignored and no cover page will be generated. 

```
@@CPNAME=<coverpage filespec>{,serverflag}
```

As mentioned above, cover pages may be created by the Cover Page Editor, which may be found in the Fax applet of the W2000 Control Panel. The Editor is similar to a text editor (like Word) except that you may insert special fields which will be replaced by values passed from the application at the time the fax is sent. The commands for doing this are given below. (Note that they all start with " `@@CP` " for Cover Page.) After designing your cover page, you save it in the normal way (with a `.COV` extension.) 

W2000 comes with a few sample cover pages that you may want to use as a basis for yours. To find them, use the _Start...Search_ facility and look for *.COV 

There may be some confusion over the placement and specification of the cover page. W2000 allows for both local and server cover pages, but it may not be entirely obvious where to put them or how to reference them other than via a fully qualified filespec. Since the @@CPNAME command supports either AMOS-style or Windows-style filespecs, you may just want to copy your .COV file into an ersatz directory (like LIB: or perhaps create a FAX:) and then just reference it using that ersatz (e.g. `@@CPNAME=FAX:COVER1.COV` ). The optional `serverflag` argument may be set to 1 if the cover page is on the server; otherwise the cover page is presumed to be on the local workstation. (The point is moot if the filespec is fully qualified.) 

If using an DevPPN format filespec for the cover page that contains a [p,pn], you must enclose the entire filespec in "quotes". Otherwise the comma in the [p,pn] will be treated as a delimiter. 

The rest of the cover page commands are purely for specifying information to be inserted into the cover page. 

```
@@CPTO=<name>{,<title>{,<company>{,<dept>{,<office location>
```

```
{,<home phone>{,<office phone>}}}}}}
```

```
@@CPTOADDR=<street addr>{,<city>{,<state>{,<zip>{,<country>}}}}
```

```
@@CPFROM=<name>{,<title>{,<company>{,<dept>{,<office location>
```

A-Shell Reference 

Page 4128 

```
{,<home phone>{,<office phone>}}}}}}
```

All `@@` fax commands must be contained on a single line in the actual print file, unlike the multi-line formatting above, which was necessary for typesetting purposes. 

```
@@CPFROMADDR=<address>
```

```
@@CPSUBJECT=<subject of fax>
```

```
@@CPTOTPAGES=<total # pages, including cover>
```

```
@@CPNOTE=<misc memo/notes for cover page>
```

`@@CPNOTE` is the only command that can appear multiple times, if needed, to specify a longer note. The maximum note size is 2K. To let the cover page formatting logic combine and wrap the lines as it chooses, end each line with a space followed by a backslash. Otherwise, each `@@CPNOTE` will start on a new line on the printed cover page. Remember to enclose the entire parameter in quotes if it contains any commas. For example: 

```
@@CPNOTE="This is a note which is continued \"
```

```
@@CPNOTE="on this line."
```

```
@@CPNOTE="This sentence should begin on a new line."
```

The last @@CPNOTE line should not end with a backslash (or else it will be printed.) 

```
@@CPFROMFAX=<sender fax #>
```

The number specified in the `@@TELNO` command will be used for the recipient fax number if such a field exists in the cover page. 

A-Shell Reference 

Page 4129 

## **UNSUPPORTED ALPHAFAX COMMANDS** 

```
@@DEFER=<time>
```

```
@@PRIORITY=<priority>
```

This ability to submit a document to the fax server now but tell it to wait until later to send it, or to alter the first-come, firstserved order of the queue is supported in the more advanced level of the Windows 2000 Fax Server API, but for now, we are using the simpler version of the interface which does not support it. Both commands are simply ignored. 

## `@@FINE` 

This is also ignored. By default all faxes are sent in the "fine" mode nowadays. 

```
@@INCLUDE=<filespec>
```

This is not supported but not ignored either. The command itself will appear in the output (which is how all unrecognized commands are handled.) Note that you can get a similar effect using the PREFIX and SUFFIX feature in the A-Shell printer ini files. 

```
@@IMAGE=<filespec>
```

```
@@OVERLAY=<filespec>
```

These commands are not supported because they are superseded by the more powerful A-Shell GDI printing commands METAFILE and IMAGE. Note, however, that while the @@IMAGE and @@OVERLAY commands worked only with AMOS BMP and PCX image formats, METAFILE works only with Enhanced Windows Metafile format and //IMAGE works with Windows BMP, PCX, TIF and JPG. Also note that IMAGE requires a license for the third-party imaging library. 

Another reason for not implementing the @@IMAGE and @@OVERLAY commands is that they were used almost exclusively for creating cover pages. Under the Windows 2000 Fax Service environment, cover pages are created in the Cover Page Editor, which has its own mechanisms for including graphics and images. 

```
@@TELNO=<name>
```

The ability to define names (which are then translated to actual fax numbers via faxlst.dat) is not supported. If this feature is important to you, please let us know as adding it would not be particularly difficult. 

A-Shell Reference 

Page 4130 

```
@@DISTRIBUTE=<filespec>
```

Distribution lists are also not currently supported, but could be if demand warrants. 

```
@@NEWDOCUMENT
```

This is also not supported. If you want to send multiple documents, send them as multiple files and print requests. 

A-Shell Reference 

Page 4131 

## **DOCUMENT FORMATTING CODES** 

AlphaFAX uses a mechanism of embedded control codes for specifying various kinds of special formatting (fonts, bold, etc.) A- Shell/FAX does not support these, but allows you to use the A-Shell GDI printing commands instead. Since the fax device acts more or less just like a Windows raster printer, virtually all of the GDI commands (except color) are operable (e.g. SETFONT, MOVETO, RECTANGLE, METAFILE, IMAGE, etc.). 

A-Shell Reference 

Page 4132 

## **SAMPLE DOCUMENT** 

```
//;This is a sample print file containing A-Shell/FAX commands.
```

```
//;Lines beginning with //; or @@; are comments;
```

```
//;Lines beginning with // are GDI commands; with @@ are fax commands.
```

```
//;To print this file, just use the PRINT.LIT command, specifying a
```

```
//;printer whose ini file specifies DEVICE=FAX:<fax name> and
```

```
//; which contains PASSTHROUGH=OFF.
```

```
//;
```

```
@@TELNO=1-123-456-7890
```

```
@@TO=Pancho Villa
```

```
@@FROM=Emiliano Zapata
```

```
@@FROMCO=Revolutionarios, S.A.
```

```
@@FROMDEPT=Provisions
```

```
//;Uncomment the @@NOTIFY line below only if certain that the email interface is supported
```

```
//;(otherwise you may get no fax at all)
```

```
//;@@NOTIFY=email@zapatista.org
```

```
@@DOCNAME=Lunch Strategy
```

```
@@CPNAME=LIB:SECRET.COV
```

```
@@CPTOTPAGES=2
```

```
@@CPSUBJECT=Plan for Lunch
```

```
@@CPTO=Pancho Villa,General,"Revolutionarios, S.A."
```

A-Shell Reference 

Page 4133 

```
@@CPTOADDR=,"Somewhere in the Sierra Madre",,,MEXICO
```

```
@@CPFROMADDR="Somewhere South of Mexico City"
```

```
@@CPNOTE="You bring the tortillas and frijoles, \"
```

```
@@CPNOTE="and I'll bring the salsa roja and cerveza."
```

```
@@CPNOTE="Buen Provecho!"
```

```
//;The rest of this document consists of regular text and
```

```
//;normal A-Shell GDI printing commands such as //SETFONT,
```

```
//;//SETMAPMODE, //TEXTOUT, etc.
```

A-Shell Reference 

Page 4134 

## **DEFINING THE FAX PRINTER** 

The fax printer is defined more or less just like any other A-Shell printer (i.e. via a printer ini file in the SYS: directory) with the following two mandatory requirements: 

```
DEVICE = FAX:<fax printer name>
```

## `PASSTHROUGH = OFF` 

The `<fax printer name>` identifies the particular fax server to use, and can be one of the following: 

- A local fax printer name (as it appears in the printer folder.) 

- A network printer UNC name, such as " `\\servername\printername` ". 

- NULL (nothing following the prefix `FAX:` ) to specify the default local fax printer. 

Some examples: 

```
DEVICE = FAX:fax
```

```
DEVICE = FAX:\\mainserver\fax1
```

```
DEVICE = FAX:
```

Note that the prefix FAX: must be used in all cases. This is how the A-Shell print spooling routine realizes that you want to use the A-Shell/FAX interface, which requires that it do some preliminary setup work (loading the winfax.dll, dynamically linking the functions needed, allocating temporary memory, pre-scanning the print file to extract the essential header commands, etc.) before doing the normal print processing of the file. 

A-Shell Reference 

Page 4135 

## **SECURITY** 

In July 2008, some security problems with a Linux system required a trip to the customer's site. Following are some notes from that time. 

I'm about to make an unscheduled trip to beautiful Omaha, all because a Linux system got compromised by Internet attack. Fortunately, the system is running well enough to keep the application going (A-Shell being nearly invincible!), but it's otherwise nearly crippled. Can't execute simple commands like ps, rpm, vi (vue works!), all the networking commands are broken, the backup program user interface is broken, etc. To compound matters, the problem started happening so long ago that it isn't even clear how far back we need to go (or just reload the OS). But I thought it might be nice to share a few warnings/thoughts/reminders about how to avoid this kind of situation: 

- Don't expose Telnet to the Internet. Use SSH instead. Same goes for FTP; use SSH (SFTP) instead and block the Telnet and 

- FTP services from the Internet. You need to leave Telnet running for local connections in order to use SSH tunneling though. 

• Make sure that you don't have obvious login/passwords (like user/user, staff/staff, etc.) We're not actually sure if this is how they broke in, but we can see from the logs hundreds of attempts to log in with various typical usernames (user, staff, admin, john, fred, etc.) It should go without saying that the root password better be secure. 

- Use a firewall, and configure it properly. In this case, they had a Cisco firewall, and it was supposed to be blocking outside 

- incoming connections except for a few special IP addresses (like mine), but apparently a lightening strike caused it to lose its rules and revert to wide-open incoming access. If possible, require all the remote users to come from fixed IP addresses (which are easy to configure in even the simplest Internet routers). 

• Employ some kind of log-checking mechanism. RHEL includes a thing called LogWatch, which can be used to display or output a semi-consolidated listing of all or selected log activity, but you still have to arrange to have it execute on a daily basis and for someone to review the logs. Better still would be to use software to dynamically look for exceptions, but there doesn't seem to be clear, obvious, and simple-to-configure choice that I can see. There are commercial utilities such as TripWire, and there are open source utilities such as swatch, but they all require a fair amount of time spent figuring out what you want them to look for and how to get them to do it. (In this case, merely reporting failed login attempts would probably have been sufficient to raise the red flag.) 

- Use a "real" backup tool (I still like BackupEdge) that allows you to fully restore the root filesystem. This is probably what I 

- will end up using. But even this is not helpful if you don't have a good rotation of backup tapes, including week-end or month- 

A-Shell Reference 

Page 4136 

end tapes going back at least a couple of months. (In this case, we know the problem started more than a month ago, but aren't sure because that's how far back the logs go.) 

- Tip: edit /etc/logrotate.conf to change the default rotate 4 to a higher value to increase the number of archived copies of the 

- logs). 

- Configure your disks so that the application is in a separate filesystem (e.g. /vm or /u). Not only does this isolate the 

- application and the root from problems originating in the other, it also makes it a lot easier to do an emergency restore (or reload) of the root filesystem, without exposing the application to risk of unwanted over-writing. 

• Install security patches. There was a time when Linux was considered reasonably immune from exploitable security flaws (and still is much much better than Windows, which requires updates on a near daily basis to remain secure), but if your server is exposed to the Internet, you need to think about updates. This is one of the advantages of going with a commercial distribution, like RHEL, which comes with a subscription for patches. 

- Turn off any services you aren't using - such as httpd, etc. 

- " - " This discussion was originally posted on the A Shell forum under the title Linux System Cracked Lessons , and may have been updated more recently than the version here. 

A-Shell Reference 

Page 4137 

## **ACCESSING SERIAL PORTS** 

Some A-BASIC applications access serial ports directly for output (e.g. `OPEN #1, "TRM0:LASER1", OUTPUT` ), or even in some cases for input. The typical reason for this is to bypass the spooler to obtain better control over a particular printing operation. Another reason may be to communicate with some kind of non-terminal, non-printer device (such as a temperature sensor, mechanical counter, voice mail system, etc.) A-Shell does not emulate the "TRM" device, but it does allow you to open raw device files, provided you use the proper syntax and that the underlying operating system supports file I/O operations on ports. 

## **Windows Serial I/O** 

Under Windows, it is possible (but not recommended) to open a serial port for output by using the following syntax: 

## `open #1, "COM1\", output` 

Note that you must replace the normal colon in COM1: with a backslash. Otherwise, A-Shell thinks COM1: is an AMOS-type logical disk. 

Unfortunately, it is not possible to open serial ports as input files. 

The recommended approaches to serial I/O under Windows are either to use AutoLog (see above), or COMIO. 

## **Unix Serial I/O** 

You can generally treat serial ports as sequential files under Unix, opening them for either INPUT or OUTPUT (or both) as shown below: 

```
open #1, "/dev/tty1a", output
```

```
open #2, "/dev/tty1a", input
```

Once open, you can use the normal PRINT or INPUT statements, although they may not work exactly as you might expect due to the large number and complexity of configurable parameters which affect serial port operations under Unix. The typical method of setting these parameters (after opening the port) is to use HOSTEX[XS] to invoke the Unix stty (or equivalent) command. (Refer 

A-Shell Reference 

Page 4138 

to the Unix "man" page or other documentation for further details on serial port settings, a subject which exceeds the scope of this discussion.) 

Note that if you are going to use the `xcall HOSTEX, "stty..."` approach, you must do so **after** you open the port. Otherwise your changes may be lost when the port is opened. 

To output to the port, you can use the PRINT command. Beware, however, that under the Unix default buffering scheme, the characters may not be "flushed" to the device until a line terminator is output. To input, you can use INPUT or INPUT LINE, but here the subtleties of the port parameters can cause considerable confusion. For character-oriented, rather than line-oriented XS input, use GET . 

You can turn off output buffering on Unix or Linux devices by opening the device as an output file and then executing `xcall MIAMEX,MX_NOBUF,87,CH` where CH is the file channel. Similarly, you can use `xcall MIAMEX,MX_FLUSHBUF,8,CH` to immediately flush any buffered characters on that channel. 

You can do character-level input from a serial port using GET: 

## **xcall GET, buf, chan, bytes'req, bytes'rcv, timeout** 

For a more sophisticated approach for serial communications, contact Soft Machines (www.softmach.com) for information on their AutoLog communications package, which, among other wonderful features, includes a subroutine interface from A-Shell. Under Windows, there is also the COMIO[XS] which offers capabilities somewhere in the middle between simple file-oriented I/O and the full feature set of AutoLog. 

A-Shell Reference 

Page 4139 

## **CONTROLLING ACCESS** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Locking Users Out 

- File Access Privileges 

A-Shell Reference 

Page 4140 

## **LOCKING USERS OUT** 

You can lock users out of A-Shell by creating a file ashell.lok in the directory where miame.ini is located. You can create this file manually, or you can use LOKOUT.SBX. File details are as follows: 

```
Line 1:  <# of seconds to wait before exiting, or 0 for unlimited>
```

```
Lines 2-N: <Any text that you want to display>
```

An example will make this more clear: 

```
0
```

```
A-Shell is currently locked for maintenance by the Big Kahuna
```

```
(starting at 5:30 PM and expected to last until 6 PM).
```

```
You can wait here, or hit ESC at any time to exit and try again later.
```

In the above example, the 0 on the first line indicates that A-Shell will wait indefinitely (until the user hits ESC, in which case it exits, or until the ashell.lok file is removed, in which case it proceeds as normal). If the 0 had been, say, 10, then the message would appear for 10 seconds but then A-Shell would exit. 

While waiting, the process had not been assigned a job, but it is using the ashell.exe or ashw32.exe) executable, and has the jobtbl and qflock files open, so if your maintenance requires exclusive access to those files, you may want to set the wait to just a few seconds (just long enough to see the message) so that you will get an opportunity at exclusive access (even if it takes a few tries). On the other hand, if the maintenance does not require exclusive access to those files, you may want to allow the users to just wait indefinitely in this mode until you signal that it is ok to proceed by removing the ashell.lok file. 

Note that the message should indicate the ESC option (unless the wait time is set to just a few seconds), since it isn't otherwise obvious. (This scheme allows for the maximum in site/language customization.) 

A-Shell Reference 

Page 4141 

To force the existing users to exit, you may be able to use KILL.LIT or FORCE.LIT, and SEND.LIT (to send a message), although this will soon be simplified via an SBX. Or, you could modify your application to check for the existence of the ashell.lok file periodically and handle its own graceful shutdown. 

A-Shell Reference 

Page 4142 

## **FILE ACCESS PRIVILEGES** 

Historically, the typical AMOS approach to limiting access to sensitive application programs was to group them within a password-protected menu program. This works reasonably well in simple cases, but obviously breaks down as the complexity of the application or of its security needs increases. For example, if several people need access to the protected programs, then they all need to share a password. If one of those users leaves the company, then you probably need to change the password, which can be a pain if many other users are involved. The problem gets worse when you have groups with overlapping privileges. To accommodate this, you may need to implement several sets of passwords and allow one or more passwords to unlock particular programs. But again, if a user is transferred from say, payroll to general ledger, you would probably have to reissue new passwords to the payroll group. 

The ultimate solution to these problems is to implement a custom security mechanism within the application that allows both programs and functions within programs (such as delete vs. add), to be restricted by user (or perhaps even category of user), which many applications have done. The problem with the latter solution is simply that it involves significant modifications to all of the programs in the application. And to some extent, it requires duplicating a lot of engineering which has already gone into the operating system, as well as requiring the maintenance of two sets of user logins and passwords (one for the operating system and one for the application). 

For those seeking something in the middle, i.e. more flexibility than the former approach and less effort than the latter, A-Shell offers a capability which leverages the file access privilege mechanisms of the host operating system and requires minimal programming. The first step is to issue individualize logins and passwords to all users. Then, define groups which correspond to access privileges, such that a user’s ability to run a particular program can be controlled by whether the user is a member of a particular group. Finally, change the access privileges on all of the programs in the application so that each program is owned by the appropriate group, and that read access is denied except to members of that group. 

Under Unix, use the CHOWN or CHGRP utilities to change group ownership, and the CHMOD utility to set individual access bits on a file. (Note that directories must have the execute bit set! RUN and LIT programs need only read access. Data files need read and write access.) Under Windows, you can set the privileges by right-clicking on the file. 

When A-Shell attempts to access a RUN or LIT program for which the current effective user does not have read privileges (i.e. which is owned or associated with a group to which the user is not a member), it will abort to the "dot prompt" with an "access denied" error. This fact alone provides the necessary security for the scheme just described to work, but aborting to the dot prompt with an error message is hardly a graceful way to deny unauthorized access. A better approach would be to automatically redirect the user to another program, perhaps the main menu of the application, or better yet, an error recovery program, which explained that the user was not authorized, and then chained to a central menu. MX_CHAINTO, allows you to define just such a 

A-Shell Reference 

Page 4143 

program. Since this definition persists for the duration of the A-Shell session, it can be established in a startup program within touching any of the application’s existing programs. 

To illustrate this, consider the case of an application that starts from a command file main.cmd, which logs the user in and starts the main menu, MENU1.RUN. We’ll create a simple standalone program, called ACCERR, to implement the access trap, and insert it into the main.cmd as follows: 

```
;MAIN.CMD - Application startup
```

```
;Log to the application directory…
```

```
LOG APP:
```

```
;Set up a handler for access violations…
```

```
RUN APP:ACCERR INIT
```

```
;Start the application main menu
```

```
:R
```

```
RUN MENU1
```

The program, ACCERR, might look something like the sample below. Note that to combine its two modes into a single program, we allow the use of a single command line argument (" `INIT` ", as shown in the command file above). When the argument is specified, the program just initializes the access trap using MX_CHAINTO and then exits. Otherwise, we assume we have been called because a user tried to run an unauthorized program, in which case we display a message before chaining to the main menu. 

```
!ACCERR.BAS - Handler for unauthorized attempts to run programs
```

```
map1 CLINE,S,80
```

```
map1 X,F
```

```
!Pick up the command line (program name and argument).
```

A-Shell Reference 

Page 4144 

```
xcall LSTLIN,CLINE    ! (e.g. "APP:ACCERR INIT")
```

```
!If "INIT" arg specified, initialize access trap to point to
```

```
!this program (whose name is the first arg on command line)
```

```
X = instr(1,ucs(CLINE)," INIT")
```

```
if X > 0 then
```

```
xcall MIAMEX,MX_CHAINTO,1,CLINE[1,X-1]
```

```
END
```

```
endif
```

```
!Otherwise, we came here because the user tried to run a program
```

```
!which was unauthorized. Display a message and chain to the menu
```

```
print "Sorry, you do not have access to run that program."
```

```
input "Hit ENTER to return to the main menu: ",A
```

```
chain "MENU1"
```

By taking advantage of the operating system’s capabilities for assigning users to groups and relating file access rights to group membership, the simple scheme just described provides a sophisticated access controls within the application, without requiring changes to the application. For many applications, this will be sufficient, and may even eliminate the need to implement a login capability within the application. (You can retrieve the user’s operating system login via GETUSN[XS] .) 

Note, however, that this scheme cannot, by itself, provide a way to limit access to functions within a program (such as to permit anyone to add a record but only certain people to delete.) However, it can simplify the implementation of such a capability. For 

A-Shell Reference 

Page 4145 

example, rather than define a database of which users have access to which functions within the application, and a special data entry program to manage that database, you might instead simply create a series of dummy control files associated with function names (e.g. "add.sys", "delete.sys", etc.) and use the access system described above to set appropriate privileges for those files. The application could then determine if a user has access to a particular function by seeing if the user can open the corresponding control file. This would require that you use an ON ERROR GOTO to trap the error that would occur when attempting to open a file to which you didn’t have access rights. 

A-Shell Reference 

Page 4146 

## **DETERMINING YOUR PLATFORM** 

Despite all efforts at cross-platform compatibility, it is often desirable to determine which platform you are running on in order to take advantage of its peculiar features (or, less positively, to avoid performing a program operation that will blow up in your face.) Fortunately, this is relative easy, and there are several ways to do it. In the simplest (and most typical) case, you probably just want to know whether you are on a Windows platform or not. An easy way to do that is just to check the directory separator character. If it is "\", then you can assume Windows. Otherwise you can assume some form of Unix or Linux. The call to get the directory separator is: 

```
xcall MIAMEX, MX_DIRSEP, dirsep$   ! returns dirsep$ = "\" or "/"
```

Alternatively, you can get more details and specific information about both the currently running operating system version and the platform that the running copy of A-Shell was compiled for, by using: 

```
xcall MIAMEX, MX_OSVER, osname {,osver, osrel, asplatform}
```

## **See Also** 

- ZTERM Escape Sequences for instructions on detemining if the terminal emulator is ZTERM, ATE or something else, 

- AUI_ENVIRONMENT for another way of detemining the characteristics of the environment or platform (particularly as they 

- relate to its GUI capabilities). 

A-Shell Reference 

Page 4147 

## **FILES AND DIRECTORIES** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- File Sizes 

- Opening Native Files 

- Transcending Filename Size Limit 

- Creating a Native Directory 

- Scanning Native Directories 

A-Shell Reference 

Page 4148 

## **FILE SIZES** 

In older versions of A-Shell, random files were limited 2GB. This NOT the case now and the new limit is too large to worry about. Note, however, that sequential files, as well as old ISAM files, remain limited to 2GB. 

Also BASORT remains limited to 2GB. You can, however, use the third-party Optech sort routine, which is much faster anyway; contact us for details if you have large files to sort, or complex sorting requirements not handled by BASORT. 

Implemented at this time was a runtime option to allow random files to grow record by record, sort of like sequential files, or like ISAM-A files. The motivation for this was initially just to get around the 2GB limit on sequential files for ISMUTL dump/load operations, but it may be useful in a variety of situations. Notes: 

- Enable the mode by setting bit GOP_EXTFIO (&h02) in the first bank of options and GOP2_AUTOX_RAN (&h01000000) in the 

- second bank, using MX_GETOPTIONS, MX_SETOPTIONS: 

```
xcall MIAMEX, MX_GETOPTIONS, options1, options2
```

```
OPTIONS1 = OPTIONS1 or GOP_EXTFIO
```

```
OPTIONS2 = OPTIONS2 or GOP2_AUTOX_RAN
```

```
xcall MIAMEX, MX_SETOPTIONS, options1, options2
```

- Once set, the mode is available to all random files. (You can also set EXTFIO using SET EXTFIO or OPTIONS=EXTFIO.) 

- Since files grow record by record, you must use span'blocks mode to open the file, i.e.: 

```
OPEN #1, FNAME$, RANDOM, RECSIZE, RECVAR, span'blocks
```

- To create the initial file, you can use CREATE.LIT or ALLOCATE (to create a 1 block file) or MAKE.LIT to create a 0 block file. 

- Or you can open the file for sequential output, then close it (also creating a 0 block file). 

- To write to the file, use the normal random file WRITE statements. If you attempt to write past the current end of the file, the 

- file will be extended as needed (on a record by record basis). 

A-Shell Reference 

Page 4149 

- To read from the file, use the normal random file READ statements. If you attempt to read past the end of the file, you will 

- get the normal illegal record error (#31). 

- To determine exactly how many records are in the file, use `XCALL SIZE, file, bytes` and divide the size in bytes by the 

- record size. (Using LOOKUP may be misleading since it returns the size as an integer number of blocks, although the actual size may not be an even multiple of 512 bytes.) 

- Since fundamentally (from the OS point of view) there is no difference between our "random" and "sequential" files, there is 

- nothing preventing you from later accessing the file as a sequential file. However, you cannot change from random to sequential access without closing and reopening the file. 

- See the test program autox.bp SOSLIB:[908,39] for an example. 

## **Old File Size Limits** 

Prior to removing the 2GB limit, this is what the docs said about file sizes: 

Most versions of A-Shell, being a 32 bit application, have a file size limit of 2 GB. But we do offer a special version of 

A-Shell/Linux which eliminates that limitation, provided the kernel also supports the LFS (Large File System) option. Contact MicroSabio for details. 

To determine if your version of A-Shell/Linux supports large files, launch it with the –d switch. If Large File Support is available, a message to that affect will be displayed. 

A-Shell Reference 

Page 4150 

## **OPENING NATIVE FILES** 

In most cases, wherever you could use a DevPPN filespec in ASB, you can also use native operating system file specifications, including long filenames (even those containing spaces) and UNC names (or Windows sharenames.) If the filespec contains a forward slash or backslash, A-Shell assumes that it is a native filespec and does not try to translate it. Examples: 

```
open #1, "c:\Program Files\WIERD.STUFF\myfile.xyz", input
```

```
open #2, "\\SERVER01\VM$\abcde\wxyz.dat", output
```

```
open #3, "/tmp/this is a strange filename.x_y.z", input
```

You can also embed Environment Variables in filespecs, using the syntax %VARNAME% (where VARNAME is the environment variable name). For example: 

```
Lookup "%TEMP%\junk.dat",X
```

```
Lookup "%HOME%/.profile",X
```

Most of the A-Shell LIT commands, and in particular those that support wildcards, can also use native filespecs, but there you must enclose them in quotes. For example: 

```
.copy hosts.txt="/etc/hosts"
```

## or: 

```
xcall ASHELL,"dir hash.lst=""/vm/miame/miame.ini""/h/k"
```

Note that environment variables are only translated in file specifications when the file is accessed. So it doesn't work in a PRINT statement, but would in an OPEN or ALLOCATE or KILL statement. 

A-Shell Reference 

Page 4151 

## **TRANSCENDING FILENAME SIZE LIMIT** 

A-Shell supports AMOS-style filenames up to 72 characters long with an eight character extension—i.e., 72.8. But if that is not enough, since ASB automatically recognizes as native any filename containing a slash, you can easily transcend the size limitation as long as you can establish the absolute or relative directory name. For example, a common requirement is to archive files by date—e.g., transaction batches, posting journals, report images, etc. Coming up with a sensible naming scheme can be a challenge even using the expanded 72.8 format. But it becomes much easier when you eliminate the name length restrictions entirely. For example, you can retain the original filenames and just prepend a date, e.g. "20230408-journl.dat". If the file was known to be in the current directory, you could later reference it with: 

```
Open #1, "./20230408-journl.dat", input    ! (Unix)
```

```
Open #1, ".\20230408-journl.dat", input    ! (Windows)
```

Of course if you are planning on archiving a lot of files, putting them all in the current directory wouldn’t be wise. Instead, you could use MX_MKPATH to create arbitrarily named subdirectories (perhaps based on the file type and/or date) and then store the files in those subdirectories. Under Windows, you could take this one step further and use a Windows File Open dialog box (MX_GETOFD) to allow the user to select (and create) arbitrary directories, returning the directory names to the application, which would then remember and use them for storing and retrieving these archived files. A variation of this approach to the use of native directory names would be to make them subdirectories of a particular AMOS-style directory, which you could retrieve the native equivalent of using MX_FSPEC. 

The main problems to watch out for when using native directory and file names have to do with the DIR command and case sensitivity. In the default display modes, DIR only displays the first six characters of a filename, and it folds them to upper case. (With the /L {##.#} switch, or if SET LONGDIR is established, it displays ## characters plus the extension, but still folds them to upper case.)This can be confusing and annoying if your directories have a mixture of upper and lower case files and/or long filenames. Fortunately, there is a DIR switch /NA{tive} which forces it to display fully-qualified native filespecs in their proper case, which pretty much eliminates the problem. 

When referencing native filenames within your programs, the simplest approach is to stick with all lower case. This will work under Windows (where it doesn’t matter) and Unix (where it does). If you use a mixture of upper and loser case, you can run into the extremely frustrating situation where DIR shows one (or more) copies of the file present, but OPEN (and other file access statements in BASIC) cannot find it. 

A-Shell Reference 

Page 4152 

Filename case can be altered during transfer between systems, so pay particular attention when transferring files to Unix. Many file transfer programs have an option to fold filenames to lower case during the transfer, which would be wise to use. If you end up with upper case filenames on your Unix system anyway, see Folding Filenames to Lower Case for information on converting them in place. 

## **History** 

- 2019 July, A Shell 6.5.1662: Increase filename size limit from 10.3 to 72.8. 

A-Shell Reference 

Page 4153 

## **CREATING A NATIVE DIRECTORY** 

To create AMOS-style PPN directories, you can use SYSACT.LIT. To create an arbitrary native directory that doesn’t fall within the emulated DevPPN format, you need to access native operating system functions. However, you can still do that without leaving A-Shell or your A-BASIC program. 

Under Unix, you could just use `xcall HOSTEX, "<create directory command>"` where the <create directory command> is a valid Unix command for creating a directory in your flavor of Unix (or Linux.) A typical example would be: 

```
xcall HOSTEX, "mkdir /vm/miame/xyz0"
```

However, under Windows this will not work. The recommended approach then is to use MX_MKPATH, which works equally well under both Windows and Unix. 

A-Shell Reference 

Page 4154 

## **SCANNING NATIVE DIRECTORIES** 

You can scan a native directory to build a list of files in one of two ways. The first way would be to use HOSTEX[XS] to launch a native operating system utility to build such a list and output it to a file, and then open the file for input to read it in. This works better in Unix than in Windows, which doesn’t have a standard way of generating a directory list in a file. 

The second way is to use MX_FINDFIRST and MX_FINDNEXT to scan the directory. Start with MX_FINDFIRST to position your "directory cursor" at the start of a specified directory, and then use MX_FINDNEXT repeatedly until it returns a non-zero status, indicating it has hit the end of the directory. 

A-Shell Reference 

Page 4155 

## **PPN NUMBERING** 

PPNs are based on decimal rather than octal notation, and may range to [999,999] instead of the previous limit of [377,377]. The octal scheme was a holdover from days of yore, when bytes were precious and real programmers worked in binary. (The very idea that the disk would be divided into "projects" and "programmers" gives some idea of the amount of dust accumulated on this concept over the years.) As modern programmers have tried to make use of PPNs as a way of organizing real-world categories of things (location numbers, store IDs, client numbers, etc.) they have increasingly found the range of 1-377 octal both limiting and annoying. So when a certain A-Shell dealer dangled an 85 node license in front of us which needed decimal PPNs, we decided it was time to do something about it. Specifically, the new PPN system allows for decimal numbers ranging from 000-999, a nearly four-fold increase over the previous range (or 16-fold if you consider all the combinations of P and PN on a single device.) Not that we recommend subdividing a device into a million (or even a thousand) PPNs, but you can do so if you so desire. In fact, the LIT utilities continue to recognize only 512 unique PPNs per device. 

Initially, the theory was to make the octal/decimal choice an option, but it became apparent that it was so entrenched in the code that it seemed best to just do it and get it over with. For the most part, the changeover should be transparent. No changes are needed to existing disk directories or ini files. However, the conversion does have some ripple effect on LITs and possibly applications, the ramifications of which we dedicate ourselves to discussing here. 

First, a large number of LIT utilities (essentially any that deal with PPNs) had to be updated, and regrettably, the updated versions are not backward compatible. To provide an easy escape valve, we packages the older versions (with .48A extensions) on the beta page as lit48a.zip, to be downloaded, unzipped, and renamed to .LIT if you decide to revert to an earlier version of A-Shell. 

To make it easy to recognize the new LITs, they are all version 3.0 or higher. 

(It should go without saying that this is one of those updates you will want to perform cleanly, i.e. with no users running the old version.) 

Second, and most important, is the question of what effect this will have on existing applications. The answer here is "hopefully none". That is to say, we've tried (and may even have succeeded) in making the new version backwards compatible with existing subroutines that retrieve or set PPN values. However, we cannot completely rule out the possibility that an application does some kind of internal manipulation of PPN information using octal conversion utility code. Before worrying about that, we'll first review the general approach we used to upgrading existing subroutines, and then list all that have changed. Based on that, you can probably quickly determine if you have anything to be concerned about. 

A-Shell Reference 

Page 4156 

General principles relating to PPN arguments in subroutines: 

- Any PPN values represented in a pair of B,1 (or a single B,2) parameters have been kept backwards compatible. That is, they 

- will work as before for the existing range of octal PPNs. They will not, however, accommodate new PPNs which require decimal digits or go beyond the previous limit of 377,377. 

Note that these B,1 parameters were always a bit awkward, due to the fact that the binary representation only made sense if reformatted as octal. If you used a PRINT statement to print out the B,1 parameters returned from a subroutine such as GETPPN, they would have appeared strange converted to decimal. (For example, [377,100] stored in a pair of B,1 variables and displayed using PRINT would come out as 255,64.) 

- PPN values represented as strings (S,3 or more) are both backwards and upwards compatible. They will work as before and 

- also accommodate PPNs such as [999,888]. 

- Any other storage format (for example, a pair of B,2 or F,6) will use the straightforward decimal representation. Fortunately, 

- there is only one commonly used subroutine that used one of these formats for PPNs: XPPN[XS] . 

Here is the complete list of subroutines affected by this change (with comments) for your review. Watch out for ALIASes though! 

|**Subroutine**|**Impact**|
|---|---|
|DSKPPN|Returns PPN as a string, fully compatible up to 999,999.|
|GETJTB|Returns PPN info in both B,1 and S,3 formats. The B,1 values continue to be treated octally as<br>before, whereas the S,3 values are unaffected. (Recommendation: use the S,3 versions and<br>ignore the B,1 versions.)|
|GETJOB|Returns the PPN in a pair of B,1 values, which continue to be supported as before (i.e. octal).|
|GETPPN|Same as for GETJOB.|
|LOG|Supports various argument lists, but all PPN parameters are strings, so there it should be<br>backwards and forwards compatible.|
|MX_GET ERSATZ<br>(return ersatz info)<br>and MX_GETDEV<br>(return device info)|Both continue to support the B,1 versions of PROG and PROJ to preserve backwards<br>compatibility. Any new programs using these routines should upgrade the PROG and PROJ<br>values to B,2 which will cause them to come back in decimal (ready for printing without the<br>need for octal conversion.) (If you decide to make this change, obviously you should do it|



A-Shell Reference 

Page 4157 

|eference||
|---|---|
||thoroughly and systematically to avoid confusion and incompatibilities between programs.)|
|PLYJOB|Returns PPN info in S,3 format, so no problem here.|
|PPNSWP|Uses a pair of B,1 fields, so backward compatible.|
|SETJTB|Allows you to log to a new PPN by setting either the B,1 or S,3 fields. As before, it uses the S,3<br>fields if the B,1 fields are both 0, so that is the way you will want to use it.|
|SETPPN|Companion to GETPPN. Uses B,1 parameters. Backwards compatible.|
|XPPN|Returns PPN info in B,2 format. Previously, you had the option (SBR=XPPNOCT) of getting the<br>returned PPN values in decimal equivalent format so that they printed as you expected. The<br>new version always works this way (i.e. SBR=XPPNOCT is effectively forced on and may be<br>removed frommiame.ini). As such, it is perfectly backwards and forwards compatible.|



A-Shell Reference 

Page 4158 

## **ROUNDING OF FLOATING POINT VARIABLES** 

Following are two discussions on the problems of rounding floating point variables. The first section was written when OPTIONS=FPROUND was added to miame.ini. The second accompanied the introduction of the subroutine MX_ROUND in A-Shell. 

## **Subtopics** 

- FPROUND 

- MIAMEX MX_ROUND 

A-Shell Reference 

Page 4159 

## **FPROUND** 

When set, this option causes A-Shell to apply a rounding factor of .000005 (5 millionths) to the INT() and FIX() functions, and to the floating point comparison operators =, <>, <=, and >=. This fudge factor can be useful in programs that use floating point variables for dollars and cents computations without taking into proper account the fact that whenever floating point values are manipulated, they begin to accumulate tiny errors in precision. If the results of such expressions are not carefully rounded to the nearest penny, the errors can add up to the point that they become noticeable. This is particularly true with non-integers, which is why the SCALE option was invented in the original A-BASIC. 

The problem of precision is inherent with all floating point numbers and affects A-Shell as well as AMOS. In fact, since A-Shell uses 64 bit floating point internally and converts back and forth to A-BASIC 48 bit format as needed, it may end up with slightly different results when you go way out to the right of the decimal point. In some cases, even though the result is more "precise" due to the higher number of bits used during computation, the greater rounding effect of 48 bit versus 64 bit representation may in some cases cause the A-Shell result to appear to be less precise than the AMOS equivalent. This difference may cause A-Shell to come up with different results than AMOS in programs that are not written to take the problems of floating point precision into account. 

For example, the following test, which would appear to always be TRUE, may succeed under 48 bit floating point representation and fail under 64 bit, since the loss of precision is only apparent with the extra bits: 

```
A = 777.77
```

```
IF (A*100) = INT(A*100) ? "EQUAL"
```

There are two ways for this statement to fail or to act differently with different levels of floating point precision. First, the actual result of A*100 may be 77776.99999999. Under the 11 digit significance of 48 bit floating point, this may be the same as 77777, but not under the 14+ digit significance of 64 bit representation. Thus INT(77776.99999999) would be 77776 rather than the expected 77777, making the test fail (by a lot.) Secondly, even if the error was on the high side (i.e. 77777.00000001) and thus didn't affect the INT() operation, the comparison would still fail in 64 bit arithmetic since 77777.00000001 <> 77777. 

OPTIONS=FPROUND will eliminate both parts of the problem. First, by rounding the argument of the INT() function to the nearest integer if within .000005 of it, and second by considering two expressions equal if they are within .000005 of each other. 

A-Shell Reference 

Page 4160 

Note that since feature applies to <= and >= comparisons, you could have the apparently illogical result of A <= B and A > B both being true (if A was .000001 greater than B.) Any program that relied on this kind of precision probably wouldn't work reliably anyway, but it is worth noting. 

Also note that the preferred way to deal with the problem of floating point representation of dollars and cents is to either use SCALE 2, or to store everything as integers, dividing by 100 only for display purposes, or if you prefer to store dollars and cents unscaled, then round your results explicitly as shown here: 

## A = <expression> using "#######.##" 

At the very least, be wary of comparing two floating point expressions for equality, since the chance of perfect equality of two 64 bit floating point results is practically nil. Assigning the expressions to variables and then comparing the variables would at least reduce the precision to 48 bit and thus give you about the same results as you would have gotten on older computers. 

To review, consider the following three cases: 

```
X:  if <expr1> = <expr2>                 (bad idea)
```

```
Y:  A = <expr1> : B = <expr2>
    if A = B                             (better)
```

```
Z:  A = <expr1> using "#######.##"
```

```
    B = <expr2> using "#######.##"
    if A = B                             (best)
```

If you are using the form in case X: or possibly even Y:, then you may benefit from OPTIONS=FPROUND. 

A-Shell Reference 

Page 4161 

## **MIAMEX MX_ROUND** 

A new tool, clumsily called "The Floating Point Variable Rounding Factor", has been introduced in the ongoing battle between floating point imprecision and expected accounting precision. 

The feature consists of the ability to declare a rounding factor for all floating point variables, that is applied whenever the variable is accessed. As an example, if your application stores all monetary figures in pennies (always dividing by 100 to convert to dollars and cents), and has no interest in fractions of pennies, then you could set the rounding factor to 1, which means that all floating point variables would be rounding to the nearest integer whenever they were accessed. On the other hand, if you store some of your amounts in dollars and cents, then you might want to set your rounding factor to .01, meaning that all variables would be rounded to the nearest .01 whenever accessed. The default factor is 0, which means that no rounding is applied. You can set the factor to anything, not just numbers 1 or smaller. For example, a financial statement program for a Fortune 100 company might set it to 1000, which would round every variable to the nearest 1000. Or a point-of-sale program in a country whose monetary system is in transition might set it to the denomination of the smallest common current unit (perhaps 25). The important thing to remember is that the factor, once set, applies to every floating point variable accessed from memory, until it is reset to some other factor. It is not automatically reset at the end of each program. However, it does not apply to LIT programs. 

The concept is somewhat similar to the OPTIONS=FPROUND, but obviously much more drastic. FPROUND operates on expressions rather than variables, generally adding or subtracting a "fudge factor" of .000005 or less, depending on the expression, in order to coerce numbers like 1.9999999997 or 2.00000000001 to "stick" to the nearest integer. (But as you can see from the number of patches to the way it works over the years, the technique is difficult to manage, and sometimes results in making the "problem" seem worse rather than better. The new variable rounding feature is much more blunt, but also more uniform and easy to understand, and thus might actually serve as a magic bullet for some applications which have not conquered the floating point precision problem through other means (such as manually rounding the results of calculations before storing them). 

To query or set the rounding factor, use: 

## **xcall MIAMEX, MX_ROUND, opcode, factor** 

where _opcode_ is 0 to retrieve the current setting and 1 to update it. _Factor_ is the rounding factor. 

The following test program will be useful for testing and experimenting with the feature. 

A-Shell Reference 

Page 4162 

```
SIGNIFICANCE 11
```

```
map1 F1,F
map1 F2,F
map1 FPROUNDFACTOR,F
map1 A$,S,1
```

```
xcall MIAMEX, MX_ROUND, 0,FPROUNDFACTOR
```

```
? "FP Rounding factor is ";FPROUNDFACTOR
input "Change it? ",A$
if ucs(A$)="Y" then &
```

```
    input "Enter new factor (0,1,.1,.01 etc): ",FPROUNDFACTOR :&
```

```
    xcall MIAMEX,MX_ROUND,1,FPROUNDFACTOR
```

```
    LOOP:
```

```
        input "Enter a value: ",F1
```

```
        ? "Value = ";F1
        F2 = F1 / 3
        ? "Value/3 = ";F2;" (";F1/3;")"
        F2 = F1 * .01
        ? "Value*.01 = ";F2;" (";F1*.01;")"
        goto LOOP
```

A-Shell Reference 

Page 4163 

The program illustrates that the variable rounding factor only affects the variables F1 and F2, but does not show up when an expression is printed directly (such as F1/3). 

At the risk of running this topic into the ground, it is worth saying a few words about why the problem exists, why it seems worse (to some people) under A-Shell than under AMOS, and why it sometimes surfaces in programs that were "working" for many years. First, the problem is inherent when floating point values are represented in the computer with a finite number of bits. Even a simple calculation like 7.7/2 might result in 3.849999999998545 rather than the 3.85 you were expecting. In this example, with the 48 bit floating point format used by the Alpha, the effective number of significant digits is about 11, and thus 3.849999999998545 would be internally rounded to 3.85 and you wouldn't notice the problem. But with the 64 bit IEEE format used by virtually every other machine outside of the Alpha, you get about 16 significant decimal digits and thus 

3.849999999998545 would remain as is. As long as you printed it with a mask, e.g. "######.##", it would always appear as "3.85" but if you didn't round it before storing it, subsequent use of the variable would carry the imprecision into other calculations. For example, if you added up several hundred thousand of these kinds of values, each with a slight rounding error, the cumulative error could easily grow to the point that it made a difference in the pennies column. 

The reason why the problem seems worse under A-Shell is simply due to the seemingly paradoxical fact that the more bits of precision, you have in the internal floating point calculations, the more likely your result will be off by a significant digit. For example, if the floating point format could only represent about 2 decimal digits, then the result of every calculation would effectively be rounded to the nearest hundredth. (Which is effectively the "capability" that the new variable rounding factor feature provides.) 

The reason why the problem sometimes suddenly appears in programs that have been working for years, is that as businesses grow and computers get faster, there is a tendency to deal with greater amounts of data and for the computations to increase in complexity. For example, in 1980, a company might have had a payroll of 100 and only a couple of simple deduction types. Now, through mergers and other growth, in both the economy and the tax code, it might have 1000 employees and several more deductions. As the number of calculations increases, the internal rounding errors can accumulate to the point that one day, a paycheck is off by a penny. And suddenly there is a panic. Or, in a more insidious variation of this problem, results from calculations may be stored in files without the rounding errors being first corrected. For example, a product history file might contain a record of the dollar amount of each sale of that product. Assuming the dollar sale amount was the result of a calculation (quantity times price, perhaps with a discount), it might well contain a slight rounding error. As in the example above with 7.7/2 = 3.849999999998545, it may take a long time before this your history file grows big enough for the error to become visible. And since the errors will, on average, split evenly on both the low and high sides, they might tend to cancel themselves 

A-Shell Reference 

Page 4164 

out, on average. But one day, you select the right combination of dates or other reporting factors and voila, the report is off by a penny. 

One way that careful programmers have dealt with this problem is to always use a rounding mask before storing a result, for example, `RESULT = <calculation> USING "#########.##"` . But if you haven't done that all along, you might find it a bit daunting to start now. 

Going back and fixing a problem like the one just described may not be easy, especially if the application now contains thousands of programs. For this kind of situation, the variable rounding factor might provide a near miracle solution. Even if you couldn't be sure whether you might have some variables that are supposed to contain tenths, or hundredths, or thousandths, you can still benefit by setting the rounding factor to, say, .00001 or even .000000001. Since the rounding errors tend to start out in the vicinity of .00000000000001, this would be more than enough to eliminate them as they occur. 

The main thing to watch out for is situations where you really do want to have a precise representation of factions like 1/3. For example, if you wanted to apply a discount of 1/3 to some vary large number, then you probably wouldn't want your 1/3 to be rounded to .33333 (instead of .33333333333). After all, 1/3 of a million is 333,333.33 but if your representation of 1/3 was merely .33333, then the result would be 333,330.00. Note, however, that the rounding factor is only applied to variables, so it would not stop you from getting a precise result for 1000000/3; it would only cause a problem if you set F=1/3 and then multiplied 1000000 by F. 

The final word then, is that if you fear that you have this problem and want to try the new variable rounding factor, start small (perhaps .000000001) and work up if that isn't sufficient. But it goes without saying that this kind of technique should not be applied without some diligent analysis and testing of your application. 

A-Shell Reference 

Page 4165 

## **SCREEN AND DISPLAY ISSUES** 

To view the topics of this section, expand the Table of Contents at left or click on the links below. 

## **Subtopics** 

- Pop-Up Utilities 

- Screen Capture 

- Setting the Window Title 

- A-Shell Screen Elements 

A-Shell Reference 

Page 4166 

## **- POP UP UTILITIES** 

The A-Shell implementation of INFLD supports a built-in hot-key mechanism allowing you to "pop up" utility programs (also known as Desk Accessories) of your own design. When enabled, the designated hot key will launch a child session (or window) of A-Shell which runs ASHPOP.RUN, a simple-minded menu program intended to be modified by you to contain items of interest to you. The source is provided, in [7,376], exactly for this purpose. We also provide a ready-to-use pop-up calculator in a program called ASHCAL. You can use these as is or as templates to put a lot of extra capability at the fingertips of your users. 

A-Shell Reference 

Page 4167 

## **SCREEN CAPTURE** 

INFLD supports the keyboard command (Control-P) to capture a picture (or "snapshot") of the screen; see Screen Pictures. To use this capability under program control, use MX_SCRNPIC. 

## **Having INFLD Generate Automatic Snapshots** 

If you specify the _type_ code **|S** (vertical bar, capital S) in an INFLD call, it will automatically generate a screenshot (appending it to the current BUF file) on exit from the field. By adding `SBR=INFDEF:|S` to miame.ini, you can arrange to create a "slide show" of an entire session. This can be helpful for creating documentation, or for monitoring background processes, or for "snooping" on users (or simply for filling up the disk and creating useless system overhead.) 

A-Shell Reference 

Page 4168 

## **SETTING THE WINDOW TITLE** 

In addition to the AG_MINTITLE (Set Minimized Window Title) and WINTITLE (Set Normal Window Title) commands, which work only under Windows, you can use the SET TITLE command under any A-Shell platform to define variable text which dynamically updates the title bar when any of the control variables specified in the title definition change. Under non-Windows platforms, it requires ZTERM or ATE in order to actually write to the title bar of the terminal emulator. See SET.LIT for details. 

A-Shell Reference 

Page 4169 

## **- A SHELL SCREEN ELEMENTS** 

Shown below are the various screen elements that are or can be used in A-Shell. 

## **1: Window Title Bar** 

By default, A-Shell shows its own version, and ATE shows the name of the connection. May be changed programmatically using AG_WINTITLE, or semi-automatically in response to changing conditions using the SET.LIT TITLE DEFINITION STRING.The icon appearing in the upper left corner, which by default is the A-Shell icon, may be changed using the command line switch for Alternate Icon (-g) or, in ATE, via an option in the connection properties dialog. 

## **2: Standard Buttons** 

The standard Windows buttons, minimize, maximize and close, will always appear unless removed. To remove them, use the command line switch Remove Menu Buttons: (-MX). 

## **3: Standard Menu Bar** 

Standard menu bar. May be removed via the command line switch No Menu No Menu(-nm), or customized programmatically using AUI_MENU commands. 

## **- 4 7: Toolbars** 

These are the top, right, bottom, left toolbars. They may be created programmatically using the Toolbar Control winstyle options CCS_TOP, CCS_RIGHT, CCS_BOTTOM, and CCS_LEFT. The thickness of each toolbar is determined by the size of the button images held within, which must all be the same size for a given toolbar but may differ between toolbars. Unlike most other elements of the screen, toolbars do not scale as the window size changes, other than to match the length of the window edge to which the toolbar is attached. 

## **- 8: Status Line Top** 

This is typically used for auxiliary messages from the host application to the user, sent via the tab(-1,128) or (-1,63) commands. The former always starts from the first position on the line, while the latter takes a position code byte for direct addressable 

A-Shell Reference 

Page 4170 

positioning. In either case, use tab(-1,129) to terminate the print operation. Status lines may be enabled and disabled using the Settings > Status Lines menu options, or programmatically via the Enable / Disable Status Lines command. For ATE they may also be configured using the Connection Properties dialog. 

## **- 9: Status Line Bottom** 

This is similar to the top status line but traditionally used for "function key labeling". There are actually two bottom status lines which toggle visibility depending on whether the Shift key is down. The unshifted line may be written to via the print commands Tab(-1,130) or (-1,54), full line or addressable position, respectively, while the shifted line may be written to via the Tab(-1,131) or (-1,55) commands. As with the top status line, terminate all status line print operations with Tab(-1,129). See top status line notes for enabling/disabling the bottom status line. 

## **- 10: Status Line Session** 

This line is reserved for messages emanating from A-Shell or ATE; for example, notification of a file transfer or print operation. A running session clock is displayed at the right edge of the line. See top status line notes for enabling/disabling. 

## **- 11: Margin Left** 

This is the left margin of the main display grid. The main display area is divided up into a grid (see #13) of a specified number of rows and columns. After dividing the available display area into the specified columns, the remaining pixels are divided in two and used for left and right margins. For example, if the width of the display area is 1000 pixels and there are 80 columns, then each column will be 12 pixels wide (12 x 80 = 960) with 40 pixels left over, which will be divided into left and right margins of 20 pixels each. To minimize the margin area, you can adjust the size of the window by dragging one of the borders. On some monitors, a maximized window may extend slightly beyond the edges of the visible screen, causing the first and last characters of each line to be truncated. To mitigate that problem, you can force a minimum margin for maximized windows, via the Misc Settings. 

## **- 12: Margin Top** 

This is the top margin of the main display grid. It works the same as the left margin; see #11 for explanation. As with left/right margins, the excess vertical space is divided evenly between the top and bottom margins. 

## **13: Main Display Area** 

A-Shell Reference 

Page 4171 

The main display area (grid) is made up of a specified number of rows and columns, usually 24 x 80, but adjustable using the Tab(-5,rows) and (-6,cols); see Terminal Functions and SET.LIT TERMINAL options. In the case of plain text, each character occupies one grid cell, whose size will determine the standard fixed-pitch font. To make that font larger, you can either increase the size of the display area, or decrease the number of rows and columns, or remove some of the status lines and/or toolbars, which otherwise take away from the space available to the main grid. Graphic objects such as proportional font text, edit boxes, buttons and other controls, as shown in the example above, are positioned using the same grid, but are not confined to the onecharacter-per-cell scheme used for plain text. For more precise positioning of graphic objects, you can make adjustments using Millirows and Millicolumns. The objects themselves are typically created with the AUI_CONTROL. 

A-Shell Reference 

Page 4172 

## **HOWTO: RTF PRINTING** 

How do I print RTF files (a) in general, and (b) so that they the _interpret_ RTF commands instead of _printing_ them? 

There are three ways to print files containing RTF commands: 

1. Create a print filter that uses MX_SHELLEX or HOSTEX to force it to be printed by some RTF-aware application (like 

Wordpad). This of course only works if the entire printfile is RTF, and will not work if you want to include this RTF text in a larger report which contains plain text. 

2. Use the internal XTEXT print function. This is similar to option one, but needs to be invoked by the user while looking at the text. 

3. Use the //XTEXT GDI printing command. This is the only option that would allow you to combine XTEXT/RTF within a larger printfile, but it does require that the entire printout file be printed through the GDI printing mechanism. This would rule out direct printing from Linux to the printer; you'd have to instead use the AUXLOC: device to route the printing through ATE. And also would eliminate the use of escape sequences to set printer functions. So it may require some other modifications to your printing logic. But fortunately, GDI reports accept plain text, so it isn't necessary to convert the entire thing to RTF. 

You may also want or need to use MX_GDICALC to calculate the space needed for a particular XTEXT chunk, so that you can decide whether to start a new page first. See the program MMOGDI in EXLIB:[908,37] for an example of that. 

A-Shell Reference 

Page 4173 

## **APPENDIX** 

A-Shell Reference 

Page 4174 

## **RELEASE NOTES** 

- Click here for current release notes, and here for the A Shell Development History covering all releases back to version 1 and 1990. 

A-Shell Reference 

Page 4175 

## **SOLUTIONS AND EXPLANATIONS** 

The A-Shell bulletin board or forum is the main respository of A-Shell questions, solutions and explanations for developers. 

A-Shell Reference 

Page 4176 

## **DISPLAYING TWO NUMERIC VALUES** 

## **A developer writes, January 2024:** 

Found an interesting display problem the other day. Don't know if it has always been there or has shown up with recent updates. It has to do with displaying the total of two numeric values. We have always been able to create a string using 'string = num using mask'. How ever if you try doing it using 'string = (num1+num2) using mask' what you get in the string is the correct digits but the number has been multiplied by 10. In order to get the correct string value you now need to use 'string = 

STR(num1+num2) using mask'. I have attached a test program that you can use to check it out. This occurs whether the display is whole numbers or has decimal points in it. I first thought it had to do with the mask that was being used but finally found that you need to use the STR() format now. Is the STR required or is there a problem with the conversion using the (num1+num2) format? If STR() format is required I think the compiler should be giving you some sort of error message. 

## **MicroSabio Reponds** 

Thanks for the interesting observation. I'm not sure if this problem has always been in AlphaBASIC, as I no longer have access to a working AMOS box. But I think there is a reasonably good chance that it has always been there as a consequence of the combination of two somewhat unique features/curses of AlphaBASIC: 

- The + operator acts as either addition or concatenation, depending on the data type of the arguments 

- Numbers get automatically converted to strings, and vice versa, based on rules which aren't always intuitively obvious. 

The second point uses a rule that sounds simple but quickly gets confusing: basically it says that the first token (variable or literal) in a statement sets the mode for that statement to either numeric or string. Then as we proceed left to right across the statement, the mode causes conversion of strings to numbers or vice versa, and that then affects the interpretation of the + operator. But, the current mode changes in response to certain functions or operators that demand a particular mode. Division, for example, demands numeric mode, so it will auto-convert strings to the right of the / operator into numbers. The STR(x) function 'demands' that x be numeric so that it can be converted to string. So if x is a string, it first gets converted to a number, and then it gets converted to a string by the STR() function, which also causes the mode of the statement to change to string. That's kind of redundant/meaningless with for STR(x), but it becomes significant with STR(x+y), since converting x and y to numbers forces the + to be addition. 

So what's happening in your example is concatenation rather than addition; not some kind 10X factor. Essentially you have something equivalent to: 

A-Shell Reference 

Page 4177 

```
((164408 + 0)/100) using mask
```

which would result in 1,644.80 as expected. But if you assign the output to a string variable, i.e: 

```
string$ = ((164408 + 0)/100) using mask
```

then the mysterious auto-conversion rules kick in. Since string$ is a string variable, the compiler switches the mode from numeric to string, which causes the arguments to the right of the equals sign to be converted to strings. The 0 is getting appended, resulting in 1644080, which then becomes 16440.80 when divided by 100. So it essentially becomes: 

```
string$ = ((str(164408) + str(0))/100) using mask
```

Your workaround of using STR around the (num1+num2) overrides that, somewhat paradoxically, because the STR() function expects numeric arguments. So it treats the num1 + num2 as a numeric addition. 

I'll admit that it seems pretty screwy, but I didn't invent that logic. And unfortunately there is no global switch to disable this mode-conversion logic and force + to act as addition. However, A-Shell does have a pair of Explicit Plus Operators, (#+ for addition and $+ for concatenation) that can be used as one way of short-circuiting this problem. That is, you could use 'string = (num1 #+ num2) using mask' to force addition instead of concatenation. 

Another alternative is to use an intermediate numeric value to receive the result of those addition operations before plugging them into the string PLINE, i.e. 'tempnum = (num1 + num2) using mask'. 

This is probably the one quirk in AlphaBASIC that causes the most problems, and virtually always it's in a situation like this where you stumble on it unexpectedly after writing thousands of programs! Don't feel bad; I'm confident it has happened to everyone, some of whom may just not realize it yet. 

A-Shell Reference 

Page 4178 

## **BOOLEAN VALUES IN INI FILES** 

Initialization file options that take a Boolean argument are somewhat internationally minded. The table below shows first-letter responses and A-Shell interpretation as true or false. 

|**True**|**False**|
|---|---|
|T (True)|F (False,Falso)|
|Y (Yes)|N (No,Non)|
|1|0|
|ON|OFF|
|Sí||
|Si (Sim)||
|OU (Oui)||
|Al (Allineare)||
|V (Verdad,vrai,verdadeiro)||



A-Shell Reference 

Page 4179 

Any other starting letter will be checked against the current LDF (language definition file) to see if it matches the singlecharacter yes or no definitions. 

A-Shell Reference 

Page 4180 

## **SOSLIB AND EXLIB** 

## **SOSLIB** 

The A-Shell Shared Open Source Library ("SOSLIB") is a collection of common definitions and useful routines. They are organized into PPNs in the [907,*] range, with each PPN focusing on a particular subject or area. The library is maintained in an online repository https://bitbucket.org/microsabio/soslib where you can obtain details and downloads. 

If you have been referred to a specific file, follow the link above, then "Source" in left column, then PPN, then file. 

## **EXLIB** 

The A-Shell Example Library ("EXLIB") is a collection of standalone example programs designed to illustrate or test particular A- Shell features. They are organized into PPNs in the [908,*] range, with each PPN focusing on a particular area. The library is maintained in an online repository https://bitbucket.org/microsabio/exlib where you can obtain details and downloads. 

If you have been referred to a specific file, follow the link above, then "Source" in left column, then PPN, then file. 

## **Downloading** 

When you follow the above links to the SOSLIB or EXLIB pages at the MicroSabio online respository, you will see "downloads" in the left pane of the page, like this: 

Clicking on "downloads" will lead to the option to "download repository;" clicking on that will begin a download of the entire SOSLIB or EXLIB into a ZIP file on your local machine. 

## **Updating Local Library** 

Unfortunately, updating your local copy of the library is not quite as straightforward as downloading. Once you have the ZIP file downloaded, there are basically two problems: 

- The steps to updating the libraries differ between Windows and Linux. The files are the same, but how you unzip and 

- distribute them is different depending on platform. 

A-Shell Reference 

Page 4181 

- You must make sure that you don't overwrite your custom versions of the files with new generic versions of those files. Since 

- you are knowledgeable and competent programmer, you will of course take precuations to not overwrite any customized versions of SOSLIB files. 

To update your local copy of the SOSLIB under Windows: 

- Use a zip/unzip program, or Windows' File Explorer, to get the multiple folders/directories from the ZIP file into their own 

- unzipped folder. 

- Open a second File Explorer window that shows your A-Shell directory tree and DSK0. Position the first and second windows 

- so you can see and access them both at the same time. 

- In the window containing the recent downloads, select all of the individual folders (click on first folder, SHIFT+click on the last 

- folder). 

- Drag-and-drop those folders (50 or so) onto DSK0 in the other window 

You should have now replaced all of your old SOSLIB files and folders with the new versions from the recent download. 

A-Shell Reference 

Page 4182 

## **ASHINC INCLUDE FILES** 

The ASHINC: ersatz directory (normally DSK0:[907,16]) contains the ++INCLUDE files supplied with A-Shell. Although these files are not mandatory for programming, they help minimize the confusion and potential for error inherent in the complicated data structures and thousands of opcodes, options and flags which are typically employed in XCALL and function parameters. By referencing the relevant ++INCLUDE files in your programs, you gain instant access to standardized MAPs, structures, and symbols that make your programs easier to read, write, and share with others, as well as maximizing the utility of our documentation, which is heavily indexed and/or searchable on these same symbols and map/structure names. 

The most recent versions of the ASHINC files can—and regularly should—be obtained from SOSLIB:[907,016]. 

The ASHINC: directory contains the following kinds of files, identified by their extension: 

|**Extension**|**Description**|
|---|---|
|DEF|Symbol definitions (e.g. define MBF_STATIC = &h00040000)|
|MAP|MAP statements|
|SDF|Structure definitions|
|BSI|Actual code ( including MAP statements, function/procedure definitions, etc.)|



Other than a small version signature (about 40 bytes), DEF and SDF files do not increase the size of the resulting RUN programs. They merely expand the "vocabulary" of the compiler. They do, however, require the COMPIL /X:2 switch. When there is both an SDF and MAP file, the SDF is generally preferable, as it allows multiple copies of the structures to be declared, using your own prefixes. The MAP files represent the older approach used before defined structures were introduced. 

A-Shell Reference 

Page 4183 

Here is an overview of the most commonly used files. New ones are added periodically, typically with names matching the XCALL or subsystem to which they refer. 

|**Filename**|**Description**|
|---|---|
|ashell.bsi|Code commonly used in LIT programs (e.g. command line processing)|
|ashell.def|A core set of symbols used in nearly every A-Shell program, especially those containing MIAMEX calls|
|ashell.sdf|Structure definitions associated with common MIAMEX calls|
|csidl.def|CSIDL_xxxx symbol definitions (used byMX_BROWSEFOLDERXSandMX_GETSHELLPATHXS)|
|evtmsg.def|Symbols used withEVTMSGXS|
|gtlang.map|Mapped structure used byGTLANGXS(get language definition)|
|hook.def|Symbols used by the file hook mechanism (seeMX_FILEHOOKXS)|
|http.def|Symbols used byHTTPXS|
|isam.def|Symbols related to ISAM|
|jobtbl.def|Symbols related to fields in the job table|



A-Shell Reference 

Page 4184 

|ell Reference|Page 4184|
|---|---|
|jobtbl.map|Mapped structure representing JOBTBL.SYS records - seeMX_READJCBXS|
|msboxx.def|Symbols related toMSBOXXXS|
|regex.def|Symbols related to regular expressions|
|sql.def|Symbols related toSQLXS|
|trmchr.map|Mapped structure used byTRMCHRXS(terminal characteristics)|
|xcall.bsi|Startup code useful in writing custom SBX routines|
|xtext.def|Symbols related toXTEXTXS|
|xtext.sdf|Structure definitions forXTEXTXSparameters|
|xtree.def|Symbols related toXTREEXS|
|xtree.map|Mapped structures compatible withXTREEXS|
|xtree.sdf|Structure definitions forXTREEXSparameters|



A-Shell Reference 

Page 4185 

## **ASB ERROR CODES** 

Following is a list of ASB errors. Note that: 

· The system displays the description for untrapped errors by loading it from the SYS:ERRMSG.xxx file where xxx is the LANGUAGE extension defined in the corresponding LDF file—e.g. USA, SPA, POR, ITA, CDN, FRE. 

- Programs can retrieve the description for an error number using the function ERRMSG(x) or ERRMSGXS. 

|**Number**|**Description**||**Number**|**Description**|
|---|---|---|---|---|
|001|Operator interrupt||071|Undefined dynstruct<br>member|
|002|System error||072|Undefined dynamic<br>function|
|003|Out of memory||100|Error during error trapping|
|004|Out of data||102|(DISAM) EBADARG illegal<br>argument|
|005|NEXT without FOR||103|(DISAM) EBADKEY illegal<br>key desc|
|006|RETURN without GOSUB||104|(DISAM) ETOOMANY too<br>many files open|



A-Shell Reference 

Page 4186 

|ell Reference||||Page 4186|
|---|---|---|---|---|
|007|RESUME without error||106|(DISAM) ENOTEXCL non-<br>exclusive access|
|008|Subscript out of range||108|(DISAM) EKEXISTS key<br>already exists|
|009|Floating point overflow||112|(DISAM) ENOCURR no<br>current record|
|010|Divide by zero||114|(DISAM) EFNAME file<br>name to long|
|011|Illegal function value||115|(DISAM) Record/Key size<br>overflow|
|012|Subroutine not found||117|(DISAM) EBADCOLL bad<br>custom collating|
|013|File already open||118|(DISAM) ELOGREAD<br>cannot read log rec|
|014|IO to unopened file||119|(DISAM) EBADLOG bad<br>log record|
|015|Record size overflow||120|(DISAM) ELOGOPEN<br>cannot open log file|



A-Shell Reference 

Page 4187 

|ell Reference||||Page 4187|
|---|---|---|---|---|
|016|File specification error||121|(DISAM) ELOGWRIT<br>cannot write log rec|
|017|File not found||122|(DISAM) ENOTRANS no<br>transaction|
|018|Device not ready||123|(DISAM) unknown error|
|019|Device full||124|(DISAM) ENOBEGIN no<br>begin work yet|
|020|Device error||126|(DISAM) EBADROWID<br>unknown error|
|021|Device in use||127|(DISAM) ENOPRIM no<br>primary key|
|022|Illegal user code||128|(DISAM) ENOLOG no<br>logging|
|023|Protection violation||129|(DISAM) EUSER unknown<br>error|
|024|Write protected||130|(DISAM) ENODBS<br>unknown error|



A-Shell Reference 

Page 4188 

|ell Reference||||Page 4188|
|---|---|---|---|---|
|025|File type mismatch||132|(DISAM) EROWSIZE row<br>size too big|
|026|Device does not exist||133|(DISAM) EAUDIT audit<br>trail exists|
|027|Bitmap kaput||201|Incompatible ISAM file|
|028|Disk not mounted||202|ISAMP.SYS not found in<br>memory|
|029|File already exists||203|Index blocks less than<br>minimum|
|030|Redimensioned array||204|Data file full|
|031|Illegal record number||205|Index file full|
|032|Invalid filename||206|Cannot change key|
|033|Stack overflow||207|Index structure smashed|
|034|Invalid syntax code||208|Attempt to add duplicate<br>key|



A-Shell Reference 

Page 4189 

|ell Reference||||Page 4189|
|---|---|---|---|---|
|035|Unsupported function||209|Insufficient free index<br>blocks|
|036|Invalid subroutine version||210|Invalid number|
|037|File in use||211|Exceeds maximum<br>percentage|
|038|Record in use||212|Too many index blocks|
|039|Deadly embrace possible||213|Invalid record size|
|040|File cannot be deleted||214|Too many concatenated<br>keys|
|041|File cannot be renamed||215|Primary key information<br>must be entered|
|042|Record not locked||216|Exceeds maximum key<br>size|
|043|Multiple link translation||217|Invalid key type|
|044|Lokser queue is full||218|Exceeds maximum binary<br>size|



A-Shell Reference 

Page 4190 

|ell Reference||||Page 4190|
|---|---|---|---|---|
|045|Device not file structured||219|Key outside record|
|046|Illegal ISAM sequence||220|Overlap keys not numeric|
|047|Random channel 0 illegal||221|Too many data file blocks|
|048|File not open||222|Exceeds second key<br>directory|
|049|File already open||223|No such secondary key<br>number|
|050|Remote not responding||224|Secondary key is deleted|
|051|First logical unit not<br>mounted||225|Dumped record no.<br>mismatch|
|052|Illegal key||226|Key information must be<br>entered|
|053|Illegal key number||227|Cannot delete primary key|
|054|String overflow||228|ISAM+ file already exists|
|055|Undefined array in XCALL||229|Data file smashed|



A-Shell Reference 

Page 4191 

|ell Reference||||Page 4191|
|---|---|---|---|---|
|060|Illegal assignment to<br>iterator||230|System error|
|061|Invalid reference to<br>collection||231|ISAM+ file needs to be<br>rebuilt|
|063|Func/Proc parameter<br>type/size mismatch||232|Null record found -<br>removed|
|064|Unsupported type (S?) or<br>scope<br>(local) of array passed by<br>reference||233|Unknown error condition|
|065|External library error||250|Hangup signal (SIGHUP)<br>received|
|066|Mismatched collection<br>types||251|Termination signal<br>(SIGTERM) received|
|067|Invalid collection<br>operation or reference||252|Your queue has been<br>Zapped!|
|068|Collection types not<br>supported in this runtime||253|Error in socket<br>communication to queue<br>server|



A-Shell Reference 

Page 4192 

|ell Reference||||Page 4192|
|---|---|---|---|---|
|069|ATE comm breakdown,<br>client unresponsive||254|Inactivity timeout|
|070|Invalid dynstruct<br>reference||255|Window closed|



A-Shell Reference 

Page 4193 

## **ZTERM ESCAPE SEQUENCES** 

A-Shell emulates some of the more common ZTERM ESC sequences, as described below. 

Note that most of the features provided by the ZTERM escape sequences are also available in A-Shell/Windows via a Tab(-10,x) sequence or a subroutine. The advantage of the Tab(-10,x) or XCALL method is that the same code will work under A-Shell/Windows and A-Shell/Unix with ATE on the client. But the advantage of the ZTERM ESC sequences is that they would work on any server platform (i.e. one that you telnet to) provided the client is ZTERM or ATE. But in the latter case, you should test to make sure you aren't running locally on A-Shell/windows, where the ESC sequences would not make much sense. 

|**ZTERM**<br>**Esc Seq**|**Tab(-10)**<br>**Command**|**Subroutine**|**Comment**|
|---|---|---|---|
|27,27,3|||EnableSerial Passthrough|
|27,27,4|||DisableSerial Passthrough|
|27,12|24|MX_SHELLEX|Execute or print windows file ("shell execute")|
|27,22|23|HOSTEX|Execute Windows command ("win exec")|
|27,15||MX_GETIP|Get client IP address|
|27,1,127|22||FTP file transfer|
|27,13|1, 2|MX_TITLE|Label window|



A-Shell Reference 

Page 4194 

|**ZTERM**<br>**Esc Seq**|**Tab(-10)**<br>**Command**|**Subroutine**|**Comment**|
|---|---|---|---|
|27, 25|27|MX_SHOW WINDOW|Set window state|
|27,16|28||Flash window|
|27,29|29||Set ftp login name/password|



Many of the ZTERM ESC sequences use a CHR(0) (aka null byte) as a delimiter. However, if for some reason you have difficulty sending null bytes, you can use CHR(128) as an equivalent alternative. 

## **Examples** 

## **Execute or print windows file ("shell execute")** 

```
?CHR(27) CHR(12);OP$;FSPEC$;CHR(0);
```

```
   (OP$ is "O" to "open" or "P" to "print)
```

```
INPUT A              ! CR for ok, Control-C for error
```

## **Execute windows command (aka "win exec")** 

```
?CHR(27);CHR(22);CMD$;CHR(0);
INPUT A               ! CR for ok, Control-C for error
```

A-Shell Reference 

Page 4195 

## **Get client ip address** 

```
?CHR(27);CHR(15);
```

```
INPUT "",IP'ADDR$
```

## **ftp file transfer** 

```
?CHR(27);CHR(1);CHR(127);DIR$;HOSTDIR$;CHR(0); &
```

```
   HOSTFILE$;CHR(0);PCFILE$;CHR(0);
```

```
INPUT A
```

ATE supports transferring entire directories, in addition to single files, by setting the HOSTFILE$ or filename portion of PCFILE$ to “*”. 

## **Label window** 

```
?CHR(27);CHR(13);TITLE$;CHR(0);
```

- `! sets title for both normal and minimized window` 

## **Set window state** 

- `?CHR(27);CHR(25);CMD$ !(CMD$ is M, X, R, or N)` 

## **Flash window** 

```
?CHR(27);CHR(16);"1"            ! start flashing
```

- `?CHR(27);CHR(16);"0"            ! stop flashing` 

A-Shell Reference 

Page 4196 

## **Set ftp login name/password** 

- `?CHR(27);CHR(29);NAME$;CHR(0);PW$;CHR(0);` 

## **Subtopics** 

- Serial Passthrough 

- Extended Example 

A-Shell Reference 

Page 4197 

## **SERIAL PASSTHROUGH** 

A-Shell/ATE supports ZTERM-type serial passthrough. 

Enable passthrough: 

```
? chr(27); chr(27); chr(3); params$; chr(0);
```

Disable passthrough: 

```
? chr(27); chr(27); chr(4);
```

_params$_ is of the form: 

```
"<port#>,<baud>,<parity>,<databits>,<stopbits>"
```

For example: 

```
"1,9600,E,7,2" (COM1, 9600 baud, even parity, 7 bits, 2 stopbits)
```

When enabled, input from the serial port is merged into the keyboard channel input. Output characters are not normally sent to the serial port. To enable that, send ^X (ASCII 24); send ^T (ASCII 20) to disable. Note that these are the standard AUX PORT ON/OFF commands for the AM6x emulation, but when they are sent while serial passthru is enabled, they have the effect of sending the output to the defined serial port rather than to the printer port. 

A-Shell Reference 

Page 4198 

## **EXTENDED EXAMPLE** 

The following example uses the login name/password stored in the ATE configuration for the ftp name/password. The function to temporarily set a new name/password has not yet been implemented. 

```
GET ZTERM/ATE ID:
```

```
   ?CHR(27);"?";
```

```
   xcall GET,BUFFER,0,2,RCVD,1000
```

```
   IF RCVD<2 goto NOT'ATE'ZTERM
```

```
   xcall TINKEY,A$               ! extra char?
   ?CHR(27);"?";
```

```
   xcall GET,BUFFER,0,3,RCVD,1000
```

```
   IF RCVD<2 goto NOT'ATE'ZTERM
```

```
   xcall TINKEY,A$               ! extra char?
   ?CHR(27);"?";
```

```
   xcall GET,BUFFER,0,2,RCVD,1000
```

```
   IF RCVD<2 or BUFFER#"ZT" goto NOT'ATE'ZTERM
   ?CHR(27);"?";
   xcall GET,BUFFER,0,14,RCVD,200
   ? "VERSION=";BUFFER
```

Most AMxxx and WYxxx terminals will respond to ESC ? with 2 bytes indicating the (row and col each offset by 32). However, to be more robust, you should allow for the possibility that the terminal will not respond at all to ESC ?, or that it will give you an extra byte (possibly a trailing CR or a leading ^Y for columns > 96). The above code uses GET[XS] with the timeout option to input 

A-Shell Reference 

Page 4199 

up to 2 chars, aborting after 1000 ms. It then uses TINKEY to grab any extra character without waiting. This sequence is repeated 4 times. After the 3rd time, ATE will respond with "ZT" (like ZTERM does). After the 4th time, it will return you "AV" following by the version string. (This is where you can distinguish ATE from ZTERM.) 

A-Shell Reference 

Page 4200 

## **ROW AND COLUMN CODES** 

These codes are used to encode numeric control information used by certain Tab functionsinto one or two ASCII bytes. Control values above 96 all use two bytes, with the first byte being Control-Y or ASCII byte number 25. 

|**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**|
|---|---|---|---|---|---|---|---|
|1|(space)||45|L||89|x|
|2|!||46|M||90|y|
|3|"||47|N||91|z|
|4|#||48|O||92|{|
|5|$||49|P||93|||
|6|%||50|Q||94|}|
|7|&||51|R||95|~|
|8|'||52|S||96|(del)|
|9|(||53|T||97|^Y (space)|



A-Shell Reference 

Page 4201 

|**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**|
|---|---|---|---|---|---|---|---|
|10|)||54|U||98|^Y !|
|11|*||55|V||99|^Y "|
|12|+||56|W||100|^Y #|
|13|,||57|X||101|^Y $|
|14|-||58|Y||102|^Y %|
|15|.||59|Z||103|^Y &|
|16|/||60|[||104|^Y '|
|17|0||61|\||105|^Y (|
|18|1||62|]||106|^Y )|
|19|2||63|^||107|^Y *|
|20|3||64|_||108|^Y +|



A-Shell Reference 

Page 4202 

|**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**|
|---|---|---|---|---|---|---|---|
|21|4||65|`||109|^Y ,|
|22|5||66|a||110|^Y -|
|23|6||67|b||111|^Y .|
|24|7||68|c||112|^Y /|
|25|8||69|d||113|^Y 0|
|26|9||70|e||114|^Y 1|
|27|:||71|f||115|^Y 2|
|28|;||72|g||116|^Y 3|
|29|<||73|h||117|^Y 4|
|30|=||74|i||118|^Y 5|
|31|>||75|j||119|^Y 6|



A-Shell Reference 

Page 4203 

|**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**|
|---|---|---|---|---|---|---|---|
|32|?||76|k||120|^Y 7|
|33|@||77|l||121|^Y 8|
|34|A||78|m||122|^Y 9|
|35|B||79|n||123|^Y :|
|36|C||80|o||124|^Y ;|
|37|D||81|p||125|^Y <|
|38|E||82|q||126|^Y =|
|39|F||83|r||127|^Y >|
|40|G||84|s||128|^Y ?|
|41|H||85|t||129|^Y @|
|42|I||86|u||130|^Y A|



A-Shell Reference 

Page 4204 

|**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**||**Row or**<br>**Col**|**ASCII**|
|---|---|---|---|---|---|---|---|
|43|J||87|v||131|^Y B|
|44|K||88|w||132|^Y C|



A-Shell Reference 

Page 4205 

## **VIRTUAL KEY SYMBOLIC NAMES** 

The Virtual Key Symbolic Names provide a convenient notation for specifying certain control characters to be transmitted into the input buffer in response to a click event on the control; See the CONTROL class _cmd_ parameter, the XTREE _XTR.kbdstr_ , the XTEXT _TXC.kbdstr_ , etc.) The names all start with VK_ followed by the name of the key as it relates to the keyboard. The names in the table below can also be altered to indicate the SHIFT or CONTROL version by inserting a “^” and/or lower case “s” after the underscore. For example, “VK_^UP refers to the keystroke Control-Up Arrow, “VK_sDOWN” refers to Shift-Down Arrow, and “VK_^sF2” refers to Control-Shift-F2. 

Note that the Virtual Key Symbolic Names can optionally be enclosed in percentage signs ("%"), e.g. "%VK_RIGHT%", which act only as syntax delimiters. Such delimiters would be unnecessary and superfluous in most cases, except in the case where multiple Virtual Key Symbolic Names are being combined. For example, to encode the sequence TAB followed by ENTER, you would need to use the format "%VK_TAB%%VK_ENTER%", since "VK_TABVK_ENTER" would not be properly recognized. 

|**Virtual Key**|**Meaning**|
|---|---|
|VK_BACK|Backspace|
|VK_DECIMAL|Decimal point on numeric keypad|
|VK_DELETE|Delete key|
|VK_DOWN|Down arrow|
|VK_DIV|Forward slash ( "/" ) on the numeric keypad|
|VK_END|End key|



A-Shell Reference 

Page 4206 

|**Virtual Key**|**Meaning**|
|---|---|
|VK_ENTER|Enter key (same as VK_RETURN)|
|VK_ESCAPE|Escape key|
|VK_HOME|Home key|
|VK_INSERT|Insert key|
|VK_LEFT|Left arrow|
|VK_MINUS or VK_SUB|Minus key on the numeric keypad|
|VK_NEXT|Next Page or Page Down Key|
|VK_PLUS or VK_ADD|Plus key on the numeric keypad|
|VK_PRIOR|Prev Page or Page Up Key|
|VK_RETURN|Return key (same as VK_ENTER)|
|VK_RIGHT|Right arrow|



A-Shell Reference 

Page 4207 

|**Virtual Key**|**Meaning**|
|---|---|
|VK_TAB|Tab key|
|VK_UP|Up arrow|
|VK_F1 thru VK_F12|F1 thru F12 keys|
|VK_x{r,d}F###|Extended virtual function key codes. See next topic.|
|^x|Control x where "x" is any character A-Z or [, /, ], ^, _)|



## **Subtopics** 

- VK_x{r,d}F### 

A-Shell Reference 

Page 4208 

## **VK_X{R,D}F###** 

The sequence "VK_x{r,d}F### allows you to generate a wide range of exitcode values in response to various click events for the associated control. 

The optional "{r,d}" may be replaced with "", "r", "d", or "rd" (to enable special handling for right click and/or double click events), and "###" is replaced by a numeric string in the range of 1 to 999999 (defining the exitcode value). The actual byte sequence transmitted will be chr(7) + chr(250), followed by the string of digits (corresponding to the ###), and terminated with a period ("."). You can input and interpret such stings yourself using a character-level input routine (such as GET, ACCEPN[XS] or the GETKEY() function), but many higher level A-Shell routines which wait on operator input events (e.g. INFLD, XTREE, XTEXT, EVENTWAIT, etc.) will do the translation for you automatically, returning the corresponding numeric _exitcode_ value. The following table of examples will help clarify: 

|**Code String**|**Click Event**|**Raw Byte Sequence**|**Exitcode**|**Notes**|
|---|---|---|---|---|
|VK_xF123|Left Click|chr(7),chr(250),"123."|-123|Left click exitcodes are negative|
||Right Click|chr(7),chr(250),"123."|-123|Since no "r" in code string, right click same as<br>left|
|VK_xrF42|Left Click|chr(7),chr(250),"42."|-42|Note: ### values < 100 not recommended<br>since they may overlap other pre-defined<br>exitcode values|
||Right Click|chr(7),chr(250),"-42."|42|"r" present; right click sequence contains "-"<br>but exitcode is positive|
||Left DblClick|chr(7),chr(250),"42.",chr(7),<br>chr(250),"42."|-42,-42|"d" not present; double click is same as 2<br>regular clicks|



A-Shell Reference 

Page 4209 

|**Code String**|**Click Event**|**Raw Byte Sequence**|**Exitcode**|**Notes**|
|---|---|---|---|---|
|VK_xrdF9999|Left Click|chr(7),chr(250),"9999."|-9999||
||Right Click|chr(7),chr(250),"-9999."|9999||
||Left DblClick|chr(7),chr(250),"9999.",<br>chr(7),chr(250),"9999000."|-9999,<br>-9999000|First click generates normal sequence; second<br>(double) click generates extended version with<br>extra "000" (x1000). See comments.|
||Right DblClick|chr(7),chr(250),"-9999.",<br>chr(7),chr(250),"-9999000."|9999,<br>9999000|Same as left double click except with positive<br>values.|



## **Comments** 

Double-click handling is particularly tricky, since by the time the second click is recognized as being part of a double-click sequence, the first click has already been responded to (by generating the corresponding single-click sequence and exitcode). So in order for this to make sense, the application's response to a double-click has to be a logical extension or continuation of its response to a single click. For example, in a screen full of clickable appointment indicators, the single click event might result in more information being displayed about the appointment, while the double click might launch a dialog to allow editing of the appointment attributes. By contrast, if the single clicked caused the application to change its context, it might then no longer be in a position to properly respond to the double click exitcode. 

A-Shell Reference 

Page 4210 

## **LIMITS AND CAPACITIES** 

## **Files and Related** 

For details on ISAM-A files, see ISAM-A Specifications & Features. 

|**Item**|**Size / limit / capacity / description**|**Updated in A-Shell**<br>**build...; old value**|
|---|---|---|
|Files|none; see ISMA-AFile Size Limits<br>.|948 of Dec 05; 2GB|
|Filenames|72+8 (72 character filename plus 8 character extension).<br>Allowable characters are A-Z, 0-9, dollar sign ( $ ),<br>hyphen ( - )  and underscore ( _ ).|1662 of June 2019; 10+3|
|Expanded DO file|~122K|864 of Feb 04; 62K|
|Random file record size|No limit. Note, however, that this applies to READ and<br>WRITE operations; there is a 2048 byte limit for SERCH.|1246 of Apr 12; 64K|
|EFS limit of sequential files open|512 (or theFILESspecification inmiame.ini, whichever<br>is less).|1244 of Feb 11; 30|
|Range of file channels|0 to 2^31 -1||



**Subroutines** 

A-Shell Reference 

Page 4211 

|**Item**|**Size / limit / capacity / description**|**Updated in A-Shell**<br>**build...; old value**|
|---|---|---|
|Number of parameters than can be passed<br>to a subroutine, function or procedure|1024|6.5.1628 of Feb 2018; 128|
|Size of subroutine name|Six characters for internal SBR names, ten<br>characters for SBX names.||
|Size of a parameter passed in or out of a<br>subroutine|2**24-1 (16,777,215) bytes||
|Number of subroutines on disk or called in<br>a single program|No limit||
|Number of modules that can be loaded into<br>user memory|96 (per job). Subroutines are modules, but<br>unless manually loaded (withLOAD.LIT) they<br>will be auto-loaded, cached, and auto-updated if<br>the SBX on disk gets updated. Auto-loaded<br>modules will be freed to make room for new<br>ones as needed.|854 of Nov 03; 32|
|AUI: number of controls|No limit. The control table expands as needed.|1166.6.1 of 16 Nov 09; 600|
|AUI: number of menu items|No limit. The menu table expands as needed.|1166.6.1 of 16 Nov 09; 250|



A-Shell Reference 

Page 4212 

|ell Reference|||
|---|---|---|
|AUI_MENU: length of individual menu item<br>command line|200||
|AUI_MENU: length of individual menu item<br>description|64|1159 of Sep 09; 32|
|BASORT: max record size|6K|7.0.1778 of Sep 25; 4K|
|INFLD: length of entry (multi-line field)|No limit|1159 of Sep 09; 16K|
|INFLD: length of multi-line edit box (|M)|4K|6.5.1671 of Nov 19; 1600|
|INFLD: SETDEF match length|300|1111 of May 08; 50|
|INFLD: tooltip characters|1023|5.1.1175, 300|
|MX_CLIPBOARD: buffer size|No limit|1194 of Nov 10; 3K|
|MX_GETOFD:_fname_parameter length|256|1222 of Jul 11; 80|
|MX_FINDFIRST, MX_FINDNEXT,<br>MX_FINDEND|20: number of directories (or sub-directory<br>levels) open via MX_FINDFIRST for scanning<br>with MX_FINDNEXT without closing via<br>MX_FINDEND||
|MX_PWCRYPT: password length|128|1175 of Feb 10; 24|



A-Shell Reference 

Page 4213 

||||
|---|---|---|
|MX_SHELLEX: parameter length|1024 individual parameter; 4096 for all<br>parameters combined|1202 of Jan 11; 500|
|PCKLST: rows|32K||
|REGEX: submatches|100|1210 of Mar 11; 20|
|XTEXT: line length|1998 characters|1253 of June 12; 998|
|XTREE: columns|200, may be editable or not|1691 of Oct 2020; 100|
|XTREE: rows|No limit|1159 of Sept 09;|
|XTREE: number of trees allowed|No limit|old limit = 32|
|XTREE: tooltip length|1023 characters|1205 of Feb 11|
|XTREE: multi-level trees|63|1737 of Aug 23; 9|



## **Compiler** 

**Item Size / limit / capacity / description Updated in A-Shell** 

A-Shell Reference 

Page 4214 

|||**build...; old value**|
|---|---|---|
|Length of a single BASIC statement<br>including continuations|16K|6.5.1628 of Feb 2018; 128;<br>3K|
|Nested ++INCLUDEs|38|6.4.1547 of March 2017; 20|
|Nesting level of SWITCH statements|8||
|Nesting level of TRACE_BEGIN / END<br>blocks|38|6.5.1644 of Aug 2018; 1|
|One Time ++INCLUDEs|No limit|5.1.1235 of Oct 11; ~400|
|Length of a variable or symbol name|260||
|Length of a DEFSTRUCT name|64||
|Number of dimensions (subscripts) in an<br>array|16||
|Number of variables|Without /AV switch, about 6400 (fewer for<br>arrays); with /AV, about 1.6 million||
|Size of RUN module|Without /A switch, calls/gotos limited to about||



A-Shell Reference 

Page 4215 

|ell Reference|||
|---|---|---|
||64K;; with /A switch, about 16 million||
|Size of DATA embedded in RUN|512K|6.5.1657 of March 2019|
|Number of functions/procedures|No specific limit other than memory available to<br>compiler||
|Number of defines, deftypes|||
|DATA statements|1024 bytes|6.5.1721 of Nov 2022; 512<br>bytes|



## **Other** 

|**Item**|**Size / limit / capacity / description**|**Updated in A-Shell**<br>**build...; old value**|
|---|---|---|
|//XL parameter length|512 characters|6.5.1725 of Feb 203; 256<br>characters|
|Ordered map key length|Unlimited|6.5.1716 of May 2022; 511<br>bytes|
|Windows printer names|100 characters|5.1.1148 of May 2009; 50|
|Print filter SBX names|10 characters|6.2.144 of Jan 2016; 6|



A-Shell Reference 

Page 4216 

|ell Reference|||
|---|---|---|
|ATE server side timeout on initial<br>handshake|6 seconds|6.2.144 of Jan 2016; 3|
|Scrollback buffer|200 lines|6.2.1422 of Jan 2016; 100|
|Associative array key|511 bytes|6.2.1421 of Nov 2015; 259|
|QUEUE|65,535||
|DEVICE name|Three or four alphabetic characters, followed by<br>one or two numeric digits, with a maximum<br>length of five combined characters.||
|Device definitions|300 for Unix, 1000 for Windows||
|Ersatz name|One to ten alphabetic or numeric characters,<br>starting with an alphabetic character, and<br>immediately followed by a colon.||
|Ersatz table auto-refresh|Every 30 seconds||
|Ersatz devices allowed|1000|979 of Jan 06; 400|
|ERSATZ=fspec length|160|1208 of Mar 11; 70|
|Printer ini file line length|256 characters|987 of Apr 07; 100|



A-Shell Reference 

Page 4217 

|ell Reference|||
|---|---|---|
||||
|Trace message in ashlog.log, length|2000||
|Trace.print statement, length|16K|1639 of July 2018; 800|
|Ashlog.log maximum filesize|10MB; new file with extension .01, .02, etc. will<br>be created when maximum filesize  is reached|1662 of June 2019; 3MB for<br>Win, 5MB for Unix|
|Command line length|300 characters|916 of Feb 05; 200|
|Number of GUI objects that can be<br>defined at any one time|No limit|1166 of Nov 09; 250|
|Number of modules that can be loaded<br>into user memory|128 (per job). Note that subroutines are<br>modules.|6.5.1679 of April 2020; 96|
|Input CSV line length|No limit|995 of Sep 07; 4K|
|INPUT statement, all forms|No limit|uncertain; 4K|
|Windows printer name|100 characters|1148 of May 09; 50|
|Command line history buffer|25 lines|1168 of Dec 09; 10|



A-Shell Reference 

Page 4218 

|ell Reference|||
|---|---|---|
|VUE line length|There is effectively no limit. When opening a file,<br>VUE reads the longest line in the file and to that<br>number adds 8K.|6.5.1631 of February 2018,<br>VUE edit 371; previously<br>VUE looked only at the first<br>100 lines, and then added<br>1K, with an overall minimum<br>limit of 4K.|
|Dynamically Sized Variables|No limit||
|HOST.LITresponse capture buffer|256|2.0(105) of Aug 11; 64K|
|PAD$(expr,len) return expression length|4096|1175 of Feb 10; 257|
|TAB(col) columns|4095|1105 of Feb 08; 472|
|Buffer to expand strings containing<br>%env% variables.|No limit|512 bytes; 6.0.1263 of Oct<br>12|
|Nested function/procedure calls|Set limit of 99 as a way of reducing the<br>likelihood and severity of problems caused by<br>accidental infinite recursion.|Unlimited; 6.1. 1387 of July<br>2014|
|Length of individual GDI print directives|No limit|512 bytes; 6.5.1664 of<br>August 2019|



A-Shell Reference 

Page 4219 

## **LIBRARIES** 

A-Shell makes use of several libraries, which are listed here. The "Notes" column in the tables indicates: 

- The source of the library: (1) developed by Microsabio; (2) purchased/licensed from external commerical sources; (3) open 

- source modules. 

- Whether the library is included with all installations of A-Shell (a), or is included only if needed and/or by special arrangement 

- (b). 

Note also that the actual library name may incorporate platform and/or version data into its name. For example, the table below lists "SftTree," while the actual filename of the DLL is "SftTree_IX86_U_75." 

## **Windows** 

A-Shell uses the following Dynamic Linked Libraries (DLLs). 

|**Name**|**Notes**|**~Size KB **|**Description**|
|---|---|---|---|
|ashico1|1, a|10,480|A-Shell icon library.|
|ASHNET|1, a|3,026|Network-related functions.|
|ASHNET2|1, a|713|SSH services for ATE.|
|FTPDLXcall2|1, a|52|FTP functions used in FTPDLX.|
|HTS14|2, a|576|HTML support for XTEXT.|
|libashmysql|1, a|16KB|ASQL interface to MySQL connector.|



A-Shell Reference 

Page 4220 

|libxl|2, a|6,327|Spreadsheet functions.|
|---|---|---|---|
|pcre3|3, a|137|Perl compatible Regular Expressions.|
|SftPrintPreview|2, a|853|APEX functions.|
|SftTabs|2, a|750|TABX control|
|SftTree|2, a|620|XTREE.|
|spell32|2, a|92|Spell-checking used in XTEXT.|
|TER19|2, a|1,680|XTEXT control.|
|txml2|2, a|92|Allows .docx files to be imported to XTEXT.|
|vic32|2, a|228|Graphics and images.|
|victw32|2, a|60|TWAIN support.|
|wodFtpDLX|2, a|920|FTP functions used in FTPDLX.|



**Name Notes ~Size KB Description** 

A-Shell Reference 

Page 4221 

|||||
|---|---|---|---|
|libashodbc|1, b|24|ASQL interface to OBDC connector.|
|libashtls|1, b|16|TLS support for TCPXxs.|
|libgnutls|3, b|2010|GNUTLS (required for libashtls)|
|libtasn1|3, b|160|GNUTLS.|
|libgpg-error|3, b|110|GNUTLS.|
|libgcrypt|3, b|1650|GNUTLS.|
|ucibv|3, b|870|GNUTLS.|
|libfcgi|3, b|40|Fast CGI support.|



## **Linux** 

**Name Source ~Size KB Description** 

A-Shell Reference 

Page 4222 

|ell Reference||||
|---|---|---|---|
|libashmysql||40|ASQL interface to MySQL connector|
|libashtls||20|TLS support for TCPXxs|
|libxl||3200|Spreadsheet functions|
|libashnet||6180|CRYPTOxs|



## **Subtopics** 

- ASHNET 

- ASHNET2 

A-Shell Reference 

Page 4223 

## **ASHNET** 

_Updated December 2022_ 

This library, available under Windows as ashnet.dll and under Linux as libashnet.so, contains core logic for several networkrelated subroutines and functions, including: 

- HTTP[XS] 

- PDFX Email Type 4 

- CRYPTO[XS] 

- FTP2[XS] 

- OAUTH2[XS] 

If needed, see the following topics, ASHNET Status Codes and Google Cloud Access Token 

## **Update Notes** 

## 1775.0.1 ASHNET.DLL / libashnet.so 1.14.204 refinement: 

|**ASHNE**<br>**T**<br>**Edit**|**A-Shell**<br>**Version**|**Release**<br>**Date**|**Description**|
|---|---|---|---|
|204|1775.0.1|2025 Aug|Support base32 encoding and decoding in Xcall CRYPTO. New flag CRYPTF_KEYBASE32<br>(&4000) added to crypto.def to support keys encoded in base32, needed to support 2FA|



A-Shell Reference 

Page 4224 

|**ASHNE**<br>**T**<br>**Edit**|**A-Shell**<br>**Version**|**Release**<br>**Date**|**Description**|
|---|---|---|---|
||||/ TOTP (two factor authentication using time-based one time passwords) generated by<br>smart phone authenticator apps.|
|200<br>199<br>198|7.0.1767|2025 Jany|Support UTF8-Latin1 conversion on HTTP response by adding the following to the<br>properties parameter:<br>ResponseCharset=UTF<br>or<br>ResponseCharset=ANSI<br>Add Internal support library / protocol updates for OAUTH2, SFTP, FTP2, TLS, CRYPTO,<br>etc.<br>Add support for new XHTTPF_NOTLS13 flag in XCALL HTTP|
|197|7.0.1761|2024 July|Update the manifest to resolve an issue where the DLL load would fail due to a<br>manifest-related conflict with some other module. Note that Linux version number was<br>also updated to 197 for consistency, although the manifest issue doesn't apply there,<br>making 196 and 197 essentially identical.|
|196|7.0.1759|2024 June|ASHNET.DLL / libashnet.so 1.14.196 update, OAUTH2 bug fix: <\003><redirect><br>clause in refresh'token$ wasn't working.|
|195|7.0.1759|2024 May|ASHNET.DLL / libashnet.so 1.14.195 update: Add optional parameter add'param to<br>OAUTH2xs.|



A-Shell Reference 

Page 4225 

|**ASHNE**<br>**T**<br>**Edit**|**A-Shell**<br>**Version**|**Release**<br>**Date**|**Description**|
|---|---|---|---|
|194|7.0.1757|2024 Apr|ASHNET.DLL / libashnet.so  1.14.194 update<br>•<br>FTP2xs : fix issue with attempt to create remote directory would return a failure<br>code if the directory already existed.<br>•<br>SFTP: fixed failure when client and server selected ssh-dss algorithm<br>•<br>HTTPxs: fix TLS 1.3 session resumption issue|
|193|7.0.1757|2024 Apr|ASHNET.DLL / libashnet.so.1.14.193 update: fixes an internal function linking failure<br>caused by some internal updating of common functions in A-Shell 7.0.1757.3.<br>libashnet.so no longer contains dynamic links back to the ashell executable, so this<br>update will work with older ashell executables but not the other way around. Problem<br>did not affect Windows DLL version.|
|192|7.0.1757|2024 Mar|ASHNET.DLL 1.14.192 update:<br>•<br>FTP2xs fix for issue with servers that issue an intermediate 150 response<br>indicating a delay for anti-virus scanning.<br>•<br>FTP2xs XFTPF_RENAME no longer invalidates the cached directory contents,<br>eliminating a directory reload for a slight performance improvement.<br>•<br>FTP2xs safeguard added to block an empty string from matching all files in a<br>wildcard delete operation. It now returns an error.<br>•<br>SFTP mitigation of SSH Terrapin Attack by adjusting the availability of of the<br>supported SSH algorithms.|
|191|7.0.1752|2023 Nov|Updated to support OAUTH2 authentication in PDFX Email Method 4, identified by the|



A-Shell Reference 

Page 4226 

|**ASHNE**<br>**T**<br>**Edit**|**A-Shell**<br>**Version**|**Release**<br>**Date**|**Description**|
|---|---|---|---|
||||"[oauth2]" prefix on the password.|
|190||2023 Aug|Close a memory (handle) leak in HTTP.|
|189|6.5.1736|2023 Aug|Various library/protocol updates and fixes:<br>•<br>FTP2xs TLS 1.3 session resumption issues with FileZilla fixed<br>•<br>FTP2xs fixed issue with wildcard directly listings on some servers<br>•<br>SFTP max packet size limitation wasn't being respected<br>•<br>HTTPxs default character now UTF-8 as it was supposed to be but previously was<br>ANSI|
|188|6.5. 1722|2022 Dec|Resolve various issues:<br>•<br>Office365 TLS negotiation<br>•<br>FTP2xs TLS negotiation and wildcard operations.<br>•<br>FTP2xs session reuse error with FileZilla Server v1.3<br>•<br>FTP2xs (SFTP) support added for ecdsa-sha2-nistp521 and -nist384 algorithms<br>•<br>OAUTH2 refinement for Microsoft endpoints to fix browser caching|
|187||2022 Nov|Support OAUTH2 OP_DEBUG flag; create oauth2dbg.log in OAUTH2.|



A-Shell Reference 

Page 4227 

|**ASHNE**<br>**T**<br>**Edit**|**A-Shell**<br>**Version**|**Release**<br>**Date**|**Description**|
|---|---|---|---|
|186||2022 Oct|Modernize RSA priv/pub key loading; support other formats besides PEM; support mode<br>3 pw decryption (http); add asutil.|
|185||2022 Oct|Fix uninitialized keybits in crypto; fix broken XHTTPF_SSL_xxx symbols.|
|184|6.5.1717|2022 June|Various fixes and enhancements to ASHNET, mostly motivated by Google Drive<br>requirements, including functionality to get aGoogle Cloud Access Token<br>.|
|183|||HTTPxs XHTTPF_FILERESP now supports the option to specify two file specs, separated<br>by a vertical bar, e.g "resp1.txt|resp1.dat". When the second file is specified, if the<br>response body is compatible, HTTP will extract an embedded file from the complete<br>response into the specified file.|
|182|||HTTPxs verbs: to specify a verb other than GET or POST, use the XHTTPF_HDRBODY<br>option to add a header of the format < Verb: xxxxxx > where xxxxx may be any verb<br>recognized by the server (e.g. PATCH, DELETE, etc.) Note that you still need to specify<br>either  XHTTPF_REQPOST or XHTTPF_REQGETX.|
|181|||HTTPxs XHTTPF_HDRBODY now works with XHTTPF_REQUPLOAD. As with all other<br>XHTTPF_HDRBODY cases, put your special headers at the top of the request body (file<br>or string), then a blank line (CRLF), then the body of the request, which in this case<br>would be the list of files to upload.|
|180|||HTTPxs XHTTPF_REQGETRAW now handles binary response bodies.|



A-Shell Reference 

Page 4228 

|**ASHNE**<br>**T**<br>**Edit**|**A-Shell**<br>**Version**|**Release**<br>**Date**|**Description**|
|---|---|---|---|
|179|6.5.1717|2022 Aug|Close a memory corruption loophole exposed by uninitialized S,0 parameters.|
|177|6.5.1709|2021 Dec|Enhancements: (1) FTP2TIMEOUT now affects SFTP as well as FTP2; (2) XFTPF_RMVEXT<br>(&h0200) now works for FTP2xs (SFTP mode only) as it does in FTPDLX.|
|175,<br>176|6.5.1703|2021 May|Fixes some issues with FTP2xs. Also includes minor updates to the underlying HTTP and<br>SSL/TLS libraries.|



## **2019 May, Ashnet 1.12.165** 

• When the XHTTPF_REQGET call fails, it now returns an abbreviated status message in the response parameter instead of the full library debug string. In cases where the call succeeds in connecting to the endpoint, but the endpoint service then rejects the request, the response will be an HTTP header—e.g. "415 Unauthorized." In the case of a complete failure to connect, the response will be empty or "0". The status parameter will give additional information, as will a subsequent call using XHTTPF_GETSTSTXT. 

• A new opcode flag, XHTTPF_REQGETX (&h01000000) has been defined to implement a more advanced version of the "GET" operation. Currently the main visible difference is that the returned reponse will be more detailed in the case of a successful connection but a failed transaction, due to some kind of logic or validation issue on the server. The HTTP.DEF file contains the updated symbol definition. 

• You can now include custom headers—using XHTTPF_HDRBODY—with the string request versions of the XHTTPF_REQPOST and XHTTPF_REQGETX operations. Previously this was only possible with XHTTPF_FILEREQ, file based requests. Format the 

A-Shell Reference 

Page 4229 

request string the same way you would the file, i.e. with CRLF between each custom header, then a blank line (terminate by CRLF), then, in the case of _REQPOST, the body of the request. GET operations have no request body. 

## **2019 May, Ashnet 1.12.164** 

Refinement to HTTP to allow custom headers to be added to a GET request (XHTTPF_REQGET). Previously this was only possible with the POST request type (XHTTPF_REQPOST / XHTTPF_REQUPLOAD). To specify custom headers, set the XHTTPF_HDRBODY flag and put the new headers into the request$ parameter, using chr(13) to separate multiple headers, e.g.: 

```
flags = XHTTPF_REQGET or XHTTPF_HDRBODY
```

```
request$ = "Referer: http://www.microsabio.com"
```

```
request$ += chr(13) + "User-Agent: A-Shell/ashnet-1.2.164"
```

```
...
xcall HTTP, 1, status, flags, url$, request$, response$, properties$
```

Note that you must specify at least 7 parameters—i.e., at least thru the properties$ parameter—even if the properties$ parameter is blank. Otherwise a more limited version of the routine will be used, which doesn't support this enhancement. 

You can also put the custom headers into a file, as you would with XHTTPF_REQPOST + XHTTPF_FILEREQ + XHTTPF_HDRBODY. With the GET request, anything following the first blank line would be ignored. 

Note that to examine/debug your headers, set the XHTTPF_DEBUG flag and then look at the DEBUG.LOG file on return from the XCALL. 

## **2018 October, Ashnet 1.12.163** 

New subroutine OAUTH2 implements the industry-standard OAUTH2 protocol for authorization via the ASHNET library update 1.12.163. 

## **2018 May, Ashnet 1.11162** 

- Support secure protocols TLS 1.1 and TLS 1.2 in HTTP via the new flags: 

A-Shell Reference 

Page 4230 

|**Symbol**|**Value**|**Description**|
|---|---|---|
|XHTTPF_SSL_TLS11|&h01000000|TLS 1.1 (or higher)|
|XHTTPF_SSL_TLS12|&h02000000|TLS 1.2 (or higher)|



- Fix problems with the ashnet.log file (XHTTPF_DEBUG) not getting written or released under some circumstances. 

- Remove 100 character limit on header lines included at the top of the request (using XHTTPF_HDRBODY). Maximum length 

- is now unlimited, which is useful when headers include lengthy signatures or digests. 

- Append a connection failure code to the XHTTPF_GETSTSTXT return string, as well as the ashnet.log file to assist with 

- debugging failed connections. See the Connection Failure Codes for a listing of the codes and meanings. 

## **2016 November, Ashnet 1.8.153, 54** 

Relink with updated SSL, SFTP and HTTP libraries to incorporate many minor bug fixes and improvements in the underlying libraries over the last 11 months. The DLL is backwards compatible to A-Shell and ATE 6.2. 

The properties options introduced in 1.8.153 now apply to the HTTPF_REQGET ("simple get") operation as well as the other operations/modes; previously they were ignored for the simple get. Also, the default timeout parameters (30 seconds on connection, 75 on read) now apply to the HTTPF_REQGET operation even if properties are not explicitly specified. Previously the timeouts were indeterminate, but definitely shorter than the new defaults. 

## **2014 May, Ashnet 1.7.145** 

Security-related enhancement: 

- supports public/private key authentication for SFTP via AG_FTP or FTPDLX. 

- fixes problems with SFTP downloads without explicit local paths. 

A-Shell Reference 

Page 4231 

- fixes a bug in CRYPTO[XS] where the dst parameter was being truncated if needed to allow for an explicit trailing null. 

- supports new CRYPTO[XS] function to generate public/private key files. 

Note: requires ASHW32.EXE 6.1.1385.0+ and should be updated at same time. 

## **2013 July, Ashnet 1.4.137** 

- Implements support for initial functionality of CRYPTO[XS] 

## **2013 June, Ashnet 1.4.135** 

- Support new HTTP[XS] arguments _certfile_ and _certpw_ 

## **Update Notes: 2012 October/November, Ashnet 1.4.132** 

- User agent in headers now shows, for example, "ashnet 1.4.131." 

- Now accepts port specifications embedded in the URL, i.e. http://www.mydomain.com:10080/mypath. Previously it only 

- accepted the port if it was appended to the end of the URL, but that is a non-standard syntax and results in the port not being included in the "Host: domain{:port}" header of a POST request. The syntax shown above, i.e. {scheme}<domain>{:port} {path} is preferable. 

- The DEBUG.REQ file (copy of the request) had an extra CR at the end of each line (CRCRLF instead of CRLF). This didn't 

- affect the actual request, but may have confused tech support efforts. 

- When the XHTTPF_DEBUG flag is set, in addition to creating the DEBUG.REQ file, it also appends a line to ashnet.log 

- indicating the ashnet.dll version, domain, port, SSL flag and return status, e.g.: 

HttpRequest v127 to www.mydomain.com port 10080 (SSL) rc=201 HTTP/1.1 201 created 

This serves mainly to eliminate doubts during debugging as to where and how the request (DEBUG.REQ) was sent. 

In addition, a new log file, DEBUG.LOG, will be created that combines lower level details about the individual steps performed within the operation, but also a transcript of what is sent and received over the wire. 

- Support custom Content-Type prefixes for uploaded files using XHTTPF_REQUPLOAD 

A-Shell Reference 

Page 4232 

- Support separate option to retrieve the HTTP status text using XHTTPF_GETSTSTXT 

- If the operation fails to connect to the server, a verbose log of the request details is now written to the file DEBUG.LE (e.g. 

- LastError), which might be helpful in debugging. 

• Added XHTTPF_REQGETRAW: like XHTTPF_REQGET (&h0020) but works around a limitation of XHTTPF_REQGET in which certain characters outside the range supported by Latin1/ANSI (e.g. Russian or Chinese) would just be dropped from the response. Can also be used to retrieve binary data containing embedded nulls (such as a file), although you must then use XHTTPF_FILERESP (&h0200) to write the response to a file. 

## **Subtopics** 

- ASHNET Status Codes 

- Google Cloud Access Token 

A-Shell Reference 

Page 4233 

## **ASHNET STATUS CODES** 

_Updated June 2022_ 

The following status (or error) codes can be returned from the various ASHNET-based routines (including FTP2, HTTP, CRYPTO and OAUTH2), typically in the status parameter. In some cases individual routines may have their own status symbols defined but they all derive from this table. 

Note the existence of a function Fn'AshNet'Error$(status) in the SOSLIB fnashnet.bsi module which returns the descriptions from the table. 

|**Symbol**|**Valu**<br>**e**|**Description**|
|---|---|---|
|ANETERR_TOOFEW|-1|too few params|
|ANETERR_NOMEM|-2|can't malloc (or out of malloc hdls)|
|ANETERR_BADOPCODE|-3|no such Opcode|
|ANETERR_PERR|-4|misc param error|
|ANETERR_LIBLINK|-5|can't dynamically link library|
|ANETERR_LICENSE|-6|license failure|
|ANETERR_ADDFILE|-7|error during adding file (upload)|



A-Shell Reference 

Page 4234 

|**Symbol**|**Valu**<br>**e**|**Description**|
|---|---|---|
|ANETERR_SYNCREQ|-8|error during SyncRequest|
|ANETERR_POSTFILE|-9|error processing file for post|
|ANETERR_STRALC|-10|unable to allocate string buf|
|ANETERR_PUTREQ|-11|error during put|
|ANETERR_DOWNLOAD|-12|error during download|
|ANETERR_LOGIN|-13|unable to log in to server (FTP OR SSH)|
|ANETERR_DIR|-14|unable to log to directory on server (FTP)|
|ANETERR_CONNECT|-15|failure to connect (ssh)|
|ANETERR_SESSION|-17|open session  failure (ssh)|
|ANETERR_PTY|-18|pty (termtype?) failure (ssh)|
|ANETERR_SHELL|-19|shell startup failure (ssh)|



A-Shell Reference 

Page 4235 

|**Symbol**|**Valu**<br>**e**|**Description**|
|---|---|---|
|ANETERR_RECV|-20|error receiving data (ssh)|
|ANETERR_SEND|-21|error sending data (ssh)|
|ANETERR_DISCONNECT|-22|connection lost (ssh)|
|ANETERR_NOCHANNEL|-23|no channel (ssh)|
|ANETERR_EOF|-24|received eof (ssh)|
|ANETERR_CERT|-25|cert problem|
|ANETERR_GET|-26|get failed (no access?)|
|ANETERR_BADCIPHER|-27|bad cipher type|
|ANETERR_BADKEYLEN|-28|invalid key len|
|ANETERR_BADCIPHERMOD<br>E|-29|bad cipher mode|
|ANETERR_BADPADDING|-30|bad padding value|



A-Shell Reference 

Page 4236 

|**Symbol**|**Valu**<br>**e**|**Description**|
|---|---|---|
||||
|ANETERR_BADFILE|-31|bad file (or file error)|
|ANETERR_CRYPTERR|-32|catch-all CRYPT errors|
|ANETERR_BADENCODE|-33|bad encoding|
|ANETERR_BADPUBKEY|-34|bad public key (or error extracting it)|
|ANETERR_BADPRVKEY|-35|bad private key (or error extracting it)|
|ANETERR_OPENREMOTE|-36|failure to open remote file|
|ANETERR_BUSY|-37|attempt to call function already executing|
|ANETERR_UPLOAD|-38|error uploading (possibly local file doesn't exist?)|
|ANETERR_CLOSEREMOTE|-39|error close remote|
|ANETERR_DEL|-40|error during remote delete|



A-Shell Reference 

Page 4237 

|**Symbol**|**Valu**<br>**e**|**Description**|
|---|---|---|
|ANETERR_OAUTH2_FC|-41|OAuth2 failed to complete|
|ANETERR_OAUTH2_DENIE<br>D|-42|OAuth2 denied|
|ANETERR_OAUTH2_FLOW|-43|OAuth2 unexpected flow state|
|ANETERR_RENAME|-44|error renaming remote file or dir|
|ANETERR_VERIFY|-45|xmlsig failed to verify|
|ANETERR_LOADSIG|-46|error loading signature|
|ANETERR_ADDREF|-47|invalid addref argument (XMLSIG)|
|ANETERR_PLATFORM|-99|unsupported platform (Windows only)|
|**Definition file:**fnashnet.bsi|||



A-Shell Reference 

Page 4238 

## **GOOGLE CLOUD ACCESS TOKEN** 

The ability to get a Google Cloud access token was added to the ASHNET library (1.14.184) to support an operation that arises when the owner of an object stored in Google Cloud Storage wants to make it available to an external user. In such a case, instead of requiring the standard browser-based OAUTH2 authentication, the owner can provide a private key, which the 

recipient can then use to request the an access token directly. Because of the special nature of the operation, it was not exposed as a standard A-Shell XCALL, but may still be called using the generic DYNLIB routine, as follows: 

## **funcsig$ = "GetGoogleCloudAccessToken(Zziz)i"** 

## **xcall DYNLIB, dlctl, funcsig$, prvkey$, token$, sizeof(token$), url, rc** 

## **Parameters** 

_prvkey$_ (String)  [in] 

is a json string containing a private key, something like: 

```
{
```

```
"type": "service_account",
```

```
"project_id": "chilkattest-1350",
```

```
"private_key_id": "fa2e36ee26986eab628b59868af8bec1d1c64c38",
```

```
"private_key": "-----BEGIN PRIVATE KEY-----\nMII....jSdy\n-----END PRIVATE KEY-----\n",
```

```
"client_email": "598922945xxxxxxxxxxxxa@developer.gserviceaccount.com",
```

```
"client_id": "5989229452xxxxxxxxxxxxxxxxa.apps.googleusercontent.com",
```

```
"auth_uri": "https:!accounts.google.com/o/oauth2/auth",
```

```
"token_uri": "https://accounts.google.com/o/oauth2/token",
```

- `"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",` 

```
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/m...com"
```

A-Shell Reference 

Page 4239 

```
}
```

## _token$_ (String, 2048)  [out] 

receives the access token 

_cb_ (Num)  [in] 

specifies the size of the token$ parameter 

_url_ (String)  [in] 

optional url; default: https://www.googleapis.com/auth/cloud-platform 

_rc_ (I4)  [out] 

return code (0 for success, else ANETERR_xxx codes) 

A-Shell Reference 

Page 4240 

## **ASHNET2** 

ASHNET2, like ASHNET, is a wrapper for various third-party library functions, making them conveniently accessible to A-Shell and ATE. In particular, ASHNET2.DLL provides SSH services to ATE which are built around the open source libraries LIBSSH2 and OpenSSL. 

|**ASHNET2**<br>**Edit**|**ASHNET2**<br>**Version**|**A-Shell**<br>**Version**|**Release**<br>**Date**|**Description**|
|---|---|---|---|---|
|212|2.5|7.0.1757|2024 Mar|Library Updates:<br>•  LIBSSH2 1.11.0; drop OpenSSL, now using WinCNG backend<br>•  OpenSSL 1.1.1w; from Shining Light Productions; superseded by<br>WinCNG above<br>•  ZLIB 1.3.1; compiled from source; zlib.lib renamed to zlibstat.lib|
|211|2.4|6.5.1724|2023 Jan|•  Retry in RECV routine to reduce spurious unexpected receive error<br>(-43) disconnects (didn't help)<br>•  Library Updates:<br>•  OpenSSL 1.1.1s (from Shining Light Productions)|
|||6.5.1688|2020 Sept|ATE transport library upgraded to OpenSSL 1.1.1g to incorporate many<br>accumulated protocol and security upgrades, bug fixes, etc. The updated<br>ASHNET.DLL 1.1.173 now supports SHA3 hash algorithms in the<br>CRYPTOxs CRYPTOP_HMAC operation via new mode parameter symbols in<br>crypto.def<br>.|
|210||6.5.1686|2020 July|Replace straggler sprintf() with sprintf_s().|



A-Shell Reference 

Page 4241 

|ell Reference|||||
|---|---|---|---|---|
|||||Library updates:<br>•  OpenSSL 1.1.1g; now just libcrypto32MD and libssl32MD; no more<br>libeay32MD or ssleay32MD<br>•  ZLIB 1.2.11; compiled zlibstat.lib from source<br>•  LIBSSH2 1.9.0; same as before<br>•  link with crypt32|
|209|2.3|6.3|2017 Sept|Fix bug failing to do DNS conversion on hostnames starting with #.|
|208|||2017 Feb|Recompile/link to update:<br>•  OpenSSL from 1.0.1g to 1.0.2k<br>•  LIBSSH2 from 1.4.3 to 1.8.0<br>•  Switch to VC2013 (required for OpenSSL package)<br>•  Don't allow connection if fingerprint needs update (and not auto-<br>accept) but user doesn't have access. Pprevents unsecure connection by<br>non-privileged user.|
|207|||2017 Feb|Recompile/link to update:<br>•  ZLIB 1.2.8<br>•  Return better error details on connection failure (ASHNET2.LOG)<br>•  Allow read access to stored ssh fingerprint for all-user configs in non-<br>admin mode /jdm|



A-Shell Reference 

Page 4242 

|ell Reference|||||
|---|---|---|---|---|
|206|2.2||2014 Dec|Return better error details on recv error.|
|205|2.2|6.1.1385|2014 May|Security-related enhancement:<br>•  supports public/private key authentication for SFTP viaAG_FTPor<br>FTPDLX.<br>•  fixes problems with SFTP downloads without explicit local paths.<br>•  fixes a bug inCRYPTOXSwhere the dst parameter was being truncated<br>if needed to allow for an explicit trailing null.<br>•  supports newCRYPTOXSfunction to generate public/private key files.<br>Note: requires ASHW32.EXE 6.1.1385.0+ and should be updated at same<br>time.|



A-Shell Reference 

Page 4243 

## **LINUX VERSIONS AND UPDATES** 

As you know, Linux comes in a variety of flavors/brands/models, and each of those change over time, resulting in multiple versions being out in the world and possibly needing to host A-Shell. The material here is NOT intended to be a catalog of those models and versions, but rather a simple listing of the ways in which A-Shell has adapted to the ever-changing Linux environment. Whenever there is a relevant update to A-Shell made because of or in response to a new version of Linux, an update note will be posted here. 

|**A-Shell Version**|**Date**|**Description**|
|---|---|---|
|1751.5.1|Nov 2023|Debian 12 ("Bookworm") version beta release. The Ubuntu 22 and Debian 12<br>executables are cross-compatible, but the Debian 12 uses a newer version of GCC (12<br>vs 11) and uses separate package repositories.|
|1740.1.1|Sept 2023|64 bit executables released for Ubuntu 22 and CentOS Stream 8 platforms.|
|1674.0|June 2020|Initial release of A-Shell for RHEL8/CentOS8.|
|1600.0|May 2017|Linux: Begin internal changes to support 64 bit executable. The ashell executable is<br>usable, but lacks several features, including support for collections. It does however<br>support MSODBC/Linux for connecting to SQL Server, which is only available in 64 bit<br>version.|



A-Shell Reference 

Page 4244 

## **- A SHELL HISTORY AND ORIGINS** 

As you probably have noticed, there are some terms used in this documentation that are not exactly intuitive or immediately understood by today's programmers. In fact, you may have been wondering why such unusual terminology is used for functions or concepts that exist everywhere in the computer world. What, for example, are PPNs? Or random access files? Or ersatz devices? Or VUE? Or LIT files? 

All of these things and more are explained by the story of A-Shell beginnings. 

Back in the mid-to-late 1970s, a company called Alpha Microsystems (hereafter "AM") was created to bring to market the first multi-user micro computer—"micro" in this context meaning "computer on a (single integrated circuit) chip." You can read about - AM and its computers on Wikipedia and on the S 100 website if you would like more information. 

In addition to AMOS (Alpha Micro Operating System), the engineers at AM created an enhanced version of the BASIC language. Over the next ten or fifteen years, AM prospered and grew as small companies around the world realized they could obtain and manage an affordable business computer. With some few exceptions, all of the programs that made the computer popular and successful were written in AlphaBASIC. There were programs, and computer dealers, to perform every imaginable kind of computer task and business function. At the peak of its lifecycle, AM had some 300 computer dealers worldwide. 

Unfortunately for AM and many firms in the computer business, including some big players such as HP, IBM and Digital Equipment Corporation, the personal computer revolution made small and mid-sized business computers largely obsolete. It didn't happen overnight, but the writing was on the wall: the future of computing was the PC. 

But what about all those programs written in AlphaBASIC? How are they going to work, when the hardware they were built for is no longer available? Computer dealers and end-users had invested thousands of hours and tens or hundreds of thousands of dollars in their programs and their businesses, and now those investments were at serious risk. 

What was needed was an AMOS work-alike—i.e., a compiler and operating environment that would allow those AlphaBASIC programs to run on non-AM hardware. Several firms created such systems, and A-Shell arguably was—or became—the best of them. The target audience for A-Shell was, of course, people and firms that were used to working with AlphaBASIC and AM computers. So of course A-Shell used the terms, language, concepts, file types, access methods, etc., that were in use in the AM world. 

Following are descriptions and histories of some of those terms and concepts. 

## **Subtopics** 

A-Shell Reference 

Page 4245 

- File Organization, Devices, PPNs 

A-Shell Reference 

Page 4246 

## **FILE ORGANIZATION, DEVICES, PPNS** 

AMOS organizes disk space into physical devices, logical units, and a pair of octal numbers referred to as the "p,pn" for "programmer, project number.". Within this structure are the files, which consist of a one-to-six character name and a one-tothree character extension. The characters used in filenames are from the "RAD50" set, which consists of 0-9, A-Z, and $. No part of the filespec is case sensitive. For example, the following are equivalent: 

```
DSK0:COPY.LIT[1,4]
```

```
dsk0:copy.lit[1,4]
```

```
Dsk0:Copy.Lit[1,4]
```

In these examples, the physical device is DSK, the logical unit is 0, and the PPN is [1,4]. The file name is COPY and the extension is LIT. 

Under AMOS, a logical unit was essentially a partition within a physical disk device, more or less equivalent to a drive letter under Windows. Within each logical unit, there were individual directories identified by a pair of octal numbers (each ranging from 0-377) referred to as a "PPN" (Project, Program Number). Individual directories (i.e. a PPN within a logical unit within a physical unit) could also be assigned aliases, called ERSATZ devices, which have the syntax of device names. This is similar to the situation under Windows where a drive letter can be mapped to another directory. These ERSATZ devices are defined in a text file DSK0:ersatz.ini[1,4]. You can add your own; each one must consist of up to six "RAD50" characters starting with an alphabetic character. 

A-Shell Reference 

Page 4247 

## **ADMINISETERA** 

The information in this section applies not only to this document but to all MicroSabio help files and documentation. 

- All of MicroSabio's documentation regarding the A-Shell family of software products can be found on the A Shell website at Downloads...Documentation. 

If you have any questions or need additional information, contact MicroSabio. 

A-Shell Reference 

Page 4248 

## **GENERAL INFORMATION** 

## **Publisher** 

MicroSabio 

6520 Platt Ave., #104 West Hills, CA 91307  USA 

web site: www.microsabio.com 

email: info@microsabio.com 

telephone: 805-543-2679 

## **Authors** 

Jack McGregor has been developing and documenting A-Shell since 1994, and his authorship continues through the date of this publication. Ty Griffin is responsible for editing, formatting, spilling and pulbishing. 

## **Support** 

MicroSabio provides good support for A-Shell and its other software products. 

- The first place to go with a question is the A Shell forum, also known as the "Bulletin Board" (BBS) or  the "A-Shell Network." You can search the forum by keyword, quite possibly finding the answer(s) you need. If not, then post your question there; you have to create an account to post a question, but doing so is painless and free. Email us if you have any problems or questions about signing up. All of the forums are moderated by MicroSabio, which means that if another user or developer does not answer your inquiry, MicroSabio staff will. 

The main MicroSabio web site contains information about A-Shell and its various modules plus documentation, prices and related materials. 

If you are not getting satisfaction via these support avenues, send MicroSabio an email message with your question and it will be answered promptly. 

A-Shell Reference 

Page 4249 

MicroSabio provides free email support for A-Shell operational issues to anyone with a current software maintenance contract, and also within the first 90 days of purchasing a license. If you are running a demo copy for evaluation purposes, you can obtain free support on the BBS. If you would like a free pre-sales consultation, please contact MicroSabio. Either of these avenues is also a good way to discuss or initiate a request for more advanced support than what we can provide for free, such as help with developing subroutines, custom enhancements to A-Shell, etc. We pride ourselves on providing a higher level of support than most other software developers with whom you may be familiar, so don't hesitate to take advantage of it. 

## **Software History** 

Following is a table showing A-Shell versions and dates published. If you are trying to track down when some particular thing - was introduced or changed, you might try searching the A Shell History documentation available on our Documentation web page. 

|**While Under Development**|**While Under Development**|**While Under Development**|**At Formal Release**|**At Formal Release**|**At Formal Release**|
|---|---|---|---|---|---|
||**First Release**|||**Final Release***||
|**Version**|**Build **|**Date**|**Version **|**Build**|**Date**|
|6.5|1600|Spring 2017|7.0|1750|September 2023|
|6.3|1500|November 2015|6.4|1545|March 2017|
|6.1|1300|Spring 2012|6.2|1421|Autumn 2015|
|5.1|1100|November 2007|6.0|1270|Autumn 2011|
|4.9|850|October 2003|5.0|997|Autumn 2007|



A-Shell Reference 

Page 4250 

|4.7|796|February 2002|4.8|833|June 2003|
|---|---|---|---|---|---|
|4.5|652|November 1998|4.6|712|December 1999|
|4.2|507|August 1996||||
|**|468|August 1995||||
|4.0|463|August 1995||||
|3.0|310|August 1993||||
|2.0|134|June 1991||||
|1.0|100|February 1990||||



## * Bug fixes continue to be applied past the date of the "final" release. 

** John Bown was the original developer of A-Shell, and continued through build 467. With build 468, Jack McGregor took over development responsibilities. 

## **Documentation History** 

Prior to 2002, A-Shell documentation was published in PDF format. In 2002, a new documentation system and format was adopted, and version numbers for the documentation—as well as printed manuals—were abandoned. Between 2002 and 2010, documentation was published in the CHM format, with PDF and DOC (MS Word) files available on request. Since 2010, all A-Shell documentation has been online in an HTML-based format called "WebHelp." 

A-Shell Reference 

Page 4251 

## **DOCUMENTATION** 

## **Using This Document** 

The author of this help file says: 

- Click on the little folder next to the topic name in the table of contents; this will expand/contract the listing of items under 

- that heading. 

- Use the _Index_ and _Search_ functions to quickly find topics of interest. 

- To copy the URL of the current page, copy it from (a) the address bar, or (b) click on "More" at the top right and then  "Save 

- Permalink URL." 

- Use "Previous" and "Next" buttons on the toolbar to go forward and backward through document. The browser's "back" 

- button takes you to the page you last viewed, _not_ to the previous page of the document. 

- To locate your position in a document after using search or index or links, click on the left-most button above the table of 

- contents and then look for the highlight. It may be necessary to scroll up/down through the table of contents. 

## **Available Docs** 

All published documentation for A-Shell and related topics are listed at the MicroSabio website on the download...documents page. If that page doesn't answer your questions about what docs are available, or if you need historical docs or docs in unlisted formats, contact MicroSabio with your concerns. 

Developer documentation—i.e., for more recent versions of A-Shell than have been formally released—may be available from other locations, which will be noted on the documents page. 

## **Other Tips** 

- You can drag the border between the table of contents and the documentation body to create more room for one side or the 

- other. 

## **Updates** 

A-Shell Reference 

Page 4252 

The A-Shell documentation is kept very up to date. Jack meticulously documents every change/addition/improvement to A-Shell, writes the text version of ashdevnotes, and posts it with new versions of the software. You can always find the up-to-the-second release notes with the latest versions of A-Shell. 

Usually within hours but no more than a day or two, Ty converts the text version of ashdevnotes into an HTML version, and posts it in the same place. All the new or changed material from ashdevnotes is incorporated immediately into the applicable manual(s) of the main A-Shell doc set, and those docs are immediately published and available. The primary A-Shell documentation, the A-Shell Reference, is normally updated no less than once a month. 

To read the latest versions of any A-Shell documentation, simply go to the download...documents page and click on the doc that interests you. 

## **Feedback** 

Just as A-Shell itself is a work in progress, so the documentation is constantly being tweaked, twiddled and improved. Ty works on the docs more or less continuously, and enthusiastically welcomes feedback of all types, particularly: 

- identification of language mistakes (typos, misspellinggs, bad sentences, missing words, etc.) 

- identification of "real" mistakes, namely saying something that isn't true 

- suggestions for better explanations 

- suggestions for index entries 

If you have any comments, ideas, suggestions or other kinds of feedback, please post them in the "All Other A-Shell Topics" at - the A Shell forum or email them to us. 

A-Shell Reference 

Page 4253 

## **FILE TYPES** 

_Reviwed and revised June 2024; see History_ 

A collection of HTML pages with index and table of contents pages, also known as "Web help," is the normal format for A-Shell online documentation. While this is the best choice for most readers in most circumstances, other file formats may be applicable or needed in some situations. Sometimes, for historical reasons or by special request, the A-Shell documents may be available in other file formats. If you would like to get the documentation in a format you don’t see, it may be available on request. Continue reading for information about document formats and files types, and why you might prefer one or another. 

**HTML** also known as "Net Help" or "Web Help:" These help files are standard web pages, with hyperlinks, tables of contents, linked indexes and search capabilities. They reside on the MicroSabio web server, are always up to date, and require no downloading step; pages are downloaded on demand—and very quickly. As long as you have a good internet connection, this is the preferred format for help/documentation files. 

**CHM** (Compiled HTML, standard Windows help files): CHM files are compilations of HTML pages into a single document which includes all the features of the HTML documents. CHM files are downloaded to and accessed from your computer, and are the preferred help file format when you do not have a good internet connection. CHM files are opened using built-in components of Windows, so no additional programs are required to view them. If you are running Windows 98 or later, you have what you need in order to read CHM files. If you download them to your Windows computer and then double-click on them, they should be properly opened and displayed in the familiar help-file context.  Note also that this file format is no longer recommended or supported by Microsoft, and therefore is becoming less common. More on CHM 

CHM files have largely been superseded by Web Help in the A-Shell documentation library. CHM files were the best choice in days of limited internet access—and still are the best choice when the internet is not available. Here is some general information on CHM files. 

## **Background Information** 

- Compiled HTML help ("CHM") is a proprietary format for help files developed by Microsoft. It was first used in 1997 

- (Win98) as a successor to the even-older WinHelp format, and is supported through Windows XP, Vista, Win7, 8, 10 and 11. Microsoft no longer creates CHM files for its own documentation and has long since moved on to new formats, but CHM will likely be supported for a long time. 

- CHM files consist of a set of individual web pages plus a hyperlinked table of contents and, optionally, an index. The pages 

A-Shell Reference 

Page 4254 

are combined into a single file, which is then compressed using LZX compression. CHM files are therefore quite efficient and and relatively small. 

- CHM files are created using a free tool from Microsoft called "HTML Workshop." There are many tools on the market for 

- creating CHM files, but they all use Microsoft's "HTML Workshop" as the engine for combining and compressing the HTML files. 

- CHM files contain "active content"—i.e., the files are executable—and therefore are frequently perceived as being security 

- risks. Gmail, for example, blocks CHM files. 

- For more information, see the Wikipedia entry for CHM files, from which some of the above facts were taken. 

## **Problems and Solutions** 

- For security reasons, CHM files will normally not be displayed properly or at all when you are trying to access them from 

- network drives or remote servers. It is possible to change your security settings to accommodate such files, but the easier solution is just to move the CHM file(s) to a local drive. 

- CHM files will not work if their path or filename includes the pound (aka hash) character '#'. The hash character signifies 

- an anchor in HTML so the CHM viewer fails to resolve the path properly and to retrieve the content. If this is your situation, move the file to a path that does not have a hash character in its name. In general, avoid using '#', '?', '&', '+', and other special characters in directory names. 

- When you click on an external link inside a CHM file, the web page is opened with Internet Explorer and not with your 

- computer's default browser. Why? Since the CHM viewer itself is a component of IE, or *is* IE operating in some special mode, the program does not issue a conventional call to the PC to use the default browser. Instead, since IE is already running and available, IE simply "tells itself" (?!!) to open the external page. There is no work-around to this "problem." 

- Windows security provisions may prevent CHM files from opening. If you get a "cannot display" message in the right pane 

- of the display window, this may be the problem. Solution: right-click on the CHM file and select _Properties_ from the popup menu. Click on the _Unblock_ button immediately below the Advanced button on the General page, then click _Apply_ . Once the CHM file has been unblocked, the _Unblock_ button disappears, and you need only do this once—i.e., not every time you open the file. 

- If the ideas and suggestions mentioned above do not resolve your problems opening CHM files, you might want to do a 

- web search for "MJ's Help Diagnostics." This is a program that checks to see if the Windows programs and components 

A-Shell Reference 

Page 4255 

needed to display CHMs are properly and completely installed on your (Windows) computer. 

**PDF** (Adobe's Portable Document Format): Various A-Shell docs have been available as PDF files in the past, and may be available on request; inquire if you are interested. Files of this type consist of exact replicas of printed pages, just as they would appear in a printed manual. If you plan to print a copy of the document, this is the best type of file to download. PDF files are not hypertext documents or pure help systems, but most documents come with an interactive table of contents. This file format and the program(s) needed to read these files are the property of Adobe Systems. If your computer does not already have a copy of Adobe® Acrobat®, which you will need in order to read the files, you may download a free copy from the Adobe Acrobat download page. If you are printing or plan to print PDFs, see note under Printing below. 

**TXT** : Text files are universally readable by all computers and all operating systems, so you can download or display them regardless of your system. They do not contain any organizational or text formatting, however, and are therefore the most difficult file type to navigate. 

**DOC and DOCX** :  These are the native file formats of Microsoft Word. From the beginnings of A-Shell documentation until 2022, all documentation was written and maintained in Word, and then published to other formats using various types of conversion and authoring programs. Although the A-Shell documents are now maintained in another format, Word files may be available; inquire if interested. 

## **Printing** 

HTML and CHM files are not particularly well-suited for printing. They are fine if you want to print a few pages or even a full section, but not if you want to print an entire doc/manual for reading and reference. The best format for printing is PDF. If you wish to print the docs, therefore, make sure to get a PDF version of the doc(s) you want to print. If you don’t see them here, contact MicroSabio and ask about a PDF for the doc in question. 

Important note on PDF printing: If you intend to print the PDF documents, be sure that your printer is configured to interpret colors as either black or white; if the printer tries to interpret colors as shades of gray, all the color printing in the document will appear as gray—i.e., light and not very readable. A-Shell help files do not use a lot of color, but they use some for text formatting and screenshots. On pure black and white printers, configured as black and white printers, the colored material prints fine. 

## **History** 

A-Shell Reference 

Page 4256 

Through approximately the year 2001, the A-Shell documentation was written in Microsoft Word and was presented to users and developers in Word or PDF files. In additional to the on-going record of changes to A-Shell, which was available in simple text format, A-Shell was described in four manuals: Setup Guide, Command Reference, XCALL Reference and Development Guide. 

In 2001, with the arrival of Ty Griffin as a member of the MicroSabio team, the A-Shell documentation remained in Word but was now processed by a "help authoring tool" called Doc-to-Help. This tool produced CHM files, which soon replaced the Word and PDF files as the "presentation of choice" for all the A-Shell documentation. Internet access was generally not fast or reliable, so the CHM format (a single file which resided on the users' computer) was much better than web-based alternatives. 

In approximately Spring 2012 and A-Shell version 6.1, two things happened: 

- The four separate documents mentioned above were consolidated into one: The A-Shell Reference. 

• The new A-Shell Reference, along with the smaller documents for A-Shell's add-on products (ATE, PDFX, EMAILX, etc.), were published in "Web Help" format instead of CHM format. Since most A-Shell users, developers and sites now had good and reliable internet connections, the Web Help format became the new standard for not just A-Shell but most of the documentation world. 

In 2015, Doc-to-Help, the tool that MicroSabio had been using to generate the CHM and HTML files presented to users, was sold for the second or third time. The old program continue to work and meet MicroSabio's needs, but the new owner of Doc-to-Help was not continuing to develop the program. MicroSabio started looking around for alternatives. 

In December 2019, after concluding that there was no future in Doc-to-Help, MicroSabio purchased a new help authoring tool called "Help & Manual." It took a couple years to learn the new system and make the full transition from old tool to new, but it eventually happened. The new online documentation published with H&M was essentially identical to the old versions published with Doc-to-Help. 

As of this writing, June 2024, Help & Manual has been in use for several years, and is nicely meeting the documentation needs of A-Shell and MicroSabio. All of our online documentation is published by H&M, and H&M the software product is undergoing continuous development and improvement, much like A-Shell itself. We expect to be using H&M for the foreseeable future, and recommend it to anybody who has documentation publishing needs. 

A-Shell Reference 

Page 4257 

## **LEGAL NOTICES** 

This documentation and the software it describes contain proprietary information belonging to MicroSabio, a California proprietorship owned entirely by Jack McGregor. The software and this related information is provided under the terms of the MicroSabio License Agreement, which contains restrictions on use and disclosure and is protected by U.S. and international copyright law. This information is confidential between MicroSabio and the client, and remains the exclusive property of MicroSabio. 

Due to continued product development, the information contained herein may change without notice. It is believed to be accurate and reliable at the time of its writing. However, no responsibility for the accuracy, completeness or use of this information is assumed by MicroSabio. If you find any problems in the documentation, please report them to the publisher. 

## **Acknowledgements** 

Digest: Copyright © 2001-2003 Christophe Devine. Used by permission via the GNU General Public License. 

Natural sort  (used in BASORT, XTREE, SORTIT and elsewhere): Copyright © 2000, 2004 Martin Pool. Used by permission. 

FastCGI  (used in libfcgi): Copyright © 2004-2021 Free Software Foundation, Inc. Licensed under the GNU Free Documentation License, version 1.3 or later. 

LibXL:  Licensed from XLWare. 

## **Trademarks** 

MicroSabio, A-Shell, INMEMO, INFLD and EZ-SPOOL are trademarks of MicroSabio and Jack McGregor. 

AIX and Informix are registered trademarks of International Business Machines Corporation. 

Alpha Micro, AMOS, and AlphaBASIC are registered trademarks of Alpha Micro Products, Inc. 

Linux is a registered trademark of Linus Torvalds. 

Microsoft and Windows are registered trademarks of Microsoft Corporation. 

A-Shell Reference 

Page 4258 

Red Hat is a trademark of Red Hat, Inc. 

UNIX is a registered trademark of The Open Group. 

ZTERM is a trademark of Rod Hewitt at Cool.stf. 

All other products, services, companies, events and publications are trademarks, registered trademarks or service marks of their respective owners. 

A-Shell Reference 

Page 4259 

## **SOFTWARE LICENSES** 

## **- MicroSabio License Agreement covering A Shell** 

This is a legal agreement between you, acting as an individual on your own behalf or as an authorized agent for your organization, and MicroSabio. By installing the software on your computer(s) or by using the software product for which this license was issued, you are agreeing to be bound by the terms of this agreement. If for any reason you do not agree to the terms of the Software License, delete all relevant files from your computer(s) and, if applicable, return all related physical items (disks, license forms, documentation, etc.) to the point of purchase within 30 days for a full refund. 

## SOFTWARE LICENSE 

_**Grant of License—Single Computer:**_ MicroSabio grants to you the right to use the accompanying software product ("Software") on a single computer. You may not network the software or otherwise use it on more than one computer. 

_**Grant of License—Multiple Computers:**_ MicroSabio grants to you the right to use the software on the specific number of computers for which the software has been licensed. You may not use the software on more than the specified number of computers. 

_**Grant of License—Multiple Users:**_ MicroSabio grants to you the right to use the software on one or more computers but only for the specific number of users for which the software has been licensed. 

_**Copyright.**_ The software is owned by MicroSabio or its suppliers and is protected by United States copyright laws and international treaty provisions. Therefore, you must treat the software like any other copyrighted material (e.g., a book or musical recording) except that you may either (a) make one copy of the software solely for backup or archive purposes, or (b) transfer the software to a single hard disk provided you keep the original solely for backup or archive purposes. 

_**Other Restrictions.**_ You may not rent, loan, sell or otherwise transfer the software to anyone else unless (a) you permanently transfer all copies in your possession, and (b) the recipient agrees to the terms of this agreement. You may not decompile, translate, reverse engineer or disassemble the software. 

A-Shell Reference 

Page 4260 

_**Limited Warranty.**_ MicroSabio warrants that the software will perform substantially in accordance with its accompanying written materials and published specifications, when properly installed on a properly configured computer for which it is intended, for a period of 90 days from the date of receipt. 

_**Customer Remedies.**_ MicroSabio's, its suppliers' and its distributors' entire liability and your exclusive remedy shall be, at MicroSabio's option, either (a) return of the price paid or (b) replacement of the software which is returned to the point of purchase with your receipt. This Limited Warranty is void if failure of the software has resulted from accident, abuse or misapplication. Any replacement software will be warranted for the remainder of the original warranty period or 30 days, whichever is longer. 

_**Limitation of Warranty.**_ MicroSabio, its suppliers and its distributors disclaim all other warranties, expressed or implied, including, but not limited to, any implied warranty of merchantability and fitness for a particular purpose. In no event shall MicroSabio. its suppliers or its distributors be liable for any consequential damages whatsoever arising out of the use of or inability to use this product, even if advised of the possibility of such damages. 

This Agreement is governed by the laws of the State of California. If you have any questions regarding the license agreement, the limited warranty or any other matters, please write to MicroSabio at the address provided on the _Contact_ page of the MicroSabio web site. 

## **DYNCALL Library License** 

The DYNCALL library provides the basis for the A-Shell subroutine "DYNLIB.SBR." 

Copyright © 2007-2021: Daniel Adler and Tassilo Philipp <tphilipp AT potion-studios DOT com> 

Contact: <dadler AT uni-goettingen DOT de>; <tphilipp AT potion-studios DOT com> 

Web resources: http://www.dyncall.org/license 

Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 

The software is provided "as is" and the author disclaims all warranties with regard to this software including all implied warranties of merchantability and fitness. In no event shall the author be liable for any special, direct, indirect, or consequential 

A-Shell Reference 

Page 4261 

damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. 

## **LIBSSH3 Library License** 

The LIBSSH3 library is used by A-Shell's "libashtls," which is used in turn by TCPX if the TCPXFLG_TLS flag is set. 

Copyright 2022, libssh.org 

Copyright 2009-2014 Daniel Stenberg 

Copyright 2008, 2009 Simon Josefsson 

Copyright 2007 Eli Fant <elifantu@mail.ru> 

Copyright 2004-2007 Sara Golemon <sarag@libssh2.org> 

Copyright 2006, 2007 The Written Word, Inc. 

Copyright 2005, 2006 Mikhail Gusarov <dottedmag@dottedmag.net> 

All rights reserved. 

Web resources: https://libssh.org/ 

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 

- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 

- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in 

- the documentation and/or other materials provided with the distribution. 

A-Shell Reference 

Page 4262 

- Neither the name of the copyright holder nor the names of any other contributors may be used to endorse or promote 

- products derived from this software without specific prior written permission. 

This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. 

eee 

## **GnuTLS Library License** 

The GnuTLS library is used by A-Shell's "ashnet2," which provides SSH2 support to ATE. 

Web resources: https://www.gnutls.org/ 

The library is licensed for use and distribution under the terms of the GNU Lesser General Public License version 2.1. 

## **LibXL License** 

This software library and toolkit is licensed from the company XLware and is used in A-Shell's implementation of AXL and CSV2XL. 

## **END OF DOCUMENT** 

