This is ansicmd.info, produced by makeinfo version 7.2 from
AnsiCmd_00_menu.texi.

      Copyright © 2022-2026

      Mahlon R. Smith, The Software Samurai

      This manual describes version 0.0.07 of the AnsiCmd library.

       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.3
       or any later version published by the Free Software Foundation;
       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
       Texts.  A copy of the license is included in the section entitled 
       "GNU Free Documentation License".


INFO-DIR-SECTION Individual utilities
START-INFO-DIR-ENTRY
* AnsiCmd library.              Application interface to ANSI escape sequeces
END-INFO-DIR-ENTRY


File: ansicmd.info,  Node: Top,  Next: Introduction,  Up: (dir)

AnsiCmd Class Link Library
**************************

      Copyright © 2022-2026

      Mahlon R. Smith, The Software Samurai

      This manual describes version 0.0.07 of the AnsiCmd library.

       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.3
       or any later version published by the Free Software Foundation;
       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
       Texts.  A copy of the license is included in the section entitled 
       "GNU Free Documentation License".


 The AnsiCmd library provides a simple, organized mechanism
 for controlling the setup of many terminal window functions
 and display options using ANSI escape sequences and basic
 terminal configuration utilities.

* Menu:

* Introduction::                 What is the AnsiCmd library?
* Invoking::                     Command-line arguments and options
* AnsiCmd Library::              Description of primary methods and data
* ACWin Class::                  Structured high-level user interface
* Development and Testing::      Structure of test methods and menus
* Building from Source::         Compile the library
* gString Text Tool::            Text Internationalization and formatting tool
* CsvView Demo App::             View CSV files (AnsiCmd basic functionality)
* AcEdit Demo App::              Simple text editor (AnsiCmd API functionality)
* TFMTest Demo App::             Exercise the TFMan class (Temp File Manager)
* Technical Support::            Make suggestions, report problems.
* Copyright Notice::             Boring, but useful.
* Index::






File: ansicmd.info,  Node: Introduction,  Next: Invoking,  Prev: Top,  Up: Top

Introduction
************


What is the AnsiCmd link library?
---------------------------------

The AnsiCmd class builds to a small, special purpose link library which may be
used to configure color attributes for the terminal window foreground and
background; text attributes such as bold, italic, and underlined; as well as
cursor positioning and text erasure using *note ANSI:: escape sequences and
*note ASCII:: control codes.

In addition, the AnsiCmd library can configure the input stream, "stdin" for
operations such as input echo options, non-blocking read and capture of system
signals such as "break" (CTRL+C), "suspend" (CTRL+Z), and "quit" (CTRL+4).
*Note Terminal Configuration::.

AnsiCmd captures all (or nearly all) keycodes which are passed from the system
as escape sequences, and converts these sequences to ordinary Unicode
codepoints.
*Note Soft Echo Options:: for examples of this conversion.


The EarthPoints Test Program
----------------------------

The AnsiCmd class library is bundled with a test application, _EarthPoints_,
(epts), which exercises the full functionality of the library. EarthPoints was
born as an experiment in how global-positioning systems calcuate distances
between points on the planet. It began as a pure command-line application to
test the math behind the distance calculations; however, your author is a
simple creature, and he was easily distracted by the possibility of using ANSI
escape sequences to add color to the output. (Geeks-R-Us :-)

This distraction quickly became a project in itself, and the full list of
ECMA-48, ANSI X3.64 escape sequences is now supported by the AnsiCmd library.


Other Test Programs
-------------------

Also included are additional test programs in various states of completion.
These applications demonstrate specific approaches to design of applications
based on the AnsiCmd library.
*Note CsvView Demo App::, and *note AcEdit Demo App:: for more information.


The gString Class
-----------------

The AnsiCmd library and the associated test programs make extensive use of the
author's gString class. The gString class encapsulated most of the smelly (but
efficient) C-language string manipulation functions such as sprintf, scanf and
so on.
Please *note gString Text Tool:: for more information.


The WaylandCB Class
-------------------

Access to the system clipboard is enabled through the WaylandCB class. This
class in under a conditional-compile directive.
Please *note Build Options:: for additional information on integration of
clipboard access into the AnsiCmd library.
For a discussion of how system clipboard access is implemented in the library,
please *note AnsiCmd Clipboard Access::.


The TFMan Class
---------------

Management of temporary files for the AnsiCmd library and the demo
applications included with the package are handled through the TFMan
(Temporary File Management) class.
Please *note TFMan Class:: and the *note TFMTest Demo App:: for an
introduction to the use of temporary files in a Linux application.

                             ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
ANSI - American National Standards Institute
(ECMA-48, ISO/IEC-6429, FIPS 86, ANSI X3.64, JIS X 0211)
<https://en.wikipedia.org/wiki/American_National_Standards_Institute>
<https://www.ecma-international.org/publications-and-standards/standards/ecma-48/>

ASCII - American Standard Code for Information Exchange.
(ISO-IR-006, ANSI_X3.4-1968, ANSI_X3.4-1986, ISO_646.irv:1991, ISO646-US,
IBM367, cp367)
<https://en.wikipedia.org/wiki/ASCII>




File: ansicmd.info,  Node: Invoking,  Next: AnsiCmd Library,  Prev: Introduction,  Up: Top

Invoking
********

There are three (3) groups of command-line options for invoking the
application (*note invocation menu:: below). Each option group is independent
of the others (with some exceptions). The 'help' and 'version' options
override all other specified options. When one of the testing options is
specified, it overrides any request for application-level (GPS) data.

  1. Terminal Configuration Options:
     These options configure the terminal environment for the application.
     Configuration options include color attributes, I/O stream options,
     “locale”, signal processing, cursor shape and more. All are optional, and
     if not specified, the default setting for that option will be used.
     Please *Note Invoking - Terminal Setup::.

  2. AnsiCmd-class Testing Options:
     These options specify a test of specific functionality within the AnsiCmd
     library. Because the EarthPoints application is primarily a test and
     demonstration application, the array of available tests is extensive.
     Each test establishes its own terminal environment according to the needs
     of the specific test, and thus may override the corresponding terminal
     setup option(s).
     All tests are within conditional compilation blocks
     (*note Build Options::), so all test code may be disabled without loss of
     application functionality.
     Please *note Invoking - AnsiCmd Tests::.

  3. EarthPoints Application Options:
     These options provide data for the top-level application functionality;
     specifically, global-positioning coordinates (latitude/longitude), and
     related data for calculating the distance between points on the globe.

     To interactively invoke the application's help menu, at the command-line
     type:
        epts --help
        epts -h
         or redirect the help menu through the “less” utility:
        epts --helpless
        epts -hl

     Please *Note Invoking - EarthPoints:: for more information.

Invocation Options
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

* Menu:

* Invoking - Terminal Setup::    Terminal Setup Options
* Invoking - AnsiCmd Tests::     Testing Options
* Invoking - EarthPoints::       Application Parameters



File: ansicmd.info,  Node: Invoking - Terminal Setup,  Next: Invoking - AnsiCmd Tests,  Up: Invoking

Invoking - Terminal Setup
=========================

When invoking the EarthPoint application (epts), terminal setup options are
specified through the “--term” command-line option:
    epts --term=SETUP_OPTIONS

Options may be specified in any order and in any combination.
Multiple options may be concatenated, seperated by commas (','):
If the argument string contains whitespace, enclose the entire argument string
in single- or double-quotes.

     # Set stream_Width==wide, Color==red/blue, Locale==French(Canada)
     epts --term=W:w,C:rb,L:fr_CA.utf8

     # Set Locale==from_terminal_environment, Panic_button==user_query,
           cursor_Style==blinking_underline
     epts --term="L:e, P:u, S:ub"

     # Set input_Buffering==unbuffered_no_echo, Ansi_compliant==no,
           Panic_button==ignore_with_alert, Color==blue/default
     epts --term='B:ux, A:n, P:ia, C:b'


Summary of Options
------------------

         OPTION          DESCRIPTION
            
     -----------------------------------------------
       *note W option:: stream Width
       
       *note C option:: Color attributes
       
       *note A option:: Ansi compliant
       
       *note B option:: input Buffering
       
       *note L option:: Locale name
       
       *note P option:: Panic button
       
       *note Q option:: Quit signal
       
       *note Z option:: suspend ctrl+Z
       
       *note S option:: cursor Style
       


 −W Stream Width.

The term “Stream Width” refers to the character width for input and output
streams for the application. Typically, the character width is either 8-bits
(char) or 32-bits (wchar_t).

For console applications, the I/O stream width is established either directly
by declaring the width _or_ by locking in the character width with the first
data read from, or written to the the I/O streams. Once locked in, the stream
width cannot be changed without closing and re-opening the stream(s), which is
not as straightforward as it sounds, and is therefore discouraged.

w - Use the wide (wcin/wcout) input/output streams.
      This is the default, and is strongly recommended.
n - Use the legacy narrow (cin/cout) input/output streams.
      The narrow I/O streams are not recommended for modern applications,
      but may be used for testing the interface.

Example:
   epts --term=W:w      # set Wide stream width

To set this option directly, call the AnsiCmd method: *note
acSetStreamWidth::.


 −C Color Attributes.

Specify the text foreground, and optionally the background color attribute(s).
The foreground color argument is required, and the background argument is
optional, and if not specified, the terminal default background will be used.

Within a console application, it is often useful, to use contrasting colors to
draw the user's attention to important information. For applications which
include the AnsiCmd library, these color attributes may be specified as a
command line option.

The -C option is used to specify one of the basic eight(8) colors (or default)
for foreground and background.

     k : blacK        b : Blue
     r : Red          m : Magenta
     g : Green        c : Cyan
     n : browN        y : greY
     d : Default

Examples:
   epts --term=C:r      # set Red foreground with Default background
   epts --term=C:cb     # set Cyan foreground with Blue background
   epts --term=C:dg     # set Default foreground with Green background

To set this option directly, call the AnsiCmd method: *note acSetFgBg::.


 −A Ansi Compliance.

The most popular terminal emulator software, Gnometerm, Konsole and XTerm all
support the core set of ANSI escape sequences. However, some terminal software
may not understand some of the basic commands such as those which reset
(disable) certain individual settings.

For terminals with this limited support, the AnsiCmd library functions can
substitute the full reset command for the unsupported individual reset
commands. While the full reset is slower and less convenient for the
application programmer, it provides a way to produce a reliable application
interface.

For example, the standard way to reset the Bold attribute is with the
aesBOLD_OFF sequence:
   acSetMod ( aesBOLD_OFF );
If this command or similar commands is not supported by the terminal, then the
global attribute reset can be called:
   acSetMod ( aesRESET );
This substitution is done automatically if the internal non-compliance flag is
set.

The level of ANSI compliance is specified by:
y - Yes, the host terminal supports the common ANSI escape sequences.
    This is the default, and should be correct in most cases.
n - No, the terminal is unable to handle some of the necessary sequences.
    Use the reliable reset when disabling an attribute.

To set this option directly, call the AnsiCmd method: *note acFullReset::.


 −B Input Buffering.

Specify the buffering options for the input stream (stdin).

By default, keyboard input at the terminal prompt is stored in the stream
buffer until the user presses the Enter key; however, application control of
the keyboard input stream is, in the author's view, critical to the success of
the application.
(Our opinions are plentiful and provided free-of-charge.)

If your applications would benefit from having full control of keyboard input,
then the -B option is used to specify the way keyboard input is captured,
filtered and presented to the application.

     b : Buffered input from stdin is enabled (default).
         Keycodes are sent to the application when the Enter key is pressed.
         The terminal automatically echoes printing characters to the display,
         and processes control codes and other non-printing keycodes using
         whatever Voodoo rituals the terminal software developers follow.

     u : Unbuffered input from stdin.
         Keycodes are available to the application as soon as the key is pressed.
         Echo of printing characters to the display is specified as a sub-option.

         Echo sub-options:
         x : Echo of data from stdin is disabled.
             This is the default and is assumed if no sub-option is specified.
         s : Soft Echo. This option automatically echoes printing characters to
             the display, but captures the so-called "special" (non-printing)
             keycodes and processes them according to the soft-echo sub-option.
             a : All "special" keycodes are captured, processed and passed on
                 to the application. This is the default soft-echo option.
             b : Basic "special" keycode group. This includes the cursor
                 positioning and edit-key groups, but not the text-selection
                 and clipboard-access keycodes.
             c : Cursor-positioning keycodes are passed to the application.
                 The edit keycodes are discarded.
             e : Edit keycodes (Backspace, Delete, Insert and Alt+Enter) plus Tab
                 and Shift+Tab are passed to the application. Cursor-positioning
                 keycodes are discarded. (useful primarily for debugging)
             d : Disable (discard) all "special" keycodes.
         *Note Soft Echo Options:: for more information.

     Examples:
        epts --term=B:b   # Buffering is enabled.
        epts --term=B:ux  # Buffering is disabled with echo disabled.
        epts --term=B:usa # Buffering is disabled, echo enabled,
                            and all special keys enabled.
        epts --term=B:usc # Buffering is disabled, echo enabled,
                            and cursor-positioning special keys enabled.
        epts --term=B:usd # Buffering is disabled, echo enabled,
                            and all special keys discarded.

To set this option directly, call the AnsiCmd method: *note acBufferedInput::.


 −L Locale Name.

Specify the “locale” to be used within the application.

A locale is the set of rules used to interpret the way text and numeric data
are processed and presented. A few examples of locale-dependent data are,
currency values, telephone numbers, timestamps and measurements.

Two command-line options are available:

     e - Environment: Activate the locale specified in the terminal
         environment. This is the default and is almost always the the
         right choice.

     locale_name - specify a valid filename for the locale to be used.

     Examples:
        epts --term=L:e             # take locale from environment
        epts --term=L:zh_CN.utf8    # specify Zhongwen (China) locale

It is very likely that the terminal environment in which your console
application runs specifies the locale via one or more environment variables.
At the command line type:
   echo $LANG
To list the types of formatting handled by the current locale, at the command
line type:
   locale
To list the UTF-8 compliant locales supported by your system, at the command
line type:
   locale -a | grep -i 'UTF'
This should yield a list of filenames such as
   en_US.UTF-8, zh_CN.utf8, es_AR.utf8

Technical Note: Except for Windoze(tm), the civilized world uses UTF-8
character encoding exclusively. Be sure that any locale specified for use in
your application is based on UTF-8 encoding.

Technical Note: If a console application does not explicitly specify a locale,
the so-called “C-locale” is used. This is not actually a locale at all but the
complete lack of a locale—resulting in a complete lack of coherent data
formatting.


 −P Panic Button.

The Break Signal, otherwise know as the Panic Button or Control+C is the
primary method of killing a console application which has locked up or has
gone off into the weeds.

By default, the terminal receives the break signal and immediately kills the
application, leaving your data in an indeterminate state.

This is fine if you don't care about your data, but if you actually don't care
about your data, _please_ step away from the keyboard — and pursue a career in
marketing. Otherwise, your application may benefit one of these options.

     i[a] - Ignore the break signal, that is capture the signal and discard it.
            Optionally produce an audible alert.
     e - Exit the application on receipt of the break signal. The shutdown is
         performed in an orderly way, returning all resources to the system
         before returning control to the terminal shell.
     u - User interaction is required. The signal handler prompts the user
         whether to exit the application or to discard the break signal
         and continue the application.
     c - Capture the signal and convert it to an ordinary keycode (wcsCTL_C)
         which is commonly used by applications as the “copy” command.
     t - The terminal is allowed to retain control of the break signal.
         If the user presses the CTRL+C key combination, the application will
         be terminated immediately, leaving the terminal in an indeterminate state.
         Although this is the default, it is not recommended.

     Examples:
        epts --term=P:i          # Ignore break signal
        epts --term=P:ia         # Ignore break signal and sound an alert
        epts --term=P:e          # Exit the application
        epts --term=P:u          # User prompt on receipt of break signal
        epts --term=P:c          # Copy command conversion
        epts --term=P:t          # Terminal handler (default)

Please *note Capturing the Break Signal:: for additional information.

To set this option directly, call the AnsiCmd method: *note
acCaptureBreakSignal::.


 −Q Quit Signal.

The Quit Signal (or Kill signal) is similar to the Panic Button described
above, except that in addition to terminating the application, it also
generates a core dump.

A core dump is a file which contains a description of the the application
state when it was terminated. This can include the register values, the call
stack (addresses and parameters), a table of RAM contents and other
information. This can be a large file, and it is recommended that it not be
generated unless you actually need it.

The Quit Signal is captured by default during configuration of the AnsiCmd
class and its derived classes. When the Quit signal is received, the
application is shut down in an orderly manner. Use the ‘Q option’ to disable
this functionality.
   epts --term=Q:n

To set/reset this option directly, call the AnsiCmd method: *note
acCaptureQuitSignal::.


 −Z Suspend Signal.

The “Suspend” signal is generated by the Ctrl+Z key combination. This signal
suspends the currently-active process (places it into hibernation). The
process will not be able to respond to any command other than a command to
resume operation. Refer to documentaiton for the ‘fg’ system utility for
information on restoring the hibernating process.

While the "suspend" functionality is a valuable tool in some contexts, it is
merely confusing to the average user when the running application simply
freezes and cannot be restarted.

For this reason, the "suspend" signal (SIGTSTP) is captured by default and is
converted to an ordinary keycode, wcsCTL_Z. The Ctrl+Z key combination is
often used by applications (LibreOffice, jEdit, etc.) to “undo” a previous
action.
   epts --term=Z:n
   epts --term=Z:y (default)


 −S Cursor Style.

Specify the shape and animation (blinking or steady) of the visible cursor.

     d - Default. Use the terminal's default cursor shape and animation.
         For most environments, a full-cell, blinking block is the default.

     b[b|s] - Block. The cursor shape is a rectangular block that fills one
              entire character cell.
              Sub-options: 'b' - blinking (default)
                           's' - steady (non-blinking)
     u[b|s] - Underline. The cursor shape is a thin horizontal bar at the
              bottom of the character cell. This resembles an underline or
              the underscore character '_'
              Sub-options: 'b' - blinking
                           's' - steady
     v[b|s] - Vertical bar. The cursor shape is a thin vertical bar at the
              left edge of the character cell. This is similar, but not
              identical to the vertical bar character: '|' on the keyboard.
              Sub-options: 'b' - blinking
                           's' - steady

     Examples:
        epts --term=S:u          # Underline (with blinking default)
        epts --term=S:vb         # Vertical bar, blinking
        epts --term=S:vs         # Vertical bar, steady (non-blinking)

To set this option directly, call the AnsiCmd method: *note
acSetCursorStyle::. Note that this method may also be used to set cursor as
invisible.

Technical Note:
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The blinking-cursor options are impacted by the terminal software's blink
timeout value. For Gnome, the default timeout is ten seconds, after which the
cursor will stop blinking and become steady state. To adjust this timeout
value under Gnome, use either the 'dconf' editor or the 'gsettings' utility.

Get the current timeout value:
   gsettings get org.gnome.desktop.interface cursor-blink-timeout
Get the range of valid values for this option:
   gsettings range org.gnome.desktop.interface cursor-blink-timeout
Set a new timeout value in seconds:
   gsettings set org.gnome.desktop.interface cursor-blink-timeout 25

Other desktop schemes will have a similar mechanism for adjusting the cursor
blink timeout value.



File: ansicmd.info,  Node: Invoking - AnsiCmd Tests,  Next: Invoking - EarthPoints,  Prev: Invoking - Terminal Setup,  Up: Invoking

Invoking - AnsiCmd Tests
========================

Tests for the AnsiCmd library are specified as arguments to the "--test"
command-line option.
   epts --test=TEST_OPTION

The specific test within a group of related tests is specified by from one to
four characters as detailed in this chapter. The first character indicates the
test group. For instance, the letter 'C' designates the group of
color-attribute tests. If a test group is invoked without indicating a
specific test, then the menu of available tests in that group will be
displayed and the application will exit.
   epts --test=C   will display the color test menu:
        Color Attribute Testing Options:
   -----------------------------------------------
   'f'  Four-bit Fgnd/Bkgnd color attributes.
   'b'  Background color attribute options.
   't'  Table lookup, 8-bit color attributes.
   'r'  R/G/B color-attribute matrix (6x6x6).
   'g'  Greyscale color attributes.
   'a'  Aixterm Fg/Bg extensions (non-standard).
   'd'  Decode tracking data for attribute mods.
   's'  Swap acaExpand foreground/background.

Similarly, if a test group and a test are specified, but the test requires an
argument or arguments, then a menu of available arguments for that test will
be displayed and the application will exit.
   epts --test=Cr   will display the RGB color test arguments:
        RGB Test Options:
   ---------------------------------------------------
   'r'  Red  : Display full range of red colors.
   'g'  Green: Display full range of green colors.
   'b'  Blue : Display full range of blue colors.
   'y'  greY : Display full range of greyscale colors.
   'w'  Web  : Display "web-safe" colors.

A few test require two(2) arguments, for example:
   epts --test=Tec   Terminal group, Echo test, Cursor keys

If a test and its argument(s) are fully specified, then optionally, the next
character indicates the text color attribute to be used for outputting the
results of the test. The available color attributes are:
   'k' blacK     'r' Red
   'g' Green     'n' browN
   'b' Blue      'm' Magenta
   'c' Cyan      'y' greY
    If not specified, the terminal default color is used.
    Note: The color-attribute tests will ignore this argument.
Examples:
   epts --test=Eb — Perform 'E'rasure test with 'b'lue text.
   epts --test=Ac  — Perform 'A'SCII code test with 'c'yan text.
   epts --test=Tig — Perform 'T'erminal 'i'nput test with 'g'reen text.
   epts --test=Wddb — Test 'W'indow 'd'ialog, sub-test 'd' with 'b'lue text.


Summary of Options
------------------

         OPTION          DESCRIPTION
     ---------------------------------------------------
       *note test C::   Color tests
       *note test P::   Positioning tests
       *note test E::   Erasure tests
       *note test A::   Ascii control code tests
       *note test F::   Font switch test
       *note test I::   Ideograph test
       *note test T::   Terminal setup tests
       *note test W::   Window tests
       *note test D::   Dialog tests
       *note test S::   Sandbox

Options for testing the functionality of the AnsiCmd-class library.

For options which require arguments, the option must be immediately followed
by the EQUAL sign ('=') which must be immediately followed by its argument. If
the argument string contains space characters, enclose it in quotation marks.

Please *note Development and Testing:: or study the AnsiCmdTest.cpp source
file for more information about how the individual tests are constructed.


 −C Color Attrubutes.

The majority of escape sequences definined in the ECMA-48 (ANSI) standard are
related to setting foreground and background color attributes. These
definitions reflect the evolution of color support on hardware terminals and
within terminal emulators from 3-bit (8 colors) to 4-bit (16 colors) through
today's so-called true-color (usually 24-bit) systems.

Each of the color palettes supported by the standard is exercised by one or
more of the color-attribute tests listed here.

     f : Four-bit color attribute tests (16-color palette)
     b : Background option tests
     t : Table lookup tests (8-bit color)
     g : Greyscale attribute tests
     a : Aixterm extensions
     r : Rgb, red/green/blue tests (24-bit color)
         r : Red spectrum
         g : Green spectrum
         b : Blue spectrum
         y : greYscale spectrum
         w : Web-safe r/g/b colors
     d : Decoding and encoding attribute tracking data
         a : API-level tests (default)
         b : Basic low-level ANSI escape tests
     s : Swap/build8Bit/buildRgb - acaExpand class utilities


 −P Positioning Tests.

One group of the escape sequence defined by the standard provides various ways
to set the cursor position. Some of these sequences set an “absolute”
(terminal-relative) position. Others define a move relative to the current
cursor position. All the supported variations are used during this test.


 −E Erasure Tests.

In the early days of computing, terminals were _extremely_ slow. For this
reason, several innovative ways of erasing an area of the display were
implemented to increase the speed of display updates. Some of these include
erasing part of a line, a whole line, and either the top half or bottom half
of the display. It is even possible to “erase” the data which has already been
scrolled out of the window. (It was a whole thing....don't ask :-)


 −A ASCII Control Codes, Function Keys and ALT Key Combinations.

ASCII Control Codes
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
ASCII control codes (00h - 1Fh) were at one time an important part of systems
which relied on serial communication (e.g. Teletype machines) for user
interaction. On modern systems, most of these codes are unused by the terminal
software and inconvenient for application use.
A few control codes however, are vital to operation. The most common are
null(00h), bell(07h), backspace(08h), horizontal-tab(09h), linefeed i.e.
newline(0Ah), vertical-tab(0Bh), form-feed(0Ch), carriage-return(0Dh), and of
course Escape(1Bh). Others may be used in specialized circumstances.
These keycodes are presented to the application as non-printing byte values,
_OR_ as system signals, which if not properly handled can cause chaos within
an application. A prime example of this would be the CTRL+C Break signal. For
this reason, these byte values and signals are captured by the AnsiCmd library
and converted to unique keycodes for use by the application. A common example
of these would be Copy/Cut/Paste and similar keycodes.
         Key         Raw      Name Of     Common
     Combination    Input     Keycode     Usage
     ───────────  ──────────  ────────    ──────────
      CTRL+C      break(03)   wcsCTL_C    Copy
      CTRL+X         18       wcsCTL_X    Cut
      CTRL+V         16       wcsCTL_V    Paste
      CTRL+Z      susp(1A)    wcsCTL_Z    Undo
      CTRL+A         01       wcsCTL_A    Select All
      CTRL+S      pause(13)   wcsCTL_S    Save
      CtrL+Q      resume(11)  wcsCTL_Q    Quit
      Ctrl+4         1C       wcsCTL_4    Kill App
      Ctrl+[         1B       wcsESCAPE   Escape

The keycodes in this group consist of the CONTROL key plus one of:
   a-z 4 5 6 7 [ \
Note that when the CONTROL key is pressed, the system ignores the SHIFT key,
so CTRL+A generates the same byte code as CTRL+a.

Function Key Combinations
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The function keys F01-F12 and their conditioned varients are often assigned to
system-level tasks, but the terminal emulator may also be configured to pass
these keycodes through to the application level.

All function keys generate escape sequences of between three(3) and seven(7)
bytes. There are 48 (12 * 4) Function key combinations available:
   a) F01-12, b) Shift+F01-12, c) Ctrl+F01-12, and
   d) Ctrl+Shift+F01-12
Only the first three groups are supported by the AnsiCmd class; (36 sequential
codepoints). When received, members of the fourth group, Ctrl+Shift+Fnn are
silently converted to Ctrl+Fnn equivalents.

The AnsiCmd library captures these sequences and converts them to ordinary
Unicode codepoints (keycodes) in the range: 0x002000 through 0x002023. Unicode
assigns these keycodes to mathematical symbols which will seldom, if ever be
generated directly by the keyboard. Some examples of the captured and
converted sequences are shown in the table.

         Key       Escape            Name Of  Unicode
     Combination  Sequence           Keycode  Codepoint
     ───────────  ─────────────────  ──────── ─────────
     F02          1B 4F 51           wcsF02   0x002001
     Shift+F02    1B 5B 31 3B 32 51  wcsSF02  0x00200D
     Ctrl+F02     1B 5B 31 3B 35 51  wcsCF02  0x002019

Please see the AnsiCmdDef.hpp source module for the full list.

ALT Key Combinations
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The Left ALT key in combination with another key provides what are commonly
known as the GUI keys. These key combinations are often used as shortcut keys
within applications. For instance, ALT+F, ALT+E and ALT+H are often used to
invoke an application's “File”, “Edit”, and “Help” menus, respectively.
Because these keycodes are presented to the application as escape sequences,
it is necessary to capture the escape sequences and convert them to unique
keycodes for use by the the application. For the examples mentioned, these
are:
         Key       Escape   Name Of
     Combination  Sequence  Keycode
     ───────────  ────────  ────────
       ALT+F       1B 46    wcsALT_F
       ALT+E       1B 45    wcsALT_E
       ALT+H       1B 48    wcsALT_H

The keycodes in this group consist of the Left ALT key plus one of:
   a-z !  "  #  $  %  &  '  (  ) *  +  ,  -  .  /  :  ;
   <  =  >  ?  @  \  ]  ^  _  {  |  }
Note that to avoid clutter, the alphabetic character are processed as case
insensitive: ALT+A yields the same keycode as ALT+a. Also, the numeric
combinations ALT+0 through ALT+9 are assigned the same keycodes as their
shifted equivalents (assumes U.S. English keyboard layout).
   ! @ # $ % ^ & * ( )
   1 2 3 4 5 6 7 8 9 0

Other Keycodes
▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The “Special Keys” group of keycodes are also reported by this test.

Please see the AnsiCmdDef.hpp source file for a full list of the assigned
keycode names. (or run this test)


 −F Font Selection Tests.

A “font” is a set of glyphs (visible pictures) which are used to represent the
“codepoints” of a character set. The ECMA-48 (ANSI) standard defines a method
for selecting any of ten(10) fonts to be used for display text.

The "Primary Font" is specified in the aeSeq enumerated type as:
    aesPRIMARY_FONT  (decimal 10)

The "Alternate Fonts" are specified by the aeSeq value of:
    aesALTERNATE_FONT
with a numeric argument between 1 and 9 (inclusive). These are translated to
ANSI command codes 11 through 19, respectively.
Please *note acSetFont:: for more information.

Testing thusfar indicates that setting alternate fonts is not supported by the
terminal emulators used during development. The font is set in the terminal's
Preferences/Settings and appears to be unavailable to console applications;
however, this tests exercises the font commands, and further research will be
conducted.


 −I Ideograph Tests.

An “ideogram” is technically a symbol representing a concept or and idea, or
what today we would call a “meme”. Street signs without words,
mathematical-operator symbols or a photo of a cat hanging onto a branch with
one paw could be considered as ideograms.

The ideograms defined by the ECMA-48 (ANSI) standard appear to have been
intended as line-drawing tools or text decorations; however, they seem to have
been abandoned before they were completed. As such, they are unlikely to be
supported by modern terminals; however, this test issues the associated escape
sequences to see what happens i.e. nothing:
   aesIDEO_UNDER     // ideogram underlined
   aesIDEO_UDOUBLE   // ideogram double-underlined
   aesIDEO_OVER      // ideogram overlined
   aesIDEO_ODOUBLE   // ideogram double-overlined
   aesIDEO_STRESS    // ideogram stress marking
   aesIDEO_OFF       // all ideogram attributes off


 −T Terminal Configuration Tests.

This test exercises the various terminal configuration options and the
internal tracking data related to those options.

     i : Input stream capture
     e : Echo options, with a focus on the "soft-echo" options.
         a : All soft-echo special keys translated. (incl. clipboard tests)
         b : Basic set of soft-echo special keys.
         c : Cursor-movement special keys translated.
         d : Disable soft-echo special-key translation.
         e : Edit keys: Backspace/Del/Insert translated.
         r : Report special key translations.
         t : Terminal echo of key input.
         n : No echo of key input.
     t : Terminal configuration validation of options, including
         input buffering, cursor style and capture of the break signal.
     b : Blocking vs. non-blocking read from 'stdin'
     r : Raw input stream reporting. The data are reported in unmodified form.
     o : Output, tests handling of multi-byte character data in the output stream.
     m : Modifiers: Bold, Italic, Underline, Reverse, Overline, etc.
     f : Formatted output. Test data formatting and output to stdout.

     Examples:
        epts --test=T      # Display the menu of sub-options
        epts --test=Tb     # Test blocking vs. non-blocking input
        epts --test=Tec    # Soft-echo options, cursor-movement keys


     Developer's Note: The text-modifier tests are included with the
     terminal configuration group because the tests include verification of
     the flags that track which modifier(s) are set at any given time.


 −W Window (ACWin) Tests.

The window group consists of API-level algorithms which are implemented at a
higher abstraction level compared to the basic ANSI escape sequences.

At an intermediate level are the line-drawing and box objects which simply
draw lines and rectangles to the display. These objects are defined by the
*note acDrawLine:: method and the *note AC_Box Class::, respectively.

At the higher level of abstraction is the *note ACWin Class:: which defines a
relatively primitive window object which optionally contains an array of text
fields and other user-interface controls (*note skForm Class::).
See also the next section which describes “dialogs”, which are functionally
sub-windows within the main window.

Visually, an ACWin window is simply a rectangle drawn within the terminal
window; however, application-level interaction is carefully range-checked and
validated to maintain the integrity of the window. This allows the application
designer to focus on the project, rather than being distracted with organizing
color change sequences, counting text columns and other low-level details.

The tests in this group exercise all the major functionality of defining and
managing the ACWin object.

     w : Window (ACWin) interactive tests
     f : Form: skForm class (and skField class) user interface controls
     t : Automatic text reformatting to fit specified dimensions
     d : Default AC_Win window constructor
     s : Save and restore static text written to the window
     m : Menus and Scrollbox controls. These controls require specialized tests.
     h : Highlight text. Scan field text for a given token, and highlight it.
     e : Documentation tool, take a screenshot to insert into documentation.
     b : Box drawing tests
     l : Line drawing tests
     x : eXternal interface tests
         a : AnsiCmd API-level clipboard tests (tty output)
         w : Window (ACWin/ACDlg) clipboard tests
         t : Temporary-file management
         s : Shell out to command line
         l : Launch external application

     Examples:
        epts --test=W    # Display the menu for the window group
        epts --test=Ww   # Interactive test of ACWin configuration
        epts --test=Wf   # User interaction via skForm control group
        epts --test=Wlg  # Line-drawing tests with 'g'reen lines
        epts --test=Wxw  # Clipboard-to-window communication

 −D Dialog (ACDlg) Tests.

The dialog tests are a functional subset of the the window tests
(*note ACWin Class::), but because the Dialog is at the highest level of
abstraction, a large number of tests are required, so they are grouped
separately.

      'D'         Dialog-oriented tests (application-level functionality).
           'q'    QuickDialog tests are specified by the letter 'q', followed
                  by the letter or number for the specific test:
                  '1' Basic information dialog (one control)
                  'e' Basic decision dialog with English pushbuttons
                  'c' Basic decision dialog with Chinese pushbuttons
                  'v' Basic decision dialog with Vietnamese pushbuttons
                  's' Basic decision dialog with Spanish pushbuttons
                  't' Auto-Timeout dialog, displayed for specified interval only
                  'p' Dialog dimensions determined by size of Preformatted text.
                  'w' Fixed-width dialog with text automatically formatted
                  'h' Fixed-height dialog with text automatically formatted
                  'r' Repositioned automatically within the parent window.
                  '?' If no test letter is specified, or if an invalid test
                      is specified, the QuickDialog test menu is displayed.
           'd'    Dialog, full initialization. Tests re specified by the letter
                  'd', followed by the letter or number for the specific test.
                  -- Dialog invocations with full initialization allow for any
                     _reasonable_ number of customized controls of all defined
                     control types, in any order and in any position.
                  'a' Preformatted text, Auto-dimensions,
                      Centered horizontally and vertically.
                  'b' Auto-height, Fixed width, Text reformatted to specified width.
                  'c' Preformatted text, Auto-width, Fixed height,
                      Centered horizontally and vertically.
                  'd' Unformatted text, Auto-dimensions,
                      Centered horizontally and vertically.
                  'e' Unformatted text, Fixed horizontal and vertical offsets,
                      Auto-height, Fixed-width.
                      Text truncated to fit available space.
                  'f' Unformatted text, Fixed horizontal and vertical offsets,
                      Fixed-height, Auto-width.
                      Text truncated to fit available space.
                  't' Unformatted text, Centered vertically and horizontally,
                      Fixed height and width specified, with height value overridden,
                      but truncation of text still required.
                  'w' Unformatted text, Centered horizontally, Fixed height and width,
                      Fixed vertical offset, Text truncated to fit available space.
                  'h' Move dialog horizontally in increments using preformatted text.
                      Resize dialog as necessary to stay within parent window.
                  'i' Move dialog horizontally in increments using unformatted text.
                      Resize dialog as necessary to stay within parent window.
                  'v' Move dialog vertically in increments using preformatted text.
                      Resize dialog as necessary to stay within parent window.
                  'u' Move dialog vertically in increments using unformatted text.
                      Resize dialog as necessary to stay within parent window.
                  'z' Dialog demonstrating all features: Pushbuttons, Radiobuttons,
                      Textboxes, static text.
                  '?' If no test letter is specified, or if an invalid test
                      is specified, the full-Dialog test menu is displayed.
           '0'    Display the menu of dialog tests.
           's'    Sidebar test. This test is unrelated to dialogs. It is
                  included in this group because this group uses an empty
                  ACWin window object which allows for easy testing of the
                  Sidebar functionality.


     Examples:
        epts --test=D    # Display the menu for the dialog group
        epts --test=Dq   # Display the menu for the QuickDialog sub-group
        epts --test=Dd   # Display the menu for the full-dialog sub-group
        epts --test=Dqp  # Dialog dimensions derived from displayed text
        epts --test=Ddz  # Dialog with samples of all control types



 −S Sandbox.

The “Sandbox” is a common name among nerdy types to indicate a work area in
which experimental operations may be performed without compromising the
platform as a whole.

Invoking the Sandbox executes user-defined functionality created for ad hoc
testing. Note that code created in the Sandbox may be affected by the AnsiCmd
class initialization as specified by arguments to the “--term” command-line
option.
*Note Invoking - Terminal Setup:: for more information.

Invoking the Sandbox test may include one or two optional arguments which are
passed as parameters to the Sandbox method. Each of these optional arguments
consists of a single alpha-numeric character, (case insensitive).

Examples:
   epts --test=S    # invoke the Sandbox with no arguments
   epts --test=St   # invoke the Sandbox with one argument
   epts --test=S4c  # invoke the Sandbox with two arguments

The specified arguments will be displayed in the top row of the window as
shown, and these parameters may be referenced in the usual way.
(A question mark will be displayed for unspecified argument(s)).
     Test ANSI Commands: 'S' '4' 'c'
     -------------------------------

     Welcome to the Sandbox!

     Example:
     void AnsiCmd::Test_Sandbox ( wchar_t parmA, wchar_t parmB )
     {
        if ( parmA == L'4' )
           this->SolveWorldHunger ( parmB ) ;
        else if ( parmA == L'5' )
           this->MakeScrambledEggs_with ( parmB ) ;
        else if ( parmA == L'?' )
           this->SpendAllDayOnTikTok () ;
     }



File: ansicmd.info,  Node: Invoking - EarthPoints,  Prev: Invoking - AnsiCmd Tests,  Up: Invoking

Invoking - EarthPoints
======================


Summary of Options
------------------

       OPTION                           DESCRIPTION
     ------------------------------------------------------------------
       *note coa option::              Specify the first set of
                                       global coordinates.
       *note cob option::              Specify the second set of
                                       global coordinates.
       *note file option::             Specify a file containing
                                       global coordinate pairs.
       *note formula option::          Specify the formula to be
                                       used to calculate distance.
       *note convert option::          Convert coordinate-pair
                                       format to alternate formats
       *note color option::            Specify color attribute for
                                       reporting results.
       *note verbose option::          Display verbose output for
                                       results of calculation.
       *note window option::           Display the report within a
                                       window object.
       *note dump option::             Display and verify contents
                                       of a file of GPS records.
       *note version option::          Reports EarthPoints version
                                       number and copyright info.
       *note help option::             Display all EarthPoints and
                                       AnsiCmd options
       *note helpless option::         Same as '--help' option
                                       except pipe through 'less'

Options may be specified in any order.

For each option that requires one or more arguments, the option name and its
argument(s) may be separated by either '=' or ' ' (space).
Note that if the argument contains whitespace, then the entire argument
sequence must be enclosed within single-quotes or double-quotes.
This prevents the terminal's shell program from “interpreting” (trashing) your
argument formatting.

Examples:
    --coa=Miami:25.775163:80.208615
    --coa 'Miami: 25.775163 : 80.208615'
    --cob="Buenos Aires: -34 36 12.0 : -58.381666667"
    --file='Europen Capitol Cities - 2007.txt'

Note: As a convenience, the long-form options may be uniquely specified in a
truncated form. At least six (6) characters of the option must be specified.
This consists of the two 'dash' characters, plus the first four characters of
the option name. Example: The “--verbose” option may be uniquely specified as
“--verb”.



GPS Coordinate Records
----------------------

A GPS coordinate record has the following format:
   [LABEL:] LATITUDE : LONGITUDE
where:

   ⏺ LABEL:    — (optional) city or place name associated with the
                  coordinates, followed by the colon character (':')
                  which separates the label from the latitude field.
   ⏺ LATITUDE  — (required) Specify the latitude for the record
                  in degrees or radians.
   ⏺ colon (:) — (required) Separates latitude and longitude values.
   ⏺ LATITUDE  — (required) Specify the longitude for the record
                  in degrees or radians.

Whitespace between fields of the record is optional, and will be ignored.
Whitespace within a coordinate field delimits the tokens within that field:
   Examples: '25 46.50978'  _or_  '25 46 30.5868'
The label field is simple text, and may contain spaces if desired.
(Note the trailing colon ':').
   Example: "Miami, Florida, USA:"

Latitude and longitude pairs may be expressed in either degrees or radians.
Within a latitude:longitude pair, each value may take one of the following
formats.

  1. a decimal degree value
       Examples:
       --coa='Miami: 25.775163 : -80.208615'
       --cob='Buenos Aires: -34.603333333 : -58.381666667'

     Note that positive degree values indicate North latitude or East
     longitude, while negative values indicate South latitude or West
     longitude."

  2. a decimal radian value
       Examples:
       --coa='Miami: 0.449861R : 4,883281R'
       --cob='Buenos Aires: 5.679243R : 5.264233R'

     Note that the trailing 'R' character of each value indicates radians.
     Note also that an arc in radians is expressed as a positive value only.

  3. an integer degree value followed by a decimal minutes value
       Examples:
       --coa='Miami: 25 46.50978 : -80 57.948611'"
       --cob='Buenos Aires: -34 36.20 : -58 22.90'

  4. an integer degree value followed by an integer minutes value, followed by
     a decimal seconds value
       Examples:
       --coa='Miami: 25 46 30.5868 : -80 57 56.91666'
       --cob='Buenos Aires: -34 36 12 : -58 22 54.0'

                             ─ ─ ─ ─ ─ ─ ─ ─ ─ ─


Invocation Options
------------------

 −−coa Coordinate pair A.

     Specify the record containing the first pair of GPS coordinates.

     Formatting of the record is described in the *note GPS Coordinate
     Records:: section, above.

     Two sets of GPS coordinates are needed to calculate arc length. See the
     "cob" option, below.

     Please *note verbose option::, below for sample output formatting.


 −−cob Coordinate pair B.

     Specify the record containing the second pair of GPS coordinates.

     Formatting of the record is described in the *note GPS Coordinate
     Records:: section, above.

     Two sets of GPS coordinates are needed to calculate arc length. See the
     "coa" option, above.

     Please *note verbose option:: below for sample output formatting.


 −−file Filespec of GPS coordinate database.

     Specify a file containing a database of GPS coordinate pairs and identify
     two specific records from that database. These records represent the
     endpoints of the arc distance to be calculated.

     The target file is a plain text file containing any number of GPS
     records. The individual records follow the same format as command-line
     record specification described at the beginnig of this chapter. An
     example database file is shown below. (Not that you would ever do
     anything so foolish, but the filename may not contain the colon ':'
     character.)

     Each target record is specified by its label, either the full label text,
     or a substring which uniquely identifies the beginning of the record
     label. The scan is case-insensitive. Specifying the database filename and
     record labels takes the form:
        --file='FILENAME:LABEL_A:LABEL_B'

     The following record specifications are equivalent.
        epts --file='GPS_Records.txt:Chicago, IL:Miami, FL'
        epts --file='GPS_Records.txt:chi:Mia'

     Alternatively, the records may be specified using the _index_ of of the
     record(s) within the database using the special token: “LABn” where 'n'
     is a zero-based index.

     Examples:
        epts --file='GPS_Records.txt:Chicago, IL:LAB14'
        epts --file='GPS_Records.txt:LAB2:Miami, FL'
        epts --file='GPS_Records.txt:LAB2:LAB16'


     Example GPS Record Database
     ...........................

     Each record lives on a seperate line. Note the range of available
     coordinate formats. Blank lines and lines beginning with the hash
     character ('#'), are interpreted as comments and will be ignored.

     # ---------------------------------------------------
     # The Not Fully United Kingdom.
     # ---------------------------------------------------
     #                                              INDEX
     #                                              -----
     # London, England                                0
     London         : 51 30 26.0 : -0 7 39.0
     
     # Edinburgh, Scotland                            1
     Edinburgh      : 55.953056 : -3.188889
     
     # Cardiff, Wales                                 2
     Cardiff        : 0.898525R : 3.086106R
     
     # Belfast, Northern Ireland                      3
     Belfast        : 54.596521 : -5.930578

     Three GPS database files are included with the AnsiCmd package:
        'US_Capitols.txt', 'UK_GPS.txt' and 'testpoints.txt'.


 −−formula Formula for arc calculation.

     Select the formula to be used for calculation of the arc distance between
     the two specified GPS coordinates.
     (Three(3) characters are sufficient to uniquely identify the argument.)

     Available formulae:
          lambert    The Lambert formula calculates the arc on an ellipsoid.
          haversine  The Haversine formula calculates the arc on a sphere.
          all        Displays the calculations for all supported formulae.

          Examples:
             epts --coa='36.1:-14.3' --cob='37.7:-12.4' --form=lambert   (default)
             epts --coa='36.1:-14.3' --cob='37.7:-12.4' --form=haversine
             epts --coa='36.1:-14.3' --cob='37.7:-12.4' --form=all

     Additional formulae may be implemented in a future release.


 −−convert Convert coordinate formatting.

     Convert one(1) latitude or longitude value from the given format to the
     alternate supported formats and display the results.

     The 'convert' option takes one argument of the form:
        --convert=GPS_COORDINATE_VALUE

     This option is useful primarily for debugging the input-parsing routines;
     however, it may also be useful for experimenting with the various GPS
     coordinate value formats.

     Example coordinate values and the report generated:

          epts --convert='-80 57 56.91666'
             Converted Value:
              dec:-80.965810      decimal degrees (degrees+minutes+seconds)
              deg:-80.000000      degrees component
              min: 57.000000      minutes component
              sec: 56.916660      seconds component
              rad: 1.728473       radians
              fmt: vfSec          source format identifier (enum valFmt)

          epts --convert=4.2579R
             Converted Value:
              dec:-63.959700
              deg:-63.000000
              min: 57.000000
              sec: 34.918520
              rad: 4.257900
              fmt: vfRad


 −−color Specify color attribute for application.

     Specify the foreground and background color attributes for display of the
     output. The terminal window's color attributes are used by default.

     If the --window option is used, then the window's border attributes may
     also be specified. (Border attributes, if specified, are ignored for TTY
     output.)

     The '--color' option may be used to specify alternate attributes. The
     format of the arguments takes the form:
        --color=text_fgnd:text_bkgnd[:border_fgnd:border_bkgnd]

     Each color is specified as one of the following:
             'black'       'blue'
             'red'         'magenta'
             'green'       'cyan'
             'brown'       'grey'

             'dflt' use terminal default attribute
          (The first four characters of the name uniquely identify the color.)

          Examples:
             epts --color=blue:grey       // blue text on grey background
             epts --color=green:dflt      // green text on default background
             epts --color=dflt:blue       // default text color on blue background

             // blue text, grey bkgnd, cyan border fgnd, black border bkgnd
             epts --color=blue:grey:cyan:black
             // default text fgnd:bkgnd, magenta border fgnd, blue border bkgnd
             epts --color=dflt:dflt:magenta:blue



 −−verbose Report verbose results.

     The standard arc-distance report displays the coordinates in both degrees
     and radians, and then displays the arc-distance in both kilometers and
     miles, calculated using the specified formula.

     The verbose arc-distance report displays the same information, except
     that the coordinate values in degrees are broken down into their
     component parts: Degrees, Minutes and Seconds.


     Standard Report:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     Miami, FL                         Buenos Aires, AR
     ======================            ======================
     LATITUDE    LONGITUDE             LATITUDE   LONGITUDE
     ----------  ----------            ----------  ----------
       0.44986     1.74169  Radians      2.53765     2.12264
      25.77516   -80.20862  Degrees    -34.60333   -58.38167
            Distance: 12905.069560 km  (8018.838378 mi)

     Verbose Report:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     Miami, FL                         Buenos Aires, AR
     ======================            ======================
     LATITUDE    LONGITUDE             LATITUDE   LONGITUDE
     ----------  ----------            ----------  ----------
       0.44986     1.74169  Radians      2.53765     2.12264
      25.77516   -80.20862  Degrees    -34.60333   -58.38167
            25         -80  Deg(int)         -34         -58
            46          12  Minutes           36          22
            31          31  Seconds           12          54
            Distance: 12905.069560 km  (8018.838378 mi)


 −−window Display report in a window.

     By default, the arc-distance report is displayed in the terminal window
     using common TTY (Teletype) style output. This output is formatted using
     basic ANSI escape sequences.

     Optionally, the arc-distance report may be formatted within an
     ACWin-class window object positioned within the terminal window. The
     ACWin class is derived from the base AnsiCmd class and implements more
     advanced ANSI formatting. It is designed to resemble an 'ncurses' dialog
     window.

     Please *note ACWin Class:: for more information.

     By default, the dialog window is positioned with the origin (upper-left
     corner) at row one(1), column four(4) of the terminal window. However,
     any position within the terminal window may be specified using parameters
     of the form: 'row:column'.

     The row and column are 1-based offsets from the upper-left corner of the
     terminal window. *Note cursor offsets:: for a discussion of 1-based
     versus 0-based terminal offsets.

     Additionally, specifying a zero (0) value for either parameter indicates
     that the dialog is to be centered in that dimension. See examples below.

     If the specified position would place any part of the dialog beyond the
     boundaries of the terminal window, then the position will be
     automatically adjusted to ensure that the entire dialog is visible.

     Examples:
        epts --window       // no position specified, use default 1:4
        epts --window=2:1   // positioned at row 2, column 1
        epts --window=12:0  // positioned at row 12, centered horizontally
        epts --window=0:5   // centered vertically, and at column 5
        epts --window=0:0   // centered both vertically and horizontally
     In the following example, the row specified is beyond the number of rows
     in the terminal window, so the vertical offset will be automagically
     adjusted such that the lower edge of the dialog is on the bottom row of
     the terminal window:
        epts --window=99:0  // auto-adjusted row, and centered horizontally

     
       ┌─┤ EarthPoints v:0.0.03 (c) 2022-2023  The Software Samurai ├─┐
       │   Miami, FL                         Buenos Aires, AR         │
       │   ======================            ======================   │
       │   LATITUDE    LONGITUDE             LATITUDE   LONGITUDE     │
       │   ----------  ----------            ----------  ----------   │
       │      0.44986     1.74169  Radians      2.53765     2.12264   │
       │     25.77516   -80.20862  Degrees    -34.60333   -58.38167   │
       │           Distance: 12905.069560 km  (8018.838378 mi)        │
       │                                                              │
       │                   Press Any Key to Exit....                  │
       └──────────────────────────────────────────────────────────────┘

     Please visit the author's website to download the NcDialog API, and for a
     discussion of full-featured dialog windows based on the ncurses library.
     *Note By the Same Author:: for details.


 −−dump Dump GPS file contents.

     Display and verify the formatting of GPS coordinate records contained in
     the specified file.

     A database of GPS coordinate records is a plain text file with a series
     of records in the form:
        Phoenix, AZ : 33 26 53.15 : -112 5 49.54
     consisting of three(3) fields, seperated by colons (':').
        Label       : Latitude    : Longitude

     Formatting of the record is described in the
     *note GPS Coordinate Records:: section, above.

     When constructing a database of GPS coordinate records, the syntax of the
     records should be verified. The syntax of each record in the database is
     verified using the "--dump" option.

     Example:
        epts --dump='US Capitols.txt'

     The following is the output for the scan of the 'testpoints.txt' file
     included in this package.

     EarthPoints (epts) v:0.0.03 Copyright(c) 2022-2023  The Software Samurai
     ========================================================================
     Validate contents of GPS record file: 'testpoints.txt'
     ------------------------------------------------------
     00) :25 46 30.5868 : -80.208615                             (OK)
     01) Miami, FL : 25 46 30.5868 : -80.208615                  (OK)
     02) Buenos Aires, AR : -34 36 12.0:-58 22.90                (OK)
     03) Indianapolis, IN : 39.768611 : -86.158056               (OK)
     04) Lafayette, IN : 40.417222 : -86.878611                  (OK)
     05) San Francisco, CA : 37.7775 : -122.416389               (OK)
     End-Of-File

     If a syntax error is found, it will be indicated by a status of “(?)”.
     For example, this record is missing the madatory field delimiter ':'
     between the Label and Latitude fields.
     01) Miami, FL   25 46 30.5868 : -80.208615                  (?)


 −−help (or −h) Display command-line help.

     Command-line Help. Display a brief summary of command-line usage and
     options. (overrides everything on command line except '--version')

        EXAMPLES:  epts --help
                   epts -h


 −−helpless (or −hl) Display command-line help.

     Display command-line help. Same as the '--help' option above except that
     the help menu will be piped through the 'less' utility.

        EXAMPLES:  epts --helpless
                   epts -hl


 −−version Report EarthPoints version number.

     Display the EarthPoints version number and copyright information.
     (overrides everything else on the command line)

     To _also_ report the AnsiCmd-class version number, append an 'a' to the
     argument.

        EXAMPLES:  epts --version
                   epts --versionA



File: ansicmd.info,  Node: AnsiCmd Library,  Next: ACWin Class,  Prev: Invoking,  Up: Top

AnsiCmd Library
***************

* Menu:

* Introductory Notes::           Overview of the working environment
* ANSI Escape Sequences::        Physical structure and use
* Terminal Configuration::       Configuring I/O streams and more
* AnsiCmd Class Methods::        Public methods and data members


File: ansicmd.info,  Node: Introductory Notes,  Next: ANSI Escape Sequences,  Up: AnsiCmd Library

Introductory Notes
==================

For those who are new to the terminal (emulator) environment, or for those who
are interested in the technical details of terminal configuration, this
chapter provides an overview of the challenges the author faced during
development of this project, and our responses to those challenges.


Terminal Environment
--------------------

A common saying in Linux is that “Everything is a file.” While it is true in
general that most things are _acessed_ as if they were files, many of the
underlying targets are not actually files on the storage media. This is
nowhere more apparent than with the input and output data streams of the
terminal emulator. Generically, these are known as Standard Input(stdin),
Standard Output(stdout) and Standard Error(stderr).

Within the AnsiCmd library, these are referred to by their so-called file
handles which are named by the 'TermStream' enumerated type:
     Name   Handle
     stdIn    0
     stdOut   1
     stdErr   2

These streams are not actual files, but the terminal's _VIRTUAL_ configuration
files. Therefore, practically speaking, when modifying terminal settings, it
doesn't matter whether the stdIn, stdOut or stdErr stream is referenced
because they are not actual file descriptors. Instead, they reference the
underlying terminal-attributes structure.
For more information, *note Terminal Configuration::.


File: ansicmd.info,  Node: ANSI Escape Sequences,  Next: Terminal Configuration,  Prev: Introductory Notes,  Up: AnsiCmd Library

ANSI Escape Sequences
=====================

ANSI (American National Standards Institute) escape sequences are simply a
well-defined set of byte sequences that may be used to communicate with the
host terminal. They are hopelessly old-fashioned, slow, unreliable, difficut
to use and all-around relics from the mid-20th century. That being said, they
are also widely supported and a lot of fun to play with.

ANSI escape sequences include functionality for cursor positioning, erasing
blocks of text, setting color attributes and text modifiers such as bold,
italic etc., and all other attributes defined by the ECMA-48, ANSI X3.64
standard. See also ISO/IEC 6429, FIPS 86, ISO/IEC 2022, JIS X 0211.

<https://en.wikipedia.org/wiki/ANSI_escape_code>



Escape-sequence Definitions
...........................

Within the AnsiCmd library, the individual ANSI escape sequences are
referenced by the “enum aeSeq” enumerated type.

aeSeq (ANSI Escape Sequence) is located in the AnsiCmdDef.hpp header file and
includes all the ANSI escape sequences defined by the ECMA-48, ISO/IEC-6429
standard.

Note that each member begins with “aes” to indicate that it belongs
specifically to this enumerated type. The short example below should give the
basic idea of how aeSeq is constructed.

enum aeSeq : short
{
   //** Text Modification Options. **
   aesRESET = 0,              // reset all attributes
   aesBOLD,                   // bold (increase intensity)
   aesFAINT,                  // faint/dim (decrease intensity)
   aesITALIC,                 // italic (or inverse)
   . . .
   //** Foreground Color Attributes (3-bit and 4-bit color selection) **
   aesFG_BLACK,               // set foreground color to black (i==24)
   aesFG_RED,                 // set foreground color to red
   aesFG_GREEN,               // set foreground color to green
   . . .
   //** Background Color Attributes (3-bit and 4-bit color selection) **
   aesBG_BLACK,               // set background color to black (i==41)
   aesBG_RED,                 // set background color to red
   aesBG_GREEN,               // set background color to green
   . . .
   //** Indexed Color Attribute Options (8-bit color and greyscale) **
   aesFG_INDEX,               // set foreground color by lookup table index (0-255)
   aesBG_INDEX,               // set background color by lookup table index (0-255)

   //** Red/Green/Blue Color Attribute Options (24-bit color) **
   aesFG_RGB,                 // set foreground color by r/g/b register number
   aesBG_RGB,                 // set background color by r/g/b register number

   //* Cursor-positioning Options *
   aesCUR_HOME,               // set cursor at 1,1
   aesCUR_ABSPOS,             // set (absolute) cursor at specified row;column position
   aesCUR_ROWSUP,             // move cursor upward by specified number of rows
   . . .
   //* Text Erasure Options *
   aesERASE_BOW,              // erase from cursor to bottom of window
   aesERASE_TOW,              // erase from cursor to top of window
   aesERASE_WIN,              // erase entire window ('clear')
   . . .
   //* Alternate Font group *
   aesPRIMARY_FONT,           // primary font      (font 0)
   aesALTERNATE_FONT,         // alternate fonts (font 1 through font 9)

   //* ASCII Control Codes. *
   aesBELL,                   // '\a' terminal "bell" (beep, ping, etc.)
   aesBKSP,                   // '\b' backspace
   aesHTAB,                   // '\t' horizontal tab
   . . .
   //* Ideogram (logogram) group of options *
   aesIDEO_UNDER,             // ideogram underlined
   aesIDEO_UDOUBLE,           // ideogram double-underlined
   aesIDEO_OVER,              // ideogram overlined
   . . .
   //** Aixterm codes are not part of the    **
   //** ANSI standard, but may be supported. **
   aesAIXFGb_BLACK,           // set foreground color to bright black (grey)
   aesAIXFGb_RED,             // set foreground color to bright red
   aesAIXFGb_GREEN,           // set foreground color to bright green
   . . .
   aesCOUNT                   // number of items in enumerated type list
} ;   // enum aeSeq

The members of aeSeq index the corresponding byte sequences which are private
data located in the AnsiCmd.cpp source module.
    static const wchar_t *ansiSeq[aesCOUNT];

A majority of the element of this array are constant byte sequences; however,
the sequences which require parameters are defined as formatting templates as
shown in these examples.

Constant byte sequence:
    L"\x1B[22;31m"      // aesFG_RED
Formatting template:
    L"\x1B[38;5;%hhum"  // aesFG_INDEX

Note that these sequences are defined as _wide_ character strings because as
explained elsewhere (*note Terminal Configuration::), 8-bit character streams
are so very 1970s.


Multi-threading
...............

ANSI escape sequences should not be used in multi-threaded applications due to
timing issues and resource conflicts. For multi-threaded applications, the
author recommends our NcDialog API, which is a fully thread-safe ncurses-based
library for creating formatted-text console applications.

One practical effect of avoiding multi-threading is in the area of library
functions which handle timing and delays.

In C++, the accepted way to delay the action is to use the 'chrono' class to
define the delay, and the 'sleep_for' method to execute it. However, ANSI
escape sequences are inherently incompatible with a multi-threaded
environment. For this reason, the AnsiCmd class uses the C-language
nanosleep() function. This function is technically sophisticated, but clunky
in implementation; so please refer to our iplementation of nanosleep():
nsleep() for details. (*note nsleep::)


File: ansicmd.info,  Node: Terminal Configuration,  Next: AnsiCmd Class Methods,  Prev: ANSI Escape Sequences,  Up: AnsiCmd Library

Terminal Configuration
======================

Initial terminal configuration is specified by passing an initialized
TermConfig object to the AnsiCmd constructor.
   *Note TermConfig Class::.

Subsequent modifications to the terminal environment are specified by calling
the associated AnsiCmd-class method(s).
   *Note AnsiCmd Class Methods::.

The actual configuration commands are issued by the TermSet object, which is a
private member of the AnsiCmd class as described below.
   *Note TermSet Class::.


TermConfig Class
----------------

Initialization of the TermConfig object may be done directly by the
application when invoking the AnsiCmd constructor:
   *note AnsiCmd constructor::,
or may be performed by the user through command-line options:
   *note Invoking - Terminal Setup::.
The options provided by the user are validated and stored in the data members
of the TermConfig object.


Data Members
............

   ⏺ TermStream termStream
     Specify the target I/O stream as a member of enum TermStream:
        stdIn (stdin), stdOut (stdout), stdErr (stderr)

     Note: In practical terms, the selection of the target stream is not
     important because changes made to one stream are reflected in all
     streams. Internally, 'stdIn' is used when not specified otherwise.

   ⏺ char configFile[gsMAXBYTES]
     NOT YET IMPLEMENTED
     Name of configuration file (default “ansicmd.cfg”) which specifies all
     terminal configuration options.

   ⏺ char localeName[LOCALE_LEN]
     Filename of alternate locale (null string by default). If not specified,
     locale will be taken from terminal environment.

     For those not familiar with the purpose of the 'locale' specification,
     the locale selected controls how characters are encoded, formatting of
     numbers, timestamps and currency, interpretation of punctuation,
     comparisons of text strings and other text formatting decisions. By
     default, applications start in the so-called “C-locale” which is not
     really a locale, but a lack of locale which interprets everything in
     terms of ASCII and English, rendering the application basically useless.
     For this reason, it is _strongly_ recommended that all application set
     the locale for the language, character set and text conventions in use by
     the target system.
     Please refer to the *note acSetLocale:: method for additional
     information.

   ⏺ EchoOpt echoOption
     The selected Echo Option specifies how the data input stream is to be
     managed.

     Characters received through 'stdin' will be echoed (displayed) in the
     terminal window according to the specified member of enum EchoOpt.

     When system buffering of input is active, the application has no direct
     control over input echo, so this option will be ignored. However, when
     input buffering is disabled (see the 'bufferInput' variable, below), the
     specified echo option will be used:
        ⚬ noEcho : input data are not echoed to the display.
        ⚬ termEcho: terminal automatically echoes input
          The terminal always controls input echo when input buffering is
          enabled, and _may be_ allowed to control input echo when buffering
          is disabled.
        ⚬ softEcho[A|B|C|D|E]: the *note acRead:: input methods echo (display)
          all graphing (printing) characters to the terminal window as they
          arrive. The “special” keys (cursor movement, text selection,
          clipboard access and backspace, delete, insert) are processed
          according to specified soft-echo sub-option.
             ▪ softEchoA - All special keys are captured, decoded and
               available to the application.
             ▪ softEchoB - Basic group of special keys. (Text selection keys
               and Copy/Cut/Paste/Undo keys are excluded.)
             ▪ softEchoC - Cursor keys only: UpArrow, DownArrow, LeftArrow,
               RightArrow, Home, End, PageUp, PageDown, Tab and Shift+Tab.
               (Edit keycodes are excluded.)
             ▪ softEchoD - Disable (capture and discard) all special keycodes.
             ▪ softEchoE - Edit keys Backspace, Delete and Insert, _plus_ Tab
               and Shift+Tab. (Cursor movement keycodes are discarded.)
          The keycodes in each special-key group may be adjusted, as we
          receive more feedback from users about how they uses these options.

          Please *note Soft Echo Options:: below for more information.

   ⏺ bool bufferInput
     Specify whether data from 'stdin' will be buffered by the system or
     whether it will be sent directly to the application as soon as it arrives
     in the input stream.
        'false' : disable input buffering
        'true;  : input buffering enabled (default)
     Note that both the soft-echo options (described above) and non-blocking
     read of the input stream require that input buffering be disabled.

   ⏺ bool wideStream
     Select the character width of the input/output streams.
        'true'  : wide (32-bit) I/O streams, wcin and wcout
        'false' : narrow (87-bit) I/O streams, cin and cout
     Please *note acSetStreamWidth:: for additional information.

   ⏺ bool nonStandard
     Specify whether the host terminal is ANSI compliant.
     A compliant terminal supports all of the common commands of ANSI standard
     (ANSI X3.64 (ISO/IEC6429)).    'true'  : non-standard terminal emulator
        'false' : ANSI compliant terminal emulator (default)
     The three terminal emulators used during development, Gnometerm, Konsole
     and XTerm are all fully compliant with the standard. To determine whether
     your preferred terminal supports all the ANSI escape sequences defined by
     the standard, run the full set of tests provided with this library.
     Please *note Development and Testing:: for full information.

   ⏺ CCH_Type bcType
     Capture the Panic Button (CTRL+C key). The signal-capture type is
     specified as a member of enum CCH_Type:
        ⚬ cchtTerm   - Terminal handles CTRL+C break-signal.
        ⚬ cchtExit   - The application terminates execution in an orderly way.
        ⚬ cchtUser   - Ask user whether to exit or discard the signal.
        ⚬ cchtCopy   - Convert the break signal to an ordinary keycode.
        ⚬ cchtIgnore - Ignore (discard) the break signal.

     *Note Capturing the Break Signal:: below for more information.

   ⏺ bool bcAlert
     For 'bcType' == cchtIgnore ONLY: Specify whether the application should
     sound an audible alert when the break signal is captured and discarded.
     (This is a polite way of telling the user to stop pressing the Panic
     Button.)
        'true' : sound the alert when break is captured and discarded
        'false': silently discard the captured break signal

   ⏺ CurStyle cursorStyle
     Select cursor style. The cursor style is specified as a member of enum
     CurStyle:
        ⚬ csDflt    Terminal default cursor style.
        ⚬ csBblock The shape of the cursor is a full-character cell,
          _blinking_ block. (This is also generally the terminal default
          shape.)
        ⚬ csSblock The shape of the cursor is a full-character cell, _steady_
          (non-blinking) block.
        ⚬ csBuline The shape of the cursor is a _blinking_ underline i.e. one
          or two pixel rows at the bottom of the character cell.
        ⚬ csSuline The shape of the cursor is a _steady_ underline i.e. one or
          two pixel rows at the bottom of the character cell.
        ⚬ csBvbar   The shape of the cursor is a _blinking_ vertical bar i.e.
          one or two pixel columns at the left edge of the character cell.
        ⚬ csSvbar   The shape of the cursor is a _steady_ vertical bar i.e.
          one or two pixel columns at the left edge of the character cell.
        ⚬ csHide    Hide the cursor i.e. make it _invisible_. Note that the
          previouly selected cursor shape will be retained.
        ⚬ csShow    Show the cursor i.e. make it _visible_.

   ⏺ suspendSignal
     Specify whether the Suspend signal is captured by the application.
     The system uses the suspend signal to put the active process into
     hibernation.

     By default, the AnsiCmd library captures this signal and converts it to
     an ordinary keycode (wcsCTL_Z). Under most circumstances, this is the
     desired action; however, if specified, the system can be allowed to
     retain control of this signal.
        'false' : the system retains control of the suspend signal
        'true'  : the suspend signal is captured and disabled (default)
     Please *note acCaptureSuspendSignal:: for additional information.

   ⏺ quitSignal
     Specify whether the Quit signal is captured by the application.
     The system uses the quit signal to immediately kill the application and
     then produce what is known as a “core dump” which is a file that contains
     information about the final state of the application.
        'false' : the system retains control of the quit signal
        'true'  : the quit signal is captured and an orderly
                  shutdown is executed (default)
     Please *note acCaptureQuitSignal:: for additional information.

   ⏺ aeSeq foreground
     Specify the initial foreground (text) color attribute.
     This is a member of the 4-bit foreground color group within
     enum aeSeq: aesFG_xxxx (default:aesFG_DFLT)
     Please *note ANSI Escape Sequences:: for examples.

   ⏺ aeSeq background
     This is a member of the 4-bit foreground color group within
     enum aeSeq: aesBG_xxxx (default:aesBG_DFLT)
     Please *note ANSI Escape Sequences:: for examples.


Capturing the Break Signal (CTRL+C)
-----------------------------------

The break signal is generated by the user pressing the Control+C key
combination. By default, the break signal is captured by the terminal which
then sends the kill signal to the application running within the terminal
window. It is often useful, however, to redirect the break signal to
application control. The AnsiCmd library can perform this redirection in
either of two ways.

  1. Activate the break-signal handler during instantiation of the AnsiCmd
     class by setting the 'bcType' member of The TermConfig object which is
     passed as the argument to the AnsiCmd constructor.
     Please *note TermConfig Class:: and *note Invoking - Terminal Setup:: for
     detailed instructions on specifying a break-signal handler using this
     method.

  2. Specify redirection of the break signal to application control through a
     call to the *note acCaptureBreakSignal:: method.

     While the first option always invokes the AnsiCmd library's default
     handler, the 'acCaptureBreakSignal' call can specify either the default
     handler _or_ an alternate handler provided by the application.

     The 'acCaptureBreakSignal' method can also be used to return control to
     the terminal's signal handler.

The mechanics of transferring control of the break signal to the application
are straightforward, but non-trivial. It is accomplished by “registering” a
signal-handler function with the system using the C-library function:
   'signal( int SIGNUM, sighandler_t ACTION )'.
This function is defined in the 'signal.h' header file.
The SIGNUM parameter in this case is the macro 'SIGINT' (the interrupt
signal). The ACTION parameter is the address (name) of the function to which
the break signal will be directed.

The terminal's signal handler is defined by the macro 'SIG_DFL', while the
application's handler may be specified by the name of any (non-member)
function in the application which is configured to process the signal.

The non-member function in the AnsiCmd library is cryptically named
'BreakSignal_Handler'. The system call is then:
   signal ( SIGINT, BreakSignal_Handler );

Because we want to provide for potential user interaction when the break
signal is received, we perform the slightly dangerous operation of allowing
the non-member function to call an AnsiCmd-class member method:
   breaksignalReceived ( int sigNum );
This is where the action takes place.

The type of operation to perform has been specified during handler setup, and
is a member of enum CCH_Type (Control_C_Handler Type).

   ⚬ cchtTerm - Terminal handles CTRL+C break-signal by issuing the kill
     signal to the application running within the terminal. Generally, this
     can be done without serious consequences; however, it may be necessary to
     manually reset the terminal by calling the 'reset' utility to return the
     terminal configuration to a known state. For instance, if the application
     is terminated using CTRL+C, the current terminal attributes will still be
     active when the terminal shell regains control.

   ⚬ cchtExit - The application will perform any specified housekeeping tasks,
     and then immediately terminate execution, returning control to the
     terminal shell program. For the AnsiCmd class, “housekeeping tasks”
     include returning the terminal configuration to its original state,
     deleting all allocated objects by calling the destructors for the objects
     in the proper order, setting the exit code and executing the C-library
     exit sequence.

   ⚬ cchtUser - Prompt user for whether to exit the application or to discard
     the break signal and continue execution.
           Break Detected. Exit? (N/y): _
     This message is written to the upper-right corner of the terminal window
     and uses a blinking text attribute to draw the user's attention.

   ⚬ cchtCopy - Convert the captured break signal to the keycode wcsCTL_C
     (Ctrl+C). The application can then process the keycode or discard it as
     desired. For instance, the ACWin class recognizes this keycode as the
     “Copy” command, and copies the selected text to the clipboard.

   ⚬ cchtIgnore - Ignore (discard) the break signal and continue execution of
     the application; optionally, sounding an audible alert so the user knows
     that the signal was received, but discarded. (*note bcAlert:: member of
     the TermConfig class for enabling the audible alert.)



Soft Echo Options
-----------------

“Soft Echo” options define a range of ways in which keyboard input can be
captured and filtered before it is echoed (written) to the terminal window.

The primary method for selecting the the soft-echo option is to specify it
during a call to the *note acBufferedInput:: method which disables input
buffering and optionally specifies the character-echo option and whether the
input stream uses a blocking or non-blocking read.

The soft-echo option may also be specified as a command-line option. See the
'echoOption' member in the discussion of the *note TermConfig Class::, above.

If the echo option is termEcho, then the terminal decides what input is echoed
to the display. If the echo option is noEcho, then keyboard input is not
written to the display.

Specifying one of the soft-echo options disables automatic echo of keyboard
input to the display, and then sorts the incomming keycodes into two main
groups: graphing (printing) characters and non-printing control codes.

Graphing (printing) characters are written to the display in the usual way,
but control codes are captured, and either converted to one of the “special”
keys or discarded according to the selected soft-echo option.

   ▪ softEchoA - All special keys are captured, decoded and available to the
     application, which can then interpret the keycode or discard it.
     This is the default soft-echo option.
   ▪ softEchoB - Basic set of special keys including the cursor keycodes, and
     the edit keycodes, but excludes the text-selection and clipboard-access
     keycodes.
   ▪ softEchoC - Cursor keys only: UpArrow, DownArrow, LeftArrow, RightArrow,
     Home, End, PageUp, PageDown, Tab and Shift+Tab.
     (Edit keycodes are excluded.)
   ▪ softEchoD - Disable (capture and discard) all special keycodes.
   ▪ softEchoE - Edit keys Backspace, Delete, Insert, AltEnter, _plus_ Tab and
     Shift+Tab. (Cursor movement keycodes are discarded.)

See the next section for more information on the “special” keycodes.


     Decoding the “Special” Keys
     ...........................

     The “special” keycodes consist of certain keycodes which are presented to
     a console application in the form of escape sequences. An escape sequence
     is a sequence of bytes beginning with the the escape character (0Bh). The
     number of bytes in an escape sequence varies from two bytes to seven
     bytes (or more on some systems).

     Many keyboard keys are encoded in this way: the Function Keys, the Cursor
     Positioning keys, the Backspace/Delete/Insert keys, and most of the
     keycodes generated in combination with the so-called _conditioning_ keys:
     Shift, Control, Alt.

     For a (nearly) complete list of keystrokes that generate escape sequences
     and the sequences they generate, please download the author's NcDialog
     API package and study the source files NCursesKeyDef.hpp and
     NCursesKeyDef_auto.hpp.

     For the AnsiCmd library, only a subset of these escape sequences are
     captured and decoded. These include the “special” keys listed in the
     table below, as well as combination-keys discussed in the following
     sections:
     *note ASCII Control Codes:: and *note GUI Keys::.

      Key Function      Esc Seq (hex)         Key Name      Glyph/Keycode
     ----------------------------------------------------------------------
       Up Arrow         1B 5B 41              wcsUARROW       ↑  2091h
       Down Arrow       1B 5B 42              wcsDARROW       ↓  2093h
       Right Arrow      1B 5B 43              wcsRARROW       →  2192h
       Left Arrow       1B 5B 44              wcsLARROW       ←  2190h
       Home Key         1B 5B 48              wcsHOME         ↖  2196h
       End Key          1B 5B 46              wcsEND          ↘  2198h
       Page Up          1B 5B 35 7E           wcsPGUP         ↗  2197h
       Page Down        1B 5B 36 7E           wcsPGDN         ↙  2199h
       Tab              09                    wcsTAB          ↱  211Bh
       Shift+Tab        1B 5B 5A              wcsSTAB         ↲  21B2h
       Backspace        7F                    wcsBKSP         ↰  21B0h
       Delete           1B 5B 33 7E           wcsDELETE       ↳  21B3h
       Insert           1B 5B 32 7E           wcsINSERT       ↥  21A5h
       Alt+Enter        1B 0A                 wcsAENTER       ↧  21A7h
       Shift+Up         1B 5B 31 3B 32 41     wcsSUP          ↾  21BEh
       Shift+Down       1B 5B 31 3B 32 42     wcsSDOWN        ⇂  21C2h
       Shift+Right      1B 5B 31 3B 32 43     wcsSRIGHT       ⇀  21C0h
       Shift+Left       1B 5B 31 3B 32 44     wcsSLEFT        ↼  21BCh
       Shift+Home       1B 5B 31 3B 32 48     wcsSHOME        ⇇  21C7h
       Shift+End        1B 5B 31 3B 32 46     wcsSEND         ⇉  21C9h
       Ctrl+Home        1B 5B 31 3B 35 48     wcsCHOME        ⇈  21C8h
       Ctrl+End         1B 5B 31 3B 35 46     wcsCEND         ⇊  21CAh
       Ctrl+C           03                    wcsCOPY         ∽  223Dh
       Ctrl+X           18                    wcsCUT          ≒  2252h
       Ctrl+V           16                    wcsPASTE        ≐  2250h
       Ctrl+A           01                    wcsSELECT       ∻  223Bh
       Ctrl+Z           1A                    wcsUNDO         ≔  2254h
         * Note: Encoding of Backspace and Delete keys
           are specified in terminal settings.

     The Copy/Cut/Paste keys (Ctrl+C, Ctrl+X, Ctrl+V) and the other ASCII
     control codes are described below: (*note ASCII Control Codes::).

     Taken together, these keycodes comprise all the standard keycodes used to
     edit text within an individual field or on a form consisting of multiple
     fields.
     Please *note skForm Class:: for a description of how these keycodes are
     interpreted within a form or a field.

     Also, please *note GUI Keys:: for keycodes which are commonly used as
     user-interface commands.



ASCII Control Codes
-------------------

ASCII control codes are generated by pressing and holding either CTRL key and
then pressing one of the alphabetic keys: 'a' through 'z', 'A' through 'Z', or
'4', '5', '6', '7'.

     HEX BYTE    HEX BYTE    HEX BYTE    HEX BYTE
     ---------   ---------   ---------   ----------
     01 Ctrl+A   0B Ctrl+K   15 Ctrl+U   1D Ctrl+5 (Ctrl+])
     02 Ctrl+B   0C Ctrl+L   16 Ctrl+V   1E Ctrl+6 (Ctrl+^)
     03 Ctrl+C   0E Ctrl+N   17 Ctrl+W   1F Ctrl+7 (Ctrl+_)
     04 Ctrl+D   0F Ctrl+O   18 Ctrl+X
     05 Ctrl+E   10 Ctrl+P   19 Ctrl+Y
     06 Ctrl+F   12 Ctrl+R   1A Ctrl+Z
     07 Ctrl+G   14 Ctrl+T

     Exceptions:
     08 Ctrl+H  Backspace, decoded as wcsBKSP (21B0h)
     09 Ctrl+I  Tab,       decoded as wcsTAB  (21B1h)
     0A Ctrl+J  Enter key i.e. newline
     0D Ctrl+M  (reported as Ctrl+J, newline)
     11 Ctrl+Q  Captured by the terminal (release terminal output)
                This signal is disabled when setting unbuffered input.
     13 Ctrl+S  Captured by the terminal (pause terminal output)
                This signal is disabled when setting unbuffered input.
     1A Ctrl+Z  This generates the SIGTSTP "Stop" signal which puts the
                current process to sleep. (wake using the 'fg' utility)
                This signal is captured and converted to wcsCTL_Z.
     1B  ---    Escape
     1C Ctrl+4  This generates the SIGQUIT "Quit" signal which kills the
                current application. This signal is captured and handled as
                if it were the break signal, implementing an orderly shutdown.

Note that the Shift key is ignored when the CTRL key is pressed. Both the
uppercase and lowercase alpha characters produce the same values, and the
Ctrl+[4 | 5 | 6 | 7] produce the same values regardless of whether the Shift
key is pressed. Examples:
      Ctrl+a == Ctrl+Shift+A
      Ctrl+5 == CTRL+Shift+5 ('%')

The Ctrl+C key _should be_ 0x03 in the sequence, but that code is tied to the
Break Signal. To recapture Ctrl+C it is necessary for the break handler to
capture the signal and push the code back into the input stream. The Break
signal handler type “cchtCopy” performs this conversion.
Please *note Capturing the Break Signal:: for a discussion of capturing and
re-purposing the break signal.
*Note acCaptureBreakSignal:: which implements the signal capture.

The Ctrl+Z key _should be_ 0x1A in the sequence, but that code is tied to the
Suspend Signal. To recapture Ctrl+Z it is necessary for the suspend handler to
capture the signal and push the code back into the input stream. The suspend
signal handler performs this conversion.
*Note acCaptureSuspendSignal:: which implements the signal capture.

The Ctrl+4 key _should be_ 0x1C in the sequence, but that code is tied to the
Quit Signal (with core dump). To recapture Ctrl+4 it is necessary for the quit
handler to capture the signal and provide for an orderly termination of the
application. (Ctrl+4 _is not_ associated with an application-level keycode.)
Note that the Ctrl+\ key combination is equivalent to Ctrl+4.
*Note acCaptureQuitSignal:: which implements the signal capture.

The Ctrl+S and Ctrl+Q keys _should be_ 0x13 and 0x11, respectively, but these
codes are tied to the Pause/Resume output stream signals. At a terminal
configuration level, the flow-control flag, IXON handles stdout flow control.
This flag is automatically _reset_ when configuring the terminal for
unbuffered input. This frees the Ctrl+S and Ctrl+Q key combinations for
application-specific purposes.
Please *note acBufferedInput:: for additional information.

Certain Control-key combinations are reserved for use by the desktop
environment or by the terminal emulator program. For instance, Ctrl+PageUp and
Ctrl+PageDown are used to navigate among terminal tabs. Most of these
so-called shortcut keys may be disabled in the terminal's preferences/settings
page.



The GUI Keys
------------

The GUI keys (Graphical User Interface keys) are keycodes that are commonly
used by applications as command shortcut keys. These keycodes are generated by
pressing one or more of the “conditioning keys” in combination with another
key. The conditioning keys are the SHIFT key, the CONTROL keys and the
left-side ALT key.

With the exception of the ASCII control codes, these keycodes are reported to
the application as escape sequences.

The GUI keycodes fall into these general categories:
  1. Key combinations using the CTRL key and an alphanumeric key.
     a-z and 4-7
     These combinations generate the ASCII control codes.
  2. The SHIFT key in combination with one of the cursor navigation keys.
     UpArrow, DownArrow, RightArrow, LeftArrow
  3. The left-side ALT key in combination with another key, _or_
     both ALT and SHIFT keys in combination with another key.
     a-z and A-Z and punctuation characters:
     ! " # $ % & ' ( ) * + , - . / : ; < = > ?  [ \ ] ^ _ { | }
     UpArrow, DownArrow, RightArrow, LeftArrow, Home, End, PageUp, PageDown
  4. Both the CTRL and ALT keys in combination with another key.
     a-z
     Note that when using the CTRL key, the state of the SHIFT key is
     generally ignored by the keyboard controller.
  5. The Function Key group: F01-F12 alone or in combination with the SHIFT
     and/or CTRL conditioning keys. (ALT+Fnn combinations are not supported.)

All key combinations which are captured are converted to constant values
defined in AnsiCmdDef.hpp.

     Technical Notes:
     − To use key combinations, first press and hold the conditioning key(s),
       _then_ press the other key, and release them all together.
     − Note that by default, the right-side ALT key is configured for entering
       keycodes that are not directly available from the keyboard.




TermSet Class
-------------

The TermSet class encapsulates the low-level access to terminal-configuration
options. The AnsiCmd class methods calls the _private_ TermSet object
('tset' member) for configuration options such as input buffering, input-echo
options, cursor style, blocking vs. non-blocking input, flushing the I/O
buffers and capture of the break signal (CTRL+C).

All methods and data members of the TermSet class are private, and are
accessed only by the AnsiCmd (or ACWin) class. This ensures that there is only
one point of access to the terminal configuration in order to avoid
unfortunate configuration conflicts.

Although the functionality discussed here is not directly available to the
application, it is interesting and educational to understand what is going on
under the floorboards, so-to-speak.

The application may request a copy of the current terminal settings to verify
that the terminal is configured as desired. The data consist of the bitfields
defined in the C-language termios structure.
*Note acGetTermInfo:: for details.


Data Members
............

   ⏺ TermIos strOrig
     This is a copy of the I/O stream setting captured during application
     startup, when the AnsiCmd/TermSet classes are first instantiated.

     This data set is used to return the terminal settings to their original
     values when the application exits, i.e when the AnsiCmd/TermSet
     destructors are called.

     Please *note AnsiCmd constructor:: for additional information.

   ⏺ TermIos strMods
     This member contains data for the current terminal configuration. It is
     updated whenever the configuration is modified.

   ⏺ TermStream aStr
     This is the (virtual) file handle for the “active” (most recently
     modified) I/O stream. it is a member of enum TermStream, consisting of
     stdIn (stdin), stdOut (stdout) and stdErr (stdErr).
     Note that stdErr is not referenced within the AnsiCmd/TermSet code, but
     is included for completeness.

     As noted elsewhere (*note Introductory Notes::), this has little
     practical value as a file handle because it references a _virtual file_
     which manages all three streams as a unit.

   ⏺ CurStyle curStyle
     The cursor style currently applied to the visible cursor. This is a
     member of enum CurStyle.

     Please *note S option:: for specifying the cursor style as a command line
     option, and the *note TermConfig Class:: for a detailed description of
     cursor styles.

   ⏺ CCH_Type cchType
     This is a member of enum CCH_Type and specifies the type of
     Control_C_Handler (break signal handler) currently in use.

     Please *note Capturing the Break Signal:: for a discussion of the
     break-signal handlers built into the AnsiCmd library.

   ⏺ EchoOpt inpEch
     This is a member of enum EchoOpt and specifies whether and how keyboard
     input is echoed (displayed) in the terminal window.

     Please *note Soft Echo Options:: and *note TermConfig Class:: for a
     discussion of input-echo options.

   ⏺ bool inpBuf
     This flag indicates whether input buffering is currently enabled.
        true == buffering enabled
       false == buffering disabled

     Please *note B option:: for specifying the input buffering option as a
     command line option, and the *note TermConfig Class:: for a description
     of input buffering.
     See also, the *note acBufferedInput:: method.

   ⏺ bool inpBlk
     This flag indicates whether blocking read is active for the input stream.

     The term “blocking read” refers to whether the execution thread should go
     to sleep while waiting for keyboard input.

     By default, blocking read is active, meaning that when the application
     requests keyboard input from the user (*note acRead::), the execution
     thread goes into a hibernation state until the terminal signals that
     input is available in the buffer.

     When blocking read is disabled, a request for user input will return the
     first keycode in the buffer, _or_ will _immediately_ return a "WEOF"
     (zero) if no data are available in the input buffer.

     The AnsiCmd library uses non-blocking read primarily for receiving escape
     sequences from the terminal program and for flushing the input buffer.
     The *note acBlockingInput:: method makes non-blocking input available in
     case the application needs similar functionality.
     NOTE: This functionality can be dangerous, so use it wisely.

   ⏺ bool cchAlert
     This flag indicates whether an audible “beep” is enabled to alert the
     user when the break signal (CTRL+C) has been received.

     Please *note Capturing the Break Signal::, and also the *note
     acCaptureBreakSignal:: method for a discussion of the break-signal
     handlers.

   ⏺ bool quitCap
     This flag indicates whether the Quit signal has been captured.
     The Quit signal is generated by either the Ctrl+4 key or Ctrl+\ key
     combination.
        true == signal has been captured and will be handled locally.
       false == terminal handles the signal
     *Note acCaptureQuitSignal:: method for further information.

   ⏺ bool suspCap
     This flag indicates whether the Suspend signal has been captured.
     The Suspend signal is generated by the Ctrl+Z key combination.
        true == signal has been captured and will be handled locally.
       false == terminal handles the signal
     *Note acCaptureSuspendSignal:: method for further information.

   ⏺ bool strCap
     This flag indicates whether the 'strOrig' member (see above) has been
     initialized.
        true == member initialized
       false == member not initialized

   ⏺ bool inpMod
     This flag indicates whether the 'strMods' member (see above) has been
     initialized.
        true == member initialized
       false == member not initialized

For additional information on terminal configuration please refer to the
documentation for the C-library functions: tcgetattr, fcntl, signal and the
termios structure and related macro definitions defined in termios.h and
unistd.h



File: ansicmd.info,  Node: AnsiCmd Class Methods,  Prev: Terminal Configuration,  Up: AnsiCmd Library

AnsiCmd Class Methods
=====================

* Menu:

* Table of Public Methods::      _
* Configuration Methods::        _
* Color Attributes::             _
* Text Modifiers::               _
* Cursor Positioning::           _
* Input Methods::                _
* Output Methods::               _
* Text Erase::                   _
* Misc Methods::                 _
* API Methods::                  _
* Development Support::          _
* Coding Example::               _




File: ansicmd.info,  Node: Table of Public Methods,  Next: Configuration Methods,  Up: AnsiCmd Class Methods

Table of Public Methods
-----------------------

The following is a list of AnsiCmd public methods, grouped by function.
Most public methods begin with the letters “ac” (Ansi Command).

The basic methods use ANSI escape sequences directly. Some of these methods
use C-library function calls to perform terminal configuration.

A few methods are implemented at a higher abstraction level (API level). These
are referred to in the documentation as Application-Program-Interface API
methods. These methods typically do not use the ANSI escape sequences
directly, but instead call a sequence of low-level (primitive) methods to
provide a less cluttered interface between the application and the AnsiCmd
library.

See also the *note ACWin Class:: in the next chapter which provides a more
sophisticated user interface whose functionality lies somewhere between the
raw ANSI escape sequences and the dialog-oriented interface of the author's
NcDialog API.
Please *note By the Same Author:: for more information.

 Method Name                   Description
-------------------------------------------------------------------------
──── Configuration ──────     ─────────────────────────────────────────
 *note AnsiCmd constructor::   Constructors
 *note AnsiCmd destructor::    Destructor
 *note acGetTermSize::         Calculate size of terminal window
 *note acGetTermDimensions::   Get a copy of stored terminal size
 *note acGetTermInfo::         Get current terminal configuration
 *note acSetLocale::           Specify a non-default locale
 *note acGetLocale::           Get current locale setting
 *note acSetStreamWidth::      Lock in wide or narrow I/O streams
 *note acBufferedInput::       Configure input-stream buffering
 *note acSetEchoOption::       Echo option (unbuffered input only)
 *note acGetEchoOption::       Report current echo option
 *note acBlockingInput::       Input blocking (unbuffered input only)
 *note acCaptureSignals::      Enable Ctrl+C Ctrl+4 Ctrl+Z signals
 *note acReleaseSignals::      Disable Ctrl+C Ctrl+4 Ctrl+Z signals
 *note acCaptureBreakSignal::  Enable/disable capture of Ctrl+C
 *note acCaptureQuitSignal::   Enable/disable capture of Ctrl+4
 *note acCaptureSuspendSignal:: Enable/disable capture of Ctrl+Z
 *note acRestoreTermInfo::     Set terminal configuration to defaults
 *note breaksignalReceived::   default break-signal handler
 *note suspendsignalReceived:: default suspend-signal handler
 *note quitsignalReceived::    default quit-signal handler
                               
──── Color Attributes ───     ─────────────────────────────────────────
 *note acSetFg::               Set text foreground (3-bit, 4-bit, AIX)
 *note acSetBg::               Set text background (3-bit, 4-bit, AIX)
 *note acSetFgBg::             Set text fgnd and bkgnd (3/4-bit, AIX)
 *note acSet8bitFg::           Set text foreground (8-bit color)
 *note acSet8bitBg::           Set text background (8-bit color)
 *note acSetRgbFg::            Set text foreground (r/g/b color)
 *note acSetRgbBg::            Set text background (r/g/b color)
 *note acSetWebFg::            Set text foreground (web-safe r/g/b)
 *note acSetWebBg::            Set text background (web-safe r/g/b)
 *note acSetGreyscaleFg::      Set text foreground (greyscale)
 *note acSetGreyscaleBg::      Set text background (greyscale)
 *note acReset::               Reset attributes and tracking data
                               
──── Text Modifiers ─────     ─────────────────────────────────────────
 *note acSetMod::              Set or reset a text modifier
 *note acResetMods::           Reset all text modifiers
 *note acFullReset::           Reset all colors and text modifiers
                               
─── Cursor Position ─────     ─────────────────────────────────────────
 *note acSetCursor::           Position the visible cursor
 *note acGetCursor::           Get current cursor position
 *note acSetCursorStyle::      Specify cursor shape
                               
───── Input Methods ─────     ─────────────────────────────────────────
 *note acRead::                Read from stdin
 *note acPause::               Read and discard next keystroke
 *note acWait::                Pause for timeout or keystroke
 *note acFlushIn::             Flush the input stream (stdin)
                               
──── Output Methods ─────     ─────────────────────────────────────────
 *note acWrite::               Write formatted data to stdout
 *note ttyWrite::              Write unformatted data (TTY style)
 *note acFlushOut::            Flush the output stream (stdout)
 *note acFlushStreams::        Flush both input and output streams
                               
──── Text Erase ─────────     ─────────────────────────────────────────
 *note acEraseArea::           Erase specified area of terminal window
                               
──── Misc Methods ───────     ─────────────────────────────────────────
 *note acBeep::                Make some noise
 *note nsleep::                Put thread to sleep
 *note acVersion::             Get AnsiCmd class version number
 *note acSetFont::             Seldom supported alternate font
 *note acSetIdeogram::         Seldom supported line drawing
                               
──── API Methods ────────     ─────────────────────────────────────────
 *note acSetAttributes::       Set bit-field color and text-mod data
 *note acComposeAttributes::   Encode bit-field color and text-mods
 *note acGetAttributes::       Get decoded bit-field color/text-mods
 *note acClearScreen::         Erase all data from terminal window
 *note acClearArea::           Erase specified area of terminal window
 *note acFormatParagraph::     Automatic text formatting
 *note acShellOut::            Temporarily return to shell program
 *note acDrawLine::            Draw a horizontal or vertical line
 *note acDrawBox::             Draw a rectangle in the terminal window
 *note acEraseBox::            Erase a rectangular area of terminal
 *note acBoxDraw::             Display an AC_Box object in terminal
 *note acBoxErase::            Erase an AC_Box object from terminal
 *note acBoxClear::            Clear the interior of an AC_Box object
 *note isSpecialKey::          Compare to list of special keycodes
 *note isCommandKey::          Compare to list of command keycodes
 *note acCreateTemppath::      Enable support for temporary files
 *note acDeleteTemppath::      Disable support for temporary files
 *note acCreateTempfile::      Create a temporary file
 *note acDeleteTempfile::      Delete a temporary file
 *note acClipboardEnable::     Establish communications with clipboard
 *note acClipboardDisable::    Terminate communications with clipboard
 *note acClipboardTest::       Test communications with clipboard
 *note acClipboardGetText::    Retrieve data from the clipboard
 *note acClipboardSetText::    Copy data to the clipboard
 *note acClipboardCharCnt::    Reports number of chars on clipboard
 *note acClipboardByteCnt::    Reports number of bytes on clipboard
                               
── Development Support ──     ─────────────────────────────────────────
 *note ansiTest::              Manage AnsiCmd library testing
 *note getDataMembers::        Get a copy of internal data members
 *note getConfig::             Get a copy of terminal configuration
 *note tseReport::             Report keycode processing



File: ansicmd.info,  Node: Configuration Methods,  Next: Color Attributes,  Prev: Table of Public Methods,  Up: AnsiCmd Class Methods

Configuration Methods
---------------------

   ▪ AnsiCmd ( void );

       Input  : none
     
       Returns: implicitly returns a pointer to object

     Default Constructor: Terminal configuration parameters are set to default
     values.
     Please *note TermConfig Class:: for details on default values.

     The usefulness of the default constructor is miniscule, and possibly full
     of surprises for the programmer and the user alike. It is _strongly_
     recommended that the initialization constructor (see below) be used for
     all non-trivial applications.


   ▪ AnsiCmd ( const TermConfig& tCfg );
       Input  : tCfg : (by reference) terminal configuration parameters 
     
       Returns: implicitly returns a pointer to object

     Initialization Constructor: Terminal configuration parameters are passed
     in the TermConfig object.

     Configuration options can be established directly by the application
     startup code, or if preferred, can be specified by the user as
     command-line options, *note Invoking::.

     Please *note TermConfig Class:: for details on parameter values passed to
     the constructor.

     Programmer's Note: The AnsiCmd class should be instantiated before any
     data is sent to the terminal's output stream. This is because the first
     output may override any subsequent output-stream width designation for
     the current session. Note that the wide (32-bit character) stream is
     strongly recommended for all modern applications. The narrow stream is
     outdated due to its close ties to ASCII text (and to 1970).


   ▪ virtual ~AnsiCmd ( void );
       Input  : none
     
       Returns: nothing

     Destructor. Return all resources to the system before exit.

     The destructor is invoked either by deleting the object:
         AnsiCmd *ansicmdPtr = new AnsiCmd( termConfig );
         delete ansicmdPtr;
     OR when the object goes out-of-scope.


   ▪ WinSize acGetTermSize ( void );
       Input  : none
     
       Returns: current terminal dimensions in a WinSize object

     Returns the terminal dimensions in both character cells and pixels.

     The WinSize structure is defined in /usr/include/bits/ioctl-types.h, and
     is one of the many system configuration parameters handled by the
     C-library ioctl function.
        struct winsize
        {
           unsigned short int ws_row;
           unsigned short int ws_col;
           unsigned short int ws_xpixel;
           unsigned short int ws_ypixel;
        };

     Note on terminal dimensions: Although the environment may contain the
     terminal dimensions when the application was invoked, this is a _copy_ of
     the environment, not the active environment, and therefore will not
     reflect user changes to the terminal window size while the application is
     active.

     The $LINES and $COLUMNS are available from the environment at the command
     line (“echo $LINES” and “echo $COLUMNS”), but are not exported to
     programs running in the terminal window.

     Note also that the pixel dimensions will probably be returned as zeros
     because under Wayland, the terminal program likely doesn't know the
     screen resolution.


   ▪ bool acGetTermDimensions ( short& rows, short& cols );

       Input  : rows  : (by reference) receives number of terminal rows
                cols  : (by reference) receives number of terminal columns
     
       Returns: 'true'  if terminal dimensions are known
                'false' if system call to get terminal dimensions failed

     Reports the dimensions of the terminal window in rows and columns.


   ▪ bool acGetTermInfo ( TermStream tStream,
                          TermIos& tIos, bool orig = false );

       Input  : tStream : one of stdIn, stdOut, stdErr
                tios    : (by reference) receives settings
                orig    : (optional, 'false' by default)
                          'false': the current terminal settings are returned
                          'true' : the original terminal settings are returned
     
       Returns: 'true'  if settings captured
                'false' if system error

     Get a copy of the current terminal I/O stream configuration (or the
     original settings captured on application start-up).

     This is a pass-through to the private TermSet method.

     (This method is primarily for development and debugging.)

          Terminal I/O Setting structure (defined in C library, termios.h)

          struct termios
          {
             tcflag_t c_iflag ;    /* input mode flags   */
             tcflag_t c_oflag ;    /* output mode flags  */
             tcflag_t c_cflag ;    /* control mode flags */
             tcflag_t c_lflag ;    /* local mode flags   */
             cc_t     c_line ;     /* line discipline    */
             cc_t     c_cc[NCCS] ; /* control characters */
          } ;

          tcflag_t is an unsigned integer (uint16_t) bit-field type.
          cc_t     is an unsigned integer type (uint8_t) representing characters
                   associated with various terminal control functions.
          'NCCS'   is a macro indicating the number of elements in the c_cc[] array.
                   (this is 19 in /usr/include/asm-generic/termbits.h


   ▪ bool acSetLocale ( const char * localeName = NULL );

       Input  : (optional, null pointer by default)
                 If specified, pointer to name of UTF-8 compliant locale filename.
                 If null pointer (or empty string: "\0"), set locale from terminal
                 environment.
     
       Returns: 'true'
                 Currently, we do not verify that 'localeName' is a valid UTF-8
                 compliant locale filename.

     Set the "locale" for the application.
     By default, the application locale is taken from terminal environment.

     Type: echo $LANG at the command prompt to get the terminal's locale. If
     desired, an alternate locale may be specified.

     For a complete listing of locales supported by your system, at the
     command prompt, type: locale -a


   ▪ const char* acGetLocale ( void );

       Input  : none
     
       Returns: pointer to locale name

     Returns a pointer to the name of the current locale.


   ▪ bool acSetStreamWidth ( bool widechar );

       Input  : widechar : select 'true' (wide stream) or 'false' (narrow stream)
     
       Returns: current state of character-width flag

     Set input/output streams' character width.
     This determines which input/output streams will be used:
          wide stream: wcin/wcout
          narrow stream: cin/cout

     IMPORTANT NOTE: This method will have no effect if called after the
                     application has performed I/O.
     The first input or output performed by the application locks in the
     character-stream width used for the application.
     C++ offers a way to set stream width directly (std::freopen), but it's
     better to get it right the first time.


   ▪ bool acBufferedInput ( bool buffered, EchoOpt echoType, bool block = true
     );

       Input  : buffered : if 'true',  enable input buffering by the terminal
                           if 'false', disable buffering and allow local control
                                       over the input stream
                echoType : member of enum EchoOpt:
                           referenced ONLY when 'buffered' == false
                           noEcho  : data from the stdin stream will not be echoed
                                     to the terminal window
                           termEcho: terminal echoes all stdin data to the window
                           softEchoA, softEchoC, softEchoD, softEchoE:
                                     terminal echo is disabled, but the acRead()
                                     methods will echo PRINTING characters to the
                                     terminal window according to the specific
                                     soft-echo sub-option.
                block    : (optional, 'true' by default)
                           enable or disable blocking-read of input stream
                           referenced ONLY when 'buffered' == false
                           if 'true',  enable blocking read of stdin
                           if 'false', disable blocking read of stdin
     
       Returns: current state of the 'buffered-input' flag (inpBuf).

     Disable buffering so each keystroke can be received as soon as the key is
     pressed, or restore terminal's control over input buffering.

     Normally, user input to the terminal (stdin) is buffered. That is, typed
     characters are stored in the terminal's private input buffer and are
     returned to the application only when the ENTER key is pressed.

     In some circumstances, however, when a “Press any key to continue...”
     functionality is desired. Local control of the input buffer is also
     necessary when capturing ANSI sequences transmitted from the terminal in
     order to prevent cluttering the window with data which is meaningless to
     the user.
     *Note acRead:: for additional info.

     IMPORTANT NOTE: When buffering is enabled (buffered!=false), then the
     'echoType' and 'block' parameters are ignored.
        — When buffering is enabled, termEcho is always enabled.
        — When buffering is enabled, blocking read of input is always enabled.
          Consequently, if modifying the echo option (*note acSetEchoOption::)
          and/or the input-blocking option (*note acBlockingInput::), then
          input buffering must have been disabled.


     Notes:
     ......

       1. The 'ICANON' flag actually controls whether the terminal references
          'VTIME' and 'VMIN' and how those values are interpreted.
       2. Buffering has no direct dependence on whether or not the characters
          are echoed when they arrive, and again, the 'ICANON' flag determines
          whether the terminal references the 'ECHO' flag'.
       3. Traditionally (and logically) echo is disabled when buffering is
          disabled. However, we provide an option to keep echo active while
          buffering is disabled.
       4. Echo should be disabled if the system is queried for a response in
          the form of an escape sequence (for instance, asking for the current
          cursor position). If echo is active, then it is likely that the
          printing characters in the the escape sequence will inappropriately
          be echoed to the screen.

          To bake a cake and eat it too, see the soft-echo option.


   ▪ bool acSetEchoOption ( EchoOpt echoType );
       Input  : echoType: member of enum EchoOpt: 
                          noEcho   : data from the stdin stream will not be
                                     echoed to the terminal window
                          termEcho : terminal echoes all stdin data to the window
     
                          For the soft-echo options, terminal echo is disabled,
                          and echo of input characters to the display is
                          handled locally by the acRead() methods which will
                          echo all PRINTING characters to the display, and
                          will decode the "special keys" (cursor keys, etc.)
                          according to the specific soft-echo sub-option.
                          softEchoA: all special keys (default soft-echo option)
                          softEchoB: basic set of special keys
                          softEchoC: cursor-movement keys only
                          softEchoD: disable all special keys
                          softEchoE: edit keys only: Backspace, Delete, Insert,
                                     plus the Tab and Shift+Tab keys
     
       Returns: 'true'  if echo option modified
                'false' if input buffering currently enabled (or invalid type)

     Select the input character echo type. (enum EchoOpt).

     Echo of user keyboard input (writing the received keycode to the display
     can be handled in a number of ways as listed above. The terminal can be
     allowed to decide what key input is echoed to the display, or the
     application can take control of key input to provide a smoother user
     interface.

     The “soft-echo” options are available for customizing the user interface.
     Please *note Decoding the Special Keys:: for more information on the
     soft-echo options.

     This option is available ONLY when input buffering has been disabled.
     Please *note acBufferedInput:: method for additional information.


   ▪ EchoOpt acGetEchoOption ( void );
       Input  : none
     
       Returns: current echo option: member of enum EchoOpt

     Get the current input-echo setting which describes how data from the
     input stream is processed.
     *Note TermConfig Class:: for a discussion of input-stream configuration
     options.


   ▪ bool acBlockingInput ( bool block );
       Input  : block : if 'true',  enable blocking read of input stream
                        if 'false', disable blocking read of input stream
     
       Returns: current state of the inpBlk flag
                'true'  == blocking-read of stdin
                'false' == non-blocking read of stdin
       Returns: 

     Enable or disable blocking read from the input stream (stdin).
     This is a pass-through method for the TermSet function which sets/resets
     The blocking/non-blocking functionality.

     IMPORTANT NOTE: Non-blocking input requires that unbuffered input be
     enabled. If not already enabled, unbuffered input (with 'noEcho') will be
     automatically enabled.


   ▪ bool acCaptureSignals ( EchoOpt eopt = softEchoA );

       Input  : eopt  : (optional, softEchoA by default)
                         specify one of the soft-echo options (enum EchoOpt)
     
       Returns: 'true'  if all settings successful
                'false' if one or more settings failed

     Disable input buffering and capture all system signals generated by
     keyboard input.

     This method is provided as a housekeeping convenience, performing a
     common sequence of terminal setup operations:
       1. If input buffering has not yet been disabled, it will be disabled
          using the specified soft-echo option, and with non-blocking read of
          the input stream.
       2. The output flow control signals will be disabled.
          The Ctrl+S (stop flow) and Ctrl+Q (resume flow) control codes become
          ordinary keycodes: wcsCTL_S and wcsCTL_Q, respectively.
       3. The Break signal will be captured and converted to an ordinary
          keycode:
             Break Signal  : SIGINT  - Ctrl+C becomes wcsCTL_C
       4. The Suspend signal will be captured and converted to an ordinary
          keycode:
             Suspend Signal: SIGTSTP - Ctrl+Z becomes wcsCTL_Z
       5. The Quit signal will be captured so that the application will be
          terminated in an orderly manner.
             Quit Signal : SIGQUIT - Ctrl+4 performs an orderly application
          shutdown
     Refer to the individual capture methods for details:
        acBufferedInput()
        acCaptureBreakSignal()
        acCaptureSuspendSignal()
        acCaptureQuitSignal()


   ▪ void acReleaseSignals ( void );

       Input  : none
     
       Returns: nothing

     Release all captured signals. Return control to the terminal software.
     Releases the following signals:
        1) Break Signal  : SIGINT  - Ctrl+C
        2) Suspend Signal: SIGTSTP - Ctrl+Z
        3) Quit Signal   : SIGQUIT - Ctrl+4


   ▪ bool acCaptureBreakSignal ( bool enable, CCH_Type handlerType,
                                 bool alert, void* handlerAddr = NULL );

       Input  : enable : if 'true',  enable application capture of the break key
                         if 'false', disable application capture of the break key
                                     terminal handles the break signal
                handlerType: (optional, cctDefault by default)
                             member of enum CCH_Type, specify the break-handler type.
                alert      : (optional, 'false' by default)
                             Referenced only when 'handlerType' == cchIgnore.
                             Optionally sound a beep when the break signal is
                             received and discarded.
                             if 'false', silently discard the break signal.
                             if 'true',  beep when discarding the break signal.
                handlerAddr: (optional, null pointer by default)
                             - by default, the internal AnsiCmd method,
                               BreakSignal_Handler() will provide an orderly response
                               to receipt of the break signal. See below for details.
                             - if the address of a handler method is specified, that
                               method will be activated by the break signal. That
                               method controls the response (if any) to the signal.
                               Note: The name of the target method is the address of
                                     that method.
                             This argument is referenced only if 'enable' is set.
     
       Returns: current state of capture flag
                'true'  break key will be captured by the application
                'false' break key will be handled by the terminal program

     Enable or disable application-level capture and processing of the BREAK
     key (CTRL+C).

     By default, the terminal software processes the break signal by
     immediately killing the application which is running in the terminal
     window. While this is certainly an efficient and reliable way to
     terminate an application, it is grossly messy and potentially dangerous.
     For instance, what if the application is editing a critical system file
     when it is terminated in mid-update? Chaos.

     In contrast, if the application itself captures the break signal, the
     application can shut down in an orderly manner, ask the user what to do,
     or simply ignore the break signal.
                            ────────────────────
     When local capture of the break signal is active, by default, the signal
     will be handled by the default (non-member) method,
     BreakSignal_Handler().

     The handler type is specified by the 'ccType' member variable which is
     initialized here.


     Valid Handler Types:
     ....................
        ⏺ cchtIgnore: Ignore the Ctrl+C key (default, cctDefault)
          Application will continue as if the signal had not been received.

        ⏺ cchtExit : Exit the application in an orderly way:
            a. the cursor will be placed on the bottom row of the terminal
               window and the row will be cleared,
            b. the terminal bell will sound,
            c. a short message will be displayed,
            d. the AnsiCmd destructor will be called, and
            e. the application will be terminated with a minus-one (-1) exit
               code.

        ⏺ cchtUser : Ask the user if they really want to exit the application:
            a. the terminal bell will sound,
            b. Clear a small area in the upper-right-hand corner of the
               terminal window. (This is assumed to be the least cluttered,
               least used area of the window.)
            c. Display a message asking the user to answer:
                  Exit? 'y'es or 'n'o: _
            d. Wait for the user's response.

        ⏺ cchtCopy : Convert the break signal to an ordinary keycode
          (wcsCTL_C) which may then be used in the common copy-and-paste
          sequence: Ctrl+C --> Ctrl+V.

        ⏺ cchtTerm : Local handler is disabled, so the local handler is not
          called.


   ▪ bool acCaptureQuitSignal ( bool enable );
       Input  : enable : if 'true',  enable application capture of the quit key
                         if 'false', disable application capture of the quit key
                                     terminal handles the signal
     
       Returns: current state of capture flag
                'true'  quit key will be captured by the application
                'false' quit key will be handled by the terminal program
     Pressing the CTRL+4 key (or the CTRL+\ key) generates the system Quit
     signal. If the system receives the Quit signal, it will immediately
     terminate the application and generate a “core dump” file.

     Core dump files are created in /var/lib/systemd/coredump by default. The
     format of the file should be ELF (Executable and Linkable) format, but
     could be an older format. An explanation of core dump files is beyond the
     scope of this document, but see the 'gdb' (GNU Debugger) utility, which
     may be used to decode the contents of core-dump files.

     The Quit Signal is captured by default during configuration of the
     AnsiCmd class and its derived classes. Then when the Quit signal is
     received, (CTRL+4 key) the application is shut down in an orderly manner,
     and a core dump _is not_ generated.
     The local Quit signal handler deletes the temporary files, releases
     dynamic memory allocations and performs general housekeeping chores.
     Before exiting the application, the bottom two rows of the terminal
     window are cleared and a message is written indicating that the
     application has been terminated.
     After all, we're not just wild animals pooping in the forest.
     (well, most of us anyway :-)

     *Note Q option:: for specifying this option as a command line parameter.

     Technical Note:
     This signal is sometimes referred to as the Kill signal, but note that
     the Quit signal is technically different from the Kill signal in that the
     Kill signal cannot be captured or modified. It is an absolute command,
     and in fact, failure to respond to the Kill signal would be considered as
     a major system bug.


   ▪ bool acCaptureSuspendSignal ( bool enable );
       Input  : enable : if 'true',  enable application capture of the suspend key
                         if 'false', disable application capture of the suspend key
                                     terminal handles the suspend signal
     
       Returns: current state of capture flag
                'true'  suspend key will be captured by the application
                'false' suspend key will be handled by the terminal program

     Enable or disable application-level capture and processing of the SUSPEND
     key CTRL+Z. Signal name: SIGTSTP.

     If this signal is seen by the terminal program, it will suspend the
     active process. That is, it will put the process into the background and
     disable direct access to it. A different process may then occupy the
     foreground, interacting with the input and output streams.
     Use the 'fg' utility to restore the hibernating process.

     Because Ctrl+Z is often used as a command (undo) within an application,
     this signal is captured by default and converted to an ordinary keycode:
     wcsCTL_Z.


   ▪ bool acRestoreTermInfo ( bool restoreAll );
       Input  : restoreAll : (optional, 'false' by default)
                             if 'false' this method restores input buffering,
                                input echo, and blocking-read settings only.
                                Break-handler, cursor style, and other terminal
                                configuration options are not affected.
                             if 'true',  all terminal setting under control of
                                the TermSet object will be returned to the states
                                when the object was instantiated. (see list below)
     
       Returns: 'true' if settings restored
                'false' if original settings not previously saved
                        or if system error

     Restore terminal stream settings to original values captured during the
     first access to the terminal settings. This probably occurred during
     creation of the TermSet-class object which is done as part of the
     AnsiCmd-class constructor sequence. The TermSet object manages the the
     current terminal settings. The settings restored depend on the state of
     the 'restoreAll' flag, and include:

       a. Buffering of input stream.
       b. Echo option (see enum EchoOpt).
       c. Blocking vs. non-blocking read of input stream.
       d. Disable local break-key handler, if active.
       e. Set cursor style to terminal default.


   ▪ void breaksignalReceived ( int sigNum );
       Input  : sigNum: signal number to be handled
                        Currently, only the SIGINT (interrupt) is handled.
       Returns: nothing

     When the break signal has been captured,
     (*note Capturing the Break Signal::), this method is called by a
     non-member method specified as the dedicated CTRL+C signal handler. The
     handler type is specified by the 'ccType' member variable which is set to
     one of the following:
     cchtIgnore: Ignore the Ctrl+C key (default, cctDefault)
     cchtExit  : Exit the application in an orderly way.
     cchtUser  : Ask the user if they really want to exit the application.
     cchtCopy  : Push the literal value for Ctrl+C (0x03) back into the input stream.
     cchtTerm  : Local handler is disabled, so this method is not called.
                             ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
     This is technically a public method; however, it is called ONLY by the
     non-member method which handles receipt of the break-signal (CTRL+C).


   ▪ void suspendsignalReceived ( int sigNum );
       Input  : sigNum: signal number to be handled
                        Currently, only the SIGSTP (suspend) is handled.
       Returns: nothing

     When the suspend signal has been captured, (*note
     acCaptureSuspendSignal::), this method is called by a non-member method
     specified as the dedicated CTRL+Z signal handler.

     This method captures the signal and converts it to an ordinary keycode:
     wcsCTL_Z.
                             ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
     This is technically a public method; however, it is called ONLY by the
     non-member method which handles receipt of the suspend-signal (CTRL+Z).


   ▪ void quitsignalReceived ( int sigNum );
       Input  : sigNum: signal number to be handled
                        Currently, only the SIGQUIT (quit) is handled.
       Returns: nothing

     When the quit signal has been captured, (*note acCaptureQuitSignal::),
     this method is called by a non-member method specified as the dedicated
     CTRL+4 signal handler. The handler will then perform an orderly shutdown
     of the application, returning all resources to the system.
                             ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
     This is technically a public method; however, it is called ONLY by the
     non-member method which handles receipt of the quit-signal (CTRL+4 or
     CTRL+\).



File: ansicmd.info,  Node: Color Attributes,  Next: Text Modifiers,  Prev: Configuration Methods,  Up: AnsiCmd Class Methods

Color Attributes
----------------

   ▪ bool acSetFg ( aeSeq fg );
       Input  : fg   : foreground color attribute (member of aeSeq)
     
       Returns: 'true'  if valid color attributes specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     Set text foreground color attribute (3-bit and 4-bit color).

     This includes both the standard 3-bit and 4-bit attributes, as well as
     the non-standard IBM Corp. AIX extensions.

          Note:
          The AIX color attributes were defined by IBM to provide interoperability
          of the terminal interface between their proprietary systems (Aixterm)
          and the Linux/UNIX world. Although these attributes are not part of the
          ANSI standard, they are widely supported and provide basic foreground
          and background colors using a slightly different (brighter) combination
          of Red/Green/Blue register values.

          The differences are demonstrated in the color-attribute tests included
          with the AnsiCmd library.
          *Note Development and Testing:: for more information.


   ▪ bool acSetBg ( aeSeq bg, bool synth );
       Input  : bg   : background color attribute (member of aeSeq)
                synth: (optional, 'true' by default)
                       if 'true',  use synthesized background color attributes
                       if 'false', use standard ANSI background color attributes
     
       Returns: 'true'  if valid color attributes specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     Set text background color attribute (3-bit and 4-bit color).

     This includes both the standard 3-bit and 4-bit attributes, as well as
     the non-standard IBM Corp. AIX extensions.
     (See note on AIX attributes, above.)


          Note on synthesis of intense background color attributes
          ........................................................

          The default color attributes for intense (bold) backgrounds are
          inadequate because the 'intense' ('bold') bit affects only the
          foreground color.

          “Synthesized” bold backgrounds are used by default, which bypasses
          the 'bold' flag problem by using a member from the color lookup
          table which is outside the basic sixteen color (4-bit) group.


   ▪ bool acSetFgBg ( aeSeq fg, aeSeq bg );
       Input  : fg   : foreground color attribute (member of aeSeq)
                bg   : background color attribute (member of aeSeq)
     
       Returns: 'true'  if valid color attributes specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     Set text foreground AND background colors (3-bit and 4-bit color).

     This includes both the standard 3-bit and 4-bit attributes, as well as
     the non-standard IBM Corp. AIX extensions.
     (See note on AIX attributes, above.)

       ┌────────────────────────────────────────────────────────────────┐
       │ Programmer's Note: The foreground is set AFTER the background  │
       │ so that if the 'bold' flag is used in the foreground escape    │
       │ sequence, it will not be masked by a subsequent non-bold       │
       │ background.                                                    │
       │                                                                │
       │ Note also that bold background color escape sequences include  │
       │ the bold flag, but unfortunately, because of the way the       │
       │ terminal interprets this flag, it affects only the foreground  │
       │ attribute.                                                     │
       │                                                                │
       │ Exception: "synthesized" bold backgrounds are used by default, │
       │ which bypasses the 'bold' flag problem by using a different    │
       │ member from the color lookup table which is outside the basic  │
       │ sixteen (4-bit) color group.                                   │
       └────────────────────────────────────────────────────────────────┘


   ▪ bool acSetFgBg ( acAttr fgbg );
       Input  : 
          fgbg : foreground/background/modifiers 
                 encoded as an acAttr bitfield
     
       Returns: 'true'

     Set text foreground/background colors using a value encoded as an acAttr
     bitfield value.
     Although the acAttr group of color attribute bitfields is defined for use
     within the AnsiCmd API; this method allows for color attributes to be
     specified using these encoded bitfield attributes regardless of whether
     the API code is compiled into the library.

     The specified value may be created directly as a logical OR of multiple
     members of the “acAttr” enumerated type.
     Example: acAttr( acaFG_GREEN | acaBG_BLACK | acaUNDERLINE)

     The bitfield value may also be built by a call to one of the
     acaExpand-class methods. *Note acaExpand class::, for details.

          ┌───────────────────────────────────────────────────────────┐
          │ Note that this is a simplified version of the API method: │
          │ 'acSetAttributes' which is preferred when the API methods │
          │ are available.                                            │
          │ This method should be used only if the library has been   │
          │ compiled without the API method group.                    │
          └───────────────────────────────────────────────────────────┘


   ▪ bool acSet8bitFg ( uint8_t fg );
       Input  : fg : index into the lookup table for 8-bit color attributes
     
       Returns: 'true'  if valid color attribute specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     Set foreground color from 8-bit-color lookup table.
     Select an index number between min8BIT through max8BIT (16-231).


   ▪ bool acSet8bitBg ( uint8_t bg );
       Input  : bg : index into the lookup table for 8-bit color attributes
     
       Returns: 'true'  if valid color attribute specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     Set background color from 8-bit-color lookup table.
     Select an index number between min8BIT through max8BIT (16-231).


   ▪ bool acSetRgbFg ( uint8_t rReg, uint8_t gReg, uint8_t bReg );
       Input  : rReg : red value
                gReg : green value
                bReg : blue value
     
       Returns: 'true'  if valid R/G/B registers specified and set
                'false' if specified parameters are out-of-range
                        (attribute will not be modified)

     Set foreground color using R/G/B register numbers.

     Each of the basic Red, Green and Blue color attributes may be displayed
     in any of 216 shades, and the color values may be in any combination.

     Each of the values may be specified as any register number between minRGB
     (16) and maxRGB (231).

     Smaller values indicate less saturation (darker colors), and larger
     values indicate greater saturation (lighter, more intense colors). If
     desired, the special value zero (0) may be used to indicate minimum
     saturation.


   ▪ bool acSetRgbBg ( uint8_t rReg, uint8_t gReg, uint8_t bReg );
       Input  : rReg : red value
                gReg : green value
                bReg : blue value
     
       Returns: 'true'  if valid R/G/B registers specified and set
                'false' if specified parameters are out-of-range
                        (attribute will not be modified)

     Set background color using R/G/B register numbers.

     Each of the basic Red, Green and Blue color attributes may be displayed
     in any of 216 shades, and the color values may be in any combination.

     Each of the values may be specified as any register number between minRGB
     (16) and maxRGB (231).

     Smaller values indicate less saturation (darker colors), and larger
     values indicate greater saturation (lighter, more intense colors).

     If desired, the special value zero (0) may be used to indicate minimum
     saturation.


   ▪ bool acSetWebFg ( WebSafeRGB hue, uint8_t shade );
       Input  : hue   : member of enum WebSafeRGB
                        wsrgbBLACK   : black color index
                        wsrgbRED     : base color index (red color block)
                        wsrgbGREEN   : base color index (green color block)
                        wsrgbBLUE    : base color index (blue color block)
                        wsrgbBROWN   : base color index (brown color block)
                        wsrgbMAGENTA : base color index (magenta color block)
                        wsrgbCYAN    : base color index (cyan color block)
                        wsrgbGREY    : base color index (grey color block)
                        Remaining members of WebSafeRGB are reserved for other
                        purposes.
                shade : intensity of the color specified by 'hue'
                        wsrgbSHADE_MIN <= shade <= wsrgbSHADE_MAX
                        where:
                        wsrgbSHADE_MIN == minimum saturation (subdued)
                        wsrgbSHADE_MAX == maximum saturation (brightest)
     
       Returns: 'true'  if valid hue and shade values specified
                'false' if specified parameters are out-of-range
                        (attribute not be modified)

     Set foreground color using "web-safe" R/G/B register value combinations.


     What's a Web Safe? Spiderman's closet?
     ......................................

     In the early days of the internet and using early versions of color
     display hardware, it was necessary to define a set of color attributes
     that could be reliably duplicated on any standard hardware with any of
     the early graphics-based web browsers. (Yes, we used to surf the web
     using text-only browsers; but you must remember that like Mister Spock,
     we were trying to build a mnemonic memory circuit using stone knives and
     bear skins.)

     The solution was to create the so-called “web-safe” set of color
     attributes. This was done by creating a 6 x 6 x 6 matrix of
     Red/Green/Blue register values yielding 216 discrete colors.
     Conceptually, each color can take one of six hex values:
     00 33 66 99 CC FF. For each color, the actual index into the 256 entry
     color lookup table is selected according to this model. See enum
     WebSafeRGB for the way this mapping is done.

     In the modern world of “true-color” computing, the idea of web-safe
     colors is a bit outdated, but it is still a valid concept in the simpler
     world of console applications, where we are limited to the palette
     specified by the terminal configuration.

     Please *note Development and Testing:: for a fuller discussion of the
     color attributes available to console applications.


   ▪ bool acSetWebBg ( WebSafeRGB hue, uint8_t shade );
       Input  : hue   : member of enum WebSafeRGB
                        wsrgbBLACK   : black color index
                        wsrgbRED     : base color index (red color block)
                        wsrgbGREEN   : base color index (green color block)
                        wsrgbBLUE    : base color index (blue color block)
                        wsrgbBROWN   : base color index (brown color block)
                        wsrgbMAGENTA : base color index (magenta color block)
                        wsrgbCYAN    : base color index (cyan color block)
                        wsrgbGREY    : base color index (grey color block)
                        Remaining members of WebSafeRGB are reserved for other
                        purposes.
                shade : intensity of the color specified by 'hue'
                        wsrgbSHADE_MIN <= shade <= wsrgbSHADE_MAX
                        where:
                        wsrgbSHADE_MIN == minimum saturation (subdued)
                        wsrgbSHADE_MAX == maximum saturation (brightest)
     
       Returns: 'true'  if valid hue and shade values specified
                'false' if specified parameters are out-of-range
                        (attribute not be modified)

     Set background color using "web-safe" R/G/B register value combinations.

     *Note acSetWebFg::, above for a description of “web-safe” colors.


   ▪ bool acSetGreyscaleFg ( uint8_t shade );
       Input  : shade : brightness of grey color: minGSCALE <= shade <= maxGSCALE
                        example: acSetGreyscaleFg ( minGSCALE + 2 ) ;
     
       Returns: 'true'  if valid greyscale attribute specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     Set Greyscale foreground color attribute. (background unchanged)

     For systems that have at least 256 colors, 24 shades of greyscale
     intensity are available. These are accessed through indices 232-255 of
     the terminal's 256-color lookup table.


   ▪ bool acSetGreyscaleBg ( uint8_t shade );
       Input  : shade : brightness of grey color: minGSCALE <= shade <= maxGSCALE
                        example: acSetGreyscaleBg ( minGSCALE + 2 ) ;
     
       Returns: 'true'  if valid greyscale attribute specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     Set Greyscale background color attribute. (foreground unchanged)

     For systems that have at least 256 colors, 24 shades of greyscale
     intensity are available. These are accessed through indices 232-255 of
     the terminal's 256-color lookup table.


   ▪ bool acSetAixFg ( aeSeq fg );
       Input  : fg   : AIX foreground color attribute (member of aeSeq)
     
       Returns: 'true'  if valid color attributes specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     NOTE: This method is obsolete. *Note acSetFg::.


   ▪ bool acSetAixBg ( aeSeq bg );
       Input  : bg   : AIX background color attribute (member of aeSeq)
     
       Returns: 'true'  if valid color attributes specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     NOTE: This method is obsolete. *Note acSetBg::.


   ▪ bool acReset ( void );
       Input  : none
     
       Returns: 'true'

     Return all ANSI attributes to terminal defaults. Set all tracking members
     to their default values. Flush the input and output buffers.

     This method does not modify the terminal configuration. It resets only
     the ANSI control environment as defined by the set of escape sequences.

     Programmer's Note: It is not possible to programatically check whether
     each attribute was actually reset; however, the ANSI reset escape
     sequence should be trustworthy.



File: ansicmd.info,  Node: Text Modifiers,  Next: Cursor Positioning,  Prev: Color Attributes,  Up: AnsiCmd Class Methods

Text Modifiers
--------------

   ▪ bool acSetMod ( aeSeq mod );
       Input  : mod  : text modification attribute (member of aeSeq)
     
       Returns: 'true'  if valid modifier attributes specified and set
                'false' if invalid parameter(s) specified
                      (attributes will not be modified)

     Set or reset the specified text modifier.

     Any text written after setting a modifier using this command will be
     displayed using the specified modifier (bold, italic, etc.). Any text
     written after resetting a modifier will be displayed _without_ the
     specified modifier.

     See *note acResetMods:: method below for a list of valid text modifiers.


   ▪ void acResetMods ( bool full );
       Input  : full: (optional, 'false' by default)
                      if 'true',  write a reset command instead of writing 
                                  the ANSI modifier-off sequences.
                                  This option is available in case the host 
                                  terminal does not support some or all of the 
                                  modifier-off sequences.
                                  NOTE: this ALSO resets the color attributes.
                      if 'false', write only the individual modifier commands,
                                  do not write the reset command
     
       Returns: nothing

     Reset all text modifiers, leaving the base foreground and background
     color attributes unchanged.

     The text modifier attributes are:
       aesBOLD,          // bold (increase intensity)
       aesFAINT,         // faint/dim (decrease intensity)
       aesITALIC,        // italic (or inverse)
       aesUNDERLINE,     // underline
       aesBLINK_SLOW,    // slow blink
       aesBLINK_FAST,    // fast blink
       aesREVERSE,       // reverse foreground and background colors
       aesCONCEAL,       // hide text
       aesXOUT,          // crossed out text (marked for deletion)
       aesFRACTUR,       // a variety of German calligraphy
       aesDBL_UNDERLINE, // double-underline (or bold off)
       aesFRAMED,        // "frame" the text
       aesENCIRCLE,      // "encircle" the text
       aesOVERLINE,      // overlined text

     Calling this method is equivalent to calling acSetMod() nine times, once
     for each of the modifer resets.
       aesBOLD_OFF,      // normal intensity (neither bold nor faint)
       aesITALIC_OFF,    // italic off (and Fractur off)
       aesUNDERLINE_OFF, // not underlined
       aesBLINK_OFF,     // not blinking
       aesREVERSE_OFF,   // not reversed
       aesCONCEAL_OFF,   // conceal off
       aesXOUT_OFF,      // not crossed out
       aesFRM_ENC_OFF,   // not framed, not encircled
       aesOVERLINE_OFF,  // overline off


   ▪ bool acFullReset ( bool enable );
       Input  : enable : 'true' to enable full reset for attribute modifications
                         'false' to disable full reset and rely upon the
                                 setting/resetting the flag which controls the
                                 specific attribute being modified
     
       Returns: current state of the full-reset flag

     Enable or disable reset of _all_ ANSI display attributes before modifying
     a text attribute.

     The AnsiCmd class is constructed so that when modifying an ANSI parameter
     other parameters will be affected as little as possible. Specifically,
     when enabling or disabling an attribute such as Bold, Underline, etc.,
     the intent is to avoid disturbing the existing forground and background
     color settings.

     However, some console software or their underlying system software may
     not support all of the single-attribute commands such as aesBOLD_OFF,
     aesITALIC_OFF, aesUNDERLINE_OFF, aesBLINK_OFF aesREVERSE_OFF,
     aesCONCEAL_OFF, aesXOUT_OFF, aesFRM_ENC_OFF, aesOVERLINE_OFF,
     aesIDEO_OFF.

     If these reset commands are not supported on a given platform, then set
     the 'fullReset' flag, and the AnsiCmd class will use the full reset
     command, aesRESET when changing terminal settings. The aesRESET command
     is supported by nearly all terminal emulators.

     *Note Invoking - Terminal Setup:: (-A option) which enables the
     full-reset flag as part of the startup sequence.



File: ansicmd.info,  Node: Cursor Positioning,  Next: Input Methods,  Prev: Text Modifiers,  Up: AnsiCmd Class Methods

Cursor Positioning
------------------


     Important Note On Cursor Positioning
     ....................................
     Cursor positions within a terminal window are always defined as _offsets_
     from some reference position. In general, offsets are relative to the
     upper-left corner of the terminal window, also known as the “origin”.
     The terminal window origin is defined as position 1:1 (not the logically
     correct 0:0).

     Unfortunately, the developers of terminal software and the authors of the
     ANSI commands and other utilities are not always on the same page
     regarding whether cursor offsets should be 0-based or 1-based. Be aware
     that a zero(0) value may be silently converted to a one(1) value, OR it
     may cause an operation to fail, or worse, produce unexpected results.

     The AnsiCmd cursor-positioning methods will accept an “absolute” value of
     zero and silently convert it to a one(1). This prevents artifacts such as
     unexpected scrolling or pushing text out of the window. However, be aware
     that not all utilities are so user friendly. Be aware!

   ▪ bool AnsiCmd::acSetCursor ( aeSeq curcmd, short arga, short argb ) const;
       Input  : curcmd: one of the members of the cursor-positioning group which
                        are included in enum aeSeq.
                        Example: acSetCursor ( aesCUR_HOME ) ;
                arga  : (optional, 1 by default)
                        for options which require arguments, 'arga' specifies the
                        first argument.
                        Example: acSetCursor ( aesCUR_ABSCOL, 30 ) ;
                argb  : (optional, 1 by default)
                        for options which require arguments, 'argb' specifies the
                        second argument.
                        Example: acSetCursor ( aesCUR_ABSPOS, 12, 60 ) ;
     
       Returns: 'true'  if valid cursor command (and valid arguments, if required)
                'false' if invalid parameter(s) specified
                        (position will not be modified)

     Set cursor position within terminal window.

     Some ANSI cursor commands perform cursor movements relative to the
     current position, while other commands set the cursor at an absolute
     position within the terminal window.

     *Note cursor offsets:: above regarding 1-based vs. 0-based cursor
     positioning.

     This method invokes the specified ANSI escape sequence directly; however,
     there are two variations on this method, described below, which may also
     be used to set the cursor position. Please choose the one that best suits
     your needs.

          NOTE: One member of the cursor-positioning group: aesCUR_REPORT,
          is not handled by this method. Instead please *note acGetCursor::.
          If aesCUR_REPORT is received, it will be ignored and 'false' will
          be returned to indicate that the request was not handled.

          Also:
          Digital Equipment Corporation (DEC) and the SCO Group (UnixWare)
          defined some of the cursor-management commands differently.
          On our test systems, the SCO commands work correctly, while
          the DEC commands do not. Your mileage may vary.


   ▪ bool AnsiCmd::acSetCursor ( short row, short col ) const;
   ▪ bool AnsiCmd::acSetCursor ( const WinPos& wp ) const;
       Input  : One of the following:
                   row : target row 
                   col : target column
                or:
                   wp  : (by reference) target row and column
     
       Returns: 'true'  if specified row/column are within the terminal window
                'false' if invalid position (cursor position not modified)

     Set absolute cursor position within terminal window.

     These methods reformat the parameters and call the low-level acSetCursor
     method described above.


   ▪ WinPos acGetCursor ( void ) const;
       Input  : none
     
       Returns: an initialized WinPos object
                (If system error or parsing error, window origin is returned.)

     Get the current cursor position within terminal window.


     Technical Notes
     ...............

     This method requires that input buffering be disabled and that input echo
     be set to 'noEcho'. The reason for this is that when buffering is active,
     the response from the terminal will not become available to the
     application until the Enter key is detected in the input stream.
     In addition, echo of input characters to the terminal window must also be
     disabled because when the system writes the response to the position
     query, it is written to stdin, which if echo were enabled would likely
     trash the currently-displayed text, or at minimum would move the cursor,
     causing a big surprise at the application level. While setting and
     restoring the buffering/echo options is an expensive operation in terms
     of CPU cycles, it is necessary for smooth operation at the application
     level.

     -- Write the ANSI sequence requesting the current cursor position.
     -- Read the response (binary data) from stdin.
     -- Decode the response which is of the form: 1B 5B (row) 3B (col) 52
          1B       escape character
          5B       left square bracket
          row      one or more ASCII numeric chars indicating row number
          3B       ';' (ASCII semicolon)
          col      one or more ASCII nummeric chars indicating column number
          52       ASCII 'R'


   ▪ bool acSetCursorStyle ( CurStyle style, aeSeq color );
       Input  : style : member of enum CurStyle
                color : (optional, default from terminal profile)
                        member of aeSeq, foreground attribute group: aesFG_xxx
                        color attribute for cursor [CURRENTLY IGNORED]
     
       Returns: 'true' if valid argument(s), else 'false'

     Set cursor type i.e. the shape of the cursor.

     Three basic cursor shapes are available in either a steady state or
     blinking:
      Block:'█'  Underline:'▁'  Vertical Bar:'▎'

     In addition, the cursor can be made invisible. The style is specified as
     a member of enum CurStyle which is the parameter for the escape sequence
     to be transmitted.
     (Note that cursor style settings are not part of the ANSI standard.)

       csBblock = 0,  // Full-character cell, blinking block
       csDflt   = 1,  // Cursor type defined by terminal configuration
       csSblock = 2,  // Full-character cell, steady (non-blinking) block
       csBuline = 3,  // Blinking underline
       csSuline = 4,  // Steady underline
       csBvbar  = 5,  // Blinking vertical bar
       csSvbar  = 6,  // Steady vertical bar
       csHide   = 7,  // Hide cursor (make it invisible)
       csShow   = 8,  // Show cursor (make it visible)

       ┌─────────────────────────────────────────────────────────────────────┐
       │ Note on cursor blink timeout:                                       │
       │ Although the cursor shape and blinking/steady status can be         │
       │ specified using this method, the terminal settings specify a        │
       │ timeout on the blinking status. For instance, the Gnometerm         │
       │ terminal emulator specifies a default timeout on the cursor's       │
       │ blink status of ten(10) seconds. This timeout can be adjusted       │
       │ using the @LDQ{}@b{gsettings}@RDQ{} utility. Example:               │
       │ Get current settings:                                               │
       │   gsettings get org.gnome.desktop.interface cursor-blink-timeout    │
       │ Report the range of valid values:                                   │
       │   gsettings range org.gnome.desktop.interface cursor-blink-timeout  │
       │ Set a new timeout of 25 seconds:                                    │
       │   gsettings set org.gnome.desktop.interface cursor-blink-timeout 25 │
       └─────────────────────────────────────────────────────────────────────┘

     Note: The cursor color attribute is automatically set by the terminal to
     the same color as the text. Theoretically, the "gsettings" utility and
     other utilities can also be used to set the cursor color, but early
     testing shows that such commands are ignored. Testing continues.



File: ansicmd.info,  Node: Input Methods,  Next: Output Methods,  Prev: Cursor Positioning,  Up: AnsiCmd Class Methods

Input Methods
-------------

   ▪ short acRead ( gString& gsIn, short limit ) const;
       Input  : gsIn  : (by reference) receives captured text (null terminated)
                limit : (optional, size of gString object by default)
                        If specified, 'limit' indicates the maximum number of
                        characters (wide-stream input) OR the maximum number of
                        bytes (narrow-stream input) that will be extracted from
                        the stdin buffer.
                        Important Note: This argument is referenced only when
                        unbuffered input is active. This argument is ignored
                        when input-stream buffering is enabled.
     
       Returns: number of characters captured (NOT the number of bytes)

     Capture user input as a sequence of characters terminated by the Enter
     key, OR when input buffering is disabled _and_ the number of characters
     specified by the 'limit' parameter has been reached.

     Internally, this method loops a call to the single-character acRead (see
     below). The called method contains most of the intelligence of the
     operation.


     Note on capture of the Enter key
     ................................
        — If the Enter key is the first and only keycode captured, the Enter
          keycode is returned and the character count returned will be one(1).

        — If the input is terminated by the Enter key, the characters captured
          _before_ the Enter key are returned. The Enter keycode will not be
          returned and is not included in the character total.

     Please *note Soft Echo Options:: for a discussion of when and how key
     input is echoed to the display.


   ▪ wchar_t  acRead ( void ) const;
       Input  : none
     
       Returns: keycode from user

     Capture a single keystroke from the user.

     The functionality of this method is dependent upon three factors:
      1) Whether input buffering is enabled,
         (*note acBufferedInput::)
      2) The active input echo option,
         (*note Soft Echo Options::)
      3) Whether input is configured for blocking or non-blocking read.
         (*note acBlockingInput::)
     Please study these options carefully and configure the input stream
     according to the needs of your application. A good place to start would
     be with 1) unbuffered input, 2) softEchoA, and 3) blocking read.


   ▪ wchar_t acPause ( bool nl = false ) const;
       Input  : nl : (optional, default: false)
                     if 'true',  after user keypress, output a newline character
                     if 'false', no output will be written to display
     
       Returns: keycode from user

     Wait for user to press a key. This is an unbuffered read, with no echo of
     the keycode to the display. Typically, this method would be used after
     the application displays a 'press any key' or similar message.

     The optional 'nl' parameter may be used to write a newline character
     (NEWLINE (0x000A) to the display after the user presses any key. This
     will move the cursor to the leftmost column of the next row. This option
     should be used only when the application is writing directly to the
     terminal window, and not when formatted (ACWin-class) data are being
     displayed.


     Technical Note: After the keycode is received, the input stream is
     flushed, that is, any data remaining in the input buffer is read and
     discarded. This is done to protect against stale data being left in the
     buffer in case the key pressed by the user generates an escape sequence
     or another multi-byte sequence. If the initial keycode received is the
     Escape keycode (0x001B), the keycode for the space key wcsSPACE (0x0020)
     will be returned instead.



   ▪ void acWait ( uint16_t seconds ) const;
       Input  :
          seconds : specifies the sleep interval in seconds (1 minute max)
                    0 <= seconds <= 60
     
       Returns: nothing

     Pause for a specified amount of time OR until user presses a key.
     This can be thought of as a combination of the acPause and nsleep
     methods.

     The specified delay is broken into segments and after each delay segment,
     the input stream is pinged to determine whether user has pressed a key.
     The pause continues until either the full pause interval is complete, or
     until user presses any key, whichever comes first.

     Any keycode received is discarded, and before return, the input stream is
     flushed to avoid abandoning any stale data in the input stream.


   ▪ void acFlushIn ( void ) const;
       Input  : none
     
       Returns: nothing

     Flush stdin, (the active input stream, wcin or cin).
     Any data still in the input stream will be discarded.


     Note On Performance
     ...................
     Flushing the input buffer relies on an _unbuffered_ input stream to
     reliably extract the stale data from the stream. If input buffering is
     enabled when this method is called, this method disables buffering before
     the flush and re-enables buffering after the flush.
     While this is effective, it does produce a small performance hit. For
     this reason, it is recommended that unless there is a clear reason to do
     otherwise, the application should disable input buffering during startup
     and then re-enable buffering just before exit.
     Please *note acBufferedInput:: for more information.

     See also *note acFlushStreams::, below.



File: ansicmd.info,  Node: Output Methods,  Next: Text Erase,  Prev: Input Methods,  Up: AnsiCmd Class Methods

Output Methods
--------------

   ▪ WinPos  acWrite ( WinPos wp, const gString& gsTxt,
                       bool flush = true ) const;

   ▪ WinPos  acWrite ( short row, short col, const gString& gsTxt,
                       bool flush = true ) const;

   ▪ WinPos  acWrite ( WinPos wp, const wchar_t* wTxt,
                       bool flush = true ) const;

   ▪ WinPos  acWrite ( short row, short col, const wchar_t* wTxt,
                       bool flush = true ) const;

   ▪ WinPos  acWrite ( WinPos wp, const char* cTxt,
                       bool flush = true ) const;

   ▪ WinPos  acWrite ( WinPos wp, wchar_t wchar,
                       bool flush = true ) const;

   ▪ WinPos  acWrite ( short row, short col, wchar_t wchar,
                       bool flush = true ) const;

   ▪ WinPos  acWrite ( WinPos wp, char cbyte, bool flush, bool newln ) const;

   ▪ WinPos  acWrite ( short row, short col, char cbyte,
                       bool flush = true ) const;

       Input  : starting cursor position in one of the following formats:
                   wp    : a WinPos object (by reference)
                         OR
                   row   : target row
                   col   : target column
     
                text data to be written in one of the following formats:
                   gsTxt : (by reference) a gString object
                         OR
                   wTxt  : a wchar_t string (32-bit characters)
                         OR
                   cTxt  : a char (byte) string
                         OR
                   wchar : a single wchar_t (wide) character
                         OR
                   cbyte : a single byte
     
                flush : (optional, default: 'true')
                        if 'true,   flush the output buffer before return
                        if 'false', do not flush the output buffer
     
       Returns: current cursor position (WinPos object)

     Write text data to stdout beginning at the specified cursor position. The
     final cursor position is at the end of the output. This is the return
     value.

          ┌──────────────────────────────────────────────────────┐
          │ This method is not reliable for writing ANSI escape  │
          │ sequences and ASCII control codes. For these special │
          │ cases, use the 'ttyWrite' method below.              │
          └──────────────────────────────────────────────────────┘

     The primary difference between this method and traditional TTY-style
     output is that _newline_ ('\n') characters are handled as a special case.
     When a newline character is encountered in the output stream, it causes
     the cursor to be placed on the next row at the _same column_ as the first
     column of the previous row. This automatic formatting allows the
     application to write formatted paragraph data without the painful task of
     having to count columns. (“You'll thank me later.” -- Adrian Monk)

     This method is actually a group of overloaded methods which provide
     flexibility in the way parameters are passed.

     Cursor position may be specified either as a WinPos object or as seperate
     row and column values.

     The source text may be formatted as:
       1. a gString object,
       2. a wchar_t (UTF-32) character array,
       3. a char (UTF-8) character array, or
       4. a single character

     By default, the output buffer is flushed after all data have been
     written. This is equivalent to the C++ sequence:
        wcout << "text_data" ;
        wcout.flush() ;
     However, flushing the output buffer is a slow operation (relatively
     speaking), so if multiple writes are performed in sequence, it is more
     efficient to flush the stream only once, after the last write of the
     sequence. For example, the following sequence writes three text strings,
     each in a different color, with the 'flush' flag set (default value) for
     the last write.
        WinPos wp( 4, 30 ) ;
        acSetFg ( aesFG_RED ) ;
        wp = acWrite ( wp, "Red textdata.\n", false ) ;
        acSetFg ( aesFG_BLUE ) ;
        wp = acWrite ( wp, "Blue text data.\n", false ) ;
        acSetFg ( aesFG_GREEN ) ;
        wp = acWrite ( wp, "Green text data.\n" ) ;

     Note that this method is aware of the terminal window dimensions.
       a. Text rows which would overrun the right edge of the terminal window
          are truncated, that is, automatic line wrap does not occur.
       b. Text data that would overrun the bottom edge of the terminal window
          will be ignored. Scrolling of the window contents _WILL NOT_ occur.

     If automatic scrolling or automatic line wrap are desired, then call the
     *note ttyWrite:: method instead.

     Note that the width of the output stream (wide or narrow stream) is
     established during the application startup sequence; therefore,
     regardless of the width of the source data, it will be transmitted using
     the established stream width.
     Please *note acSetStreamWidth::, or the
     *note W option:: command-line option for more information on stream
     configuration.


   ▪ void  ttyWrite ( const gString& gsTxt,
                      bool flush = true, bool nl = false ) const;
   ▪ void  ttyWrite ( const wchar_t* wTxt,
                      bool flush = true, bool nl = false ) const;
   ▪ void  ttyWrite ( const char* cTxt,
                      bool flush = true, bool nl = false ) const;
   ▪ void  ttyWrite ( const uint_8* uTxt,
                      bool flush = true, bool nl = false ) const;
   ▪ void  ttyWrite ( wchar_t wchar,
                      bool flush = true, bool nl = false ) const;
   ▪ void  ttyWrite ( char cbyte,
                      bool flush = true, bool nl = false ) const;

       Input  : text data to be written in one of the following formats:
                   gsTxt : (by reference) a gString object
                         OR
                   wTxt  : a wchar_t string (32-bit characters)
                         OR
                   cTxt  : a char (byte) string
                         OR
                   uTxt  : a UTF-8 (byte) string
                         OR
                   wchar : a single UTF-32 character
                         OR
                   cbyte : a single byte (generally: an ASCII control code)
                flush : (optional, 'true' by default)
                        if 'true,   flush the output buffer before return
                        if 'false', do not flush the output buffer
                nl    : (optional, default: 'false')
                        append a newline character to the output
     
       Returns: nothing

     Write text data (or ANSI sequence) to stdout beginning at the current
     cursor position. This emulates the action of a teletype machine (TTY).
     (If you don't know what a teletype machine is, your grandparents will
     explain it to you.)

     Any newline characters encountered will cause the cursor to be positioned
     on the first (leftmost) column of the line below, and if on the last line
     in the window, all data will be scrolled upward.
     Text will automatically wrap at the right edge of the window.

     This method is actually a group of overloaded methods which provide
     flexibility in the way parameters are passed. The source text may be
     formatted as
       1. a gString object,
       2. a wchar_t (UTF-32) character array,
       3. a char (UTF-8) character array, or
       4. a single character

     By default, the output buffer is flushed after all data have been
     written. This is equivalent to the C++ sequence:
        wcout << "text_data" ;
        wcout.flush() ;
     However, flushing the output buffer is a slow operation (relatively
     speaking), so if multiple writes are performed in sequence, it is more
     efficient to flush the stream only once, after the last write of the
     sequence. For example, the following sequence writes three text strings,
     each in a different color, with the 'flush' flag set (default value) for
     the last write.
        acSetCursor ( 4, 1 ) ;
        acSetFg ( aesFG_RED ) ;
        ttyWrite ( "Red textdata.\n", false ) ;
        acSetFg ( aesFG_BLUE ) ;
        ttyWrite ( "Blue text data.\n", false ) ;
        acSetFg ( aesFG_GREEN ) ;
        ttyWrite ( "Green text data.\n" ) ;

     Note that the width of the output stream (wide or narrow stream) is
     established during the application startup sequence; therefore,
     regardless of the width of the source data, it will be transmitted using
     the established stream width.
     Please *note acSetStreamWidth::, or the
     *note W option:: command-line option for more information on stream
     configuration.


   ▪ void acFlushOut ( void ) const;

       Input  : none
     
       Returns: nothing

     Flush stdout, (the active output stream, wcout or cout).
     Any data still in the output stream will be written to the terminal
     window.

     Note that the output methods *note acWrite:: and *note ttyWrite:: by
     default, flush the output stream at the end of each write. The acFlushOut
     method may be used to explicitly flush the data from the stream.

     See also *note acFlushStreams::, below.


   ▪ void acFlushStreams ( void ) const;
       Input  : none
     
       Returns: nothing

     Flush (write) any data in the stdout stream and discard an stale data in
     the stdin stream.

     This method combines calls to *note acFlushIn:: and *note acFlushOut:: as
     described above.

     Technical Note: Although every effort has been made to clear the I/O
     buffers as needed, transmission and receipt of ANSI escape sequences can
     be interrupted or broken, causing display artifacts or other problems.
     Explicitly flushing the buffers at critical moments can help to reduce
     such accidents.



File: ansicmd.info,  Node: Text Erase,  Next: Misc Methods,  Prev: Output Methods,  Up: AnsiCmd Class Methods

Text Erase
----------

   ▪ bool acEraseArea ( aeSeq area, short rowOff, short colOff );
       Input  : cur   : one of the members of the text-erasure group within
                        enum aeSeq.
                        example: acEraseArea ( aesERASE_WIN ) ;
                rowOff: (optional, ZERO by default) If a non-zero value is
                        specified, the cursor will be shifted upward (negative
                        values) or downward (positive values) from the current
                        cursor position before the erasure occurs.
                colOff: (optional, ZERO by default) If a non-zero value is
                        specified, the cursor will be shifted leftward (negative
                        values) or rightward (positive values) from the current
                        cursor position before the erasure occurs.
     
       Returns: 'true' if successful
                'false' if invalid parameter(s) specified

     Erase the specified area of the terminal window.
     The area to be erased is specified by one of the ANSI erasure commands.
       aesERASE_BOW,   // erase from cursor to bottom of window
       aesERASE_TOW,   // erase from cursor to top of window
       aesERASE_WIN,   // erase entire window ('clear')
       aesERASE_SAVED, // erase "saved" lines
       aesERASE_EOL,   // erase from cursor to end of line
       aesERASE_BOL,   // erase from cursor to beginning of line
       aesERASE_LINE,  // erase entire line
     The specified erasure is performed relative to the current cursor
     position UNLESS an offset is specified:
       rowOff : row offset from current row
       colOff : column offset from current column
     Important Note: If the specified offset moves the cursor beyond the edge
     of the terminal window, unexpected side-effects may occur.

     See also the direct erasure method, *note acClearArea::.



File: ansicmd.info,  Node: Misc Methods,  Next: API Methods,  Prev: Text Erase,  Up: AnsiCmd Class Methods

Misc Methods
------------

   ▪ void AnsiCmd::acBeep ( short repeat, short delay, int freq ) const;
       Input  : repeat : (optional, 1 by default) repeat count
                         Range: 1 - 32,767
                delay  : (optional, 5 by default i.e. 1/2 second)
                         delay between successive beeps in tenths of a second
                         in the range: 2 - 600 (0.2sec through 1.0min)
                         Note: The system is unable to handle short delays, so
                               a delay of two-tenths second is the safe minimum.
                freq   : (optional, -1 by default)
                         if specified, this is the auditory frequency of the beep
                         [CURRENTLY IGNORED]
     
       Returns: nothing

     Invoke the console's default auditory alert (beep).

     When called without parameters, the acBeep method produces a single beep
     (or whatever sound your terminal is set up to produce when the ASCII Bell
     control code is received.

     Three optional parameters are available: 'repeat', 'delay', and freq' as
     shown above.

     The repeat parameter is straightforward, specifying the number of
     individual beeps to produce from 1 (default) to 32,767, although we can
     attest that anything over about 200 will cause everyone in your household
     to toss the nearest loose object in your direction.

     The delay parameter specifies the (approximate) pause between beeps. The
     quality and repeatability of the tone is heavily dependent upon the delay
     between beeps. This is because the the actual physical timer used and the
     system code which controls it are both shared resources.
     The delay interval may be specified as a multiple of 0.10 (1 tenth)
     second, with the default being 0.5 (5 tenths) second, and the maximum
     being one minute (600 tenths). For a stable repeatable sound, the
     _practical_ minimum is two or three tenths (0.2 - 0.3) of a second.

     The freq parameter specifies the frequency of the tone that will be
     produced. For the current (pre)release, this parameter is ignored, and
     the tone is produced by simply issuing the ASCII Bell control code.
     For the production release, however, we hope to implement a more robust
     and flexible sound control.


   ▪ void AnsiCmd::nsleep ( uint16_t tenths, uint16_t millisec,
            time_t nanosec ) const;

       Input  : tenths  : specifies the sleep interval in tenths of a second
                          (1/10 sec == 0.10 sec)
                millisec: (optional, zero by default) for finer control over the
                          length of the delay, specify a delay in milliseconds.
                nanosec : (optional, zero by default) for even finer control over
                          the length of the delay, specify a delay in nanoseconds.
                          [CURRENTLY IGNORED]
     
       Returns: nothing

     Sleep (pause) execution for the specified time period. This method
     encapsulates access to the C-language 'nanosleep' function. It is
     intended to simplify the the interface and replaces direct calls to the
     obsolete C-language sleep and usleep functions.

     The primary delay value is specified in tenths of a second (0.10sec),
     with a secondary delay specification in milliseconds (0.001sec). The sum
     of the two values specifies the total duration of the delay.
     Thus the effective minimum delay is 1 millisecond, while the theoretical
     maximum delay is: 65535/10 or 6553 minutes + 65535 milliseconds or
     approximately 6618 minutes.This is an impractically large number, so we
     arbitrarily limit the maximum delay to 61 minutes, which is approximately
     60 minutes more than anyone will likely ever need.
                   1 millisecond <= delay <= 61.0 minutes
     Note that the 'nanosec' parameter is currently ignored. (see tech notes
     below)

     The philosophy here is that delays of less than one tenth of a second are
     not very useful for a human interface, while smaller delays are oriented
     toward computer-oriented tasks and which are limited only by the
     resolution of the clock referenced by the called function.



     Technical Notes
     .............

     In C++, the cosmopolitan way to delay the action is to use the 'chrono'
     class to define the delay, and the 'sleep_for' method to execute it.
     Example: chrono::duration<short>aWhile( 10 );
              this_thread::sleep_for( aWhile );
     Example: chrono::duration<short, std::milli>aMoment( 250 );
              this_thread::sleep_for( aMoment );
     The chrono/sleep_for C++ implementation is much cleaner and more
     intuitive than nanosleep(); however, ANSI escape sequences are by
     definition incompatible with multi-threaded environments, so we do not
     introduce multi-threading in the AnsiCmd class.
     Instead, we use the 'nanosleep' function which is technically
     sophisticated, but clunky in implementation. That is why we isolate it
     here to avoid cluttering up our otherwise lovely code.

     The nanosleep C-library function is defined in time.h and takes as
     parameters two 'timespec' structures as shown.

          #include <time.h>
          struct timespec
          {
             time_t tv_sec ;  /* seconds */
             long   tv_nsec ; /* nanoseconds */
          };
          nanosleep ( const struct timespec *req, struct timespec *rem ) ;

     The first parameter 'req' (the ‘request’) specifies the duration of the
     sleep interval in seconds and nanoseconds. Note that the nanosleep
     function rounds the nanosecond value ('tv_nsec') upward to the resolution
     of the clock. Note also that the ('tv_nsec') value is limited to
     9,000,000,000 (nine billion nanoseconds). Any larger value will generate
     an error.

     If the requested interval is completed without interruption, the second
     parameter ('rem') (the ‘remainder’) remains unused. If however, the sleep
     interval is interrupted by some system event, then the second parameter
     receives the remainder of the delay so that nanosleep can be called again
     to complete the specified sleep interval.

     The resolution of the clock used for this interval is also a significant
     factor in the accuracy of the operation.
     It is important to keep in mind that although nanosleep claims to be
     accurate in the nanosecond range, a number of factors may affect the
     results. For instance, the default Linux scheduler is based on
     ten-millisecond intervals, so sequential calls may be limited to this
     resolution. Some newer systems with newer kernel support may be able to
     provide a resolution of one(1) millisecond.

     See the documentation for the C-library 'clock_getres' function for more
     information on the clocks available on the host system.
     See also: "man 7 time", which indicates that the _effective_ resolution
     is between 1 and 10 milliseconds.
     Also see the resolutions specified in the file: "/proc/timer_list". Most
     of the entries in that file specify a resolution of 1 nanosecond, but we
     see this as more aspirational, than mathematical.

     While the nanosleep function cannot be relied upon by timing-critical
     operations which may be affected by these factors, for user-oriented
     delays, into the tens-of-milliseconds range, however, the nanosleep
     function is a welcome addition to the C-language library.


   ▪ const char * acVersion ( void ) const;
       Input  : none
     
       Returns: pointer to version string

     This method return a const pointer to a string containing the AnsiCmd
     class version number. The version number takes the form: x.y.zz, where
     'x' is the major version, 'y' is the minor version and 'zz' is the step
     version.
     Example: 0.0.03

     Unlike some other developers whom we will politely not name (Firefox),
     this author does not advance the major or minor version number without a
     very good reason. Therefore, even packages we have had in circulation for
     twenty years seldom advance beyond version 0.2.00. For instance, the
     gString class distributed with package, which we first released in 2011
     is now at version 0.0.32, and yes, it is absolutely solid.


   ▪ bool AnsiCmd::acSetFont ( aeSeq font, uint8_t fontnum );
       Input  : font   : one of aesPRIMARY_FONT or aesALTERNATE_FONT which are
                         members of enum eSeq.
                fontnum: (optional, zero(0) by default)
                         specify the alternate font, range: 1 through 9
     
       Returns: 'true'  if valid greyscale attribute specified and set
                'false' if invalid parameter(s) specified
                        (attributes will not be modified)

     Specify the terminal font used to write subsequent text data.

     Specify the 'font' parameter as a member of enum aeSeq:
          aesPRIMARY_FONT   set the primary font as the active font
                            ('fontnum' parameter is ignored)
          aesALTERNATE_FONT set one of the alternate fonts as the active font
                USER#   1  2  3  4  5  6  7  8  9  translates to:
                ANSI#  11 12 13 14 15 16 17 18 19

     These commands are not recognized on any of our development platforms,
     but the font test is available for testing them on your particular
     system: (*note Test_AltFonts::).


   ▪ bool acSetIdeogram ( aeSeq idea );
       Input  : idea  : member of enum aeSeq within the ideogram-command group.
     
       Returns: 'true'  if valid argument
                'false' if invalid parameter(s) specified
                        (attribute will not be modified)

     Interface to the seldom-supported and little-used "ideogram" (logogram)
     group of ANSI commands.

     It is unclear what this group of commands was originally intended to do.
     Presumably they were intended to provide some kind of border or
     highlighting around a block of text.
       aesIDEO_UNDER       // ideogram underlined
       aesIDEO_UDOUBLE     // ideogram double-underlined
       aesIDEO_OVER        // ideogram overlined
       aesIDEO_ODOUBLE     // ideogram double-overlined
       aesIDEO_STRESS      // ideogram stress marking (italic?)
       aesIDEO_OFF         // all ideogram attributes off
     These are probably non-functional, but they can be tested using this
     method.

     *Note acDrawBox:: and *note acDrawLine:: methods for line drawing
     options.



File: ansicmd.info,  Node: API Methods,  Next: Development Support,  Prev: Misc Methods,  Up: AnsiCmd Class Methods

API Methods
-----------

The API (Application Programming Interface) methods are designed to
encapsulate some of the more common operations performed as a sequence of
calls to the low-level primitive methods. Using the API methods reduces code
clutter at the application level, which will hopefully reduce development and
debugging time for the application.

*note Color Attribute Methods::
The most significant difference between the ANSI primitives and the API layer
is the way color attributes are encoded. While the terminal emulator program
interprets the ANSI escape sequences to set color attributes and text
modifiers, it is rather inconvenient to work with them directly. Internally,
the AnsiCmd library encodes color attributes as 32-bit bit fields.
    *note List of Attribute Names::
    *note Attribute Bitfield Definitions::

*note Display Formatting Methods::
Erase the current data displayed in the specified area of the terminal window,
or format text paragraph data to fit within a specified area.

*note Line Drawing Methods::
Draw horizontal and vertical lines or draw rectangles in the terminal window.

*note Identify "Special" Keycodes::
Identify whether a given keycode matches one of the defined “special” or
“command-key” keycodes.

*note Temporary File Management::
Create and manage temporary files for useby the application.

*note Communicate With System Clipboard::
Establish a communications channel with the system clipboard and exchange text
data with the clipboard.
    *note AnsiCmd Clipboard Access::

                            ────────────────────


Color Attribute Methods
.......................

   ▪ bool AnsiCmd::acSetAttributes ( acAttr newAttr, bool resetAll = false );

       Input  : newAttr : bitfield containing the logical OR of the desired
                          foreground/background attributes and text modifiers.
                resetAll: (optional, 'false' by default)
                          if 'false', only the the attributes specified by
                                      'newAttr' will be modified.
                          if 'true',  all attributes and modifiers will be reset
                                      to their default values before the new
                                      attributes are applied.
     
       Returns: 'true' if successful, else 'false' (currently always 'true')

     Modify or replace the current color attributes and/or text modifiers.

     The basic group of AnsiCmd methods set or reset one attribute per call by
     issuing the corresponding ANSI escape sequence designated as a member of
     enum aeSeq (ansi escape Sequence). The acSetAttributes method, by
     contrast, takes as a parameter the _logical OR_ of an arbitrary number of
     attributes designated as members of enum acAttr (ansi cmd Attribute).
     Arguably, this provides a cleaner interface between the application layer
     and the display-formatting functionality.

     The individual enum acAttr members are OR'd together to produce the
     'newAttr' parameter sent to acSetAttributes.

     The examples below demonstrate how a logical OR of acAttr values
     specifies the attribute(s) to be modified.

     Note that when performing any mathematical operation using members of an
     enumerated type such as enum acAttr, the compiler will complain. For
     instance, when performing a logical OR using members of enum acAttr, the
     compiler insists that the result be cast back into the acAttr type. For
     example, the compiler will complain about this assigment:
        acAttr newAttr = acaFG_BLUE | acaBG_GREEN ;
     so to make the compiler happy we perform a cast back to the type:
        acAttr newAttr = acAttr(acaFG_BLUE | acaBG_GREEN) ;
     Please *note enum acAttr::, below for more detailed information.

        ⚬ To set the foreground color attribute to blue text:
             acSetAttributes ( acaFG_BLUE ) ;

        ⚬ To set the background color attribute to green:
             acSetAttributes ( acaBG_GREEN ) ;

        ⚬ To simultaneously set both foreground and background color
          attributes:
             acSetAttributes ( acAttr(acaFG_BLUE | acaBG_GREEN) ) ;

        ⚬ To set Bold and Italic text modifiers:
             acSetAttributes ( acAttr(acaBOLD | acaITALIC) ) ;

        ⚬ To reset only a specific text modifier (or modifiers) combine the
          modifier(s) with the “acaCLEAR_MODS” member:
             acSetAttributes ( acAttr(acaCLEAR_MODS | acaBOLD) ) ;

        ⚬ To reset all text modifiers (i.e. plain text), call with _only_ the
          “acaCLEAR_MODS” member:
             acSetAttributes ( acaCLEAR_MODS ) ;

        ⚬ To set Bold, blue foreground text, either specify a blue foreground
          in combination with the Bold attribute, or specify the bold blue
          attribute directly:
             acSetAttributes ( acAttr(acaBOLD | acaFG_BLUE) ) ;
             or
             acSetAttributes ( acaFGb_BLUE ) ;

        ⚬ RGB (Red/Green/Blue) or 8-bit color foreground and background
          attributes are specified as index values rather than as individual
          members of enum acAttr. For this reason, setting RGB or 8-bit
          attributes is a two-step process.
          First, call acComposeAttributes (described below) to construct the
          bitfield value, then call acSetAttributes with the resulting value.

          RGB attribute values combine 'acaFG_RBG' and/or 'acaBG_RGB' with
          “web-safe” color indices in the range:
          wsrgbMIN <= index <= wsrgbMAX. This example sets both foreground and
          background to web-safe RGB attributes:
          acAttr aca = acComposeAttributes( 14, 221, true, true );
          acSetAttributes ( aca );

          Eight-bit attributes combine 'acaFG_INDEX' and/or 'acaBG_INDEX' with
          8-bit color indices in the range: min8BIT <= index <= max8BIT. This
          example sets both foreground and background to 8-bit attributes:
          acAttr aca = acComposeAttributes( 32, 112, false, false );
          acSetAttributes ( aca );
          *Note acComposeAttributes:: below for additional examples.

        ⚬ To reset all attributes and modifiers to their default values, and
          then set new fgnd/bgnd attributes and text modifiers, call with the
          'resetAll' flag set:
             acSetAttributes ( acAttr(acaFG_BLUE | acaBG_GREY | acaUNDERLINE), true ) ;

        ⚬ To reset all attributes and modifiers to their default values, use
          the “acaATTR_DFLT” member in combination with the 'resetAll' flag:
             acSetAttributes ( acaATTR_DFLT, true ) ;


   ▪ acAttr acComposeAttributes ( uint8_t fgVal, uint8_t bgVal, bool rgbfg,
                                  bool rgbbg, acAttr mods = acaPLAINTXT )
       Input  : fgVal  : foreground index (8-bit index or web-safe RGB index)
                         -- if 'rgb' reset, then value interpreted as 8-bit index.
                            Range: 16-231 (or greyscale:232-255)
                         -- if 'rgb' set, then value interpreted as web-safe RGB
                            index. Range: 0-252
                         -- if 'rgb' reset AND 'fgVal' 0-15, then assume 4-bit color
                bgVal  : background index (8-bit index or web-safe RGB index)
                         -- if 'rgb' reset, then value interpreted as 8-bit index.
                            Range: 16-231 (or greyscale:232-255)
                         -- if 'rgb' set, then value interpreted as web-safe RGB
                            index. Range: 0-252
                         -- if 'rgb' reset AND 'fgVal' 0-15, then assume 4-bit color
                rgbfg  : if set, fgVal is interpreted as a (web-safe) RGB index
                         if reset, fgVal is interpreted as a 4/8-bit index
                rgbbg  : if set, bgVal is interpreted as a (web-safe) RGB index
                         if reset, bgVal is interpreted as a 4/8-bit index
                mods   : (optional, acaPLAINTXT by default)
                         logical OR of acAttr text-modifier flags)
     
       Returns: the constructed acAttr value
                (if a value is out-of-range, terminal default will be used)

     Construct an acAttr attribute bitmap from component values:
     Call this method when composing attributes with 8-bit fgnd/bgnd indices
     or web-safe RGB fgnd/bgnd indices.

     Use the constructed value as the parameter for a call to
     *note acSetAttributes::, above.


     Examples:
     ▔▔▔▔▔▔▔▔▔
     acAttr aca ;      // receives the constructed value
     
     Construct an 8-bit foreground and background value:
       aca = acComposeAttributes ( min8BIT + 2, min8BIT + 27, false, false );
     Construct a value with a 4-bit foreground on an 8-bit background:
       aca = acComposeAttributes ( 3, max8BIT - 32, false, false );
     Construct the same attribute value, but adding italic text.
       aca = acComposeAttributes ( 3, max8BIT - 32, false, false, acaITALIC );
     Construct a web-safe RGB foreground and background value:
       aca = acComposeAttributes ( wsrgbMIN + 16, wsrgbMAX - 32, true, true );
     Construct a value with an 8-bit foreground on an RGB background.
       aca = acComposeAttributes ( 201, wsrgbMIN + 32, false, true );
     Construct the same attribute value, but adding underlined text.
       aca = acComposeAttributes ( 201, wsrgbMIN + 32, false, true, acaUNDERLINE );
     Construct the same attribute value, but with italic _and_ underlined text.
       aca = acComposeAttributes ( 201, wsrgbMIN + 32, false, true, 
                                   acAttr(acaITALIC | acaUNDERLINE) );
     
     Use the constructed value to set the specified attributes:
       acSetAttributes ( aca );
         or
       acSetAttributes ( acAttr(aca | acaITALIC | acaUNDERLINE) );

     Note on 4-bit values:
     The 4-bit color attributes are individually named, so the attributes may
     be specified directly.
     Examples: acSetAttributes( acAttr(acaFG_BLUE | acaBGb_BROWN) );
               acSetAttributes( acAttr(acaFG_DFLT | acaBGb_BLUE) );
               acSetAttributes( acAttr(acaFG_DFLT | acaBG_DFLT) );
     Although this method is not designed to configure 4-bit color indices
     (0-15), they will be handled correctly, EXCEPT THAT it is not possible to
     specify terminal default foreground or background using this method.
       aca = acComposeAttributes ( 3, 12, false, false );


   ▪ void acGetAttributes ( acaExpand& decodedAttr );

       Input  : decodedAttr: (by reference) instance of an acaExpand object 
                             to receive data.
     
       Returns: nothing

     Get a decoded copy of the current color attributes and text modifier
     flags.

     The bitfield containing the attributes is decoded into it component
     values.

     Refer to the description of the *note acaExpand class:: data members for
     more information.

                            ────────────────────

     Technical Notes on the acAttr Enumerated Type
     .............................................

     The acAttr (AnsiCmd Attributes) enumerated type provides
     application-level color-attribute and text-modifier configuration for
     terminal applications.
     The enumerated list, enum acAttr is defined in AnsiCmdDef.hpp.

     Members of this type specify color attributes and text modifiers in a
     consistent format which encapsulates the primitive ANSI escape sequences
     defined for terminal-window text formatting. (see enum aeSeq).

     Within the AnsiCmd class, these values are decoded and mapped to their
     corresponding ANSI escape sequences (or group of sequences). This allows
     the application to focus on algorithms and user interaction rather than
     reading and writing binary data within the terminal window.

     Although acAttr is defined as an enumerated type, is constructed as a
     group of macros defining bitfields. This allows the macros to be grouped
     in a coherent manner while also allowing bitwise OR operations for the
     desired foreground, background and text-modifier attributes. For example,
     combine foreground, background attributes PLUS the “bold” and “italic”
     text attributes, then pass the value as an argument to one of the
     application-level methods.
        acAttr txtAttr = acAttr(acaFG_GREEN | acaBG_GREY | acaBOLD | acaITALIC) ;
        acSetAttributes ( txtAttr ) ;

     Technical Note: The compiler will complain when performing any
     mathematical operations on members of an enumerated type; therefore, be
     sure to cast the OR'd value back to the acAttr type. For instance, the
     following would cause a compiler warning: acAttr a; a |= acaBOLD;
     Instead, use the following syntax: a = acAttr(a | acaBOLD);

     See also the acaExpand class below for more information on encoding and
     decoding the bitfield values.

                            ────────────────────

     Bit Twiddling — the acaExpand Class
     ....................................

     Late Night host, Seth Meyers once defined nerds as people “with
     coffee-breath and crippling anxiety.” While that characterization was a
     bit rude, he actually wasn't wrong. For all OCD sufferers, (otherwise
     known as technically proficient people), having more information is like
     having a mug of hot cocoa and a warm blanket.

     So, while accessing the API method group (which includes the ACWin
     class), does not require an understanding of the bit manipulations that
     occur within the AnsiCmd library, our nerd DNA insists that we have at
     least a general idea what's going on in the binary jungle.

     All significant bit-oriented operations are encapsulated within the
     acaExpand class. The data managed by the acaExpand class are derived from
     the acAttr enumerated type and the WebSafeRGB enumerated type. These are
     both defined in AnsiCmdDef.hpp.

     The acaExpand class is also defined in AnsiCmdDef.hpp, and is implemented
     in the AnsiCmdAca.cpp source module.

     All methods and data members of the acaExpand class are “public”;
     however, the live data are not available to the application (Duh!). If
     desired, however, _a copy of the live data_ data may be retrieved and
     studied.
     Please *note acGetAttributes::, above.

     acaExpand Methods
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

     ~acaExpand ( void ) ; // destructor

     acaExpand ( void ) ; // default constructor

     acaExpand ( acAttr bits ) ;
     Initialization Constructor:
     The 'bits' parameter consists of one or more members of enum acAttr
     combined using a logical OR. Example:
        acaExpand aca( acAttr(acaFG_RED | acaBG_GREY) );

     void decode ( acAttr bits ) ;
     Decode the specified bitfield value into it component parts and store
     them in the data members.
        acaExpand aca;
        aca.decode( acAttr(acaFG_RED | acaBG_GREY) );

     acAttr modify ( acAttr acaValue, bool add ) ;
     Add (or remove) one or more elements to (from) the bitfield value.
        'acaValue'  specifies the item(s) to be modified.
             'add'  (optional, 'true' by default)
                    referenced ONLY for text modifiers, not color attributes
                    if true, add the 'acaValue' items to the existing bitfield
                    if false, remove (reset) the specified items
        acaEx.modify( acaBOLD, true );
        acaEx.modify( acaBOLD, false );
        acaEx.modify( acAttr(acaFGb_RED | acaBG_BLUE) );

     void update ( aeSeq aesValue, uint8_t colorIndx = ZERO );
     Update attribute tracking data by converting the provided member of
     enum aeSeq to the equivalent acAttr bitfield value.
        'aesValue'  aeSeq item specifying attribute to be updated
       'colorIndx'  for aeSeq items requiring a color-attribute index value
     (Used internally, but not really useful at the application level.)

     acAttr compose ( void );
     Construct an acAttr attribute bitmap from the data in the data members:
     fgIndex, bgIndex and the boolean (flag) members. This is the reverse of
     the 'decode' method, above, and is used to encode 8-bit and RGB attribute
     indices. (Used internally, but not really useful at the application
     level.)
     Please refer to the API-level method *note acComposeAttributes:: which
     calls the 'compose' method with consistent formatting.

     bool swap ( void );
     Swap (exchange) the foreground and background attributes.
     Text modifiers are not affected.

     acAttr buildRgb ( bool fg, WebSafeRGB fgVal, 
                       bool bg = false, WebSafeRGB bgVal = wsrgbMIN ) const
     Construct an acAttr bitfield from web-safe RGB color indices.
     Specify RGB values for foreground and/or background color attributes. The
     values are members of enum WebSafeRGB which encode the RGB 'hue' and
     'shade' used to initialize the Red/Green/Blue register values.
        'fg'     'true'  if foreground value specified in 'fgVal'
                 'false' if 'fgVal' is to be ignored
        'fgVal'  member of enum WebSafeRGB
                 if 'fg' flag is set, web-safe RGB foreground value
                 if 'fg' flag is reset, this value is ignored
        'bg'     'true'  if background value specified in 'bgVal'
                 'false' if 'bgVal' is to be ignored
        'bgVal'  member of enum WebSafeRGB
                 if 'bg' flag is set, web-safe RGB background value
                 if 'bg' flag is reset, this value is ignored
     Returns: the constructed acAttr bitfield (If one or more parameters
     out-of-range, acaATTR_DFLT is returned.

     Examples:
     1) Construct a bitfield with medium red foreground and dark blue background.
        acaExpand aca ;
        acAttr newVal =
              aca.buildRgbVal ( true, WebSafeRGB(wsrgbRED + wsrgbSHADE_MED),
                               true, wsrgbBLUE );
        aca.decode( newVal );
     
     2) Construct a bitfield with bright cyan background, and with a standard 
        4-bit (non-RGB) blue foreground.
        acaExpand aca ;
        acAttr newVal =
              aca.buildRgbVal ( false, wsrgbMIN,
                                true, WebSafeRGB(wsrgbCYAN + wsrgbSHADES - 1) );
        newVal = acAttr(newVal | acaFG_BLUE);
        aca.decode( newVal );
     
     3) Construct a bitfield with bright magenta foreground, and a medium blue 
        background shade.
        acaExpand aca ;
        acAttr newVal =
              aca.buildRgb ( true, WebSafeRGB(wsrgbMAGENTA + wsrgbSHADE_MAX), 
                             true, WebSafeRGB(wsrgbBLUE + wsrgbSHADE_MED / 2) );
              aca.decode( newVal );
     
     4) Construct a bitfield with bright yellow foreground and a medium blue
        background.
        acaExpand aca ;
        acAttr newVal =
              acaBld.buildRgb( true, WebSafeRGB(wsrgbBROWN + wsrgbSHADE_MAX),
                               true, WebSafeRGB(wsrgbBLUE + wsrgbSHADE_MAX * 0.65) );
        aca.decode( newVal );

     acAttr build8Bit ( bool fg, uint8_t fgVal, bool bg, uint8_t bgVal ) const
        'fg'     'true'  if foreground value specified in 'fgVal'
                 'false' if 'fgVal' is to be ignored
        'fgVal'  index of foreground attribute, range: min8BIT - max8BIT
                 if 'fg' flag is set, calculate foreground bitfield
                 if 'fg' flag is reset, this value is ignored
                         and foreground bits are initialized as reset
        'bg'     (optional, 'false' by default)
                 'true'  if background value specified in 'bgVal'
                 'false' if 'bgVal' is to be ignored
        'bgVal'  (optional, min8BIT by default)
                 index of background attribute, range: min8BIT - max8BIT
                 if 'bg' flag is set, calculate background bitfield
                 if 'bg' flag is reset, this value is ignored
                         and background bits are initialized as reset
     Returns: the constructed acAttr bitfield

        acaExpand acaBld ;
        acAttr pbAttr = acaBld.build8Bit( true, 160, true, 82 ) ;
        acAttr sbAttr = acaBld.build8Bit( true, 16, true, 219 ) ;
        acAttr rbAttr = acaBld.build8Bit( false, 0, true, 219 ) ;
        acAttr sbAttr = acaBld.build8Bit( true, 16 ) ;
     

     aeSeq bits2aeseq ( acAttr acaBits, uint8_t byteIndx, bool isFgnd, bool isRgb );
     Convert between acAttr (bitfield) and aeSeq (ANSI escape sequence).
     Note: If the aeSeq value is one of the 4-bit "bold" foreground
     attributes, the 'boldMod' flag is set. Otherwise the flag is not
     modified.
         'acaBits'  acAttr bitfields to be converted
        'byteIndx'  byte index value (either foreground or background index)
                    (currently unused)
          'isFgnd'  true if foreground target, false if background target
           'isRgb'  (optional, false by default)
                    true if 'acaBits' references one of the
                         web-safeRGB register indices, minRGB-maxRGB.
                    'false if 'acaBits' is a lookup table index:
                          0-15 : 4-bit color index
                        16-231 : 8-bit color index
                       232-255 : greyscale index
     Returns: member of enum aeSeq

        acAttr attrBits = acAttr(acaFG_CYAN | acaBG_BLUE) ;
        WebSafeRGB attrRgb = wsrgbBLUE + wsrgbSHADE_MED ;
        acaExpand acax ;
        // 8-bit background
        aeSeq attrSeq = acaex.bits2aeseq ( attrBits, 0, false );
        // RGB foreground
        attrSeq = acaex.bits2aeseq ( attrRgb, 0, true, true );
     

     acAttr aeseq2bits ( aeSeq aesCmd, bool& setFlag );
     Convert between aeSeq (ANSI escape sequence) and acAttr (bitfield).
     For named escape sequences only; specifically:
        a) 4-bit foreground
        b) 4-bit background
        c) text modifier flags
     All other aeSeq values return acaPLAINTXT (i.e. zero).
     Note: If the aeSeq value is one of the 4-bit "bold" foreground or
     background attributes, the 'boldMod' flag is set. Otherwise the flag is
     not modified.
          'aesCmd'  member of enum aeSeq to be converted
         'setFlag'  (by reference) receives the state of the internal
                    set/reset flag associated with the attribute
     Returns: member of enum acAttr

        aeSeq fgnd = aesFGb_BLUE ;
        bool flag ;
        acaExpand acax ;
        acAttr convAttr = acax.aeseq2bits( fgnd, flag ) ;
     
        Returns:
        convAttr == acaFGb_BLUE  and  flag == true
     

     bool web2regs ( uint8_t webrgb, bool fgnd );
     Convert web-safe RGB index into red/green/blue RGB register values.
          'webrgb'  value indicating one of the web-safe RGB register groups
                    in the range: wsrgbMIN <= webrgb <= wsrgbMAX.
            'fgnd'  true if fgnd attributes, false if bgnd attributes
     216 web-safe colors are defined by the standard, which are mapped to the
     256 color indices defined for terminal color attributes and are then
     translated to individual R, G and B register values as shown.
                     DARK >>>> LIGHT   CORRESPONDING RGB REGISTER INDICES
      Black        :    0               16;16;16
      Red group    :    1      36       22;16;16  >>>>  231;16;16
      Green group  :   37      72       16;22;16  >>>>  16;231;16
      Blue group   :   73     108       16;16;22  >>>>  16;16;231
      Brown group  :  109     144       22;22;16  >>>>  231;231;16
      Magenta group:  145     180       22;16;22  >>>>  231;16;231
      Cyan group   :  181     216       16;22;22  >>>>  16;231;231
      Grey group   :  217     231       22;22;22  >>>>  231;231;231

     void reset ( bool modsOnly = false ) ;
     Reset (clear) all data members. Optionally, reset text-mod flags only.
        'modsOnly'  if true, reset only the text-modifier attributes
                    if false, reset all color and text-modifier attributes

     acaExpand Data Members
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

     Note that while there is some redundancy among the members, the layout of
     the data members is constructed for speed of access and to minimize the
     need for higher-level methods to perform bitwise operations. This in turn
     reduces the chance of processing errors.

     acAttr    acaVal;    full, encoded acAttr value
     uint32_t  fgBits;    nine bits defining foreground:
                          index byte + fg default flag
     uint32_t  bgBits;    nine bits defining background:
                          index byte + bg default flag
     uint32_t  allFlags;  all binary flags (excludes fg/bg indices)
     uint32_t  modFlags;  text-modification flags (subset of 'allFlags')
     acAttr    acaFgnd;   8-bit field defining the foreground index
     acAttr    acaBgnd;   8-bit field defining the background index
     aeSeq     aesFgType; Foreground attribute _type_:
                          aesFG_DFLT:  4-bit color
                          aesFG_INDEX: 8-bit color
                          aesFG_RGB:   r/g/b color
     aeSeq     aesBgType; Background attribute _type_:
                          aesBG_DFLT:  4-bit color
                          aesBG_INDEX: 8-bit color
                          aesBG_RGB:   r/g/b color
     aeSeq     aesFgnd;   4-bit foreground (member of enum aeSeq)
     aeSeq     aesBgnd;   4-bit background (member of enum aeSeq)
     uint8_t   fgIndex;   foreground byte index
     uint8_t   bgIndex;   background byte index
     uint8_t   rgbFgR;    if RGB foreground, Red register value
     uint8_t   rgbFgG;    if RGB foreground, Green register value
     uint8_t   rgbFgB;    if RGB foreground, Blue register value
     uint8_t   rgbBgR;    if RGB background, Red register value
     uint8_t   rgbBgG;    if RGB background, Green register value
     uint8_t   rgbBgB;    if RGB background, Blue register value
     bool      fgDflt;    if set, terminal default foreground
                          (ignore fg index bits)
     bool      bgDflt;    if set, terminal default background
                          (ignore bg index bits)
     bool      boldMod;   if set, Bold (intense) text
     bool      italicMod; if set, Italic text
     bool      ulineMod;  if set, Underlined text
     bool      olineMod;  if set, Overlined text
     bool      xoutMod;   if set, X-out (strikethrough) text
     bool      blinkMod;  if set, Blinking text
     bool      invisMod;  if set, Invisible (concealed) text
     bool      revMod;    if set, Reversed foreground and background
     bool      clrMods;   if set, Clear existing mods before setting new mods
     bool      fgRgb;     if set, rgbFgR, rgbFgG and rgbFgB contain
                          the foreground color
     bool      bgRgb;     if set, rgbGbR, rgbBgG, and rgbBgB contain
                          the background color


     acaExpand Decoding Examples
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

     AnsiCmd (enum acAttr) color-attribute bit fields:
     0x000000FF  index for foreground color
                 ......00-......0F  16  4-bit color attributes
                 ......10-......E7  216 8-bit color attributes
                 ......E8-......FF  24  greyscale color attributes
                 ......00-......FC  232 RGB color attributes
     0x0000FF00  index for background color
                 ....00..-....0F..  16  4-bit color attributes
                 ....10..-....E7..  216 8-bit color attributes
                 ....E8..-....FF..  24  greyscale color attributes
                 ....00..-....FC..  232 RGB color attributes
     0x00FF0000  text modifier flags
                 ..00....   plain text (no modifiers)
                 ..01....   bold (intense)
                 ..02....   italic
                 ..04....   underline
                 ..08....   overline
                 ..10....   x-out (strike-through)
                 ..20....   blink
                 ..40....   concealed (invisible)
                 ..80....   reversed fg/bg
     0xFF000000  additional flags
                 01......   clear existing modifiers before setting the new ones
                 02......   use terminal default foreground attribute
                            (foreground index ignored)
                 04......   if set, it indicates that foreground index is the
                            index of a "web-safe" RGB foreground color attribute
                            with a range of: minRGB <= value <= maxRGB
                 08......   use terminal default background attribute
                            (background index ignored)
                 10......   if set, it indicates that background index is the
                            index of a "web-safe" RGB background color attribute
                            with a range of: minRGB <= value <= maxRGB
                 20......   (reserved)
                 40......   (reserved)
                 80......   (reserved as internal placeholder value)
     
     The following shows some examples of how the bitfield is constructed.
     The contruction is performed by creating a logical OR of enum acAttr members;
     or in the case of 8-bit and RGB color attributes by using the 'compose' method
     described above.
     See also the AnsiCmd 'acComposeAttributes' public method.
     
     To specify the terminal default foreground attribute, set the acaFG_DFLT flag.
     The foreground index value will be ignored.
        Fgnd:  xxxx-x01x-xxxx-xxxx-xxxx-xxxx-....-....
     
     To specify the terminal default background attribute, set the acaBG_DFLT flag. 
     The background index value will be ignored.
        Bgnd:  xxx0-1xxx-xxxx-xxxx-....-....-xxxx-xxxx
     
     To specify a 4-bit foreground attribute, _reset_ the acaFG_DFLT and
     acaFG_RGB flags and insert the desired member of enum acAttr in the range:
     acaFG_BLACK through acaFGb_GREY inclusive.
     
     To specify a 4-bit background attribute, _reset_ the acaBG_DFLT and
     acaBG_RGB flags and insert the desired member of enum acAttr in the range:
     acaBG_BLACK through acaBGb_GREY inclusive.
     
     To specify an 8-bit indexed color foreground attribute, initialize the
     foreground index and _reset_ both the acaFG_DFLT and acaFG_RGB flags.
        Fgnd:  xxxx-x00x-xxxx-xxxx-xxxx-xxxx-nnnn-nnnn
     
     To specify an 8-bit indexed color background attribute, initialize the
     background index and _reset_ both the acaBG_DFLT and acaBG_RGB flags.
        Bgnd:  xxx0-0xxx-xxxx-xxxx-nnnn-nnnn-xxxx-xxxx
     
     To specify one of the "web-safe" RGB register combinations, initialize
     the foreground or background index and set the acaFG_RGB or acaBG_RGB 
     flag, respectively. 
        Fgnd:  xxxx-x10x-xxxx-xxxx-xxxx-xxxx-nnnn-nnnn
        Bgnd:  xxx1-0xxx-xxxx-xxxx-nnnn-nnnn-xxxx-xxxx
     
     To set one or more text modifiers, _reset_ the acaCLEAR_MODS flag and
     create a logical OR of the desired attributes. (include existing fg/bg bits.)
     Ex: acAttr fgbg = acAttr(acaFG_BLUE | acaBGb_RED);
         acAttr((fgbg |acaBOLD | acaITALIC | acaUNDERLINE) & ~acaCLEAR_MODS)
        Mods:  xxxx-xxx0-xxxx-x111-xxxx-xxxx-xxxx-xxxx
     
     To reset one or more text modifier, set the acaCLEAR_MODS flag and _set_
     the flag(s) for the modfier(s) to be reset. (include existing fg/bg bits.)
     Ex: acAttr(fgbg | acaITALIC | acaCLEAR_MODS)
        Mods:  xxxx-xxx1-0000-0010-xxxx-xxxx-xxxx-xxxx

     _____________________________________________________________________



Display Formatting Methods
..........................

   ▪ void acClearScreen ( wchar_t fillchar = L' ',
                          acAttr fillattr = acaUSEDFLT );

       Input  : fillchar: (optional, space character ' ' by default)
                          specify a (single-column) character to be written to
                          each character cell of the terminal window
                fillattr: (optional, default: terminal default attribute)
                          color attribute for clearing the terminal window.
                          Note: If a non-default attribute is specified, that will
                                be the current fg/bg attribute on return.
     
       Returns: nothing

     Clear the entire terminal window using the specified fill character and
     color attribute.

     On return, the visible cursor will be at the HOME position (1,1).


   ▪ bool acClearArea ( short row, short col, short height, short width,
                        wchar_t fillchar = L' ',  
                        acAttr fillattr = acaUSEDFLT );
   ▪ bool acClearArea ( WinPos wpOrig, short height, short width,
                        wchar_t fillchar = L' ',  
                        acAttr fillattr = acaUSEDFLT );

       Input  : row     : top row of target area
                col     : left column of target area
                       OR
                wpOrig  : top row and left column of target area
     
                height  : number of rows in target area
                width   : number of columns in target area
                fillchar: (optional, ' ' by default)
                          specify a (single-column) character to be written to
                          each character cell in the target area
                fillattr: (optional, default: terminal default attribute)
                          color attribute for clearing the target area.
                          Note: If a non-default attribute is specified, that will
                                be the current fg/bg attribute on return.
     
       Returns: 'true'  if successful
                'false' if parameter(s) out-of-range

     Clear the specified rectangular area using spaces (default), or using the
     specified fill character.
     *Note acDrawLine:: below for an example invocation.

     Position, height and width of the area are adjusted as necessary to
     remain within the terminal window.
     See also the note in *note cursor offsets:: regarding 1-based vs. 0-based
     cursor positioning.

     Note: On return, the cursor position within the window will be
     indeterminate, so it is caller's responsibility to adjust cursor
     position.


   ▪ short acFormatParagraph ( gString& gsTxt, short maxRows, short maxCols,
                               bool trunc = true, bool hypenbrk = false,
                               short *truncIndex = NULL );
   ▪ short acFormatParagraph ( wchar_t* wTxt, short maxRows, short maxCols,
                               bool trunc = true, bool hypenbrk = false,
                               short *truncIndex = NULL );

       Input  : on entry, contains raw message text and
                on return, contains formatted message text
                gsTxt    : (by reference) a gString Object
                         OR
                wTxt     : a wchar_t string (32-bit characters)
     
                maxRows  : maximum rows for message
                maxCols  : maximum columns on any message row
                trunc    : (optional, 'true' by default)
                           if 'true',  truncate the data if necessary to ensure
                                       that the data do not extend beyond the
                                       specified target area
                           if 'false', format the entire source text array, even
                                       if doing so requires violating the specified
                                       height of the target area (maxRows).
                                       (see also 'truncIndx' parameter)
                hyphenbrk: (optional, 'false' by default)
                           if 'false', automatic line breaks occur after space 
                                       characters only.
                                        ASCII space   (U+0020)
                                        CJK space     (U+3000)
                                        CJK comma     (U+3001) (see notes)
                                        CJK full stop (U+3002) (see notes)
                           if 'true',  in addition to the space ' ' characters,
                                       enable line break at:
                                        ASCII hyphen    '-' (U+002D)
                                        Unicode &mdash; '—' (U+2014)
                                        Unicode &ndash; '–' (U+2013)
                                        Unicode &minus; '−' (U+2212)
                truncIndx: (optional, null pointer by default)
                            -- referenced _only_ when the 'trunc' flag is reset
                            if specified, points to a variable to receive the
                            index at which the data _would_have_been_ truncted to
                            fit the specified height of the target area if the
                            'trunc' flag had been set.
                            a) A positive value indicates that the data have not
                               been truncated, AND that the data extend beyond the
                               the specified target area.
                            b) A negative value indicates that it was not necessary
                               to truncate the data i.e. the data fit entirely
                               within the target area.
     
       Returns: number of text rows in formatted paragraph

     Reformat the provided text to fit within the specified dimensions.

       1) Remove all newlines.
       2) Perform word wrap to limit width of each row of the paragraph.
       3) If necessary, truncate the text to limit height of the paragraph.
          (but see the 'trunc' and 'truncIndx' parameters)

     This method is used internally by the ACWin-class objects when writing
     text in the window and when creating dialogs within the window, but may
     be used freely when sizing text for display.

     Both single-width and CJK double-width (two column) characters are
     handled by the this method.
     Note: “CJK” indicates the Chinese, Japanese, Korean (and historically,
     Vietnamese) character sets.

     Notes on automatic word wrap:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

       1. Line breaks occur _after_ the space character at the end of a token,
          (word). This means that the line is broken by placing the newline
          _after_ the identified space character.
          Note: Currently the ASCII space character (20h) and the two-column
          CJK space (U+3000) are the only whitespace characters recognized.

          Special Case: In every-day use, CJK text seldom contains any spaces
          at all within a sentence, or even between sentences. Two-column
          punctuation is designed to provide a visual spacing effect. For this
          reason, we have made the design decision to process the following
          CJK ideographs as whitespace:
                  '、' comma U+3001 and '。' full stop U+3002

          Caution: Tab characters ('\t') _are not_ recognized as whitespace
          characters because they are effectively variable width characters.
          Don't use them!

          Optionally, the ASCII hyphen and the Unicode hyphen-like characters
          can be treated as if they were whitespace for purposes of
          calculating where to break a line. See the 'hyphenbrk' parameter.

       2. When reformatting the data, it is possible that the text will be
          pushed beyond the specified number of rows. In this case, we have
          two options:
            a. Truncate the text after the last specified row is filled.
            b. Alert the caller about the number of rows actually required.
               Optionally, we can indicate the index at which the text would
               have been truncated so that caller can manually truncate the
               text if desired. (see the 'truncIndx' parameter)

       3. It is possible that a single token (word) will be longer than the
          width of the target area. Handling this (unlikely) scenario
          complicates the line-break algorithm, but could come into play; for
          instance: filespecs, URLs, or German words. :-)
          Filespecs and URLs should be parsed using specialized formatting
          methods. Long words, especially hyphenated words can be a problem.
          This method can optionally break after hyphens (see the 'hyphenbrk'
          parameter).

       4. Notes on automatic hyphenation at mid-word line breaks:
          Technically, hyphens should be placed between syllables, but that
          would require a full dictionary of the target language.
          “Can open... worms everywhere.” (Thank you, Chandler Bing.)
             − The hyphen used is the the Unicode &ndash; U+2013. This
               facilitates stripping them from the text if the text is copied
               and pasted elsewhere.
               Note the ideally we would use the so-called “soft hyphen,”
               Unicode &shy; U+00AD, but unfortunately the terminal sees that
               as a zero-width character making it invisible under most
               circumstances.
               Example of stripping characters using the gString utility:
                gString gsTxt(
                     "Dashing–through–the–snow–in–a–one-horse–open–sleigh." );
                short sindx = ZERO ;
                while ( (sindx = gsTxt.find( nDASH, sindx )) >= ZERO )
                   gsTxt.erase( sindx, 1 ) ;
               Yields: "Dashing through the snow in a one-horse open sleigh."
               Note that the ASCII hyphen between 'one' and 'horse' is not
               affected.
               Please *note gString Text Tool:: for more information on the
               gString text internationalization utility.

             − Programmer's Note: If the current character is the same width
               as the hyphen, then the hyphen will be at the right edge of the
               target area. Otherwise there will be a one-column gap at the
               end of the line.
             − Special case: For multi-column characters, it is assumed that
               the characters belong to one of the CJK character sets. (This
               may not be true, but multi-column characters seldom appear in
               Romance languages.
               Therefore, for multi-column characters only, hyphens _are not_
               inserted after mid-token line breaks because there is no way of
               knowing if we are breaking in mid-word or between words unless
               we have access to dictionaries for those languages.
               (Again, “...worms everywhere.”)


   ▪ int acShellOut ( const char* cmd = NULL, bool clrWin = false,
                      acAttr txtAttr = acaUSEDFLT );

       Input  :
          cmd    : (optional, default: null pointer) command to be executed
                   -- any valid command, or sequence of commands may be
                      specified, using the syntax recognized by the shell
                      program.
                   -- if a command is not specified, the default shell
                      program is invoked with a message similar to:
                      "type 'exit' to return."
          clrWin : (optional, default: false)
                   if 'false', the called application begins output at the
                               at the current cursor position
                   if 'true',  clear the terminal window before invoking the
                               command. The command will appear at the top
                               of the terminal window
          txtAttr: (optional, default: acaUSEDFLT)
                   -- if the default value is seen, the the current color
                      attribute settings will be used for both the optional
                      clear of the window and for the text written by the
                      called terminal application.
                   -- if a non-default value is specified, it is used for
                      both clearing the terminal window ('clrWin' parameter)
                      and as the color attributes used by the called program
                      for writing text to the window.
                      Note: Many console utilities override the existing
                            terminal attributes, so the specified attribute
                            may be ignored.
     
       Returns: exit code of child process
          Ideally, this is the exit code of the last utility run in the
          child process, but this cannot be guaranteed.

     Temporarily return control to terminal shell program.
       1. If specified, set foreground/background color attributes.
       2. If specified, clear the terminal window.
       3. Return I/O buffering and input echo settings to the terminal
          defaults.
       4. Any signal handlers which have been set within the application will
          become inactive while the shell program is in control. These signals
          will become available to the shell program and any utilities
          executing within the shell.
          Please *note acCaptureSignals:: for a discussion of available signal
          handlers.
       5. When the application regains control, the previous I/O buffering,
          echo option and color attributes will be restored.

     This method uses the standard library 'system' function which in turn
     uses members of the 'exec' function group to format and execute the
     command and its arguments.
     Refer to standard library docs for details:
         info system
         man 3 system

     See also the ACWin-class *note ShellOut:: method.
     _____________________________________________________________________



Line Drawing Methods
....................

   ▪ WinPos acDrawLine ( const WinPos& wpOrig, short length, bool vertical,
                         LineType lType = ltSINGLE,
                         wchar_t begChar = L'\0', wchar_t endChar = L'\0' );

       Input  : pos     : offset from upper-left corner of terminal window to
                          upper-left corner of box (1-based)
                length  : length of the line: number of number of rows (vertical),
                          or number of columns (horizontal).
                vertical: 'true'  : vertical line
                          'false' : horizontal line
                lType   : (optional, ltSINGLE by default) line style
                           member of enum LineType: either ltSINGLE or ltDUAL
                begChar : (optional, null character by default)
                           specify the beginning endpoint character
                endChar : (optional, null character by default)
                           specify the final endpoint character
     
       Returns: cursor position at the end of the line:
                For horizontal lines, this is the column following the last character.
                For vertical lines, this is the column below the last character.

     Draw a horizontal or vertical line in the terminal window.
     Horizontal lines are drawn left-to-right.
     Vertical lines are drawn top-to-bottom.

     Optionally, the endpoint character(s) may be specified for the beginning
     and/or end of the line. The valid endpoint characters include any of the
     line-drawing glyphs defined in AnsiCmdDef.hpp. Note however, that the
     'begChar' and 'endChar' parameter are not range checked, so the character
     specified (if any), will be written. (Use single-column characters only.)
     If the endpoint(s) are not specified, the line-drawing character is used
     as the endpoint character.

     Example:
        // define the dimensions of the box
        short hgt = 9, wid = 25 ;
        // define the upper left corner of the box object
        WinPos wp( 9, 9 ) ;
        // clear target area using optional color attributes, and note that
        // on return, the specified colors are still active.
        acClearArea ( wp, hgt, wid, L' ', acAttr(acaFGb_CYAN | acaBG_BLUE) ) ;
        // draw the box
        acDrawBox ( wp, hgt, wid, ltDUAL ) ;
        // move downward to start position of first line
        wp.row += 4 ;
        // draw a line the full width of the box with connections on each end
        acDrawLine ( wp, 25, false, ltSINGLE, wcsLTEEdv, wcsRTEEdv ) ;
        // move to the top center of the box
        wp = { 9, 21 } ;
        // draw a line that connects with the box at the top and terminates
        // with a line-intersection character
        wp = acDrawLine ( wp, 5, true, ltSINGLE, wcsTTEEdh, wcsINSECT ) ;
        // draw a line from below the intersect character to the bottom
        // of the box, and which terminates with a connector character
        acDrawLine ( wp, 4, true, ltSINGLE, NULLCHAR, wcsBTEEdh ) ;
     
             ╔═══════════╤═══════════╗
             ║           │           ║
             ║           │           ║
             ║           │           ║
             ╟───────────┼───────────╢
             ║           │           ║
             ║           │           ║
             ║           │           ║
             ╚═══════════╧═══════════╝


   ▪ WinPos acDrawBox ( WinPos pos, short height, short width,
                        LineType lType = ltSINGLE, const char *text = NULL );

       Input  : pos   : offset from upper-left corner of terminal window to
                        upper-left corner of box (1-based)
                height: number of rows for box
                width : number of columns for box
                lType : (optional, ltSINGLE by default) line style
                        member of enum LineType: either ltSINGLE or ltDUAL
                text  : (optional, null pointer by default)
                        If specified, text to be written to interior of box.
     
       Returns: current cursor position within the box

     Draw a box in the terminal window and optionally write text in the box.

     This is a greatly simplified form of drawing a window. It simply draws a
     rectangle in the terminal window at the specified position and of the
     specified dimensions.
     The box is drawn using the currently active foreground and background
     colors.

     If parameters are out-of-range, the position and dimensions will be
     modified as necessary to fit within the terminal window.

     The position of the visible cursor is returned.
     If the 'text' parameter specifies text data to be written into the box,
     then the cursor will be positioned at the end of the text. Otherwise, the
     cursor will be positioned at the top-left corner of the interior of the
     box.
     *Note acDrawLine:: above for an example invocation.


   ▪ void acEraseBox ( WinPos wpOrig, short height, short width );

       Input  : pos   : offset from upper-left corner of terminal window to
                        upper-left corner of box (1-based)
                height: number of rows for box
                width : number of columns for box
     
       Returns: nothing

     Erase the specified area. This is a companion method to the acDrawBox
     method above. acEraseBox simply calls the low-level method to clear the
     text from the specified area.



     The AC_Box Class
     ................

   ▪ WinPos acBoxDraw ( AC_Box& box, const char* text = NULL );

       Input  : box : (by reference) configuration parameters for the object
                text: (optional, null pointer by default)
                      If specified, text to be written to interior of box.
     
       Returns: coordinates of upper-left corner of text area within the box
                (These coordinates are the one-based offset from the )
                (upper-left corner of the terminal window.           )

     Display the data of an AC_Box object in the terminal window.

       1. Clear the target area.
       2. Draw the box.
       3. Initialize the interior of the box to the specified background
          color.
       4. If specified, write the initial text to the interior of the box.
            a. Text will be written using the foreground and background
               attributes specified for the interior.
            b. Caller is responsible for ensuring that the text fits entirely
               within the interior area, AND that the final cursor position
               also lies within the interior area. Automatic text formatting
               is not performed.
       5. On return, the visible cursor will be positioned at the origin
          (upper-left corner) of the text area _unless_ initial text data were
          specified, in which case the visible cursor will be positioned at
          the end-of-text.
       6. On return, color attributes will have been set to terminal defaults.


     AC_Box Example
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔

     WinPos boxOrigin( 1, 16 ) ;
     short  boxHEIGHT = 11 ;
     short  boxWIDTH  = 48 ;
     LineType lType   = ltSINGLE ;
     aeSeq  borderFg  = aesFGb_GREY ;
     aeSeq  borderBg  = aesBG_BLUE ;
     aeSeq  textFg    = aesFG_BLUE ;
     aeSeq  textBg    = aesBG_CYAN ;
     const char* title = "  Life Is A.. What?!  " ;
     
     AC_Box box( boxOrigin, boxHEIGHT, boxWIDTH, lType, 
                 borderFg, borderBg, textFg, textBg, title ) ;
     acBoxDraw ( box, "\n\n     Life is like a box of chocolates.\n"
                          "     You never know what you're gonna get.\n"
                          "      -- Forrest G." ) ;
     
           ┌───────────┤  Life Is A.. What?!  ├───────────┐
           │                                              │
           │                                              │
           │     Life is like a box of chocolates.        │
           │     You never know what you're gonna get.    │
           │      -- Forrest G.                           │
           │                                              │
           │                                              │
           │                                              │
           │                                              │
           └──────────────────────────────────────────────┘


   ▪ void acBoxErase ( const AC_Box& box );

       Input  : box : (by reference) configuration parameters for the object
       Returns: nothing

     Erase the rectangular area drawn by the acBoxDraw method, above.

     The current color attributes will be used to clear the area.


   ▪ WinPos acBoxClear ( const AC_Box& box );

       Input  : box : (by reference) configuration parameters for the object
       Returns: coordinates of upper-left corner of text area within the box

     Erase the text area of of an AC_Box object.

       1. On return, the foreground/background color attributes are set to the
          colors specified for the interior of the object.
       2. On return, the visible cursor is set to the upper-left corner of the
          text area.

     _____________________________________________________________________



Identify "Special" Keycodes
...........................

   ▪ bool isSpecialKey ( wchar_t& wkey, bool alert = false,
                         EchoOpt *eopt = NULL ) const;

       Input  : wkey : (by reference) keycode to be tested
     
                alert: (optional, 'false' by default) audible alert
                       'true'  execute a terminal beep if keycode under test
                               IS one of the supported soft-echo keycodes, but
                               IS NOT not included in the active soft-echo group.
                       'false' do not execute an audible alert
                eopt : (optional, null pointer by default)
                       If specified, this is a pointer to an alternate soft-echo
                       option to be used for the test.
                          (used internally for special-key verification)
     
       Returns: 'true'  if key is one of the ACTIVE special keys
                'false' if key is not one of the active special keys
                        If the caller's keycode is a Special key that IS NOT a
                        member of the active group. the keycode will be set to
                        the null character (NULLCHAR) on return.

     Determine whether the specified keycode is one of the "special" keys, AND
     whether that keycode is a member of the active soft-echo sub-group.

     The test is performed against the soft-echo option specified by the prior
     terminal setup, (but see the 'eopt' argument).

     The available character-echo options are members of enum EchoOpt.
     Please refer to *note TermConfig Class::, and specifically the
     'echoOption' member variable for terminal setup information.

     Each of the soft-echo options encompasses a subset of the supported
     "special" keycodes.
     Please *note Soft Echo Options:: for a description of the soft-echo
     groups.

     NOTE: This method should not be called when the echo option is not one of
     the soft-echo options, but if it is, it will only result in a harmess
     waste of CPU cycles.


   ▪ bool isCommandKey ( wchar_t& wkey, bool all = false ) const;

       Input  : wkey : (by reference) keycode to be tested
                all  : (optional, 'false' by default)
                       if 'true', include the "special" keycodes as command keycodes*
                       if 'false, "special" keycodes are excluded
     
       Returns: 'true' if keycode is one of the command keycodes, else 'false'

     Determine whether the specified keycode is one of the converted keycodes:
      1) ASCII control codes: Ctrl+A - Ctrl+Z, Ctrl+4, Ctrl+5, Ctrl+6, Ctrl+7.
      2) "GUI" command keys: Alt+A - Alt+Z, Alt+punctuation characters.
      3) Ctrl + navigation keys.
      4) Left Alt + navigation keys
      5) Function keys: wcsF01-fcsF12, wcsSF01-wcsSF12, wcsCF01-wcsCF12

     By default, this test _excludes_ the “special” keycodes. (*note
     isSpecialKey::), however, this method may optionally _include_ the
     “special” keycodes within the command-key group by setting the 'all'
     flag.

          Technical Note: These keycodes have been converted from escape
          sequences or ASCII control codes to graphing characters; however,
          they should not be echoed to the display. They would just look like
          garbage from the user's point of view. If the keycode is not
          associated with an action within the application, it should be
          discarded. See the (protected) normalkeyProc method for additional
          information.

     _____________________________________________________________________



Temporary File Management
.........................

Temporary files are an integral part of any application which needs to
interact with the host system or with other applications. The AnsiCmd library
provides full support for creating and managing temporary files within the
system temporary directory.

Although the AnsiCmd library does not make use of temporary files internally;
most non-trivial applications do. For this reason, management of temporary
files for applications based on the AnsiCmd library is encapsulated here to
provide a clean interface to the compiler's standard library functions for
creating and deleting temporary files.

These methods, in turn, rely on the author's TFMan class which is a
stand-alone class included in, but functionally seperate from the
AnsiCmd/ACWin/ACDlg group.
Please *note TFMan Class:: for a full description of this class and the
associated test utility *note TFMTest Demo App::.

                            ────────────────────

   ▪ bool acCreateTemppath ( const char* prefix = NULL );

       Input  : prefix : (optional, default: null pointer)
                         specify a constant token which will prefix the name of the
                         temporary sub-directory in which temp files will be created.
                         If a prefix is not specified, then the default "ANSICMD_"
                         prefix token is used.
                         Important Note: Use only valid filename characters 
                                         (not "special" chars) for the prefix string
     
       Returns: 'true'  if path/dirname created successfully
                'false' if call to standard library function failed

     Enable support for temporary files:
     Create a unique sub-directory within the system's temp-file directory to
     contain the application's temporary files.

     Internally, this is implemented by creating an instance of the 'TFMan'
     class. The Temp File Manager class encapsulates creation and deletion of
     temporary files. This prevents one of the most common programmer errors,
     namely exiting the application and leaving orphaned temp files for the
     system to clean up. This can be especially important if your temp files
     contain sensitive information.

     The optional 'prefix' parameter is used as the leading substring for the
     filename to be constructed. A unique six-character sequence will be
     appended to this sequence to form the name of the subdirectory.
          Example:
             AnsiCmd *acptr = new AnsiCmd() ;
             acptr->acCreateTemppath ( "MyApp_" ) ;
          will result in a directory name of the form:
             MyApp_rPuyzA
     This name is guaranteed to be unique within the system's temporary
     directory.

     If no prefix is specified, then the default prefix ("ANSICMD_") will be
     used.


   ▪ void acDeleteTemppath ( void );

       Input  : none
       Returns: nothing 

     Disable support for temporary files.
     Delete the sub-directory containing the application's temporary files and
     any files remaining in that subdirectory.

       1) May be called directly by the application layer, or else
       2) Will be called by the AnsiCmd-class destructor.


   ▪ bool acCreateTempfile ( gString& tempPath );

       Input  :
          tmpPath: (by reference) receives the path/filename of the new file
       Returns:
          'true'  if file created successfully
          'false' if library call failed

     Create a unique path/filename for a temporary file, then create the file.
     The file will have been closed and will be empty (will contain no data).

          gString tmpPath ;
          ACWin* win = new ACWin( ... );
          ...
          win->acCreateTempname ( "SAM_" ) ;
          if ( (win->acCreateTempfile ( tmpPath )) )
          {
             ofstream ofs ( tmpPath.ustr(), ofstream::out | ofstream::app ) ;
             if ( (ofs.is_open()) )
             {
                ofs << "Write some data to the temp file." << endl ;
                ofs.close() ;
             }
          }
          // This is optional. If this method is not explicitly called by
          // the application, it will be called by the ACWin/AnsiCmd destructor.
          win->acDeleteTempname () ;


   ▪ bool acDeleteTempfile ( const gString& tempPath );

       Input  :
        tmpPath : full path/filename specification of source
       Returns:
          'true'  if successfully deleted
          'false' if library call failed

     Delete the specified temporary file.

     This method will delete the specified file _ONLY_ if the file resides
     within the temporary subdirectory created by acCreateTemppath.

     _____________________________________________________________________



Communicate With System Clipboard
.................................

   ▪ bool acClipboardEnable ( gString* version = NULL );

       Input  :
          version : (optional, default: null pointer) if specified, 
                     pointer to gString object which receives version 
                     number of the WaylandCB class _and_ if available, 
                     the version number of the wl-clipboard utility.
     
       Returns: 
          'true'  if system clipboard connection established
          'false' if unable to connect: wl-clipboard utilities 
                  not installed or inaccessable, or system error

     Establish communications with the system clipboard.
     It is assumed that the system clipboard is managed by the Wayland
     protocol, which is the case for most modern Linux distributions.

     Create a temporary file in the system temp directory. This file is used
     for communications with the external “wl-clipboard” utilities, “wl-copy”
     and “wl-paste”.
     Please *note AnsiCmd Clipboard Access:: for a discussion of these
     utilities.

     If the wl-clipboard utilities are installed and accessible, establish the
     connection with the system clipboard.

     This is done through a simple handshake sequence which writes a short
     text string to the system clipboard, then reads it back. If the received
     data equal the transmitted data, the connection is verified.

     Technical Note: If the connection was previously established, then the
     call to acClipboardEnable will reset and re-initialize the connection.

     Note on version number report:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     If the optional version number parameter is included in the call, the two
     version-number sub-strings are returned in the gString object, separated
     by a newline character ('\n') as shown:
       "x.y.zz\na.b.c"
     where "x.y.zz" is the WaylandCB version, and "a.b.c" is the reported
     wl-copy/wl-paste version. Example:
       0.0.06\n2.2.1
     If communication with the wl-clipboard utilities cannot be established,
     the version number will be of the form: “0.0.06\nunknown”


   ▪ void acClipboardDisable ( void );

       Input  : none
     
       Returns: nothing

     Terminate the connection to system clipboard.

     1) Delete the temp files used for communication.
     2) Delete the WaylandCB-class object.
     3) Return all resources to the system.

     Technical Note: If the application forgets to call acClipboardDisable on
     exit, the AnsiCmd destructor will release the system resources.


   ▪ bool acClipboardTest ( void );

       Input  : none
     
       Returns: 'true'  if connection verified, else 'false'

     Test the connection with the Wayland clipboard.

     Send a short message to the clipboard, then retrieve the data and compare
     the results.


   ▪ int acClipboardGetText ( gString& gsTxt );

       Input  : gsTxt : (by reference) receives contents of clipboard
     
       Returns: number of characters returned

     Get a copy of the text data on the clipboard.

     Technical Note: If communication with the system (Wayland) clipboard has
     been established (*note acClipboardEnable::), the data are copied from
     the system clipboard to the local clipboard buffer, and a copy is then
     returned to caller.
     If communication with the system clipboard has not been established, the
     data currently in the local clipboard buffer are returned.

          Within a high-level window (ACWin) or dialog (ACDlg) context,
          copy/cut/paste operations are handled by the skForm/skField class.
          *Note AnsiCmd Clipboard Access::, below for more information.


   ▪ int acGetClipboardSetText ( const gString& gsTxt );

       Input  : gsTxt : (by reference) contains data to be written
     
       Returns: number of characters written

     Write the specified text data to the clipboard.

     Technical Note: The data are first written to the local clipboard buffer;
     then, if communication with the system (Wayland) clipboard has been
     previously established, the data are copied to the system clipboard.

          Within a high-level window (ACWin) or dialog (ACDlg) context,
          copy/cut/paste operations are handled by the skForm/skField class.
          *Note AnsiCmd Clipboard Access::, below for more information.


   ▪ int acClipboardCharCnt ( void );

       Input  : none
     
       Returns: number of (wchar_t) characters (including NULLCHAR)
                Note that a value of one(1) indicates an empty string.

     Returns the number of UTF-32 characters currently in the local clipboard
     buffer.

       1. If connected to the system (Wayland) clipboard, return size of
          system clipboard data.
          Note: This operation will refresh the contents of the local
          clipboard buffer.
       2. If NOT connected to the system clipboard, value returned is the
          number of UTF-32 characters stored on the local clipboard.

     Important Note: It can *NEVER* be assumed that one character equals one
     byte.


   ▪ int acClipboardByteCnt ( void );

       Input  : none
     
       Returns: number of data bytes (including NULLCHAR)
                Note that a value of one(1) indicates an empty string.

     Returns the number of UTF-8 bytes of data on the clipboard.

       1. If connected to the system (Wayland) clipboard, return size of
          system clipboard data.
          Note: This operation will refresh the contents of the local
          clipboard buffer.
       2. If NOT connected to the system clipboard, value returned is the
          number of UTF-8 data bytes stored on the local clipboard.

                            ────────────────────

AnsiCmd Clipboard Access
........................

  1. The “clipboard” is an area of system memory which can be used to transfer
     text, images and other data among the active applications and system
     processes, _or_ between segments of a single application.

  2. Under most modern flavors of Linux, the “Wayland Protocol” manages
     communications among the system server and its clients, which includes
     the system clipboard.

  3. While terminal applications are _technically_ able to handle any type of
     data on the clipboard, practically speaking, only text data should be
     transferred between the terminal window and the clipboard.

  4. The AnsiCmd library implements a “_local clipboard_” which performs
     copy-and-paste operations within the application. The local clipboard is
     under the INCLUDE_API conditional compile directive.

  5. The AnsiCmd library is built specifically to avoid third-party tools; and
     therefore _direct_ communication between the library and the _system
     clipboard_ is not provided; however, an _indirect_ communications channel
     to the system clipboard is available, as follows:

       a. The AnsiCmd interface with the system clipboard is is included in
          this package and is under the INCLUDE_WAYLANDCB
          conditional-compilation directive which enables this author's (very
          simple) WaylandCB class.
          Please *note Build Options:: for information on including the
          WaylandCB module in the build.

       b. The WaylandCB class object communicates with the system clipboard
          through the Linux utility package, wl-clipboard. The wl-clipboard
          suite was written by Sergey Bugaev and is available on most Linux
          mirror sites:
             sudo dnf install 'wl-clipboard' or
             sudo apt-get install 'wl-clipboard'
          If the wl-clipboard utility has been installed on the system and its
          component interface modules (wl-copy and wl-paste) are visible on
          the path, then the WaylandCB object may be initialized at any time
          after the AnsiCmd (or ACWin) object has been instantiated.
             AnsiCmd* acptr = new AnsiCmd( ... );
             acptr->acClipboardEnable();

       c. If communication between the system (Wayland) clipboard and the
          AnsiCmd local clipboard has been established, then data may be
          exchanged between the current application and all other processes
          which use the system clipboard.

       d. If wl-clipboard is not installed, or if communication cannot be
          established, then the application will be limited to the local
          clipboard.

     Technical Note: The standalone WaylandCB module
     (*note By the Same Author::) may be compiled directly into the
     application instead. If needed, this would provide the application more
     direct control of the clipboard interface. In that case, to avoid
     resource conflicts, the AnsiCmd instance of the class should should not
     be enabled.
     For full details on the WaylandCB class and the associated test app,
     please visit the author's website.

  6. Clipboard operations Within an skForm object.
     The AnsiCmd methods (*note acClipboardSetText::, etc.) which send data to
     the clipboard and retrieve data from the clipboard are for use outside
     any window (ACWin object) or dialog (ACDlg object).

     Within an ACWin or ACDlg object, data are exchanged with the clipboard
     via protected member methods: ('cbCopy' and 'cbPaste'). Text selection,
     Copy, Cut are Paste operations are initiated using the “special” key
     associated with the operation while a Textbox (ftTB) control has the
     input focus.
          Ctrl+C            wcsCOPY    Copy selected text to clipboard
          Ctrl+X            wcsCUT     Copy selected text, then delete source text
          Ctrl+V            wcsPASTE   Paste text at the IP position
          Ctrl+A            wcsSELECT  Select or deselect all
          Shift+RightArrow  wcsSRIGHT  Select text moving rightward
          Shift+LeftArrow   wcsSLEFT   Select text moving leftward
          Shift+UpArrow     wcsSUP     Select text moving upward
          Shift+DownArrow   wcsSDOWN   Select text moving downward
     Please *note Decoding the Special Keys:: for a complete list of defined
     “special keys”.

     Invoking the “Copy” or “Cut” operation will copy the “selected” text of
     the Textbox field with input focus to the clipboard. Note that selected
     text is _underlined_ within the field.
     The data is first copied to the local (AnsiCmd) clipboard, and then if
     the application has enabled communications with the system clipboard,
     (*note acClipboardEnable::), the data are copied from the local clipboard
     to the system clipboard, where it will be available to all processes of
     the system.

     (If no text within the field has been “selected”, then the Copy/Cut
     command will be ignored.)

     Invoking the “Paste” operation will copy the text stored on the clipboard
     to the IP (insertion point, i.e. the current cursor position) within the
     Textbox field which has the input focus.
     If the application has enabled communications with the system clipboard,
     data is first copied from the system clipboard to the local (AnsiCmd)
     clipboard. Then a copy of the data on the local clipboard is written to
     the target Textbox field.

     If there is “selected” text within the target field the selected text
     will be replaced by the clipboard data. Otherwise the clipboard data will
     be inserted into the existing text (if any) of the field.
     Technical Note: The Paste operation ignores the current state of the
     Insert/Overstrike flag when inserting text.

     (If the field with input focus is not a Textbox field, then the Paste
     command will be ignored.)



File: ansicmd.info,  Node: Development Support,  Next: Coding Example,  Prev: API Methods,  Up: AnsiCmd Class Methods

Development Support
-------------------

   ▪ void ansiTest ( dbgArgs& args );
       Input  : args : (by reference) test to perform and test options
                       major   : specifies the test to perform
                       minor   : specifies test sub-section
                       supp    : specifies sub-test for RGB, etc.
     
       Returns: nothing

     This method is a gateway to the debugging code. If debugging disabled
     (DEBUG_ANSICMD == 0), then a warning message is displayed.

     Perform the specified test of terminal functionality. This functionality
     is divided into different groups. *Note ansiTest_Menu:: method for
     details.


   ▪ void getDataMembers ( acaExpand* ab, locale* lo, short& tr, short& tc,
                           short& fn, bool& fr, bool& ws ) const

       Input  : lo : receives a pointer to current locale structure
                tr : (by reference) receives terminal rows
                tc : (by reference) receives terminal columns
                fn : (by reference) receives current font number
                fr : (by reference) receives the 'full-reset' flag value
                ws : (by reference) receives the 'wide-stream' flag value
     
       Returns: nothing

     Returns a copy of the protected data members of the class.

     Used primarily by the ACWin class to synchronize terminal configuration,
     but may be used by the curious app designer.


     void getConfig ( termConfig& tCfg ) ;

       Input  : tCfg : (by reference) receives configuration data
       Returns: nothing

     For use during development: The terminal-configuration data used by the
     AnsiCmd class are private members; however, during development, it is
     often useful to retrieve a snapshot of the current terminal configuration
     to verify that the terminal is configured as intended.



     void tseReport ( const skForm& skf, const WinPos& wpRpt, uint8_t
     secret_code ) ;

     Although this method is _"technically"_ a public method, it is called
     _ONLY_ by the test method, Test_SoftEcho() (and its callback function) to
     report user input and keycode processing. *



File: ansicmd.info,  Node: Coding Example,  Prev: Development Support,  Up: AnsiCmd Class Methods

Coding Example
--------------

The following example demonstrates application startup including creation of
an AnsiCmd-class object which provides terminal setup and color attribute
control capabilities.

Under C++, the 'main' function does as little as possible.
It simply passes the command-line arguments and terminal environment to the
application class, which returns to 'main' only when it is time to exit.

The application class is unique to each application, allocating data storage
and providing the functionality and user interface needed to complete the
tasks for which it was designed.

The EarthPoints application class is typical of such classes in that it
leverages well-established classes and library functions to do most of the
work of the application. The application class provides coordination among the
various components to produce the desired results. A really good application
will also add something the world has never seen before.

The EarthPoints application does not aim so high. It is simply a vehicle for
development and testing of the AnsiCmd class library, which is itself
interesting, but not particulary innovative. The AnsiCmd library could be
characterized as a nerd's version of binge-watching a Netflix series during a
long, long Covid-19 lockdown while on vacation in Guangxi Province.

     int main ( int argc, char* argv[], char* argenv[] )
     {
        //* For capture and parsing of command-line arguments.*
        //* (includes the application environment variables)  *
        commArgs ca( argc, argv, argenv ) ;

        //* Instantiate the application class *
        EarthPoints *ep = new EarthPoints ( ca ) ;

        //* Save a local copy of the exit code, then invoke *
        //* the EarthPoints destructor. This returns all    *
        //* allocated resources to the system, including    *
        //* the allocated AnsiCmd object.                   *
        xCode xcode = ep->exitCode ;
        delete ep ;

        //* Exit, returning control to the shell.*
        exit ( xcode ) ;

     }  //* End main() *

     //* The EarthPoints constructor gathers the command-line arguments, *
     //* creates an AnsiCmd class object and exercises its functionality.*
     EarthPoints::EarthPoints ( commArgs& ca )
     {
        gString gsOut ;                        // text formatting

        //* Initialize all class data members.*
        this->reset () ;

        //* Parse command-line arguments *
        clArgs userOption = this->GetCommandLineArgs ( ca ) ;

        //* Create the AnsiCmd object and configure terminal settings.*
        //* Note that color attributes are set during initialization. *
        this->ansi = new AnsiCmd ( ca.tConfig ) ;

        //* Exercise the AnsiCmd library functionality. (sample) *
        this->ColorTheEarth () ;

        this->ansi->acFlushStreams () ;     // flush the I/O streams

     }  //* End EarthPoints() *

     //* The EarthPoint destructor releases the statically *
     //* allocated resources back to the system.           *
     EarthPoints::~EarthPoints ( void )
     {
        //* Restore original terminal settings *
        if ( this->ansi != NULL )
           delete ( this->ansi ) ;

     }  //* End ~EarthPoints() *

     //* This method exercises a sample of  *
     //* the AnsiCmd library functionality. *
     void EarthPoints::ColorTheEarth ( void )
     {
        //* Configure the input stream ('stdin') for unbuffered input.*
        this->ansi->acBufferedInput ( false, softEchoA ) ;

        this->ansi->acEraseArea ( aesERASE_WIN ) ; // clear the terminal window

        //* The title will be displayed using the color attributes *
        //* specified when creating the AnsiCmd object.            *
        //* (If not specified, then this is the terminal defaults.)*
        WinPos wp( 1, 1 ) ;     // cursor position is window origin
        wp = this->ansi->acWrite ( wp, "Welcome to Earth!\n"
                                       "-----------------\n\n" ) ;
        // (wp now contains terminal offset 4;1)

        //* Set color attributes and write some text.*
        this->ansi->acSetFgBg ( aesFGb_BLUE, aesBG_MAGENTA ) ;
        this->ansi->ttyWrite ( "This text is bright blue on a magenta background.\n" ) ;

        this->ansi->acSetMod ( aesUNDERLINE ) ; // set the 'underline' text modifier
        this->ansi->ttyWrite ( "This text uses the existing color attributes,\n"
                               "with the addition of the 'underline' modifier.\n" ) ;

        this->ansi->acSetMod ( aesUNDERLINE_OFF ) ; // reset underline modifier

        short termRows, termCols ;
        gString gs ;
        this->ansi->acGetTermDimensions ( termRows, termCols ) ;
        gs.compose( "Terminal window size is %hd rows by %hd columns.\n",
                    &termRows, &termCols ) ;
        this->ansi->ttyWrite ( gs ) ;

        this->ansi->acSetBg ( aesBG_GREEN ) ; // set a new background color
        this->ansi->ttyWrite ( "  Press Any Key To Exit... " ) ;

        this->ansi->acRead () ;             // wait for user response

        //* Reset color attributes to terminal defaults *
        this->ansi->acReset () ;

        //* Set the cursor position to the saved position,  *
        //* then erase all text from the cursor position to *
        //* the Bottom Of the Window.                       *
        this->ansi->acSetCursor ( wp ) ;
        this->ansi->acEraseArea ( aesERASE_BOW ) ;

        //* Goodbye! *
        this->ansi->acWrite ( wp, "Thanks for visiting Earth.\n"
                                  "Preparing to leave orbit.\n\n" ) ;

        //* Restore all terminal settings to defaults *
        this->ansi->acRestoreTermInfo ( true ) ;

     }   //* ColorTheEarth() *



File: ansicmd.info,  Node: ACWin Class,  Next: Development and Testing,  Prev: AnsiCmd Library,  Up: Top

ACWin Class
***********

The AnsiCmd Window class, ACWin, is a “derived” class based upon the AnsiCmd
class. This means that it includes all the public methods of its parent and
methods which are unique to the new class.

ACWin implements a more sophisticated level of abstraction from the basic
reading and writing of ANSI escape sequences. It defines a “window”, a
bordered rectangular area within the terminal display. The interior of the
window can be used directly to display text data, or may contain various
user-interface constructs (*note skForm Class::), or both direct display and
user interface fields. In addition, “dialogs” (sub-windows)
(*note Dialog sub-Windows::) may be created within the primary window either
to display informational messages or to interact with the user via “control”
objects such as Pushbuttons.

* Menu:

* ACWin Public Methods::         Public methods of the ACWin class
* skForm Class::                 Using the skForm and skField classes
* Dialog sub-Windows::           Configure and invoke sub-windows



File: ansicmd.info,  Node: ACWin Public Methods,  Next: skForm Class,  Up: ACWin Class

ACWin Public Methods
====================

This table lists the public methods of the ACWin class.

 Method Name                         Description
---------------------------------------------------------------------------
─── Window-Oriented Methods ───     ──────────────────────────────────────
 *note ACWin constructor::           Constructors
 *note ACWin destructor::            Destructor
 *note OpenWindow::                  Open the window (make it visible)
 *note CloseWindow::                 Close the window
 *note RefreshWin::                  Redraw the window
 *note HideWin::                     Erase window from display
 *note MoveWin::                     Move window to another position
 *note ClearWin::                    Erase interior of window
 *note ClearRow::                    Erase specified interior row
 *note Write::                       Write directly to window interior
 *note GetCursorPos::                Get cursor position in the window
 *note SetCursorPos::                Set cursor position in the window
 *note SetTitle::                    Specify window title text
 *note SetTextAttr::                 Specify window interior colors
 *note SetBorderAttr::               Specify window border colors
 *note WinInfo::                     Report basic window information
                                     
─── Form-Oriented Methods ─────     ──────────────────────────────────────
 *note EditForm::                    User edit of skForm object
 *note GetForm::                     Get a pointer to skForm object
 *note GetInputFocus::               Get index of field with focus
 *note SetInputFocus::               Set input focus to a field
 *note Focus2NextField::             Move input focus to next field
 *note Focus2PrevField::             Move input focus to prev field
 *note InsertKey::                   Configure the Insert key
 *note isInsertMode::                Report insert/overstrike flag
 *note AlertEnable::                 Enable/disable auditory alert
 *note EstablishCallback::           Specify a callback function
 *note KeycodePush::                 Push a keycode into input stream
                                     
─── Field-Oriented Methods ────     ──────────────────────────────────────
 *note SetFieldText::                Replace text in specified field
 *note GetFieldText::                Get a copy of text in field
 *note SetFieldAttr::                Set color attributes for a field
 *note SetFieldIP::                  Set insertion point and cursor
 *note GetFieldIP::                  Get current insertion point
 *note GetFieldItem::                Report highlighted item
 *note SetFieldState::               Set binary state of field
 *note GetFieldState::               Get binary state of field
 *note SetFieldFlow::                Specify auto word wrap option
 *note SetFieldLabel::               Attach a label to the field
 *note SetFieldOutline::             Draw a border around a field
 *note SetFieldHotkey::              Assign a hotkey to the field
 *note SetFieldHidden::              Set/reset visibility of field
 *note SetReadOnly::                 Set/reset field to read-only
 *note SetFieldData::                Set field text, color and IP
 *note GetFieldData::                Report current field stats
 *note RefreshField::                Redraw text in a field
 *note ClearField::                  Delete text in specified field
 *note ReformatFieldText::           Reformat text to fit field
 *note ScrollFieldText::             Auto scroll for multi-row data
 *note ShiftFieldText::              Block shift for multi-row data
 *note HilightFieldText::            Highlight a segment of text data
                                     
─── Dialog-Oriented Methods ───     ──────────────────────────────────────
 *note QuickDialog::                 Simple Info/Decision dialog
 *note Dialog::                      Full-initialization dialog
 *note Dialog_GetText::              Get data from dialog textbox
 *note Dialog_SetText::              Set data of dialog textbox
 *note Dialog_SetAttr::              Set multi-color attributes
 *note Dialog_GetItem::              Get dialog menu item
 *note Dialog_SetItem::              Set dialog menu selection
 *note Dialog_GetState::             Get state of dialog radiobutton
 *note Dialog_GetStateXOR::          Get state of radiobutton XOR group
 *note Dialog_GetField::             Get pointer to dialog field object
 *note Dialog_Hilite::               Highlight a segment of text data
 *note Dialog_SetFocus::             Set input focus to target field
 *note Dialog_SetReadOnly::          Set/Reset field's read-only flag
 *note Dialog_Scroll::               Adjust control's insertion point
 *note Dialog_Write::                Write text to dialog window
 *note Dialog_Refresh::              Redraw the dialog window
                                     
─────── Utility Methods ───────     ──────────────────────────────────────
 *note FormatParagraph::             Automatic text formatting
 *note ParagraphSize::               Calculate text dimensions
 *note isPrint::                     Test for “graphing” characters
 *note EnableFootnotes::             Enable/disable output of footnotes
 *note Footnote::                    Write message in bottom border
 *note Sidebar::                     Write message in left/right border
 *note DrawBox::                     Draw a rectangle in text area
 *note DrawLine::                    Draw a line in the text area
 *note LaunchDefaultApp::            Invoke an external application
 *note ShellOut::                    Invoke an app in current window
                                     
───── Development Support ─────     ──────────────────────────────────────
 *note GetWinAttributes::            Report color attributes
 *note GetWinConfig::                Report height, width and position
 *note GetFifo::                     Report saved static text
 *note dumpConfig2Log::              Write config data to log
 *note dumpField2Log::               Write skField stats to log
 *note dumpMrp2Log::                 Write MRParse data to log
 *note dumpFifo2Log::                Write BlockFifo data to log
 *note dumpFifoRecord2Log::          Write a single FIFO record to log
 *note Screenshot::                  Take a screenshot of the window

     _____________________________________________________________________


Window-Oriented Methods
-----------------------

   ▪ ACWin ( void );

       Input  : none
     
       Returns: implicitly returns pointer to object

     Default Constructor:
     Create a default window defined as:
         posRow  : offset one row from top of terminal window
         posCol  : centered in the terminal window
         winHgt  : height == eight(8) rows
         winWid  : width == thirty-six(36) columns
         All other parameters use the initialization defaults.

     The default window is rather useless, so the initialization constructor,
     below, is recommended.


   ▪ ACWin ( short posRow, short posCol, short winHeight, short winWidth,
             LineType bdrLine = ltSINGLE, acAttr bdrAttrib = acaATTR_DFLT,
             acAttr txtAttrib = acaATTR_DFLT,
             const char* winTitle = NULL, skForm *formDef = NULL );

       Input  : posRow    : Row    - position of window within the terminal window
                posCol    : Column - position of window within the terminal window
                winHeight : Height of window in rows
                winWidth  : Width of window in columns
                bdrLine   : (optional, member enum LineType, ltSINGLE by default)
                            border style i.e. type of line for border
                            Note: specifying either ltHORIZ OR ltVERT will cause
                            the border to be drawn with spaces only (no line).
                bdrAttrib : (optional, acaATTR_DFLT by default, terminal defaults)
                            border color attributes OR'd value of acAttr bitfields
                txtAttrib : (optional, acaATTR_DFLT by default, terminal defaults)
                            interior color attributes and text modifiers
                            OR'd value of acAttr bitfields
                winTitle  : (optional, null pointer by default)
                            if specified, text for window title displayed in
                            top border
                formDef   : (optional, null pointer by default)
                            an 'skForm' object which specifies the
                            position and dimensions of the input fields
     
       Returns: implicitly returns pointer to object

     Initialization Constructor:
     Four parameters are required: upper-left row, upper-left column, window
     height (rows) and window width (columns).

     Other parameters, if not specified, are set to default values.

     Example Instantiation:
        ACWin *winPtr = new ACWin( 1, 1, 24, 80 );

     Important Note: 'OpenWindow' should be the _first_ ACWin method called
     after instantiation because it completes initialization of the internal
     data; however, all standard AnsiCmd-class methods are available through
     the window object pointer immediately after instantiation.
     For instance: winPtr->acCaptureBreakSignal ( true, cchtIgnore, true );


     Notes:
     ▔▔▔▔▔▔

       a. 'posRow' and 'posCol' specify the absolute (1-based) position of the
          window within the terminal display area. This is referred to as the
          window ‘origin” which is the upper-left corner of the window. If the
          argument specifies a zero value, it will be silently set to one(1).

       b. 'winHeight' and 'winWidth' specify the number of rows and columns,
          respectively defining the dimensions of the window, _including_ the
          border.

       c. 'bdrAttrib' defines the color attributes for the window border, and
          accepts all foreground/background color attributes and text
          modifiers; however, certain text modifiers are not compatible with
          line-drawing data, and are silently disabled.

       d. 'txtAttrib' defines the color attributes for the window interior,
          and accepts all foreground/background color attributes and text
          modifiers.

       e. 'winTitle' specifies an optional title which is centered in the top
          border of the window.
          Example: ┌───────┤ Wolfie's Favorite Chew Toys ├───────┐
          It is recommended that the first and last characters of the title
          text be space characters. This is not enforced, but it allows the
          title text to be offset from the border line glyphs which makes for
          better readability.

       f. Initialization of the default 'skForm' object within the text area
          of the window is described in the next section. Direct
          initialization of the skForm gives full control of the number,
          dimesions and position of the user input fields within the window.
          Please *note skForm Class::, below for more information.

       g. Within the ACWin object the user input stream (stdin) is configured
          for unbuffered input, non-blocking read of input data and uses the
          softEchoA option to filter keyboard input and echo input to the
          display.
          Please *note acBufferedInput:: and *note Soft Echo Options:: for
          more information on configuration of the input stream.


   ▪ ~ACWin ( void );

       Input  : none
     
       Returns: nothing 

     Destructor: Return all allocated resources to the system before exit.

     The destructor is invoked by deleting the ACWin object. This example
     creates the default ACWin object, opens the window, closes the window,
     then deletes the object.
        ACWin *winPtr = new ACWin;
        winPtr->OpenWindow( "Hello World!" );
        winPtr->acRead();  // wait for keypress
        winPtr->CloseWindow();
        delete winPtr;

     If the ACWin object was created as an automatic variable, then the
     destructor is called when the object goes out-of-scope; that is, when the
     execution thread exits the scope in which the object was created.
        void myProgram ( void )
        {
           ACWin acw;
           acw.OpenWindow( "Hello World!" );
           acw.acRead();  // wait for keypress
           acw.CloseWindow();
           return;  // object goes out-of-scope here
        }


   ▪ WinPos OpenWindow ( const char* initText = NULL, short initField = -1 );

       Input  : initText : (optional, null pointer by default)
                           initial text to be written to window
                initField: (optional, -1 by default) [CURRENTLY IGNORED]
                           index of target field for storing 'initText' data
                           Ignored if 'initText' not specified.
     
       Returns: cursor position (offset) i.e. text insertion point
                This is the character cell following the text in 'initText',
                or if no initial text was specified, the upper-left corner.

     Complete the window setup sequence and display the window within the
     terminal display.

     For user input fields of the window's skForm object which have been
     initialized with text data, the text will be displayed.

     On return, the visible cursor will be positioned at the text insertion
     point (IP) of the field which has the input focus.

     Important Note: 'OpenWindow' should be the _first_ ACWin method called
     because it completes initialization of the internal data. If any other
     ACWin method is called before 'OpenWindow', it may cause a reference to
     uninitialized data.
     All standard AnsiCmd-class methods are available through the window
     object pointer immediately after instantiation.


   ▪ void CloseWindow ( bool clear = true, acAttr fillColor = acaUSEDFLT );

       Input  : clear    : (optional, 'true' by default)
                           if 'true',  clear (erase) the display area
                           if 'false', do not clear the display area
                fillColor: (optional, terminal dflt attr by default)
                           color attribute used to erase the window.
     
       Returns: nothing

     Close the window. Relinquish control of the window object.

     By default, the window is erased from the terminal display as part of the
     closing sequence; but the visual display may optionally be retained, even
     though control over the space has been returned to the system. This
     includes returning control of input stream buffering to the system.

     Note that the window object still exists in memory. To release the
     window's resources, invoke the destructor i.e. delete the ACWin object.
       Example: ACWin *winPtr new ACWin ;  ...  delete winPtr ;
     or if the window was created as an automatic variable, the object will be
     deleted when it goes out-of-scope. (*note ACWin destructor::)


   ▪ void RefreshWin ( void );

       Input  : none
     
       Returns: nothing

     Redraw the window to display any changes that have been made, or to
     recover when other data have obscured the the window.
     For instance, call RefreshWin after a previoius call to HideWin.

     The border will be redrawn, the interior of the window will be cleared,
     and the static text (if any) will be written, and the fields of the
     skForm object will be redrawn.


   ▪ void HideWin ( acAttr fillAttr = acaUSEDFLT );

       Input  : fillAttr : (optional, default: terminal default attributes)
                           color attribute used to erase data from window.
     
       Returns: nothing

     Temporarily erase the window from the terminal display.
     All window data are retained but are not visible to the user.

     To make the window visible again, call *note RefreshWin::.


   ▪ void MoveWin ( const WinPos& newPos, const char *newText = NULL );

       Input  : newPos   : (by reference) new row/column position for window origin
                           (upper-left corner of window)
                newText  : (optional, null pointer by default)
                           text to be written to interior of window, beginning at
                           the upper left corner of the window interior.
     
       Returns: 'true'  if success
                'false' window position not updated if specified position 
                        would place any part of the window beyond the edges 
                        of the terminal window.

     Move the window to another position within the terminal display.
     This is simply erasing the window, updating the base position and
     redrawing the window at the new position.

     The author has found this to be a useful way to draw the user's attention
     to some needed action, and of course a moving window could be the basis
     for a customized screen-saver application.


   ▪ WinPos ClearWin ( acAttr newAttr = acaUSEDFLT );

       Input  : newAttr : (optional, acaUSEDFLT by default)
                          new color attributes for text area of window
                          (logical OR of forground and background color)
                          (attributes and text modifiers               )
     
       Returns: Cursor position (text insertion point)
                This is the upper-left corner of the text area (0/0).

     Erase all text from the interior (text area) of the window.

     The text in the skForm object (if any) is retained, but is not redrawn.
     See also *note RefreshWin::.


   ▪ WinPos ClearRow ( short trgRow, acAttr txtAttr = acaUSEDFLT );

       Input  : trgRow  : target row (0-based offset into text area)
                txtAttr : (optional, acaUSEDFLT by default)
                          new color attributes for text area of window
                          (logical OR of forground and background color)
                          (attributes and attribute modifiers          )
     
       Returns: Cursor position (text insertion point)
                This is the left edge of the specified row (trgRow/0).
                Note: If 'trgRow' is out-of-range, window will not be modified.

     Erase text from the specified row of the text area.

     Note: ClearRow does not clear the stored text-field data associated with
     the target row. To clear a single text field within the window, use the
     *note ClearField:: method instead.


   ▪ WinPos Write ( WinPos txtPos, const wchar_t* txtData,
                    acAttr txtAttr = acaUSEDFLT, bool clear = false );
   ▪ WinPos Write ( WinPos txtPos, const gString& txtData,
                    acAttr txtAttr = acaUSEDFLT, bool clear = false );
   ▪ WinPos Write ( WinPos txtPos, const char* txtData,
                    acAttr txtAttr = acaUSEDFLT, bool clear = false );
   ▪ WinPos Write ( WinPos txtPos, wchar_t txtData,
                    acAttr txtAttr = acaUSEDFLT, bool clear = false );

       Input  : txtPos : WinPos-class object indicates the zero-based
                         offset from upper-left corner of window interior
                txt    : text to write in one of the following formats:
                         -- gString object by reference
                         -- wchar_t pointer
                         -- char pointer
                         -- a single wchar_t character
                txtAttr: (optional, existing text attributes by default)
                         text attributes and text modifiers
                clear  : (optional, 'false' by default)
                         if 'false', existing displayed text unmodified
                         if 'true',  erase window interior before write
     
       Returns: current cursor position (window offset)

     Write text to the interior of the window.
     This group of methods writes directly into the window's text area,
     bypassing and obscuring any defined text fields.

     These methods will automatically reformat the text if necessary to ensure
     that the text does not extend into or beyond the window border.
     Please *note acFormatParagraph:: for more information on automatic text
     formatting.

     To write text into one of the input fields within the window,
     *note SetFieldText::.


   ▪ WinPos GetCursorPos ( void );

       Input  : none
     
       Returns: current cursor position (window offset)

     Get the current cursor offset within the window's text area.


   ▪ WinPos SetCursorPos ( const WinPos& wPos );
   ▪ WinPos SetCursorPos ( short rOff, short cOff );

               
       Input  : Cursor position may be specified in either of 2 ways:
                wPos : (by reference) offset from upper-left corner of
                       window's text area (0-based offset)
                    OR
                rOff : row offset
                cOff : column offset
     
       Returns: current cursor position (window offset)

     Set the cursor offset within the window's text area.


   ▪ bool SetTitle ( const char* newTitle, acAttr titAttr = acaUSEDFLT,
                     LineType bdrLine = ltHORIZ );

       Input  : newTitle : text of window title
                           (empty string or null pointer erases title)
                titAttr  : (optional, existing attributes by default)
                           If specified, this is a logical OR of acAttr
                           values specifying the foreground/background
                           color attributes.
                           See the 'acAttr' enumerated type for details.
                bdrLine  : (optional, ltHORIZ i.e. invalid line type
                            by default) If specified, new border style:
                           ltSINGLE or ltDUAL
     
       Returns: 'true'  if success
                'false' if title truncated to fit

     Set the window title.
     Draw the title centered in the top border of the window.


   ▪ void SetTextAttr ( acAttr txtAttr );

       Input  : txtAttr : (acAttr bitfield) a logical OR of forground and
                          background color attributes and attribute modifiers
     
       Returns: nothing

     Set the color attributes and modifiers for the window interior (text
     area).


   ▪ void SetBorderAttr ( acAttr bdrAttr, LineType bdrStyle = ltHORIZ );

       Input  : bdrAttr : (acAttr bitfield) a logical OR of forground and
                          background color attributes and attribute modifiers
                bdrStyle: (optional, ltHORIZ i.e. an invalid value by default)
                          specify the border line style, either ltSINGLE or ltDUAL
     
       Returns: nothing

     Set the color attributes and modifiers for the window border.

     Optionally, the line style of the border may be changed by specifying one
     of the valid border line styles, either ltSINGLE or ltDUAL.


   ▪ void WinInfo ( winInfo& wInfo );

       Input  : wInfo: (by reference) a winInfo-class object to receive the data
     
       Returns: nothing

     Returns a copy of the window's current size, position, attributes and
     other basic information.

     This information is used primarly for development and debugging; however,
     it often may be useful to get a snapshot of the window configuration,
     especially the 'skf' and 'tcfg' structures.

     class winInfo
     {
        public:
        WinPos winBase ;      //* Terminal window offset (1-based)
        short height ;        //* Height of window object (rows)
        short width ;         //* Width of window object (columns)
        short txtRows ;       //* Number of text (interior) rows
        short txtCols ;       //* Number of text (interior) columns
        acAttr bdrAttr ;      //* Color attributes for window border
        acAttr txtAttr ;      //* Color attributes for window interior
        LineType bdrStyle ;   //* Line type for border
        const skForm *skf ;   //* Definition of text fields within the window
        bool  wcbConnect ;    //* Set if connected with Wayland clipboard
        termConfig tcfg ;     //* Terminal configuration data
     } ;

     Note that the current window dimensions and position are not guaranteed
     to be those specified during instantiation. This is because the
     constructor range checks and automatically adjusts these values as
     necessary to fit within the terminal window.



     █████████████████████████████████████████████████████████████████████


Form-Oriented Methods
---------------------

   ▪ wchar_t EditForm ( short& focusFld, short exitField = -1,
                        wchar_t exitChar = NULLCHAR );

       Input  : focusFld : (by reference) receives the index of the field with
                           input focus on return to caller.
                           (initial value ignored)
                exitField: (optional, default: -1) If specified, this is the index 
                           of the ftPB (Pushbutton) control that, when pressed, 
                           will cause the loop to terminate, and a return to caller.
                exitChar : (optional, default: '\0') If specified, when this 
                           character is received, the loop will terminate and 
                           return to caller.
                           Note: If a callback method has been established which 
                           will determine when to return to caller, then 'exitChar'
                           should contain the default value.
     
       Returns: keycode of last key pressed

     Interactively edit the fields defined within the skForm object.

     The skForm class defines an array of user-interface fields within the
     window which can be used to create an interactive user interface within a
     console application.

     Keyboard input is captured, formatted and written into the fields.
     Certain “special keys” are defined for navigating within and among the
     fields. These keycodes are discussed in the chapter on terminal
     configuration.
     Please *note Soft Echo Options:: for more information.

     A technical description of the skForm class and the associated skField
     class as well as a discussion of user interaction with these objects can
     be found at:
     *note skForm Class:: and *note skField Class::.

     There are three ways to exit the user-interface loop:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
       1. When the Pushbutton control specified by 'exitField' is pressed.
          Typically, a window will include an 'Exit', 'Quit', 'Close' or
          similar pushbutton that may be selected by the user to close the
          window. If defined, the index of this Pushbutton may be specified by
          the optional 'exitField' parameter. Then when user selects this
          control, the loop will terminate and control will be returned to
          caller. If 'exitField' contains the default value (-1), then the
          parameter will be ignored.

       2. When the character specified by 'exitChar' is received from the
          user.
          The optional 'exitChar' parameter may be used to specify that when
          the specified keycode is received, the loop will terminate and
          control will be returned to caller. If 'exitChar' contains the
          default value ('\0'), then the parameter will be ignored. This is an
          experimental parameter, and thusfar has not proven to be very
          useful; however, it remains a valid option.

       3. Via a signal from the callback method.
          To directly monitor user activity within the EditForm loop, a
          “_callback_” method may be established at the application level. The
          user interface loop will then invoke the callback method for each
          keystroke entered by the user.
          Please *note EstablishCallback:: for additional information.


   ▪ const skForm* GetForm ( void );

       Input  : nothing
     
       Returns: pointer to the window's skForm object.

     Get a pointer to the window's skForm object.
     Note: This is a 'const' pointer. Contents may not be modified.

     This method is useful when the call to *note EditForm:: has returned,
     because it reports the final contents and states of the skForm control
     array.

     It is also useful during the development process.

     A technical description of the skForm class and the associated skField
     class as well as a discussion of user interaction with these objects can
     be found at:
     *note skForm Class:: and *note skField Class::.


   ▪ short GetInputFocus ( void );

       Input  : none
     
       Returns: index of field with focus

     Returns the index of the field within the skForm object which currently
     has the input focus.
     This value may also be obtained directly if a previous call to GetForm
     has initialized a pointer to the internal skForm-class data.
     *Note GetForm::, for more information.


   ▪ WinPos SetInputFocus ( short fldIndex );

       Input  : fldIndex: index of target text field
                          The specified field becomes the active field.
     
       Returns: index of field with focus

     Set input focus to the specified field, and refresh field contents.
     The cursor is placed on the text insertion point (IP) of the field.

     Note: Read-only fields cannot receive the input focus.


   ▪ WinPos Focus2NextField ( void );

       Input  : none
       Returns: index of field with focus

     Set input focus to the next field, and refresh field contents.
     If already on the last field (index==fCnt-1), wrap around to the first
     field of the array.

     On return, the cursor is positioned in the field with input focus.

     Note: Read-only fields cannot receive the input focus.


   ▪ WinPos Focus2PrevField ( void );

       Input  : none
       Returns: index of field with focus

     Set input focus to the previous field, and refresh field contents.
     If already on the first field (index==zero), wrap around to the last
     field of the array.

     On return, the cursor is positioned in the field with input focus.

     Note: Read-only fields cannot receive the input focus.


   ▪ bool InsertKey ( bool enable, bool initMode, bool styles = false,
                      CurStyle insStyle = istyleDFLT,
                      CurStyle ovrStyle = ostyleDFLT );

       Input  : enable  : 'true'  == enable user access to Insert key
                                     (this is the default)
                          'false' == disable user access to Insert key
                                     (the mode is locked by application)
                initMode: initial input mode
                          'true'  == Insert Mode
                          'false' == Overstrike Mode
                styles  : (optional 'false' by default)
                          Enable or disable automatic change of cursor
                          style when Insert/Overstrike is toggled.
                          'true'  == enable cursor style change
                          'false' == disable cursor style change
                insStyle: (optional, istyleDFLT by default)
                           cursor style for insert mode
                           referenced only when the 'styles' flag is set
                ovrStyle: (optional, ostyleDFLT by default)
                           cursor style for overstrike mode
                           referenced only when the 'styles' flag is set
     
       Returns: 'true' if Insert/Overstrike toggle enabled, else 'false'

     Enable or disable user access to the Insert/Overstrike input mode when
     user is editing a field, and specify the initial mode.

     Insert/Overstrike toggle is active by default, and the initial mode is
     Insert Mode. For some fields, or some kinds of data, however, it is
     useful to set one mode or the other and lock out user access.

     Optionally enable or disable cursor style change when Insert/Overstrike
     mode is toggled. This provides a visual cue to the user whether Insert
     mode or Overstrike mode is active.
     Optionally, the cursor style for each mode may be specified as a member
     of enum CurStyle (excluding csShow and csHide).


   ▪ bool ACWin::isInsertMode ( void );

       Input  : none
     
       Returns: current state of the Insert/Overstrike flag

     Reports the current state of the skForm object's Insert/Overstrike flag.

     If set, Insert Mode:
     A character written to the target field will be inserted at the current
     cursor position, which will push trailing text to the right.

     If reset, Overstrike Mode:
     A character written to the target field will replace (overwrite) the text
     at the current cursor position.

     See also the InsertKey method, above.


   ▪ bool AlertEnable ( bool enable );

       Input  : enable : if 'true',  enable alert
                         if 'false', disable alert
     
       Returns: current state of the alert flag

     Enable/disable auditory alert when user presses an invalid key.

     The auditory alert is specified during instantiation of the ACWin/skForm
     object; however, the alert may be enabled or disabled using this method.
     Please *note skForm Class:: for more information.


   ▪ EstablishCallback ( CUPTR methodname );

       Input  : valid pointer to caller's method of the correct type
                OR NULL pointer to disable existing callback
     
       Returns: nothing

     Establish (or disable) a callback method which gives the application
     layer access to user input so that text fields and other controls in the
     parent window may be dynamically updated.
     The specified method will be called from within the user-input loop of
     the *note EditForm:: method.

     The external method handles situations that the parent window cannot.
     For example:
      - secondary validation of text data.
      - respond in real time to user keyboard input
      - manual update of read-only or hidden controls
      - signal that the window is to be closed

     The following example of specifying a callback function is taken from the
     Test_Menu method in AnsiCmdTest.cpp.

        // static non-member pointer providing the non-member
        // callback function with access to the ACWin object.
        static ACWin* tmwPtr = NULL ;
     
        ACWin *win = new ACWin
              ( winROW, winCOL,          // position (upper-left corner) 
                winHEIGHT, winWIDTH,     // dimensions (height, width)
                ltSINGLE,                // border style
                acaBorder,               // border attributes
                acaInterior,             // interior attributes
                " ACWin MenuBar and Context Menu ", // window title
                skfPtr                   // skForm data template
              ) ;
     
        win->OpenWindow () ;             // make the window visible
        tmwPtr = win ;                   // give callback method access to ACWin object
     
        // Specify the callback function to be 
        // invoked from within the user-input loop.
        win->EstablishCallback ( &tmw_Callback ) ;
     
        win->EditForm ( f, NULLCHAR ) ;  // interact with the user
        win->CloseWindow ( false ) ;     // close the window
     
        tmwPtr = NULL ;                  // reset the external pointer (be safe)
        delete ( win ) ;                 // release the allocated resourses

     The callback function is based on the the following template:
       typedef wchar_t (*CUPTR)( short ctrlIndex, 
                                 wchar_t wkey, bool firstTime );
     The 'ctrlIndex' parameter reports the index of the field which currently
     has the input focus.
     The 'wkey' parameter reports the keycode from the user interface.
     The 'firstTime' flag is set _ONLY_ during the initial call which allow
     the callback function to initialize its internal data.

     The callback function monitors keyboard input and responds to user
     requests which cannot be handled automatically by EditForm.
     For example, if the user “presses” a Pushbutton or sets/resets a
     Radiobutton, the associated action is performed.

     The most obvious of the callback actions is responding to the Pushbutton
     control which closes the window and returns control to the terminal
     window shell program. In this example, the Exit pushbutton is selected by
     the user, either by:
      1) moving the input focus to that pushbutton and pressing
         the 'Enter' (or 'Space') key, or
      2) Pressing the "hotkey" associated with the control, which
         which in this case is ALT+X.
     Note that EditForm automatically interprets the “hotkeys” associated with
     individual controls and moves the input focus to that control. Then the
     Enter key is passed to the callback indicating that that control has been
     “selected”.
     As shown in the example, if the control with focus is the Exit pushbutton
     and if the keycode indicates that the control has been “selected”, then
     the special 'exit' keycode is returned, signalling that EditForm should
     terminate the loop and return control to the application level.

        const short fldPB_MBAR = ZERO ;  // index of pushbutton activating menu bar
        const short fldPB_EXIT = ZERO ;  // index of 'Exit' pushbutton
     
        if ( firstTime )                 // first call
        {
           // initialize static data (if any)
        }
     
        if ( (wkey == wcsENTER) || (wkey == wcsSPACE) )
        {
           if ( ctrlIndex == fldPB_MBAR )
           {
              . . .
              wkey = L'\0' ;             // signal that keycode was handled
           }
           else if ( ctrlIndex == fldPB_EXIT )
              wkey = wcsCTL_4 ;          // signal loop termination
        }
     
        return wkey ;

     The received keycode ('wkey') can be returned as received, or can be
     modified as a signal to the EditForm loop.

     If the operation has been fully handled, the callback will return the
     null character (L'\0').

     If the callback method returns wcsCTL_4, it is the signal that EditForm
     should terminate the loop and return to caller. Note that wcsCTL_4 is the
     ASCII code for the SIGQUIT signal, and will never be transmitted _to_ the
     callback method as the 'wkey' parameter.
                                 ──────────
     Note: A callback template defining an application-class member method is
     under development. This will complement the non-member callback described
     above, and will provide a simpler mechanism for monitoring user activity.
     This requires C++17 support, so we have delayed implementation until the
     community has made the transition.


   ▪ KeycodePush ( wchar_t wKey );

       Input  :
          wKey   : keycode to be placed into the queue
     
       Returns: 
          'true'  if keycode successfully pushed into the input queue
          'false' if input queue is full

     Push a keycode into the input stream.
     All valid wchar_t (wide) keycodes are accepted. The maximum number of
     keycodes which can be pushed into the input stream FIFO queue without an
     intervening read is defined as KEYPUSH_MAX (currently 16).

          Keycode FIFO Queue Development
          ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
          Three additional methods are defined for management of the input
          stream FIFO queue. These are under a conditional compile directive
          and are used only during development.

          Clear (reset) the KecodePush FIFO queue.
          All keycodes in the queue will be discarded. Note that this does not
          affect data in the system key input stream.
           ▪  void KeycodePush_Clear ( void );

          Return the number of keycodes currently in the keycode pushback FIFO
          queue, and optionally, return a copy of the current contents of the
          queue.
           ▪  short KeycodePush_Report ( wchar_t* kfifo = NULL );
              wchar_t fifoCopy[KEYCODE_MAX] ;
              short kpCount = win->KeycodePush_Report ( fifoCopy ) ;

          Extract a keycode from the keycode pushback FIFO queue.
          (If the queue is empty, wait for key input from the keyboard.
           ▪  wchar_t KeycodePush_Pull ( void );

          Please study the keyPushback class for an example of how a FIFO
          queue works. Because this is a very small FIFO, it is implemented
          the easy way, with data shifted each time an item is removed. In a
          more sophisticated implementation, a dual-indexed wrap-around
          sequence would be used to enhance performance.

     █████████████████████████████████████████████████████████████████████


Field-Oriented Methods
----------------------

   ▪ bool SetFieldText ( short fIndx, const gString& srcTxt,
                         bool refresh = true );
   ▪ bool SetFieldText ( short fIndx, const wchar_t* srcTxt,
                         bool refresh = true );
   ▪ bool SetFieldText ( short fIndx, const char* srcTxt,
                         bool refresh = true );

       Input  : fIndx : index of target field within the skForm object
                srcTxt: text to be written to target field
                        Text data may be in the form:
                        1) gString object (by reference)
                        2) pointer to wide (wchar_t) text data
                        3) pointer to UTF-8 (byte-oriented) text data
                refresh : (optional, default: true)
                          if 'true',  refresh the field display
                          if 'false', do not refresh the display
     
       Returns: 'true'  if successful
                'false' if invalid field index specified, or if operation
                        is not supported for target field type

     Replace the current contents of the field with new data.
     The 'ip' (text insertion point) of the field is set to zero, and the
     cursor is set to the field origin.

     Field types for which text data may be modified:
      1) ftTB (Textbox), 2) ftSB Scrollbox, 3) ftPB (Pushbutton)
     Text for other field types is set during instantiation and remains
     static.


   ▪ int GetFieldText ( short fIndx, gString& txtBuf ) const;
   ▪ int GetFieldText ( short fIndx, wchar_t* txtBuf, int maxChars ) const;
   ▪ int GetFieldText ( short fIndx, char* txtBuf, int maxBytes ) const;

       Input  : fIndx   : index of target field within the skForm object
                txtBuf  : (by reference) receives a copy of field text
                       OR pointer to wchar_t buffer
                       OR pointer to char (UTF-8) buffer
                maxChars: for wchar_t target buffer, maximum number of wchar_t 
                          characters to write
                       OR
                maxBytes: for char target buffer, maximum number of UTF-8 
                          bytes to write
     
       Returns: number of characters written to target buffer including null
                terminator (if target is UTF-8 buffer, byte count is returned)
                -- If invalid field index specified, or if operation is not
                   supported for target field type, the target buffer is set
                   to an empty string, and a zero value is returned.
                -- If the text is larger than the target buffer, then text 
                   will be truncated to fit the target.

     Get a copy of the current contents of the target Textbox (ftTB) field.

     IMPORTANT NOTE: Target buffer must be large enough to hold _AT LEAST_
     two(2) wchar_t characters OR five(5) UTF-8 bytes.
     Otherwise, you may as well be working for Microsoft.


   ▪ bool SetFieldAttr ( short fIndx, acAttr txtAttr );

       Input  : fIndx   : index of target field within the skForm object
                txtAttr : (acAttr bitfield) a logical OR of forground and
                          background color attributes and attribute modifiers
                          (note: use of 'underline' modifier not recommended)
     
       Returns: 'true'  if attribute set successfully
                'false' if invalid field index specified

     Set the color attributes and modifiers for the specified text field.
     Refresh the field display using the modified attributes.

     On return, the cursor is positioned in the field with input focus.


   ▪ bool SetFieldAttr ( short fIndx, const acAttr* rowAttr, short rowCnt );

       Input  :
          fIndx  : index of target field (ftMB or ftSB only)
          rowAttr: pointer to an array of acAttr color attributes, one
                   attribute for each text row of the control.
          rowCnt : number of attribute values in the 'rowAttr' array (>zero).
                   (The minimum _practical_ value is two(2).
     
       Returns: 'true'  if attribute set successfully
                'false' if invalid field index specified, or
                        if field type does not support per-row
                        attributes, or if 'rowCnt' out-of-range

     Set the color attributes and modifiers for the specified field.
     The array of attributes will be applied one per text row within the
     field.

     Multi-color attributes apply _only_ to Menus (ftMB) and Scrollbox (ftSB)
     controls. These control types contain data which is not edited, and
     therefore the color specified for each row will remain unchanged until
     the window is closed.

     It is recommended that this method be called AFTER instantiation of the
     ACWin object, but BEFORE the call to OpenWindow. If called after the
     window has been opened, then on return from the call, the application
     should refresh the display explicitly. This will ensure that the changes
     are visible.

     To specify per-row color attributes for controls within an ACDlg
     sub-window, please *note colorConfig::.



   ▪ bool SetFieldIP ( short fIndx, short newIp,
                       bool centered = false, bool refresh = true );

       Input  :
          fIndx   : index of target field
          newIp   : character offset into the text of the field
                    ZERO <= newIp <= text characters
                    where ZERO == field origin and any value at or beyond
                    the number of characters in the array signals that IP
                    should be set to end-of-text.
          centered: (optional, default:false) vertically center
                    the row containing the IP within the field.
          refresh : (optional, default:true) refresh display
                    if 'true'  make changes visible
                    if 'false' do not update display
     
       Returns: 'true'  if successful
                'false' if invalid field index specified

     Set the insertion point (IP) for the field. This will set the cursor
     position over the character at the specified offset.

     Field types supported by this method are:
      1) ftTB (Textbox) 2) ftSB (Scrollbox).
     Insertion point for other field types is managed programatically.

     Scrolling to ensure that new IP position is within visible space:
       1. If target IP is already within visible space no scrolling will
          occur; the cursor will simply be placed over the target character.
       2. If target IP is above visible space, the row containing the cursor
          will be positioned at the top row of the field.
       3. If target IP is below visible space, the row containing the cursor
          will be positioned at the bottom row of the field.
       4. The optional 'centered' parameter will further adjust the position
          of the row containing the target IP so that it will be vertically
          centered within the field.
          Technical Note: The vertical centering option is fully functional;
          however, the implementation requires three(3) display updates rather
          than the one update needed if centering is not specified. (It's
          cute, but it's slow, so be aware!)

     If 'fIndx' references the field which has input focus, the visible cursor
     will also be updated by default, but see the 'refresh' parameter.

     Special case: If 'newIp' is greater that the number of characters in the
     field, IP will be set to end-of-text (referencing the null terminator).

     Example
     ▔▔▔▔▔▔▔
     For example, if user wants to find a tune in the playlist, she will type
     in a keyword or phrase and the application will locate the token and
     bring that song title into the visible space.

          ╔══════╣  Bryan Adams Play List  ╠══════╗
          ║▶ All for One, All for Love            ║
          ║  Baby When You're Gone                ║
          ║  Back To You                          ║
          ║  Brothers Under The Sun               ║
          ║  Can't Stop This Thing We Started     ║
          ║  Christmas Time                       ║
          ║  Cloud Number Nine                    ║
          ║  Desire                               ║
          ║  Do I Have To Say The Words           ║
          ║ ──────────────────────────────────────║
          ║ Find: Get Off                         ║
          ║ ──────────────────────────────────────║
          ║           PLAY       CANCEL           ║
          ╚═══════════════════════════════════════╝

     (Simplified) Code
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     enum fieldNames : short
     {
        fnLIST = ZERO,
        fnFIND,
        fnPLAY,
        fnCANCEL,
        fnFIELDS
     }
     
     int trgetIp ;
     gString gsList, gsFind ;
     // Get text of "List" field
     win->GetFieldText ( fnLIST, gsList ) ;
     // Get text of "Find" field
     win->GetFieldText ( fnFIND, gsFind ) ;
     // Set focus to list field
     win->SetInputFocus ( fnLIST ) ;
     
     // Search for token in the list
     if ( (targetIp = gsList.find( gsFind.gstr() )) >= ZERO )
     {
        // Set Insertion Point to first character of token
        win->SetFieldIP ( fnLIST, targetIP, true, true ) ;
        // Clear the search text
        win->SetFieldText ( fnFIND, "", true ) ;
     }
     // Display error message
     else
        win->SetFieldText( fnFIND, "Title Not Found", true ) ;

          ╔══════╣  Bryan Adams Play List  ╠══════╗
          ║  Desire                               ║
          ║  Do I Have To Say The Words           ║
          ║  Don't Let Go                         ║
          ║  Everything I Do                      ║
          ║▶ Get Off My Back                      ║
          ║  Have You Ever Really Loved A Woman   ║
          ║  Heaven                               ║
          ║  Here I Am                            ║
          ║  I Finally Found Someone              ║
          ║ ──────────────────────────────────────║
          ║ Find:                                 ║
          ║ ──────────────────────────────────────║
          ║           PLAY       CANCEL           ║
          ╚═══════════════════════════════════════╝

     For a more complex example, see 'gotoLine' method of the
     *note AcEdit Demo App::.


   ▪ int GetFieldIP ( short fIndx );
       Input  : fIndx   : index of target field
     
       Returns: current character offset into the text of the field
                (if invalid field index specified, zero will be returned)

     Get the current insertion point (IP) for the specified field.

     Note that although this method returns the IP value for all control
     types, this value will be meaningful _only_ for Textbox (ftTB) fields,
     and possibly Scrollbox (ftSB) fields. For other types of controls IP and
     cursor position are not meaningful.
     For controls with “selectable items” i.e. menus (ftMB) and Scrollbox
     (ftSB) controls, refer to the GetFieldItem below, or to the skField-class
     *note getItem:: method.


   ▪ bool GetFieldItem ( short fIndx, short& itemIndex,
                         wchar_t& itemHotkey, gString* itemText = NULL );

       Input  :
          fIndx     : index of target control
          itemIndex : (by reference) receives (0-based) index of item which 
                      is referenced by the IP
          itemHotkey: (by reference) receives the "hotkey" character (if any) 
                      for that item. 
                      If no hotkey indicator found, '?' is returned.
          itemText  : (optional, default: null pointer)
                      If specified, this is a pointer to a gString object 
                      which will receive the text of the target item.
     
       Returns:
          'true'  if successful
          'false' if invalid field index or target is of unsupported 
                  control type
                  'itemIndex' will be set to -1 and
                  'itemHotkey' will be set to '?', and
                  'itemText' if specified, will be set to an empty string.

     For Menus (ftMB) and Scrollbox controls (ftSB), retrieve the index of the
     "item" (row) containing the insertion point ('ip'). Generally, this is
     the currently hightlighted item or the item which was highlighted when
     the control lost focus. The “hotkey” character for the item (if any) is
     also extracted from the item text.

     This method will typically be called from the application's callback
     function after the item-selection signal (Enter key) is received;
     however, a prior item selection is not necessary. It is also useful after
     return from the *note EditForm:: method.

     This method calls the low level (but still public) skField-class getItem
     method. This low-level method is intended primarily for use by
     dialog-oriented callback functions, and is somewhat more difficult to
     use. The GetFieldItem method makes the operation somewhat less painful.
     Please *note skField Public Methods:: for more information.


   ▪ bool SetFieldState ( short fIndx, bool state, bool refresh = false );
       Input  : fIndx   : index of target field within the skForm object
                state   : if 'true',  set field state
                          if 'false', reset field state
                refresh : (optional, 'false' by default)
                          if 'true',  refresh the field display
                          if 'false', do not refresh the field
     
       Returns: current state of the field

     Set the "state" of a binary field.
     Currently, this applies only to Radiobuttons (type==ftRB).

     When the binary state is 'set', the indicator character is displayed
     between the delimiters:
        [♦] Allow your internet provider to sell your personal info.
     When the state is 'reset', the indicator character is replaced by a space
     character.
        [ ] Allow your internet provider to sell your personal info.


   ▪ bool GetFieldState ( short fIndx, short* xorMember = NULL );
       Input  :
          fIndx    : index of target field within the skForm object
          xorMember: (optional, default: null pointer) for XOR groups only
                     if specifed, the referenced variable receives the index
                     of the control whose 'set' flag is 'true.
     
       Returns:
          current state of 'state' flag for field referenced by 'fIndx'

     Get the current "state" of a binary field.
     Currently, this applies only to Radiobuttons (type==ftRB).

     XOR Groups:
     ▔▔▔▔▔▔▔▔▔▔▔

     For radiobutton XOR groups, the binary state for only one member of the
     group can be “set” i.e. ‘true’. If 'fIndx' references a member of an XOR
     group, _and_ if the 'xorMember' pointer is non-null, then the variable
     referenced by 'xorMember' receives the index of the group member whose
     flag is “set”.
        — If the control referenced by 'fIndx' is not a Radiobutton or is not
          a member of an XOR group, then 'xorMember' is ignored.
        — Note that in the (unlikely) case where no member of the XOR group
          has its flag set, 'xorMember' will receive the 'fIndx' value.


   ▪ void SetFieldFlow ( short fIndx, FloType fType, bool refresh = false );

       Input  : fIndx   : index of target text field
                fType   : member of enum FloType
                refresh : (optional, 'false' by default)
                          if 'true',  immediately reformat field text
                                      and update the display
                          if 'false', text is reformatted, as needed but
                                      display is not updated
     
       Returns: 'true'  if flow option set successfully
                'false' if invalid field index specified or if target field
                        is a single-row field or invalid 'fType'

     Set the text-flow type and optionally reformat the existing text.
     Note that this option applies only to multi-row text fields. Text of
     single-row fields is always truncated at the edge of the field (see
     flowShift option).

     The available text-flow options are specified by enum FloType and are:
       a. floToken – Automatic text wrap by token. A “token” is a sequence of
          characters delimited by whitespace or in certain cases, also by
          punctuation.
          In general, the application should format the text in the 'txt'
          member as desired; however, if necessary, the text will be
          automatically reformatted to fit within the field.
          To do this, any existing newline characters ('\n') in the source
          text are removed, and the text data are reformated to fit within the
          specified height and width of the field. If lines of text must be
          wrapped to keep them within the boundaries of the field, then line
          breaks will be inserted _after_ the last whitespace character that
          fits on the line. Whitespace characters are defined as one of the
          following:
             ASCII Space (U+0020)
             CJKSPACE    (U+3000)
             CJKCOMMA    (U+3001)
             CJKSTOP     (U+3002)
       b. floHyphen – Same as 'floToken' above, with the addition of the
          following hyphen-like characters being recognized as whitespace.
             ASCII Minus (U+002D)
             uMINUS      (U+2212) HTML &minus;
             nDASH       (U+2013) HTML &ndash;
             mDASH       (U+2014) HTML &mdash;
             sDASH       (U+00AD) HTML &shy;
       c. floChar – Automatic text wrap by character.
          This is the brain-damaged form of inserting line breaks, in that the
          breaks are inserted after the last _character_ that will fit on the
          line. Although this is not pretty, it is faster than scanning for
          whitespace, and is useful if you are not sure whether each text row
          will fit the available space.
          Note that if the text has been preformatted to fit within the field,
          then this option will not alter formatting of the output.
       d. floShift – This option disables word wrap. Instead, each text row
          that is too wide to fit in the field will be truncated for display
          to avoid violating the field boundaries. Note that the source text
          itself is not altered; only the _displayed_ data are affected.
          This is what might be described as “text-editor mode.” The data are
          shifted both vertically and horizontally as the user scrolls through
          the data. This is in contrast to the 'floToken' formatting described
          above in that 'floToken' data are only scrolled vertically.
       e. floDflt – This option is used as a placeholder for optional call
          parameters, and is interpreted to mean that the existing word-wrap
          option is not to be modified.

     For more information on auto-formatting please refer to
     *note acFormatParagraph::
     or the gString-class method, *note formatParagraph::.


   ▪ bool SetFieldLabel ( short fIndx, const char* labText,
                          acAttr labAttr = acaUSEDFLT, bool center = false );
       Input  :
          fIndx   : index of target field 
          labText : display text, optionally including a "hotkey" character. 
                    A hotkey is specified using the CARET character ('^') 
                    followed by the ASCII character which indicates the 
                    keycode to be used as a hotkey. (see examples) 
          labAttr : (optional, default: text attributes of parent window) 
                    color attributes for label text. 
          center  : (optional, 'false' by default) horizontal offset 
                    if set, center the label horizontally in the row above 
                            the field 
                    if reset, label is positioned one row above and in 
                            the same column as the left edge of the field 
     
       Returns: 'true' if label successfully written, else 'false'

     Assign a label, with or without embedded hotkey, to the specified field.

        • Labels may be assigned only to Textbox (ftTB) and Scrollbox (ftSB)
          controls.
        • Labels are incompatible with Menubox controls (FldType ftMB).
          *note SetFieldHotkey:: for setting hotkeys for menu controls.
        • This method may not be used for Pushbuttons and Radiobuttons.
          This is because for Pushbutton (ftPB) and Radiobutton (ftRB)
          controls, the label (and optional hotkey) are integrated into the
          control definition.
        • Label length: 1 <= length <= labelLEN. This is the storage capacity
          expressed as the maximum number of _characters_ (currently 64) for a
          label. Text will be truncated if necessary to fit the storage array.
        • Label width (columns): Text will be truncated if necessary to avoid
          violation of window border.
        • The range of valid hotkeys is: wcsALT_A <= hotkey <= wcsALT_RB. This
          corresponds to ASCII A-Z, a-z, and most punctuation characters.
          The specified hotkey should be unique within the window.
        • The label is positioned one row above the target field with the
          horizontal offset determined by the 'center' parameter.
          If the position conflicts with another object in the window, the
          display data may be corrupted. You have been warned!
        • Example of a label containing a hotkey specification:
             "Gra^pefruit"
          where the caret preceeds 'p', indicating that the hotkey is the
          ALT+p key combination which is assigned to the wcsALT_P keycode
          constant.
        • Technical Notes:
             ◦ Label may not extend into the window border.
             ◦ Label may not be an empty string.
             ◦ Label may not contain newline characters. If it does, they will
               be silently removed.
             ◦ If label includes a hotkey, it must be one of the defined valid
               hotkeys. The specified hotkey must be unique to the window. No
               other control may be assigned the same hotkey.
             ◦ It is the application's responsibility to ensure that the label
               does not violate the space reserved for any other item. A
               programatic test for such a violation would just be too
               expensive.
             ◦ If the target field is to have BOTH a border and a label, then
               call the *note SetFieldOutline:: method instead.

     The following is a screenshot of a window demonstrating both field labels
     and field outlines. This test window may be found in the Test_Form method
     in AnsiCmdTest.cpp.

           ┌──────┤  Window Formatted With "skForm" ├─────┐
           │   Animals(ALT+A)   Vegetables(ALT+V)         │
           │                                              │
           │ Tab among fields. Edit the fields as desired.│
           │ "Hotkeys" == ALT key + underlined character. │
           │ ┌Multi-row Field───────────────────────────┐ │
           │ │Edit keys are: Left, Right, Home, End,    │ │
           │ │Tab, Shift+Tab, PageUp, PageDown, plus    │ │
           │ │Backspace, Delete and Insert.             │ │
           │ └──────────────────────────────────────────┘ │
           │ ┌Empty Field─────────┐┌TiengViet Field─────┐ │
           │ │                    ││Gặp tôi ở Sai Gon.  │ │
           │ └────────────────────┘└────────────────────┘ │
           │ ┌Zhongwen Field────────────────────────────┐ │
           │ │这他妈的并不像看起来那么容易。            │ │
           │ └──────────────────────────────────────────┘ │
           │  [◆] Blue Border       [ ] Alt. Interior     │
           │  [ ] Yellow Border      Alternate Outlines   │
           │  [ ] Green Border      [◆] Ins/Ovr Key       │
           │     ╔══════Scrolling - View Only════════╗    │
           │     ║ There once was a man from Kirkuk, ║    │
           │     ║ Known far and wide for his luck,  ║    │
           │     ║ Till while jogging one day,       ║    │
           │     ╚═══════════════════════════════════╝    │
           │           ╔══════════════════════╗           │
           │           ║ EXIT - 出口 - Salida ║           │
           │           ╚══════════════════════╝           │
           └──────────────────────────────────────────────┘

     Note that the pretty colors and text underlining are not supported in the
     Texinfo document. Please see the HTML documents to view the window in all
     its glory. :-)



   ▪ bool SetFieldOutline ( short fIndx, LineType lType, acAttr lnAttr );

       Input  : fIndx   : index of target field
                          if 'fIndx' == number of fields defined, then draw an
                          outline around each field.
                lType   : (optional, ltSINGLE by default) line style
                           member of enum LineType: ltSINGLE or ltDUAL
                lnAttr  : (optional, acaUSEDFLT by default)
                          If specified, color attributes to be used.
                          If not specified, stored text attributes used.
     
       Returns: 'true'  if successful
                'false' if invalid field index or insufficient space 
                        around the target field

     Draw an outline around the outside of the specified field within the
     window border. The contents of the field will be refreshed after the
     border is drawn.

     The target field must have at least one space open on all sides. That is,
     it must not be positioned against the window border, and must not be
     adjacent to any other field.

     This method calculates the position and dimensions for the outline and
     then calls the *note DrawBox:: method described elsewhere in this
     document.

     Note: Potential incursion into the border is range checked; however,
     potential incursion into other fields _is not_ tested. Beware!

     For Textbox (ftTB) and Scrollbox (ftSB) controls, a label may optionally
     be assigned to the field. This label will be positioned in the upper
     border of the field outline.
     Please *note SetFieldLabel:: for additional information.

     Example
     ▔▔▔▔▔▔▔

        ┌───────────────────┤ Outline Demo ├────────────────────┐
        │┌─ Oscar Wilde ───────────────────────────────────────┐│
        ││▒▒▒▒Be yourself; everyone else is already taken.▒▒▒▒▒││
        │└─────────────────────────────────────────────────────┘│
        │                                                       │
        │┌─────────────────── Old Uncle Ben ───────────────────┐│
        ││With great power comes great responsibility.▒▒▒▒▒▒▒▒▒││
        │└─────────────────────────────────────────────────────┘│
        │                                                       │
        │ ╔══════ Quiet Garden ══════╗                          │
        │ ║                          ║                          │
        │ ║ In my quiet garden       ║                          │
        │ ║ The fish are so polite   ║                          │
        │ ║ They seldom speak        ║                          │
        │ ║ To interrupt my reverie. ║                          │
        │ ║              马伦 — 2013 ║                          │
        │ ╚══════════════════════════╝                          │
        │                     ╔══════════╗                      │
        │                     ║   EXIT   ║                      │
        │                     ╚══════════╝                      │
        └───────────────────────────────────────────────────────┘


   ▪ bool SetFieldHotkey ( short fIndx, wchar_t hotKey );
       Input  : fIndx   : index of target field within the skForm object 
                hotKey  : hotkey character 
     
       Returns: 'true' if hotkey set successfully 
                'false' if invalid control index, unsupported control type, 
                        specified keycode is not one of the valid hotkey 
                        characters, target control's hotkey was previously set 

     Set the "hotkey" for the specified control. A hotkey is a character used
     to move the input focus to the associated control.
        – The range of valid hotkeys is: wcsALT_A <= hotkey <= wcsALT_RB.
          This corresponds to the 'ALT' key plus ASCII A-Z, a-z, and most
          punctuation characters.
        – The majority of CONTROL+ A-Z characters are also available as
          hotkeys.

          Technical Note: A conditional compile directive controls whether
          these keycodes when received, will be automatically converted to the
          equivalent ALT+n keycode. See the private isHotkey method for
          details.

          When this conversion is enabled, if user presses one of the CTL+n
          keys, it will be automatically converted to the equivalent ALT+n
          keycode, and the converted keycode will be used to perform the
          action specified for that hotkey.
          For example: If the hotkey ALT+B is assigned to a Pushbutton control
          via the text of the control:
             “   ^BACKUP   ”,
          then the control would be displayed with the 'B' underlined.
             ▒▒▒BACKUP▒▒▒
                ▔
          The user may then select the control using either ALT+B (wcsALT_B)
          or CTL+B (wcsCTL_B) which will have been converted to wcsALT_B.

          When this conversion is disabled, then CTL+B and ALT+B are seen as
          different hotkeys.

          Certain Control+n keycodes are reserved as specific command keys.
          For example, the 'wcsCTL_C', 'wcsCTL_X', 'wcsCTL_V' are reserved for
          “Copy”, “Cut” and “Paste” respectively.
          Please *note ASCII Control Codes:: for a further information.
        – The function keys may also be used as hotkeys:
          wcsF01 <= hotkey <= wcsCF12
        – The specified hotkey should be unique within the window.

     Please *note test A:: which describes these keycodes in further detail.
     Refer also to the source code for the private methods isHotkey and
     isFunky which define the full range of available hotkeys.

     Note that the standard method for hotkey specification is to embed the
     hotkey character in the control label so that the user has a visual cue,
     (*note SetFieldLabel::).
     Menubox controls (ftMB) do not have labels. For this reason, if a hotkey
     is desired for a menu control, it must be set during skField
     instantiation (*note skForm Class::), OR via this method after ACWin
     instantiation.

     This method may also be used to set the hotkey for some other types of
     controls (ftTB, ftSB), but this is not recommended because there would be
     no visible cue to assist the user.

     Note that for Pushbutton and Radiobutton controls, the label (and
     therefore the hotkey, if any) are embedded in the control itself; and
     therefore this method may not be used to set the hotkey for those control
     types. Note also that if a hotkey has been previously specified for the
     target control, it will not be overwritten by this method.


   ▪ bool SetFieldHidden ( short fIndx, bool hidden,
                           bool readOnly, bool refresh );
       Input  : 
          fIndx    : index of target field within the skForm object
          hidden   ; if 'true',  field will become invisible when the window
                                 is refreshed
                     if 'false', field will become visible when refreshed
          readOnly : if 'true',  field cannot receive input focus
                     if 'false', field can receive input focus
          refresh  : if 'true',  if 'hidden' is set, refresh the entire
                                    window interior
                                 if 'hidden' is reset, refresh only the
                                    target field
                     if 'false', display is not updated
     
       Returns: 'true'  if operation successful
                'false' if operation fails (invalid field index)

     Set the visible/hidden state of the target control and optionally refresh
     the display.

     Except for menu controls, all controls are set as visible by default;
     however, for complex user interface configurations, it is common for some
     inactive controls to be obscured by other controls. Those obscured
     controls become visible and active when needed and then return to the
     background. In this way, a creative use of the 'hidden' and 'read-only'
     flags can make efficient use of the limited space within the terminal
     window.

     As an example, the AcEdit application included in this package defines at
     least fourteen controls which share the application window: a menu group,
     a line-number field, a gutter field, a context menu and five overlapping
     controls for editing text: upper/lower, left/right and full-window
     textbox controls. *Note AcEdit Demo App:: for details.

     Making the changes visible:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
       1. If target control is set as 'hidden', AND if 'refresh' is specified,
          then the entire window interior will be refreshed to restore display
          of any controls or static text that had been obscured by that
          control.
       2. If target control is set visible, AND if 'refresh' is specified,
          then only the target control will be refreshed.


   ▪ bool SetReadOnly ( short fIndx, bool set );

       Input  : fIndx   : index of target field within the skForm object
                set    : if 'true',  set field as read-only
                         if 'false', set field as user-accessible
     
       Returns: current state of the read-only flag

     Enable or disable read-only state for the specified field.

     If a field is set as read-only, then it cannot receive the input focus;
     and therefore cannot be accessed by the user. A field which has been set
     as read-only may or may not be visible (*note SetFieldHidden:: above).


   ▪ bool SetFieldData ( short fIndx, const gString& srcTxt,
                         acAttr txtAttr = acaUSEDFLT,
                         short newIp = ZERO, bool refresh = true );
   ▪ bool SetFieldData ( short fIndx, const wchar_t* srcTxt,
                         acAttr txtAttr = acaUSEDFLT,
                         short newIp = ZERO, bool refresh = true );
   ▪ bool SetFieldData ( short fIndx, const char* srcTxt,
                         acAttr txtAttr = acaUSEDFLT,
                         short newIp = ZERO, bool refresh = true );

       Input  : 
          fIndx   : index of target field within the skForm object
          srcTxt  : (by reference) new text data for field
          txtAttr : (optional, default: acaUSEDFLT, indicating that
                    current attributes should not be modified)
                    acAttr bitfield which is a logical OR of forground and
                    background color attributes and text modifiers
          newIp   : (optional, zero(0) by default)
                    character offset into the text of the field
                    ZERO <= newIp <= text characters
                    where ZERO == field origin and any value at or beyond
                    the number of characters in the array signals that IP
                    should be set to end-of-text.
          refresh : (optional, default:true) refresh display
                    if 'true'  make changes visible
                    if 'false' do not update display
     
       Returns: 'true'  if successful
                'false' if invalid field index specified

     Set or modify the setup data for the specified field.

     The effect is the same as seperately calling three individual methods:
        SetFieldText, SetFieldAttr and SetFieldIP (see above),
     except that this method is more efficient if modifying multiple
     parameters.

     Not all parameters apply equally to all field types. Some combinations of
     field-type and configuration settings are fixed on instantiation, and
     some configuration settings are managed internally by the library
     methods.

          Legend:
            1) "modify" value may be modified under application control.
               (Note that timing may be an issue, so make modifications)
               (only when target field does not have focus.            )
            2) "static" indicates that value is set during
               instantiation and cannot be modified.
            3) "program" value is programatically managed by
               the library.

            Field  Text    Color   Ins.
            Type   Data    Attr    Point
            -----  ------  -----   ------
            ftTB   modify  modify  modify
            ftSB   modify  modify  modify
            ftPB   modify  modify  static
            ftRB   static  modify  static
            ftMB   static  modify  program


   ▪  bool GetFieldData ( short fIndx, skField& skfld ) const;

       Input  : fIndx   : index of target field within the skForm object
                skfld   : (by reference) receives a copy of data members
     
       Returns: 'true'  if successful
                'false' if invalid field index specified

     Get a copy of the current settings for the specified field.
     This method is intended primarily for reporting data during development;
     however, this method may also be useful at the application level for
     analysis of the field data after the *note EditForm:: method has returned
     control to the application.

     NOTE: All data members _including_ protected members are reported.

     Please *note skForm Class:: for details on the structure and usage of the
     skField-class data members.


   ▪ void RefreshField ( short fIndx );

       Input  :
          fIndx: index of target field
                 If fIndx < ZERO || fIndx >= total of fields defined (fCnt),
                 then all fields will be refreshed.
     
       Returns: nothing

     Refresh (erase and redraw) the contents of the specified field, or
     optionally, refresh all fields defined by the skForm object.

     Input focus remains on the currently active field, and cursor is returned
     to insertion point within that field.

     Technical Note:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     There are two ways to refresh the field labels or field outlines in
     addition to the field itself. The first is to set 'fIndx' to 'fCnt' when
     calling this method, so that all fields will be refreshed. The other is
     to call *note RefreshWin:: instead. Either option will redraw the data
     for all fields, while RefreshWin will _also_ redraw any static text in
     the window.


   ▪ void RefreshField ( void );

       Input  : none
     
       Returns: nothing

     Refresh (erase and redraw) the contents of the field which currently has
     input focus.


   ▪ bool ClearField ( short fIndx, bool delText = false,
                       acAttr txtAttr = acaUSEDFLT );

       Input  : 
          fIndx   : index of target field
          delText : (optional, 'false' by default)
                    if 'true',  delete the stored text of the field
                    if 'false', stored text is not modified
          txtAttr : (optional, acaUSEDFLT by default)
                   color attributes for the operation
                   (logical OR of forground and background color)
                   (attributes and text modifiers               )
                    -- If not specified, then current field attributes 
                       will be used.
                   if 'delText' is set: field attributes will be updated
                   if 'delText' is reset: specified attributes will be used
                                for the clear operation, but won't be saved
     
       Returns: 'true'  if target field cleared
                'false' if fIndx out-of-range or if field type of target 
                        is not supported by this operation (data not modified)

     Erase text from the specified text-field display. Optionally, the stored
     text is also deleted.

     This operation applies _ONLY_ to fields with editable text, specifically,
     Textbox fields (field type: ftTB).


   ▪ bool ReformatFieldText ( short fIndx, FloType floType = floDflt );
       Input  :
          fIndx  : index of target field 
          floType: (optional, 'floDflt' by default) member of enum FloType 
                   specify the type of text formatting to be used 
                   If 'floDflt', use the existing formatting option; 
                   otherwise, set the formatting type to the specified 
                   value before reformatting the data. 
      
       Returns: 'true'  if operation is successful 
                'false' if a) invalid field index specified
                           b) target field is not a multi-row textbox
                              field (ftTB) 

     Reformat text of the target field using the specified formatting type.
     All existing newline characters are removed and the data are reformatted
     according to the specified formatting option.
      1) Set new formatting option if specified.
      2) Remove existing formatting (newline characters).
      3) Reformat the data.
      4) Set IP and logical cursor to field origin (upper-left corner).
      5) Refresh the display.

     This operation applies ONLY to multi-row textbox fields (ftTB).
     Note also that target field should not have the input focus when data are
     reformatted because it could easily confuse the poor user.

     See also: *note SetFieldFlow:: which sets the formatting option, and
     reformats the data _only_ if necessary to keep the text within the field
     boundaries.


   ▪ bool ScrollFieldText ( short fIndx, short steps );
       Input  : fIndx   : index of target field
                steps   : number of rows to scroll
     
       Returns: 'true'  if successful scroll
                'false' if already at limit in specified direction

     Scroll upward or downward through multi-row text fields under program
     control.

     This method applies only to multi-row fields Textbox (ftTB) and Scrollbox
     (ftSB), and is ignored for single-row fields and other field types.

     Examples:
     (note how the sign of the shift determines direction of scroll)
     steps ==   1   scroll up by one row (bring rows below into view)
     steps ==  -1   scroll down by one row(bring rows above into view)
     steps ==  hgt  scroll upward by one page
     steps == -hgt  scroll downward by one page
     steps ==   0   scroll to the first row of text
     steps ==  999  scroll to the last row of text. Note that any value
                    at or beyond the last text row will signal a move
                    to end-of-text.
          This _much-too-complex_ example demonstrates the concept:
          // Create and open the window
          ACWin* win = new ACWin ( ... );
           ...
          win->OpenWindow ();
          // Get a pointer to the live data
          const skForm* skfp = win->GetForm ();
          short trg = 4,   // target field
                txtHeight, // text dimensions
                txtWidth ;
          win->ParagraphSize ( skfp->fld[trg].txt, txtHeight, txtWidth );
          // Scroll downward by one row
          win->ScrollFieldText ( trg, 1 );
          // Scroll upward by one row
          win->ScrollFieldText ( trg, -1 );
          // Scroll downward by one page
          win->ScrollFieldText ( trg, skfp->fld[trg].hgt );
          // Scroll upward by on page
          win->ScrollFieldText ( trg, -(skfp->fld[trg].hgt) );
          // Scroll to end-of-text
          win->ScrollFieldText ( trg, txtHeight );
          // Scroll to top-of-text
          win->ScrollFieldText ( trg, 0 );


   ▪ bool ShiftFieldText ( short fIndx, short steps );
       Input  :
          fIndx : index of target field
          steps : direction of shift
                  positive value: shift text upward by one row
                  (toward bottom of text)
                  negative value: shift text downward by one row
                  (toward top of text)
     
       Returns:
          'true'  if successful shift and/or cursor movement
          'false' if already at limit in specified direction
                  or target control does not support text shift
                  or parameterout-of-range

     Perform a vertical block shift of Textbox data, either upward or
     downward.
     This method applies _only_ to multi-row Textbox (ftTB) controls.

     This is similar to the *note ScrollFieldText:: method which steps the
     cursor through the rows of text data, EXCEPT that for ShiftFieldText, the
     cursor position remains constant (continues to reference the same
     character) unless the shift would place it outside of the visible space.

     Technical Note: The ‘steps’ parameter is currently limited to a
     single-row shift: -1 <= steps <= 1. It would be possible to implement a
     multi-row shift; however, the usefulness of that enhancement is not
     currently apparent.


   ▪ bool HilightFieldText ( short fIndx, bool set, int begin, int len,
                             acAttr txtmod = acaUSEDFLT,
                             bool center = false );

       Input  :
          fIndx : index of target field
          set   : if 'true',  highlight the text segment
                  if 'false', clear the highlight
          begin : index of first (leftmost) character to highlight
                  (referenced only when 'set' != 'false')
          len   : number of characters in highlighted segment
                  Note: If segment spans rows, be sure to include
                        the newlines in the count.
                  (referenced only when 'set' != 'false')
          txtmod: (optional, default:acaUSEDFLT)
                  text modifier attribute for highlighted text segment
                  - If specified, text modifier attribute for highlighted
                    text segment. One of the following:
                     acaBOLD      bold-text modifier
                     acaITALIC    italic-text modifier
                     acaUNDERLINE underline-text modifier
                     acaOVERLINE  overline-text modifier
                     acaXOUT      x-out (strikethrough) text modifier
                     acaBLINK     blinking-text modifier
                     acaCONCEAL   concealed (invisible) text
                     acaREVERSE   reversed fgnd/bkgnd (default attribute)
                     Note: OR'd combinations of these modifiers are not allowed.
                  - If not specified, then use previously-specified modifier
                    (if any), else acaREVERSE (fg/bg attributes reversed)
           center: (optional, default: true)
                   if set, assure that highlight is within visible
                           space by adjusting the IP if necessary.
                   if reset, do not adjust IP (highlighted text
                           may or may not  be visible).
     
       Returns:
          'true'  if highlight set/cleared
          'false' a) 'fIndx' references an upsupported control type
                  b) parameter out-of-range

     For Textbox controls only (ftTB), highlight a segment of text using one
     of the text-modifier attributes. If the target field is currently
     visible, the field will be refreshed before return.

     Note that while any combination of the acAttr color attributes may be
     freely OR'd under most circumstances, for this method, exactly one
     text-modifier attribute may be specified as the highlight attribute.

          Example:
          // For a field containg a list of animals, highlight
          // the word 'kangaroo' if found in the text:

          const char* Kanga = "kangaroo" ;
          const int   KangaLen = 8 ;
          const acAttr txtMod = acaREVERSE ;
          gString gsTxt ;
          int hl_begin ;
          win->GetFieldText ( ZOO_TBOX, gsTxt ) ; // get a copy of field text

          // If the target word is present in the text, highlight it
          // by specifying the index of the first character and the
          // number of characters to be highlighted.
          if ( (hl_begin = gsTxt.find( Kanga )) >= ZERO )
          {
             win->HilightFieldText ( ZOO_ANIMALS, true,
                                     hl_begin, KangaLen, txtMod, true ) ;
          }

     For a functional example, please execute the highlighting test:
        ./epts --test=Wh


     Technical Notes:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
       a. Text highlighting uses the same algorithm as the text-selection
          (copy/cut/paste) functionality, and shares some data members with
          that function. For this reason, within a single Textbox field,
          “highlighted” text cannot be present simultaneously with “selected”
          text. Highlighted data and selected data may be present
          simultaneously in _different_ Textbox fields.

          Calling this method will release any “selected” segment in the
          target field. If the user selects text using any of the selection
          keys:
          (Shift + Left/Right/Up/Down or ALT + A), it will release any
          highlight within the field.
          Please *note AnsiCmd Clipboard Access:: for a discussion of text
          selection and moving text to and from the clipboard.

       b. Note that if the highlighted segment is positioned outside the
          visible text area of the field, then by default ('center=true'), the
          text will be scrolled to bring the highlighted segment into view and
          will be (approximately) centered within the visible space.
          If centering is not specified, no scrolling will occur, and the
          highlighted segment may or may not be visible.

       c. The text-selection modifier is acaUNDERLINE, so this modifier is not
          recommended as a highlight modifier because it would tend to confuse
          the poor user.

       d. Using the same text-modifier attribute in both the base color
          attribute for field text _and_ as highlight modifier will cause
          visual anomalies, so please choose a highlight attribute which will
          avoid this conflict. For instance, if the base attribute for the
          field is:
             acAttr(acaFG_BLUE | acaBG_CYAN | acaITALIC) 
          then acaITALIC should not be used as the highlight attribute.

       e. For dialog windows, please *note Dialog_Hilite::.

       f. Text hilighting is currently available only for Textbox (ftTB)
          controls; however, support for highlighted text within Scrollbox
          (ftSB) controls may be added in a future release.


   ▪ bool SetHilightMod ( short fIndx, acAttr txtmod );

       Input  : 
          fIndx : index of target field
          txtmod: text modifier attribute for highlighting text segments
     
       Returns:
          'true'  if highlight attribute initialized
          'false' a) 'fIndx' references an upsupported control type
                  b) parameter out-of-range (default parameter set)

     For Textbox controls only (ftTB), set the text-modifier attribute to be
     used for highlighting text segments within the field.

     Note that no text is actually highlighted by this method; only the
     attribute is initialized.
     Please see the *note HilightFieldText:: method, above for additional
     information.
     See also the skField *note setHiliteMod:: method.



     █████████████████████████████████████████████████████████████████████


Dialog-Oriented Methods
-----------------------

A dialog is a small window within the parent window which provides information
to the user, and optionally asks for a decision or gathers other information
from the user.
Please *note Dialog sub-Windows:: for a more detailed discussion of Dialog
window functionality.

   ▪ bool QuickDialog ( const gString& gsMsg, bool query,
                        const char* title = NULL,
                        short height = 0, short width = 0,
                        short vOff = 0, short hOff = -1,
                        short timeout = 0, bool dbg = false );

       Input  : 
           gsMsg : (by reference) contains the message(s) to be displayed.
                   The text may be a formatted paragraph with each text 
                   row terminated by a newline character (\n), OR may be 
                   unformatted text which will be automatically formatted 
                   to fit within the dimensions as specified below.
           query : 'true'  indicates a decision dialog, and user is 
                           prompted for a yes/no response
                   'false' indicates an information dialog, and user is 
                           prompted to press Enter to exit
           title : (optional, default: null pointer)
                   If specified, this is the dialog title text which will 
                   be centered in the top border of the dialog.
           height: (optional, zero (0) by default) height of dialog window 
                   in rows. A zero value indicates that the dialog is 
                   automatically sized to accomodate the dimensions of the 
                   message text in the 'gsMsg' parameter
           width : (optional, zero (0) by default) width of the dialog 
                   window in columns. A zero value indicates that the dialog 
                   is automatically sized to accomodate the message text 
                   in the 'gsMsg' parameter
           vOff  : (optional, default: 0) vertical offset into the parent 
                   window's text area (0-based)
                   A negative value indicates that the dialog is to be 
                   centered vertically in the parent window.
           hOff  : (optional, default -1) horizontal offset into parent 
                   window's text area (0-based).
                   A negative value indicates that the dialog is to be 
                   centered horizontally in the parent window.
           timeout: (optional, zero by default) automatic timeout of 
                    dialog display in seconds
                    -- By default, the dialog is closed when one of the 
                       pushbutton controls is activated.
                    -- If a positive value (in seconds) is specified, the 
                       dialog will close automatically after the specified 
                       number of seconds has elapsed OR when any keycode is 
                       received, whichever comes first.
           dbg   : (optional, default: false) for debugging only:
                   if reset, refresh the parent window on return 
                   if set,   dialog remains visible on return
     
       Returns: if 'query' flag is set, then the user response is returned:
                   'true'  if control at index zero(0) selected 
                   'false' if control at index one(1) selected 
                if 'query' flag is reset, i.e. dialog has only one control, 
                   then return value is always 'true'.

     Generate a “quick” dialog window within the application's ACWin-class
     window.

     QuickDialog invocations are the simpler of the two dialog types,
     requiring fewer configuration parameters. QuickDialogs are generated in
     either of two modes (see 'query' parameter).
       1) information mode
          An information dialog displays a message and has one pushbutton
          control. The user selects that control to close the dialog and
          return execution to the parent window.
       2) decision mode
          A decision dialog displays a question, and has two pushbutton
          controls which allows the user to make a binary choice:
          (yes/no , save/discard , continue/abort , etc.).

     Working examples of the quick dialog may be found in the AnsiCmd test
     suite.
     Invoke the EarthPoints test application with:
       ./epts --test=Dq
     for a list of quick-dialog tests.

     For a fully-configurable dialog, see the Dialog method below, which
     accepts customized values for all configuration parameters.


   ▪ bool Dialog ( short dlgHgt, short dlgWid, skForm* formDef,
                   const char* sTxt = NULL, const char* tTxt = NULL,
                   short vOff = -1, short hOff = -1,
                   LineType ltype = ltSINGLE,
                   acAttr bdrAttr = acaUSEDFLT,
                   acAttr txtAttr = acaUSEDFLT,
                   short tvOff = 0, short thOff = 1,
                   bool dbg = false );

     Input  :
        dlgHgt: dialog height (rows) 
                A value of zero (0) indicates that the height of the dialog 
                is based on the height (rows) of the PREFORMATTED text it 
                contains, plus necessary padding (typically an additional 
                three(3) rows). 
                The height of the dialog may be calculated as the rows 
                needed by the controls plus the height of the static text 
                data, plus top and bottom borders. Some additional space is 
                recommended to present a pleasing and easily-readable 
                display. 
        dlgWid: dialog width (columns) 
                A value of zero (0) indicates that the width of the dialog 
                is based on the width (columns) of the PREFORMATTED text it 
                contains, plus necessary padding (typically an additional 
                four(4) columns). 
                The width of the dialog may be calculated as the columns 
                needed by the widest row of controls, or the width of the 
                static text, whichever is greatest, plus the right and left 
                borders. Some additional space is recommended to present 
                a pleasing and easily-readable display. 
        formDef:pointer to user-interface control definitions (skForm object) 
                -- At least one of the defined controls MUST BE a Pushbutton 
                   control; otherwise it is an unrecoverable error. 
                -- Certain member values are overridden by the values in 
                   the skForm object of the parent window. 
                -- Invalid or out-of-range members will be silently 
                   corrected to maintain dialog integrity. 
                -- See note below regarding data modified before return 
                   to caller. 
        sTxt  : static text written to be written to dialog interior 
                (a null pointer or an empty string indicates that there is 
                 no static message) 
        tTxt  : dialog title, if specified, will be written centered in the top 
                border of the dialog.
                (a null pointer or an empty string indicates that 
                 the dialog will have no title)
        vOff  : vertical offset (0-based) in rows from top of parent window 
                (optional, default: -1) A value of -1 specifies that 
                dialog is centered vertically in the parent window. 
        hOff  : horizontal offset (0-based) in columns, from left edge of 
                parent window. 
                (optional, default: -1) A value of -1 specifies that 
                dialog is centered horizontally in the parent window. 
        ltype : border style (optional, default: ltSINGLE) 
                Member of enum LineType (ltSINGLE or ltDUAL) 
        battr : border color attributes 
                (optional, default: color attributes are taken from those 
                of the parent window. 
        tattr : text (dialog interior) color attributes 
                (optional, default: color attributes are taken from those 
                of the parent window. 
        tvOff : static text position, vertical offset 
                (optional, default: 0, top row of dialog interior) 
        thOff : static text position. horizontal offset 
                (optional, default: 1, inset one column from left edge of dialog)
        callbk: (optional, default: null pointer) pointer to a non-member callback 
                function. (See typedef CUPTR for details.)
                If specified, this function will be called by the EditDialog method
                each time the user presses a key.
        dbg   : (optional, false by default) for debugging only: 
                if reset, refresh the parent window on return 
                if set,   dialog remains visible for analysis
      
     Returns:
        index of control with focus when dialog is closed 
        (this is the same value contained in formDef->fi) 
     
        The structure referenced by 'formDef' may have been updated 
        to contain additional information: 
          a) Text controls (ftTB): The text of the field may have been 
              modified by user.  The data may be retrieved directly from
              the skField object.
          b) Radiobutton controls (ftRB): The 'set' flag which indicates 
             the binary state of the control (set or reset) may have changed.
             This flag may be read directly from the skField object.
          c) Context Menu controls (ftMB): If a menu item has been selected, 
             a call to the skField-class getItem() method will return the item.
          d) Scrollbox controls (ftSB): If a scrollbox item has been selected, 
             a call to the skField-class getItem() method will return the item.
     
        If the formDef object as received has been malformed, certain 
        parameters will have been corrected if possible; or if corrections 
        are not possible: 
          a) formDef will be ignored, 
          b) a warning will be displayed, and 
          c) a minus one (-1) will be returned. 

     Generate a dialog window within the application ACWin window. The
     dimensions, position and color attributes are specified directly, while
     the dialog's controls are defined by passing a pointer to a
     fully-initialized skForm-class object. The referenced skForm object is
     updated in response to user interaction, so that when the dialog is
     closed, caller may interpret any changes the user has made to the
     controls' status. (see notes below)

     Note that verification of all parameters is performed by this method, and
     adjustments will be made to the position and dimensions of the dialog if
     necessary to make the dialog fit within the parent window. In addition,
     the display text, and the position of the controls will be adjusted if
     necessary to fit within the dialog. Keep in mind however, that it is
     impractical to test for all varieties of foolishness, such as overlapping
     controls, so construct dialogs with care.

     Working examples of the full-initialization dialog may be found in the
     AnsiCmd test suite.
     Invoke the EarthPoints test application with:
       ./epts --test=Dd
     for a list of dialog tests.

     Please *note Dialog sub-Windows:: for a more detailed discussion of
     Dialog window functionality.
                            ────────────────────


          ┌─────────────────────────────────────────────────────────────┐
          │ The following group of methods is intended specifically     │
          │ for use by callback functions, and are active only when a   │
          │ dialog window is currently open.                            │
          │ The methods of this group are used to access the dialog's   │
          │ internal data structures in response to user input.         │
          │ Please *note Dialog Callback:: for additional information.  │
          └─────────────────────────────────────────────────────────────┘

   ▪ bool Dialog_GetText ( short ctrlIndx, gString& txtData );

       Input  :
          ctrlIndx : index of target control within the dialog
          txtData  : (by reference) receives a copy of the Textbox text
     
       Returns:
          'true' if a dialog is currently under edit, AND
                 if 'ctrlIndx' refrences a control of the correct type
                 for the operation
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For Textbox controls (ftTB) within a dialog, retrieve a copy of current
     text data.


   ▪ bool Dialog_SetText ( short ctrlIndx, const gString& txtData,
                           acAttr color = acaUSEDFLT, bool refresh = true );

       Input  :
          ctrlIndx : index of target control within the dialog
          txtData  : (by reference) text which will replace the current text
          color    : (optional, default: acaUSEDFLT)
                     if specified this is the new color attribute for the
                     control, else control attribute is unchanged
          refresh  : (optional, default: true)
                     if 'true',  refresh the display after update
                     if 'false', display is not refreshed
     
       Returns:
          'true' if a dialog is currently under edit, AND
                 if 'ctrlIndx' refrences a control of the correct type
                 for the operation
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For Textbox (ftTB) and Scrollbox (ftSB) controls only, replace existing
     display text for the control.
     Optionally, set new base color attribute for the control.

     The display is updated by default, but update can be delayed by resetting
     the 'refresh' parameter.


   ▪ bool Dialog_SetAttr ( short ctrlIndx, const acAttr* acaArray,
                           short acaCnt, bool refresh = true );

       Input  :
          ctrlIndx : index of target control within the dialog
          acaArray : pointer to an array of acAttr color attributes, one
                     attribute for each text row of the control.
          acaCnt   : number of attribute values in the 'rowAttr' array (>zero)
                     The minimum _practical_ value is two(2).
          refresh  : (optional, default: true)
                     if 'true',  refresh the display after update
                     if 'false', display is not refreshed
     
       Returns:
          'true' if a dialog is currently under edit, AND
                 if 'ctrlIndx' refrences a control of the correct type
                 for the operation
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     Specify an array of color attributes, one for each item (row) displayed
     in the control. Only certain control types accept multi-color attributes:
        Scrollbox controls (ftSB)
        Multi-row Menus (ftMB)
     Please *note colorConfig:: and *note skField config example:: for details
     on constructing an array of color attributes for use within the target
     control.

     The display is updated by default, but update can be delayed by resetting
     the 'refresh' parameter.


   ▪ bool Dialog_GetItem ( short ctrlIndx, gString& itemText,
                           short& itemNum, bool select = true );

       Input  :
          ctrlIndx : index of target control within the dialog
          itemText : (by reference) receives text of the highlighted line item
          itemNum  : (by reference) receives the (0-based) item number (index)
                     of the highlighted item
          select   : (optional, default: true)
                     if 'true'  return the user 'selected' item (if any)
                                else, return highlighted item
                     if 'false' return the highlighted item
          clear    : (optional, default: false)
                     if 'true'  clear (reset) any current "selection" and
                                refresh the control to erase the selection
                                indicator.
                     if 'false' selection is not modified
     
       Returns:
          'true' if a dialog is currently under edit, AND
                 if 'ctrlIndx' refrences a control of the correct type
                 for the operation
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For Menus and Scrollbox controls within a dialog, return the data for the
     highlighted “item”.

       1. An "item" is the data for a display row within the control.
          Generally, this is the highlighted item i.e. the text under the
          cursor.
          Exception: If the user has “selected” a menu item via the Enter or
          Space keys, then the “selected” item, rather than the highlighted
          item will be returned.

       2. The "item number" is the index of the of the row containing the
          item.
            a. The optional 'select' parameter specifies whether the
               “selected” item (if any) should be returned or if the
               highlighted item should always be the returned item.
               A "selected" item is an item for which the user has highlighted
               an item and then pressed the Enter or Space key.

       3. The "item text" is the text displayed on that row.
            a. For Menu controls, this is the display text _excluding_ the
               border characters. Any newline character and leading/trailing
               whitespace will also be removed.
               Example: "│Clear Bookmarks  │\n" becomes
                        "Clear Bookmarks"
               If the menu item includes a “hotkey” indicator (caret '^'),
               then the menu text will include the caret:
                        "Clear ^Bookmarks".

            b. For Scrollbox controls, this is the display text _excluding_
               the newline character and any leading/trailing whitespace.
               Example: " The cow in the meadow goes moo.     \n" becomes
                        "The cow in the meadow goes moo."

          Clear Parameter
          ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
          If the 'clear' parameter is set, then before return, the current
          item selection (if any) will be cleared and the associated selection
          indicator, if visible will be removed.
          This is useful if the item selection has already been handled or if
          item selection is unneeded.
          Note that there is a potential timing issue for clearing the 'sitem'
          selection member. If this method is called from within a callback in
          response to selection keystroke (Enter/Space), then the actual
          selection has not yet occurred. In this case, the callback would
          need to signal that the selection keycode has been handled. To do
          this, the callback would return an alternate keycode instead of the
          Enter/Space. Suggestions: return NULLCHAR to indicate that the
          keycode has been handled, or return wcsTAB to move the input focus
          to the next field.
          Please *note Dialog Callback:: for more information on callback
          functions.

          Please refer to the *note getItem:: method in the chapter on skField
          Public Methods for a technical description of 'items' and item
          selection.


   ▪ bool Dialog_SetItem ( short ctrlIndx, short itemNum,
                           bool refresh = true );

       Input  :
          ctrlIndx : index of target control within the dialog
          itemNum  : index (0-based) of the item to be set as selected
                     Note: If valueos out-of-range, then nearest _valid_
                           item will be selected.
          refresh  : (optional, default: true)
                     if 'true'  refresh the display
                     if 'false' display is not updated
     
       Returns:
          'true' if: a) a dialog is currently under edit,
                     b) 'ctrlIndx' refrences a control of the correct type
                        for the operation
                     c) the target control _does not_ have input focus
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For Menus and Scrollbox controls within a dialog: set the "selected item"
     explicitly. This will draw user's attention to the item and indicate the
     current selection. Note that items are zero-based; that is, the first
     item is item zero(0).

     The target control must not have input focus when this method is called.


      ----------------Scrollbox-----------------     Context Menu
     ┌──────────────────────────────────────────┐   ╔════════════╗
     │ There once was a man from Kirkuk,        │   ║Pigs Grunt  ║
     │▷Who was known far and wide for his luck, │━┳━║Birds Fly   ║
     │ Till while jogging one day,              │ ┃ ║Cows Moo    ║
     └──────────────────────────────────────────┘ ┃ ║Goats Bleat ║
                                                  ┃ ╚════════════╝
             Item #1 is "selected":  ━━━━━━━━━━━━━┛

     Within Scrollbox controls, the “selected” item is indicated by an arrow
     at the left edge of the text; while for Menus, the “selected” item is
     displayed in bold/italic font.

     If successful, control is refreshed to visually indicate the selected
     item.

     Note that the Menu selection indicator is not visible in
     the 'info' docs. See the HTML docs for a better representation.



   ▪ bool Dialog_GetState ( short ctrlIndx, bool& rbState );

       Input  :
          ctrlIndx : index of target control within the dialog
          rbState  : (by reference) receives the current state of the control
     
       Returns:
          'true' if a dialog is currently under edit, AND
                 if 'ctrlIndx' refrences a control of the correct type
                 for the operation
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For binary-state controls within a dialog, return the current 'state'
     flag value: 'set' or 'reset'.
     Currently, the binary state flag applies only to Radiobutton controls.


   ▪ bool Dialog_GetStateXOR ( short ctrlIndx, short& rbIndx );

       Input  :
          ctrlIndx : index of target control within the dialog
          rbIndx   : (by reference) receives index of XOR group member
                     whose state flag is currently set
     
       Returns:
          'true' if a dialog is currently under edit, AND
                 if 'ctrlIndx' refrences a control of the correct type
                    for the operation, AND
                 if the target control is a member of an XOR group
                    then 'rbIndx' receives the target index
          else 'false' ('rbIndx' receives 'fCnt')

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For binary-state controls within a dialog which are configured as XOR
     group members, return the index of the control within the group whose
     binary state is 'set'.
     If the target is not a member of an XOR group, then the
     *note Dialog_GetState:: method should be called instead.

     Currently, the binary state flag applies only to Radiobutton controls.


   ▪ bool Dialog_GetField ( short ctrlIndx, const skField*& skfPtr );

       Input  :
          ctrlIndx : index of target control within the dialog
          skfPtr   : (by reference) receives a pointer to _constant_ skField
                     object. Access to all public data members is available.
                     Access to 'const' methods (if any) is also available.
     
       Returns:
          'true'  if a dialog is currently under edit, AND
                  if 'ctrlIndx' refrences a control of the correct type
                  for the operation
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For controls within a dialog, return a pointer to the specified control
     object. This is a const pointer, meaning that the public data may be
     analyzed, but no data within the object may be modified.

     The example below retrieves the dimensions of the control and formats a
     paragraph of text according to the dimensions. The new text is then
     written to the target control.
        gString gs( "Four score and seven years ago"
                    "...shall not perish from the earth." ) ;
        const skField* skfPtr = NULL ;
        if ( (this->win->Dialog_GetField ( fldTXTBOX, skfPtr )) )
        {
           short fldHeight = skfPtr->hgt ;
                 fldWidth  = skfPtr->wid ;
           this->win->FormatParagraph ( gs, fldHeight, fldWidth,
                                        false, false ) ;
           this->Dialog_SetText ( fldTXTBOX, gs,
                                  acAttr(acaFG_BLUE | acaBGb_RED) ) ;
        }


   ▪ Dialog_Hilite ( short ctrlIndx, bool set, int begin, int len,
                     acAttr txtmod = acaREVERSE );

       Input  :
          ctrlIndx : index of target field
          set   : if 'true',  highlight the text segment
                  if 'false', clear the highlight
          begin : index of first (leftmost) character to highlight
                  (referenced only when 'set' != 'false')
          len   : number of characters in highlighted segment
                  Note: If segment spans rows, be sure to include
                        the newlines in the count.
                  (referenced only when 'set' != 'false')
          txtmod: (optional, default:acaUSEDFLT)
                  text modifier attribute for highlighted text segment
                  - If specified, text modifier attribute for highlighted
                    text segment. One of the following:
                     acaBOLD      bold-text modifier
                     acaITALIC    italic-text modifier
                     acaUNDERLINE underline-text modifier
                     acaOVERLINE  overline-text modifier
                     acaXOUT      x-out (strikethrough) text modifier
                     acaBLINK     blinking-text modifier
                     acaCONCEAL   concealed (invisible) text
                     acaREVERSE   reversed fgnd/bkgnd (default)
                     Note: OR'd combinations of these modifiers are not allowed.
                  - If not specified, then use previously-specified modifier
                    (if any), else acaREVERSE (fg/bg attributes reversed)
           center: (optional, default: true)
                   if set, assure that highlight is within visible
                           space by adjusting the IP if necessary.
                   if reset, do not adjust IP
                           (highlighted text may or may not  be visible).
     
       Returns:
          'true'  if highlight set/cleared
          'false' a) 'fIndx' references an upsupported control type
                  b) parameter out-of-range

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For Textbox controls only (ftTB), highlight a segment of text using one
     of the text-modifier attributes. If the target field is currently
     visible, the field will be refreshed before return.

     Note that while any combination of the acAttr color attributes may be
     freely OR'd under most circumstances, for this method, exactly one
     text-modifier attribute may be specified as the highlight attribute.

     Please *note HilightFieldText:: for a techninal description of this
     functionality.


   ▪ bool Dialog_SetFocus ( short ctrlIndx );

       Input  :
          ctrlIndx : index of target control within the dialog
     
       Returns: 
          'true' if a dialog is currently under edit, AND if 'ctrlIndx'
                refrences a control of the correct type for the operation
                AND if the target control is not set as read-only
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For controls within a dialog, set the input focus to the specified
     control.


   ▪ bool Dialog_SetReadOnly ( short ctrlIndx, bool read_only );

       Input  :
          ctrlIndx : index of target control within the dialog
          read_only: if 'true',  set field as read-only
                                 (cannot receive input focus)
                     if 'false', reset the read-only flag
                                 (can receive input focus)
     
       Returns: 
          'true' if a dialog is currently under edit, AND if 'ctrlIndx'
                refrences a control of the correct type for the operation
                AND if the target control does not currently have input focus
          else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For controls within a dialog, set or reset the read-only flag.
     If the read-only flag is set, then control cannot receive the input
     focus.


   ▪ bool Dialog_Scroll ( short ctrlIndx, int& steps,
                          bool head = false, bool tail = false);

       Input  :
          ctrlIndx : index of target control within the dialog
          steps    : (by reference) number of steps to scroll
                     This value is ignored if 'head' or 'tail' flag is set.
                       scroll == 0, no scrolling will occur, but on return,
                                    value will be _current_ item/IP.
                       scroll >  0, scroll forward toward tail of data
                       scroll <  0, scroll backward toward head of data
          head     : (optional, default: false) if specified, move to head
                     of data (overrides value in 'steps')
          tail     : (optional, default: false) if specified, move to tail
                     of data (overrides value in 'steps')
     
       Returns: 
          'true' if a dialog is currently under edit, AND if 'ctrlIndx'
                refrences a control of the correct type for the operation
                 -- On return, 'steps' will contain the currently referenced
                    item number, or for Textbox controls, the IP.
     
          else 'false' ('steps' is not modified)

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     For controls with a visible cursor position: Textbox (ftTB), Scrollbox
     (ftSB) or Context Menus (ftMB) only.
       1. Textbox Controls: Scroll horizontally, right or left, one character
          per step.
       2. Scrollbox Controls:
          Scroll vertically, up or down, one line item per step.
       3. Menu Controls:
          Scroll vertically, up or down, one item per step. Wrap-around will
          not occur. Note that only "context" menus (multi-row, stand-alone
          menus) are supported by this method.

     Scrolling is managed by the control's 'ip' (Insertion Point) member.
     Position of the highlight (Menus or Scrollbox controls) or visible cursor
     (Textbox controls) is calculated based on the value of 'ip'.
     The 'steps' value is range checked to prevent the insertion point from
     overruning the data.

     The 'head' and 'tail' flags override the value in 'steps', and the 'head'
     flag overrides the 'tail' flag.

     Special case: If both 'head' and 'tail' are reset and if 'steps' is set
     to zero, then the current position is reported, but not modified.


   ▪ bool Dialog_Write ( const wchar_t* txt, short yOff, short xOff,
                         bool clear = false, acAttr color = acaUSEDFLT );
   ▪ bool Dialog_Write ( const char* txt, short yOff, short xOff,
                         bool clear = false, acAttr color = acaUSEDFLT );

       Input  :
          txt    : text to be written to dialog interior.
                   Either: wchar_t* or char*
          yOff   : position: offset in rows from top of dialog interior
                   with zero(0) being the top row.
          xOff   : position: offset in columns from left edge of dialog
                   Note that all dialog text is automatically indented by
                   one column from both the left and right borders, so an
                   xOff value of zero will display text starting in column 1.
          clear  : (optional, default: false) clear the target row before
                   writing the data.
          color  : (optional, default: acaUSEDFLT)
                   if specified this is the color attribute used to write
                   the text. Otherwise, text will be written using the
                   dialog's interior attribute.
     
       Returns: 'true' if a dialog is currently under edit
                 else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     Write one line of text to the interior of the dialog.
       a. Text will be truncated if necessary to fit within the available
          space.
       b. Static text may not occupy the same space as a control object. If it
          does, it will be invisible.
       c. Note that the text is written directly to the display.
          Neither the text nor the color attribute are stored.
       d. _CAUTION!_ - Do not overwrite control objects within the dialog!
          Although the text data are truncated if necessary to prevent
          incursion into the dialog border, at this time, programatic testing
          for overwrite of control objects is considered too expensive an
          operation.

          If you are uncertain about positioning of static text data within
          the dialog, it is recommended that a read-only Textbox control be
          defined for display of transitory messages.


   ▪ bool Dialog_Refresh ( bool full = false );

       Input  : full : (optional, default: false)
                       if 'false' redraw the interior of the dialog only
                                  this includes the static text data and
                                  all controls
                       if 'true', redraw the dialog border, then redraw
                                  the dialog interior
     
       Returns: 'true' if a dialog is currently under edit
                 else 'false'

     Note: This method is active _only_ when a dialog (ACDlg object) is open;
     and _only_ if a callback method was specified when dialog was created.

     Refresh (redraw) the dialog. This method may be called from within the
     application-level callback to restore the display in case the dialog has
     been obscured by another operation.

     If the parent window has also been obscured by the operation, _refresh
     the parent window first_, then refresh the dialog window.

     █████████████████████████████████████████████████████████████████████


Utility Methods
---------------

   ▪ short FormatParagraph ( gString& gsTxt, short maxRows, short maxCols,
                             bool trunc = true, bool hypenbrk = false,
                             short *truncIndex = NULL );

     This is a pass-through to the *note acFormatParagraph:: method.


   ▪ void ParagraphSize ( const gString& gs, short& msgHeight, short& msgWidth
     );
   ▪ void ParagraphSize ( const gString& gs, int& msgHeight, int& msgWidth );

       Input  :
          gs        : (by reference) text to be analyzed
          msgHeight : (by reference) receives number of text rows
          msgWidth  : (by reference) receives number of text columns
     
       Returns: nothing

     Calculate the dimensions (height and width) of the specified block of
     text.

     This method can be used to measure the height in rows and width in
     columns for a paragraph of text data. This is useful for determining how
     the text will fit within the window, or the dimensions required for a
     field in which to display the text. Note that the number of text rows is
     determined by the number of newline characters ('\n') found (excluding
     trailing newline, if any).
     Dimensions are calculated as shown in the following example.

       ACWin *win( . . . ) ;
       short txtRows, txtCols ;
     
       gString gsText = 
         "There once was a man from Kirkuk, \n"
         "Who was known far and wide for his luck, \n"
         "Till while jogging one day, \n"
         "he looked the wrong way, \n"
         "Whereupon he was hit by a truck." ;
     
       win->ParagraphSize ( gsText, txtRows, txtCols ) ;
       gString bsOut( "\n\"Text Dimensions are %hd rows by %hd columns.\"\n",
                      &txtRows, &txtCols ) ;
       win->ttyWrite ( bsOut ) ;
     
       Yields:
         "Text Dimensions are 5 rows by 41 columns."

          Programmer's Note: This method is overloaded for pointers to int32_t.
          The author has found that it is too easy to get confused between 32-bit
          text indices and 16-bit window coordinates.


   ▪ bool isPrint ( wchar_t wkey );

       Input  : keycode to be tested
     
       Returns: true if a "graphing" character, else 'false'

     A locale-aware version of the 'std::isprint' function.

     The locale-aware version of 'isprint' takes into account all graphing
     characters of all languages supported by the Unicode standard. This means
     that whatever input language is being used for the application, all
     codepoints of that language will be handled as expected.

     Whitespace Keycodes:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     Canon says that the Space ' ', Enter '\n', Tab '\t' and similar
     codepoints are classed as whitespace rather than graphing characters;
     however, canon is wrong on this issue.
     This method recognizes these as graphing characters simply because when
     written, they cause updates to the display.

     Keycodes reserved by the AnsiCmd library:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     A small range of Unicode codepoints is reserved by the library for
     assignment to decoded ANSI escape sequence, control codes, “conditioned”
     keys and ALT-key combinations.
     These reserved keycodes consist primarily of arrows, geometric shapes,
     and typographic symbols. These keycodes are not integral to any written
     language, and should seldom, if ever be needed in daily user
     interactions.

     The range of keycodes in this group are technically graphing characters
     but have been reassigned by the AnsiCmd library, and will not be reported
     as graphing characters by this method. Most of these are assigned to:
        1) wcsALT_A - wcsALT_RB
        2) wcsCTL_A - wcsCTL_7
        3) wcsF01   - wcsCF12
        4) various "conditioned" keys, cursor-movement keys, etc.
     The exclusion range is defined by the constants RESKEY_MIN and RESKEY_MAX
     which correspond to keycode assignments wcsF01 and wcsALT_RB,
     respectively. Note that not all keycodes within this range are currently
     assigned. Some are reserved for future development.

     Line-drawing characters, bullet characters and similar keycodes defined
     by the AnsiCmd library fall outside the reserved range, and therefore
     _ARE_ reported as graphing characters.

     If any codepoints within the reserved range needs to be displayed within
     a specific project, this should not be a problem so long as the AnsiCmd
     user-interface methods do not see them and try to “interpret” them.

     It may be educational to study the full Unicode character table which can
     be found at: https://www.utf8-chartable.de/


   ▪ bool EnableFootnotes ( bool enable );

       Input  : enable: set   : enable output from the Footnote method.
                        reset : disable output from Footnote method.
     
       Returns: current state of the footnote flag

     Enable or disable output to the window written through the 'Footnote'
     group of methods described below.


   ▪ void Footnote ( const gString& msg, short pause,
                     acAttr color = acaUSEDFLT, bool center = false );
   ▪ void Footnote ( const wchar_t* msg, short pause,
                     acAttr color = acaUSEDFLT, bool center = false );
   ▪ void Footnote ( const char* msg, short pause,
                     acAttr color = acaUSEDFLT, bool center = false );

       Input  :
          msg   : text of message to be written.
                  -- Message will be truncated if necessary to the
                     width of the window minus 4.
                  -- If 'msg' is an empty string, then erase any
                     existing message and restore the border.
          pause : time in tenths-of-a-second to wait before erasing message
                  a value of zero(0) indicates that message is to
                  remain visible on return.
          color : (optional, existing border attributes by default)
                  foreground/background color attributes for message display
          center: (optional, 'false' by default)
                  if 'true',  center the message horizontally
                  if 'false', message is positioned at left edge of the space
     
       Returns: nothing

     Write a message in the lower border of the window. This could be a
     message to the user, or could be a temporary diagnostic message used
     during development. Optionally, wait, a moment, then erase the message,
     (see 'pause' argument).

     For best visual presentation, the first and last characters of the
     message should be spaces, but this is not enforced.

     Pleasse refer to the Test_SoftEcho method or refer to the example output
     in the diagram below.


   ▪ void Sidebar ( const gString& msg, bool left, acAttr color = acaUSEDFLT,
                    short offset = ZERO, bool clear = false ) ;
   ▪ void Sidebar ( const wchar_t* msg, bool left, acAttr color = acaUSEDFLT,
                    short offset = ZERO, bool clear = false );
   ▪ void Sidebar ( const char* msg, bool left, acAttr color = acaUSEDFLT,
                    short offset = ZERO, bool clear = false );

       Input  : 
          msg   : text of message to be written.
                  -- Message will be truncated if necessary to the
                     height of the window minus 4.
                  -- If 'msg' is an empty string, then erase any
                     existing message and restore the border.
          left  : if 'true',  message is displayed in left edge border
                  if 'false', message is displayed in right edge border
          color : (optional, existing border attributes by default)
                  foreground/background color attributes for message display
          offset: (optional, zero by default) Specify the offset
                   (number of rows) from vertically centered position.
                  if  0,  message is vertically centered
                  if <0,  message is offset upward from centered by
                          specified number of rows.
                  if >0,  message is offset downward from centered by
                          specified number of rows.
          clear : (optional, 'false' by default)
                  if 'true',  clear any existing message from the border
                              before writing the new message
                  if 'false', existing messages are unaffected
                              (unless the new message overwrites an old one)
     
       Returns: nothing

     Display a message in the left or right border of the window.
     The Sidebar may have no practical value, but it's fun. :-)

         ┌────────┤  Title  ├──────────┐
         ┴                             │
         H                             │
         i                             ┴
         ┬                             M
         │                             o
         │                             m
         │                             !
         │                             ┬
         │                             │
         │                             │
         └─────┤ Smelly Footnote ├─────┘
     
       ACWin *win = new ACWin ( ... ) ;
       win->SetTitle ( "  Title  " ) ;
       win->Sidebar ( "Hi", true, acaATTR_DFLT, -2) ;
       win->Footnote ( " Smelly Footnote ", 0, acaATTR_DFLT, false ) ;
       win->Sidebar ( "Mom!", false, acAttr(acaFG_GREEN | acaBG_BLUE), 0) ;
     NOTE: A live test is under conditional compile in the Test_Dialog method.

     Technical note on original cursor position.
     Ideally, the cursor position on exit should be the position on
     entry; however, saving the original position via a call to
     acGetCursor() is functional, but UNBEARABLY slow (> 0.5 seconds).
     Instead, before return, the field with focus is refreshed,
     positioning the cursor in that field. There is no guarantee that
     is where the cursor originally was; therefore, it is recommended
     that caller consider explicitly setting cursor position on return.


   ▪ bool DrawBox ( WinPos wpOrig, short height, short width,
                    LineType lType, acAttr bxAttr, bool clear );

       Input  : pos   : offset from upper-left corner of text area to
                        upper-left corner of box (0-based)
                height: number of rows for box
                width : number of columns for box
                lType : (optional, ltSINGLE by default) line style
                        member of enum LineType: (ltSINGLE or ltDUAL)
                bxAttr: (optional, acaUSEDFLT by default)
                        If specified, these are the color attributes used.
                        If not specified, stored text attributes are used.
                clear : (optional, 'false' by default)
                        if 'false', interior of box is cleared using 'bxAttr'
                        if 'true',  interior of box is cleared using the interior
                                    color attributes of the parent window
     
       Returns: 'true'  if box fits within the window text area
                'false' if invalid offset or dimensions specified

     Draw a rectangle within the window's text area.

     The position, dimensions, line style and color attributes may be
     specified. See the example below.

     Note that the minimum dimensions for the rectangle are two rows by two
     columns (2x2). At the minimum dimension, of course there is no space for
     text within the box.


   ▪ WinPos DrawLine ( const WinPos& wpOrig, short length, bool vertical,
                       LineType lType, wchar_t begChar, wchar_t endChar,
                       acAttr lnAttr );

       Input  : pos     : offset from upper-left corner of window (0-based)
                length  : length of the line: number of number of rows
                          (vertical), or number of columns (horizontal).
                vertical: 'true'  : vertical line
                          'false' : horizontal line
                lType   : (optional, ltSINGLE by default) line style
                           member of enum LineType: either ltSINGLE or ltDUAL
                begChar : (optional, null character by default)
                           specify the beginning endpoint character
                endChar : (optional, null character by default)
                           specify the final endpoint character
                lnAttr  : (optional, acaUSEDFLT by default)
                          If specified, these are the color attributes used.
                          If not specified, stored text attributes are used.
     
       Returns: cursor position at the end of the line:
                For horizontal lines, the column following the last character
                (limited at right edge of window)
                For vertical lines, the column below the last character
                (limited at bottom edge of window)

     Draw a horizontal or vertical line within the window's text area.
     — Horizontal lines are drawn left-to-right.
     — Vertical lines are drawn top-to-bottom.

     This is a specialized instance of the AnsiCmd acDrawLine() method. The
     only difference is that the parameters are range checked to fit entirely
     within the window. Note that if an endpoint of the line intersects the
     border of the window, the endpoint will be drawn using the color
     attributes of the border, while the portion of the line within the text
     area of the window will be drawn using the color attributes of the window
     interior, or the attributes specified by the optional 'lnAttr' parameter.

          Note: If the line intersects the window border, the endpoint
          character will be automatically selected to match the intersection
          of the drawn line and the border line style. As a corollary to this
          automatic character selection, avoid positioning the start of a line
          such that it would obscure the window title (if any). Definitions
          for the line-drawing characters may be found in AnsiCmdDef.hpp.


     Line-drawing Examples
     .....................

          ┌───┬────────┤ Line-drawing Tests ├────────╥───┐
          ├───┼──────────────────────────────────────╫───┤
          │   │       ├──────────────────────┤       ║   │
          │   │      ╠════════════════════════╣      ║   │
          ╞═══╪══════════════════════════════════════╬═══╡
          │   │  ┬   ╔════════════════════════╗   ╦  ║   │
          │   │  │   ║ ║ ────────────────── │ ║   ║  ║   │
          │   │  │   ║ ║ ══════════════════ │ ║   ║  ║   │
          │   │  ┴   ╚════════════════════════╝   ╩  ║   │
          └───┴──────────────────────────────────────╨───┘


   ▪ int LaunchDefaultApp ( const char* targFile, bool redirect = true );

       Input  :
          targFile : filespec of file to be processed by the external application
          redirect : (optional, 'true' by default)
                     if 'true',  redirect stdout and stderr to temp files
                     if 'false', allow stdout and stderr to write to the 
                                 terminal window
     
       Returns: 
          the child process ID (an integer value)
          returns minus one (-1) if child process was not created

     Launch the system default application for handling the specified type of
     file.

     Technical Description:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     Launching an external application is done by creating a child process to
     perform the actual launch, while the parent process continues execution
     of the application code. This operation is done via a call to the
     standard library's 'vfork' function.
       a. The 'targFile' parameter:
          This is the filespec for the file to be processed by the external
          application. This may be either a full-path specification or a
          relative path; or if a URL is specified, then that page will be
          opened in the browser.
             /home/sam/Documents/XmasList.html
             ./XmasList.html
             "../../Music/Kansas/Dust In the Wind"
       b. The 'redirect' parameter:
          By default, the displayed startup information (if any) for the child
          process is redirected to temporary files to avoid trashing the
          parent application's display. If desired, the startup information
          will be written to the terminal window (redirect==false); but in
          this case, the application's display data should be saved before
          calling LaunchDefaultApp. (*Note HideWin::).
       c. The 'xdg-open' system utility:
          When called, this utility scans the system's MIME-type (Multipurpose
          Internet Mail Extension) database to determine the user's specified
          default application for processing files of that MIME type. For
          example:
             win->LaunchDefaultApp ( ../Texinfo/ansicmd.html );
          This will invoke the user's default browser to display the specified
          HTML file. If the browser is not open, it will be opened. If the
          browser is already open, a new tab (or a new instance of the
          browser) will be created to display the file. The precise action is
          determined by the settings of the target application.
       d. Redirecting stdin/stderr streams:
          Redirection of a data stream is handled by the standard library's
          'dup2' function. This is somewhat more complex than redirection
          using 'pipes'. See the 'dup2' documentation for details.
       e. See also *note ShellOut::, below, which opens an external
          application in the current terminal window.


   ▪ int ShellOut ( const gString& shellCmd,
                    acAttr textColor = acaUSEDFLT );

       Input  :
          shellCmd : (by reference) invoke the specified shell builtin 
                     command, shell program or console utility program
                     - If an empty string, then invoke a copy of 
                       the 'bash' shell.
                       NOTE: If the default shell IS NOT 'bash', then 
                       'shellCmd' should be used to specify the target 
                       shell program.
          textColor: (optional, default: acaUSE_DFLT)
                     specify an alternate foreground/background
                     color for text data written to stdout.
                     [This parameter is currently ignored.]
     
       Returns: exit code of child process
          Ideally, this is the exit code of the last utility run
          in the child process, but this cannot be guaranteed.

     Go to command shell in the current terminal window.
       1. Save the application window display data.
       2. Clear the terminal window
       3. Put the AnsiCmd engine (including ACWin object) into hibernation
          mode.
       4. Invoke the specified application (if any)
          If no application is specified, invoke 'bash' (or current shell
          program).
          In this case, user will need to type 'exit' to return to
          application.
       5. Wake the AnsiCmd engine from hiberation mode.
       6. Return control of the Input stream to the ACWin object.
       7. Redraw the application window.
          As a side effect, this also restores the color attributes.

     Important Note: This method should be called ONLY from the main
     application window. _AND_ there should be no sub-dialogs open. If invoked
     from a sub-dialog, then the primary window's display data will not be
     properly saved.


     _____________________________________________________________________


Development Support Methods
---------------------------

     ┌────────────────────────────────────────────────────────────────┐
     │ A beginning developer may ask:                                 │
     │ "Why are the debugging routines so fancy?"                     │
     │                                                                │
     │ Answer:                                                        │
     │ Writing the debugging routines is a concrete expression of the │
     │ thought process which informs the overall project development. │
     │            Highly recommended for all developers.              │
     │            (It's almost as important as coffee :)              │
     └────────────────────────────────────────────────────────────────┘


   ▪ void GetWinAttributes ( acaExpand& txtExp, acaExpand& bdrExp );
       Input  :
          txtExp : (by reference) acaExpand object to receive text attributes
          bdrExp : (by reference) acaExpand object to receive border attributes
       Returns: nothing
     Debugging method: Get a copy of the window attributes.


   ▪ WinPos GetWinConfig ( short& height, short& width );
       Input  :
          txtExp : (by reference) receives window height (rows)
          bdrExp : (by reference) receives window width (columns)
       Returns: window position (offset into terminal window)
     Debugging method: Get a copy of the window dimensions and position.


   ▪ const BlockFifo* GetFifo ( void );

       Input  : none
       Returns: const pointer to the private @b{BlockFifo} object.
     Debugging method: Get a pointer to the FIFO queue which contains the
     static text of the window. For an example, please refer to the Test_Fifo
     method in AnsiCmdTest.cpp. Run this test using: epts --test=Ws.

   ▪ void dumpConfig2Log ( const wchar_t* title );
   ▪ void dumpField2Log ( const skField* fptr, const wchar_t* title,
                          bool verbose = false );
   ▪ void dumpMrp2Log ( const skField* fptr,
                        const wchar_t* title = NULL, bool brief = false );
   ▪ void dumpFifo2Log ( const BlockFifo* bptr,
                         const wchar_t* title = NULL );
   ▪ void dumpFifoRecord2Log ( const DataBlock* dbptr );

     Debugging methods: Write various diagnostic data to the debugging log
     file.

     During development a log file is created when the application is
     launched. This file is cryptically named: "dbg.log". Startup and shutdown
     data are written to this file, and depending on which
     conditional-compilation declarations are enabled, a large amout of
     additional data are recorded in the log. *Note Build Options:: for more
     information.

     Please refer to the individual methods listed for an explanation of the
     data written in each case.


   ▪ void ACWin::Screenshot ( bool html = false, const char* desc = NULL );
       Input  :
          html : (optional, default == false) output format 
                 true  : HTML markup 
                 false : plain text 
          desc : (optional, default == null pointer) discriptive text 
     
       Returns: nothing 

     Capture a screenshot of the specified ACWin object to the log file.
     The capture is performed in a sectioned format as shown, and the
     developer is then responsible for integrating the sections to produce the
     finished screenshot.
       1. Window border (including optional window title)
       2. Static text block(s)
          These are sequences of text which have been written directly to the
          interior of the window, bypassing the control objects.
       3. Array of controls, in indexed order. Each control is written with
          outline and label, if specified.

     This procedure is significantly different from the author's NcDialog
     library (based on ncurses) which performs window capture in a
     fully-integrated way, including color attributes. The AnsiCmd/ACWin/ACDlg
     library, however, is a much simpler creature.

     Plain-text Screenshots
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     For monochrome plain-text screenshots (Texinfo '.info' documents), it is
     likely more efficient to simply copy-and-paste from the terminal window,
     but if the 'html' parameter is reset, a plain-text capture will be
     performed. See the Linux documentation for Ctrl+Shift+c and Ctrl+Shift+v
     copy-and-paste commands.

     HTML Screenshots
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     For HTML documentation, copy-and-paste is inefficient and error prone, so
     it is likely more efficient to use this capture method. This is
     especially true for a developer who is not fluent in HTML/CSS markup
     because placeholder HTML/CSS3 style instructions are embedded in the
     screen-capture.

     The HTML output is placed inside a <div class="tscap">...</div> pair of
     tags which defines the dimensions, font family, basic color scheme and so
     on.

     Each row of the window border is bracketed by a placeholder sequence:
     <span class="xxxx">...</span> which provides a method for specification
     of color attributes for the left and right borders. Example:
     <span class="bl_r">┌─────┐</span>
     <span class="bl_r">│</span> Hi! <span class="bl_r">│</span>
     <span class="bl_r">└─────┘</span>
     which specifies blue text with foreground and background attributes
     reversed.
             ┌─────┐
             │ Hi! │
             └─────┘
     Please refer to the CSS class definitions in infodoc-styles.css for a
     description of the color-attribute classes.

     Each object within the window is also enclosed within a similar sequence.

     For greater control over the color palette, instead of calling out the
     pre-defined color attribute classes, the <span class="xxxx;"> tag may be
     replaced with something similar to:
        <span style="color:#0033FF; background-color:#99FF99;">
     This tag specifies “web-safe” foreground and background color attributes.
     Please run the color tests (*note test C::) included in this package, and
     visit the author's website for a document “HTML/CSS Color Chart”
     describing web-safe colors.

     Hotkey designators are displayed using the 'underline' text-modifier
     attribute. For these characters, a callout for the the CSS "ulin" class
     is embedded in the HTML output. For example the text of a Pushbutton may
     be written as:              "Buy Some ^Jiǎozǐ Today"
     The caret character ('^') indicates that the next character is the hotkey
     character, 'J' in this example. Thus the HTML would be:
     <span class="xxxx">Buy Some <span class="ulin">J</span>iǎozǐ Today</span>
     This will cause the 'J' to be underlined in the output.

     The primary test window for this functionality is *note Test_Cookie::,
     which is a simple window used in the Texinfo documentation.
     (*Note skForm Class::.)

     Note that the Screenshot method is _huge_ compared to its actual
     usefulness, so be sure its conditional-compilation is disabled:
           #define DEBUG_PHOTO (0)  
     when the method is not in use. *Note Building from Source:: for details.




File: ansicmd.info,  Node: skForm Class,  Next: Dialog sub-Windows,  Prev: ACWin Public Methods,  Up: ACWin Class

skForm Class
============

Communication between the application and the user is the most complex (and
most error prone) task for the application developer. Most of us would prefer
to avoid user interactions as much as possible; however, without users (filthy
beasts as they may be) there wouldn't be much need for applications.

When designing an application, it must be assumed that the user interface
section will not only require more code and more development time than any
other section; it will require the developer to compensate for users' (often
illogical) assumptions about the program, and their blithe refusal to read the
documentation.
The skForm and skField interface classes are your humble author's attempt to
make this process as painless as possible.

* Menu:

* User Interaction::             Communication with the user
* skForm Public Methods::        Public methods of the skForm class
* skForm Data Members::          Initialization of skForm data members
* skField Public Methods::       Public methods of the skField class
* skField Data Members::         Initialization of skField data members
* UI Control Types::             User interface controls
* skForm Initialization::        Sample initialization of skForm




File: ansicmd.info,  Node: User Interaction,  Next: skForm Public Methods,  Up: skForm Class

User Interaction
----------------

Some developers will want to write directly into the terminal window, and read
the user's responses directly from the window. The AnsiCmd primitives *note
acRead::, *note acWrite::, *note ttyWrite::, etc. are designed for this type
of interaction.

Others will want to design an array of text-input fields and other types of
controls for user interactions.
These controls are defined by Some-Kind-of-Form i.e. the 'skForm' class.
Both the ACWin class (window) and the ACDlg class (dialog) support
skForm-class objects. Within the skForm object, an array of 'skField' objects
defines the individual controls for user interaction.

If the ACWin constructor is called without specifying an skForm object, a
default skForm object is created based on the size of the window. The default
skForm object will be created with one(1) text-box (ftTB) skField object which
takes the dimensions of the window interior.

To achieve direct control over the way the skForm object is configured, a
pointer to an initialized skForm object is passed to the ACWin or ACDlg
constructor.

// Define and initialize an skForm/skField object.
skForm* skfp = new skForm
{
   FLD_COUNT,
   new skField[FLD_COUNT]
   {
      . . .
   },
   // Initialize remaining skForm parameters to default values.
   . . .
} ;

// Create a window.
ACWin *win = new ACWin
      ( winROW, winCOL,                // position (upper-left corner) 
        winHEIGHT, winWIDTH,           // dimensions (height, width)
        ltSINGLE,                      // border style
        bdrAttr,                       // border attributes
        intAttr,                       // interior attributes
        "  Secrets of the Universe  ", // window title
        skfp                           // pointer to skForm object
      ) ;

// Create a dialog within a parent window
this->win->Dialog
      ( dlgHgt, dlgWid,       // dialog dimensions
        skfp,                 // pointer to skForm object
        staticText,           // text written directly to dialog interior
        dlgTitle,             // dialog title
        ZERO, -1,             // dialog offset within parent window
        ltDUAL,               // border style
        acaUSEDFLT,           // border color attribute
        this->dlgAttr,        // interior color attribute
        0, 1,                 // interior text offset
        nonmember_dlgCallback // address of callback function
      ) ;

The position and dimensions of each field must fall entirely within the text
area of the window, and the fields should not overlap (unless the obscured
field(s) are set as “hidden”).

Although range checking and automatic positioning and size adjustments of the
controls is performed, an over-caffinated developer could still cause chaos,
so it is important to carefully verify the parameters which define the
individual controls.

There are several ACWin objects and ACDlg invocations created in the test code
included in this package. Some tests write text directly into the window,
while others write into the defined fields (or some combination of the two).
Please refer to those examples, as well as the discussion of skForm and
skField classes below.



File: ansicmd.info,  Node: skForm Public Methods,  Next: skForm Data Members,  Prev: User Interaction,  Up: skForm Class

skForm Public Methods
---------------------

The skForm-class object is a mostly passive construct, that is, the object
doesn't perform many tasks directly. Its primary function is to store and
display information in an orderly and predictable way. The ACWin or ACDlg
object updates this information in response to user activity.
Please *note EditForm:: which acts as the gateway to the skForm data.

   ▪ skForm ( short fieldCount );

       Input  : fieldCount : number of skField objects
                             Range: 1 through 99
     
       Returns: implicitly returns a pointer to the object

     Simple constructor. Allocate resources for the skForm object and an array
     of skField objects. All data members receive default values.

     It is assumed that the application will populate all necessary data
     members after instantiation. Please see the initialization constructor
     below for more detailed information on the initialization of the
     individual data members.

     Technical Note: The default constructor (the constructor with no
     arguments) is set as private in order to protect the application layer
     from creating an unusable object.


   ▪ skForm ( short fieldCount, skField* fldArray,
              short fldIndex = ZERO, acAttr fldAttr = acaUSEDFLT,
              bool noisy = true, bool ioFlag = true, bool ioToggle = true,
              bool ioCursor = false,
              CurStyle insCursor = csBblock, CurStyle ovrCursor = csBuline );

       Input  : fldCount: number of objects in 'fldArray' (1-99)
                fldArray: pointer to an array of skField objects defining 
                          the form
                //** Optional Arguments **
                fldIndex: (optional, default: zero)
                          index of field which receives initial input focus 
                fldAttr : (optional, default: acaUSEDFLT)
                          For fields which change color when they receive 
                          input focus, this is the focus color attribute.
                          -- acaUSEDFLT: If default attributes specified, then 
                             when field receives input focus, the field's 
                             embedded foreground and background attributes are 
                             swapped.
                          -- If focus-color attributes are specified, then 
                             when field receives input focus, this attribute 
                             overrides the field's embedded attributes for as 
                             long as the field holds focus, at which time the 
                             embedded attributes are restored.
                noisy   : (optional, default: true)
                          if 'true',  beep on unhandled keycode received
                          if 'false', silently discard the unhandled keycode
                ioFlag  : (optional, default: set)
                          initial state of Insert/Overstrike flag
                          set  : Insert mode
                          reset: Overstrike mode
                ioToggle: (optional, default: true)
                          if 'true',  user may toggle between Insert mode and 
                                      Overstrike mode
                          if 'false', mode is fixed, and cannot be modified 
                                      by user 
                ioCursor: (optional, default: false)
                          if 'true', shape of cursor changes to indicate 
                                     current state of Insert/Overstrike flag
                          if 'false', cursor shape is not modified for 
                                      Insert/Overstrike mode
                insCursor: (optional, default: csBblock)
                           member of enum CurStyle indicating the cursor shape 
                           to be used when in Insert mode.
                           (If 'ioCursor' flag is reset, then )
                           (only this cursor style is used.   )
                ovrCursor: (optional, default: csBuline)
                           member of enum CurStyle indicating the cursor shape 
                           to be used when in Overstrike mode.
     
       Returns: constructors _implicitly_ return a pointer to the object
     

     Initialization constructor.
     This constructor fully initializes the skForm data members AND transfers
     the data from caller's skField array to the internal skField array.

     Important Note: The number of elements in 'fldArray' must match the value
     in 'fldCount'. If the array is larger than ‘fldCount’, then some field
     definitions may be discarded. If the array is smaller than ‘fldCount’,
     then a segmentation fault will be the likely result. Be Aware!

     Note that range checking and error correction are not performed by this
     constructor. Any needed corrections are made during instantiation of the
     parent window so that the values may be compared to the window
     definition.


   ▪ void operator= ( const skForm *skfp );

       Input  : (by reference) the skForm object containing source data
     
       Returns: nothing

     Assignment Operator: make a copy of the specified skForm object.
     The copy will include both the public and protected data members.

     If the assignment operator is used correctly, then source and target
     arrays should have the same number of elements; however, if the dynamic
     allocations do not match, the target allocations will be released and
     re-allocated to accomodate the data to be copied.


   ▪ ~skForm( void );

       Input  : none
     
       Returns: none

     Destructor: Release the dynamic allocation and delete the skForm object.

     For an “automatic” constructor allocation:
       skForm skf( 6,
                   new skField[6] = { ... },
                   ... );
     The destructor will be invoked when the object goes out of scope.

     For a constructor created in dynamic memory:
       sdForm* skf_ptr = new skForm
               ( 6, 
                 new skField[6] = { ... },
                 ... );
     The destructor is invoked directly:
       delete skf_ptr;

     ┌──────────────────────────────────────────────────────────────────────┐
     │ Teacher Rant:                                                        │
     │ Note that forgetting to delete a dynamically-allocated object when   │
     │ the task is complete would be considered as a "memory leak", a       │
     │ failure to return system resources once they are no longer needed.   │
     │ The author once spent five weeks chasing memory leaks in a           │
     │ multi-node Solaris system. It was not pretty. Please use extra care  │
     │ when working with dynamic memory allocations.                        │
     └──────────────────────────────────────────────────────────────────────┘


   ▪ bool skfProtectedMembers ( WinPos& p_base, wchar_t& p_pKey,
                                short& p_seli, bool& p_foot, bool& p_dlg )
     const;

       Input  : 
          p_base : (by reference) receives offset for upper left 
                    corner of parent window
          p_pKey : (by reference) receives most recent 'special'
                    keycode processed
          p_seli : (by reference) receives index of field containing
                    'selected' text (if any)
          p_foot : (by reference) receives the 'footer' flag
                    'true'  if Footer messages are enabled
                    'false' if Footer messages are disabled
          p_dlg  : (by reference) receives the 'dialog' flag
                    'true'  if skForm container is an ACDlg object
                    'false' if skForm container is an ACWin object
     
       Returns: 'true'  if AnsiCmd library debugging code is enabled:
                        (caller's parameters have been initialized)
                'false' if AnsiCmd library debugging code is disabled:
                        (caller's parameters returned uninitialized)

     For Debugging Only.

     This method reports the “protected” data members of the skForm class.
     These values are not directly available at the application level, but may
     be useful during development.



File: ansicmd.info,  Node: skForm Data Members,  Next: skField Public Methods,  Prev: skForm Public Methods,  Up: skForm Class

skForm Data Members
-------------------

   — fCnt (internal use only)
     This is the number of elements in the 'fld' array of skField objects.
     While this value is technically a public data member, it is set only
     once, during instantiation of the skForm object, and may not be modified
     after that.

   — fld
     Pointer to an array of one or more skField objects which is dynamically
     allocated by the skForm constructor. Templates for these fields may be
     individually initialized by the application, then passed to the ACWin or
     ACDlg constructor, which performs range checking and adjustmens as
     necessary, and then copies the application's values to the internal
     skForm object.

   — fi
     Field Index. This value is used internally to track the index of the
     field which currently has the input focus. (default: zero)
     The initial value may be set to indicate the field with initial input
     focus, but is under control of the window during user interactions.

   — faca
     If the field uses different color attributes based on whether the field
     has the input focus, this is the color attribute for when the field has
     input focus.
     For fields which do not include a visible cursor, use of this color is a
     visual indication of which field has focus.

   — beep
     If set, this flag indicates that an auditory warning will sound when the
     user presses an invalid key. When reset, invalid keystrokes are silently
     discarded. (default: 'true')
     To modify this value, please *note AlertEnable::.

   — ins
     Insert flag. When set, indicates Insert mode. When reset, indicates
     Overstrike mode. (default: 'true')
     This flag is referenced when user is modifying the text within a Textbox
     field (ftTB) to determine the input “mode”. The user can toggle between
     the modes by pressing the Insert key _unless_ the 'togg' flag is reset.
     (see below)
     To modify Insert key setup, please *note InsertKey::.

   — togg
     If set, user may toggle the Insert/Overstrike mode. If reset, Ins/Ovr
     mode is locked in its current state and may not be modified by the user.
     (default: 'true')

   — insc
     If set, this flag indicates that the cursor style changes when the
     insert/overstrike mode is toggled. (default: 'false'.)
     The cursor style for each mode may be specified using the 'icur' and
     'ocur' members described below.

   — icur
     If 'insc' is set, this is the cursor style used when in Insert Mode.
     Default: 'csBblock'. (ignored when 'insc' is reset)

   — ocur
     If 'insc' is set, this is the cursor style used when in Overstrike Mode.
     Default: 'csBuline'. (ignored when 'insc' is reset)

     Protected Data Members
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

   — base (‘protected’, internal use only)
     This is the zero-based offset from the upper-left corner of the ACWin (or
     ACDlg) object's interior. Used for calculating the position of the
     visible cursor.

   — pkey (‘protected’, internal use only)
     Previous Key: This value tracks the most recent user input value.

   — seli (‘protected’, internal use only)
     Selection Index: This value tracks the index of the field (if any) which
     contains “selected” text. This facilitates communication with the system
     clipboard.

   — foot (‘protected’, internal use only)
     Enables or disables the method used to write “footnotes”, that is,
     diagnostic messages to the lower border of the window.
     *Note EnableFootnotes:: for setting and resetting this flag.

   — dlg (‘protected’, internal use only)
     Used to distinguish whether operating in the parent window or a child
     dialog window. (The ACDlg class is a derived class based on the ACWin
     class.)
     *Note ACDlg Class:: for additional information.



File: ansicmd.info,  Node: skField Public Methods,  Next: skField Data Members,  Prev: skForm Data Members,  Up: skForm Class

skField Public Methods
----------------------

   ▪ skField ( FldType fldType, short fldHeight, short fldWidth,
               short fldOffsetY, short fldOffsetX,
               //* Optional Arguments *
               const char* fldText = NULL, acAttr fldAttr = acaATTR_DFLT,
               FloType fldFlow = floChar, bool readOnly = false,
               bool fldBorder = false, bool fldHidden = false,
               bool fldLocked = true, bool binState = false,
               wchar_t hotKey = NULLCHAR, wchar_t groupId = noGROUP );

       Input  :
          fldType    : field type, member of enum FldType
          fldHeight  : field height in rows
          fldWidth   : field width in columns
          fldOffsetY : vertical offset from parent window origin
          fldOffsetX : horizontal offset from parent window origin
          fldText    : (optional, default: an empty string "\0")
                       Initial text data. Data configuration is dependent 
                       on the field type. See documentation for details.
          fldAttr    : (optional, default: acaATTR_DFLT)
                       color attribute for field
                       Note that for field types which change color when they 
                       receive input focus, this is the non-focus color.
          fldFlow    : (optional, default: floDflt) text flow
                       Automatic text formatting option for the field.
                       Formatting option is dependent on field type, and is 
                       fully configurable only for Textbox controls (ftTB).
          readOnly   : (optional, default: false)
                       if set,  field is view only, cannot receive focus
          fldBorder  : (optional, default: false)
                        if false, field has no border.
                           Exception: Menubox controls always have a border.
                        if true,  draw an outline around the field
                           Note: Default line type and color attribute will be 
                                 used to draw the outline. For a non-default 
                                 line type or attribute, see SetFieldOutline().
          fldHidden  : (optional, default: false)
                       if set, field is not displayed and cannot receive focus
          fldLocked  : (optional, default: true)
                       if set, field is always visible (unless obscured by 
                               another field.)
                       if reset, field becomes invisible when it loses focus. 
                               (This is primarily for menus.)
          binState   : (optional, default: false)
                       For binary-state controls only (Radiobuttons), 
                       specifies the initial state: "set" or "reset".
          hotKey     : (optional, default: null L'\0')
                       if specified, this is the hotkey character for setting 
                       focus to field. Please see documentation about 
                       specification and use of hotkeys.
          groupId    : (optional, default: noGROUP)
                       For fields whih can be grouped(Menubox and Radiobutton)
                       this is the character used to identify the members 
                       of the group.
     
       Returns: constructors _implicitly_ return a pointer to the object

     Initialization constructor.
     The first five(5) arguments are required. The remaining arguments are
     optional and if not specified, will receive default values.

     The ACWin class test methods provide several examples of skField
     initialization.
     A representative sample initialization (*note skForm Initialization::) is
     shown below.
     *Note test W::, sub-test 'f' for additional information.


   ▪ skField ( void );

       Input  : none
     
       Returns: constructors _implicitly_ return a pointer to the object

     The default constructor creates an skField object and initializes all
     members to their default values. This constructor has little practical
     value, but it remains a public method for those who wish to experiment.
     See the initialization constructor above for a more robust
     implementation.


   ▪ ~skField ( void );

       Input  : none
     
       Returns: nothing

     Destructor.

     The destructor is like the cleaning crew that comes into your Cabo hotel
     room after Spring Break. All resources allocated from the system are
     returned to the system, the mini-fridge is restocked and the iguana you
     forgot was in the shower is returned to the wild.
     (Lo siento mucho, Abue; tenía 19 años y estaba un poco fuera de control.)


   ▪ void operator= ( const skField& skf );

       Input  : (by reference) the skField object containing source data
     
       Returns: nothing

     Assignment Operator: make a copy of the specified skField object.
     The copy will include both the public and protected data members.
     See also the skForm operator=() above.


   ▪ bool outlineConfig ( LineType lType, acAttr lAttr = acaUSEDFLT );

       Input  :
          lType   : line type for border, member of enum LineType
                    ltSINGLE (default), ltDUAL, ltHORIZ (invisible border)
          lAttr   : (optional, default: acaUSEDFLT) border color attribute
                    if not specified, takes attribute of window interior
                    -- Note that this parameter does not apply to menu
                       controls which take their outline color from the
                       menu data.
     
       Returns: 'true'  if successful
                'false' if field type does not allow borders

     Set the line type and attribute for the field outline.

     The data members which contain these values are 'protected', that is,
     they are not available at the application level. This skField public
     method is provided so these values can be initialized before the window
     or dialog is instantiated. The configured fields will be displayed when
     the window(dialog) is opened.

       a. Note that this method should be called ONLY before the window (or
          dialog) constructor is called. To initialize the border _after_ the
          window/dialog is created, call the ACWin-class SetFieldOutline
          method instead.
       b. Field outlines are incompatible for Menu controls (ftMB) because
          menus have integrated borders.
       c. Because this call does not reference the parent window(dialog),
          error checking of positioning or interference with the border and
          with other fields cannot be performed here. For this reason, use
          caution when initiating these values.
       d. This method is intended primarily for initializing the
          skForm/skField object to be used as a parameter when invoking a
          full-initialization dialog; however, it is possible to use this
          method when initializing the skForm/skField object to be used as a
          parameter when defining an ACWin object. In this case, use extra
          care in positioning the specified control.

     Please *note skField config example:: below for an example of using
     outlineConfig.


   ▪ bool labelConfig ( const char* labText,
                         acAttr labAttr = acaUSEDFLT, bool center = false);

       Input  :
          labText : display text, optionally including a "hotkey" character.
                    A hotkey is specified using the CARET character ('^')
                    followed by the ASCII character which indicates the@item
                    keycode to be used as a hotkey. (see example above)
          labAttr : (optional, default: acaUSEDFLT) color attribute for label
                    If not specified label color is set to color of parent
                    window interior
          center  : (optional, default:'false') horizontal offset
                    if set, center the label horizontally above the field
                    if reset, label offset is in the same column as the
                              left edge of the field
     
       Returns: 'true'  if successful
                'false' if field type does not allow external label

     Specify label text, color and position.

     The data members which contain these values are 'protected', that is,
     they are not available at the application level. This skField public
     method is provided so these values can be initialized before the window
     or dialog is instantiated. The configured fields will be displayed when
     the window (or dialog) is opened.

     Note that this method should be called ONLY before the window (or dialog)
     constructor is called. To initialize the border _after_ the window is
     created, call the ACWin-class SetFieldLabel method instead.

     The following control types will accept labels:
      1) ftTB - Textbox
      2) ftSB - Scrollbox
      3) ftMB - Menu
         Note that only certain menus may have labels.
          a) Context menus i.e. multi-row menus which are not group members.
          b) Menubar menus i.e. single-row menus which anchor a group
             of menu controls.
      External labels are incompatible for Pushbuttons (ftPB) and Radiobuttons
      (ftRB) because the field text _is_ the label.
      See below for a label configuration method specifically for Radiobuttons.

     Please *note skField config example:: below for an example of using
     labelConfig.


   ▪ bool labelConfig ( acAttr labAttr, bool lableft = false );

       Input  :
          labAttr : color attributes for Radiobutton label
                    If acaUSEDFLT specified, then label color is set to color
                    of parent window interior
          lableft : (optional, default:'false') horizontal offset
                    if set, label is displayed to the left of the control
                    if reset, label is displayed to the right of the control
     
       Returns: 'true'  if successful
                'false' if incorrect field type

     Specify label color attributes and position.

     This overload is designed for Radiobutton controls (ftRB) only.
     To initialize labels for other types of controls, see above.

     By default Radiobutton labels inherit the color attributes of the parent
     window/dialog _and_ the label is positioned to the right of the field.
     This method allows direct specification of the label attributes and
     optionally allows the label to be positioned to the left of the control.

     The data members which contain these values are 'protected', that is,
     they are not available at the application level. This skField public
     method is provided so these values can be initialized before the window
     or dialog is instantiated. The configured fields will be displayed when
     the window(dialog) is opened.

     Note that this method should be called ONLY before the window (or dialog)
     constructor is called.

       skForm* skfp( ... ) ;
       // Field definition and formatting for a Radiobutton control:
       // The caret character, if present, indicates the hotkey 
       // character for setting input focus to target field.
       // Define the text and position of the control
       short row_offset = 2, col_offset 14 ;
       const char* rbDef = "[♦] Comp^uter Science" ;
     
       // By default the field and label would be displayed as:
             [♦] Computer Science
                   ▔
       // If label configuration with field/label swap, the overall
       // position within the window will be unchanged, but field 
       // and label will swap positions as shown.:
       skfp->fld[n].labelConfig ( acAttr(acaFG_BLUE|acaUSEDFLT), true );
             Computer Science [♦]
                 ▔

     Note that a space after the closing brace will automatically be removed,
     and a space will be appended to the label text:
        "[♦] Computer Science" becomes
        "Computer Science [♦]"
     *Note AcEdit Demo App::, 'Compare Files' dialog for a working example of
     this option.


   ▪ bool colorConfig ( const acAttr* rowAttr, short rowCnt );

       Input  :
          rowAttr: pointer to an array of acAttr color attributes, one
                   attribute for each text row of the control.
          rowCnt : number of attribute values in the 'rowAttr' array
                   Value must be greater than zero, and the minimum
                   _practical_ value is two(2)
     
       Returns:
          'true'  if successful
          'false' if field type does not support per-row attributes
                  or if 'rowCnt' less than minimum

     Specify an array of color attributes, one for each item (row of text
     data) within the control.

     Customization of text color attributes is often useful to enhance
     readability of multi-row controls which contain fixed display text. For
     multi-row Menu controls (ftMB) and Scrollbox controls (ftSB) _only_,
     color attributes for each individual display row may be specified.

     The data member which contains these color values is 'protected', that
     is, it is not available at the application level. This skField public
     method is provided so that custom color attributes may be specified, one
     attribute per text row, _after_ the skField object has been instantiated,
     but _before_ the window (or dialog) constructor is called.
     The reonfigured field will be displayed when the window(dialog) is
     opened.

     The following control types support custom color attributes:
     These control types are designed to contain read-only data; (the data may
     may not be edited under user control); therefore, it is possible to embed
     color attributes within the displayed text.

       1. ftMB - Menu
           - All items within a menu are visible simultaneously whenever the menu
             itself is visible. Therefore one custom color must be specified for
             each item. Do not specify attributes for the upper or lower borders.
           - Note that the specified attributes apply _only_ to the text
             displayed within the control, and _not_ to the borders
             drawn around the text.
           - Only multi-row (multi-item) menus support custom colors.
             A single-row menu (menu bar) is excluded, because it has only
             one row, and therefore only one color.

       2. ftSB - Scrollbox
           - Scrollbox controls may contain any number of text items, although
             the number of items visible at any moment is determined by the
             height of the control. Therefore, a custom color must be specified
             for each item (row) whether it is visible or not.
           - Please note that if text data provided for a Scrollbox control is
             incorrectly formatted, it will be automatically reformatted to
             fit the control. If this happens, the color attribute specified
             for each row may not be as expected. Beware!

     Any valid acAttr color attribute bitfield may be specified.
     The acUSEDFLT value indicates that the target item will use the attribute
     specified in the skField's 'aca' member. This is the attribute for the
     control as a whole.

     Please refer to the example below.


     IMPORTANT NOTE:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

     This method includes some defensive programming; however, it is not
     possible to anticipate all potential foolishness, so be careful! Applying
     per-item color attributes must rely on text data formatting which has not
     yet been programatically validated.

     This method should only be called for controls within a dialog (ACDlg)
     object, and _only_ if you are certain that the text to be displayed
     within the control has been properly dimensioned, ensuring that the
     attribute count will equal item count.

     For controls within a window (ACWin) object, please use the *note
     SetFieldAttr:: method instead. Using SetFieldAttr will be safer because
     it will be called after the control dimensions and text formatting have
     been verified.


     skField config example
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

     // Create and initialize an skForm object with an array of three(3)
     // skField objects: a Textbox, a Context Menu and a Pushbutton.
     sdForm* skf_ptr = new skForm
             ( 3, 
               new skField[3] = 
               {
                 { ftTB, ... }, // Textbox      (index 0)
                 { ftMB, ... }, // Context Menu (index 1)
                 { ftPB, ... }, // Pushbutton   (index 2)
               },
               ... );
     
     // Specify that an outline is to be drawn around 
     // the Textbox control.
     skf_ptr->fld[0].outlineConfig ( ltDUAL,
                                     acAttr(acaFG_BLUE | acaBG_CYAN) );
     
     // Specify a label for the Textbox control 
     skf_ptr->fld[0].labelConfig ( "Date Of Birth " );
     
     // Specify a label for the Menu control,
     // (centered, with contrasting color).
     skf_ptr->fld[0].labelConfig ( "  Education Level  ",
                                   acaFG_BLACK | acaBG_GREY), true );
     
     // Specify an array of per-item color attributes for the Menu.
     // In this example, progressive web-safe RGB colors are built.
     // The divider item inherits the color of the menu control.
     // (Note the extra element appended for safety.)
     acaExpand acex ;
     el00 = acex.buildRgb( true, wsrgbBLACK, 
                           true, WebSafeRGB(wsrgbBROWN + wsrgbSHADE_MED));
      ...
     el10 = acex.buildRgb( true, WebSafeRGB(wsrgbRED + 9), 
                           true, WebSafeRGB(wsrgbGREY + wsrgbSHADE_MED));
     
     short COLOR_ELEMENTS = 11;
     acAttr acArray[COLOR_ELEMENTS + 1] =
        { el00, el01, el02, el03, el04, el05, el06, 
          acaUSEDFLT, el08, el09, el10, acaUSEDFLT };
     
     skf_ptr->fld[1].colorConfig ( acArray, COLOR_ELEMENTS );
     ┌────────────────── Biographical Data ──────────────────┐
     │                                                       │
     │                               Education Level         │
     │  ╔Date Of Birth ═════╗  ┌──────────────────────────┐  │
     │  ║02/29/1996         ║  │ Primary School Primate   │  │
     │  ╚═══════════════════╝  │ Middle School Muskrat    │  │
     │                         │ High School Hyena        │  │
     │                         │ Associate of Animals     │  │
     │                         │ Bachelor of Bulldookie   │  │
     │                         │ Master of Monkey Dung    │  │
     │                         │ Piled Higher and Deeper  │  │
     │                         │ ──────────────────────── │  │
     │                         │ School of Hard Knocks    │  │
     │                         │ Ain't Got None           │  │
     │                         │ Don't Wanna Know Nothin' │  │
     │                         └──────────────────────────┘  │
     │                                                       │
     │                      ▒▒▒CLOSE▒▒▒                      │
     └───────────────────────────────────────────────────────┘
     (Color attributes are not visible in the )
     (info document but see the HTML document.)


   ▪ bool getItem ( gString& iTxt, short& iNum, bool selnum = false ) const;

       Input  :
          iTxt  : (by reference) receives item text data
          iNum  : (by reference) receives the index of the "item" referenced
                  by the 'ip' member (item referenced by the cursor)
                  (This is the 0-based item index.)
          selnum: (optional, default: false) for multi-row controls only 
                  if set AND if a previously "selected" item (sitem >= zero), 
                     return index of "selected" item.
                  if reset, return index of item containing the IP.
     
       Returns: 'true'  if supported target control type (ftMB || ftSB), AND
                        if item identified
                else 'false'

     For Menus (ftMB) and Scrollbox controls (ftSB), retrieve the index of the
     "item" (row) containing the insertion point ('ip'). Generally, this is
     the currently hightlighted item or the item which was highlighted when
     the control lost focus.

     The 'getItem' method returns both the item index and the actual text of
     the item.

     The optional 'selnum' parameter may be used to report either the target
     control's highlighted item _or_ the item (if any) “selected” by the user
     via the Enter or Space key.

     The text of a menu item may contain an embedded hotkey indicator which is
     identified as the character following the caret ('^').
     Example "Sa^ve file" where the 'v' is the hotkey character.
     This is described more fully in the chapter *note skField Data Members::.

     This method will typically be called from an application callback
     function or immediately after a dialog window has closed.
     *Note EstablishCallback:: or the *note Dialog:: method's 'callbk'
     parameter for more information on establishing and using callbacks.

     Also, *note GetFieldItem:: which is a form-oriented method which provides
     information similar to getItem.


     Understanding “Items”
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
     For purposes of this discussion, an “item” is a row of text displayed
     within the control.
     For example, the following diagram shows the different types of menus: a)
     context menu, b) menu group sub-menu, and c) the ‘Menubar’ (single-row
     menu).

          Context Menu          Group Submenu
        ┌────────────────┐
        │Open a file     │    │Open a file     │ <-- iNum == zero
        │Save file       │    │Save file       │
        │Close file      │    │Close file      │
        │Exit Application│    │Exit Application│ <-- iNum == 3
        └────────────────┘    └────────────────┘
     
        Example menubar:
        ----------------
               | File  Edit  View  Help |
                 ↥     ↥     ↥     ↥
          item:  0     1     2     3
     

     Scrollbox controls (ftSB) typically contain plain, paragraph-oriented
     text data, not itemized data records; however, if desired, the
     application may define each display row of the Scrollbox control as a
     data item. This implements what is essentially a scrolling menu for
     situations where there are a large number of items to be displayed.
     The following example is taken from the *note AcEdit Demo App:: which
     displays a list of files in the current directory, and asks the user to
     select a file to be edited. This type of control can accomodate any
     reasonable number of items.
     The '▶' indicator character, identifies the current item, and when the
     user presses the Enter or Space key, that item is “selected”. In the
     example, the indicator is on AcEdit.cpp and its item index is four(4).
     When the Scrollbox loses focus, the selection indicator will be replaced
     by the '▷' character.

     ╔══════╣  Open a File For Editing  ╠════════╗
     ║  .. parent directory                      ║
     ║  > 1_TestData                             ║
     ║  · ace                                    ║
     ║  · ace.cfg                                ║
     ║▶ · AcEdit.cpp                             ║ <-- iNum == 4
     ║  · AcEdit.hpp                             ║
     ║  · AcEdit.o                               ║
     ║  · AcEditCfg.cpp                          ║
     ║  · AcEditCfg.o                            ║
     ║  · dbg.log                                ║
     ║  · gString.hpp                            ║
     ║ ───────────────────────────────────────── ║
     ║             OPEN       CANCEL             ║
     ╚═══════════════════════════════════════════╝


   ▪ bool skField::setHiliteMod ( acAttr txtMod );

       Input  :
          txtmod:
             text modifier attribute for highlighting text segments.
             One of the following text modifier attributes:
              acaBOLD      bold-text modifier
              acaITALIC    italic-text modifier
              acaUNDERLINE underline-text modifier (not recommended)
              acaOVERLINE  overline-text modifier
              acaXOUT      x-out (strikethrough) text modifier
              acaBLINK     blinking-text modifier
              acaCONCEAL   concealed (invisible) text
              acaREVERSE   reversed fgnd/bkgnd (default)
             The specified modifier flag _should not_ also be set
             as an element of control's base color attribute.
             Note: OR'd combinations of these modifiers are not allowed.
     
       Returns:
          'true'  if highlight attribute set successfully
          'false' if a) invalid modifier specified and discarded.
                        (default modifier, acaREVERSE, will be used)
                     b) field type does not support text highlighting

     For Textbox (ftTB) controls, set the text-modifier attribute to be used
     for highlighted substrings.

     The data member which contains this value is 'protected', that is, it is
     not available at the application level. This method can be called for any
     Textbox field in an initialized skForm object, before the window/dialog
     has been defined.

     //* Define an skForm object with two controls. *
     skForm* skfp = new skForm
     (
        fldCOUNT,
        new skField[fldCOUNT]
        {
           //* Field index 0: ftTB (Textbox: fldTB_SEGMENT) *
           {
              ftTB,             // field type
              . . .
           },
           //* Field index 1: ftPB (Pushbutton: fldPB_FWRD) *
           {
              ftPB,                            // field type
              . . .
           },
        } ;
        . . .
     );
     
     //* Set the modifier for text highlight *
     skfp->fld[0].setHiliteMod ( acaITALIC );
     
     //* Define an ACWin object *
     ACWin *win = new ACWin
           ( winROW, winCOL,           // position (upper-left corner) 
             winHEIGHT, winWIDTH,      // dimensions (height, width)
             ltDUAL,                   // border style
             acaBorder,                // border attributes
             acaInterior,              // interior attributes
             " Highlight Field Text ", // window title
             skfPtr
           ) ;

     To set the hilight modifier after the window has been created,
     please *note SetHilightMod:: or *note HilightFieldText::.

     Notes:
     ▔▔▔▔▔▔

       a. The specified value will replace any previous highlight attribute.
       b. If the HilightFieldText() method is called with any attribute value
          other than the default (acaUSEDFLT), that value will replace any
          value set by this method.
       c. This method does not refresh the display, so the new highlight
          attribute will not be visible until the next time the field is
          refreshed.


   ▪ bool getHilite ( int& begin, int& len, gString& gsTxt );

       Input  :
          begin : (by reference) receives index of first (leftmost)
                  character of highlighted text segment
          len   : (by reference) receives the number of characters in 
                  the highlighted segment
          gsTxt : (by reference) receives a copy of the highlighted text
          hmod  : (optional, default:null pointer) if specified, target
                  receives current text-modifier attribute used to highlight
                  the text segment
     
       Returns:
          'true'  if highlighted text data successfullly captured.
          'false' a) target field contains no highlighted/selected text data
                  b) field type does not support text highlighting
                  If 'false', then 'begin' and 'len' are set to zero, 
                  'hmod' is set to acaPLAINTEXT and 'gsTxt' is cleared
                  (set to empty string).

     Returns a copy of highlighted text segment within a Textbox (ftTB) field.
     This method was developed primarily for use during development; however,
     it may have other uses.

     Conceptually similar to copying a “selected” text substring to the
     clipboard, except that the data are returned directly to caller without
     accessing the clipboard.

     Technical Note: This method does not distinguish between “highlighted”
     text and “selected” text.
     The text delimited by the 'sela' and 'selb' members is returned
     regardless.

     Example:
     This method is used in the callback function for the *note Test_Hilite::
     method of the AnsiCmd test suite. Refer to thtCallback() in
     AnsiCmdTest.cpp for details.

          gString gsOut, gs ;
          skField skfld ;
          int get_beg, get_len ;
          acAttr get_hmod ;

          win->GetFieldData ( ctrlIndex, skfld ) ;
          skfld.getHilite ( get_beg, get_len, gs, &get_hmod ) ;
          gsOut.compose( " Capture Highlight '%S' beg:%d len:%d hmod:%08X ",
                         gs.gstr(), &get_beg, &get_len, &get_hmod ) ;
          win->Footnote ( gsOut.gstr(), 35 ) ;

     Please *note HilightFieldText:: for more information on text
     highlighting.



File: ansicmd.info,  Node: skField Data Members,  Next: UI Control Types,  Prev: skField Public Methods,  Up: skForm Class

skField Data Members
--------------------

The data members of the skField class support multiple types of user interface
controls (*note UI Control Types::).

Most of the members are public, that is, the application can initialize them
and monitor modification arising from user interactions. Other members are
“protected”, meaning that they are not directly available to the application.
These members must be protected to maintain data integrity; however, most can
be read and modified indirectly using public methods of the ACWin class, the
skForm class, the skField class, or some combination of these.

Some public members must be initialized explicitly, while others can be used
with default values. These defaults are listed here.


Public Data Members
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

   — type
     Field Type: Specifies the type of field as a member of enum FldType. The
     type of field defines how the user interacts with the field.
     *Note UI Control Types:: for notes on the individual control types.

   — hgt
     Height: This is the number of vertical rows for the field.
     Minimum: 1 row for most types, but 2 rows for Menus
              and Scrollbox controls.
     Maximum: Height of parent window minus 2.

   — wid
     Width : This is the number horizontal columns for the field.

     Minimum: 1 column, but 3-6 columns is the _practical_
              minimum for most types.
     Maximum: Width of parent window minus 2.

   — orig
     This is the 0-based offset from the skForm's 'base' coordinates, which in
     turn is the 1-based offset from the upper-left corner of the terminal
     window.
     Note that within an ACWin object, 'skForm.base' is the same as the
     'txtBase' member of the ACWin object.
     Minimum: 0,0 which is the upper left corner of the container.
     Maximum: Height of (container-2) _minus_ 'hgt'.
              Width of (container-2) _minus_ 'wid'.

   — txt
     Text displayed in the field.
     The initial text required for a control depends upon the control type,
     its dimensions and other factors. Pushbuttons, Radiobuttons, Menus and
     Scrolbox controls, for instance, contain only fixed text which is set
     when the control is initialized.
     In contrast, Textbox controls may initially be empty or may contain any
     reasonable amount of formatted or unformatted text, which may then be
     updated either programatically or through user interaction.

     The text of each field is managed within a gString object.
     Please *note gString Text Tool:: for more information.
     The amount of storage space allocated is calculated dynamically up to a
     limit if gsALLOCMAX (1.0 Megabyte).
     To modify field text, please *note SetFieldText::.

   — aca
     Optional parameter, default: acaUSEDFLT.
     This member holds the color attributes of the field, which is a logical
     OR of enum acAttr values. If the default value is used, then field colors
     will inherited from the window interior attributes.
     To modify this value, please *note SetFieldAttr::.

   — flow
     Optional parameter, default: floChar for multi-row textbox, floShift for
     all other types.
     Flow control (multi-row Textbox fields only): This field contains a value
     from enum FloType and indicates the type of automatic formatting to be
     performed.
     Please *note SetFieldFlow:: for a description of formatting options.

   — ip
     Optional parameter, default: zero(0), upper left corner of field.
     Insertion Point: This is the character index for the logical cursor
     position within the field. The position of the visible cursor is
     calculated from this value, and user input is inserted into the text at
     that point.
     To modify this value, please *note SetFieldIP::.

   — ro
     Optional parameter, default: false.
     Read Only: If set, the field cannot receive input focus. This means that
     the contents may be read but the data may not be modified under user
     control.
     If reset, the field can receive input focus, and for Textbox controls,
     the user can modify the text of the field.
     To modify this value, please *note SetReadOnly::.

   — bdr
     Optional parameter, default: false.
     This flag may be set ('true') to indicate that a border is to be drawn
     around the field.
     Note that the 'bdr' flag is public and may therefore be specified during
     instantiation; however the 'btype' (border line type) and 'battr' (border
     line color) are protected members, so if a non-default border is needed,
     it should be set after opening the window.
     All types of controls support borders, _except_ Menus (ftMB), for which
     the border is built into the text of the control.
     Please *note SetFieldOutline:: method for details.

   — hide
     Optional parameter, default: false (except for menus).
     If the field is set to hidden, it is not visible, and it will become
     visible and available to the user only if the associated hotkey (if any)
     is pressed; or if the application re-enables display of the field.
     Menu controls are a special case, in that they are automatically set as
     invisible when they lose focus.
     Please *note SetFieldHidden:: method for details.

   — lock
     Optional parameter, default: true (except for menus).
     The 'lock' flag is primarily used to control visibility and accessibility
     of menu controls when they receive and lose the input focus.
     When the 'lock' flag is set, it indicates that the control is always
     visible in the window regardless of whether it has focus (unless is
     obscured by another control). When 'lock' is reset, the menu field will
     be set as invisible and inactive when it loses focus (see 'hide' flag).
     Exception: A Menubar control stays open if any member of its group has
     focus. This flag may also be used in combination with the 'hide' flag to
     de-activate other types of fields which are not currently in use. This
     prevents wasted time refreshing fields which are fully obscured by other
     fields.
     Currently, this flag is initialized during instantiation and may not be
     modified under program control. This decision may be revisited in a later
     release.

   — state
     Optional parameter, default: false.
     For Radiobuttons and other binary-state controls, this flag indicates the
     current state (set or reset i.e. 'true' or 'false').
     Please *note SetFieldState:: for more information.

   — hkey
     Optional parameter, default: null character ('\0'), no hotkey assigned.
     Hotkey assigned to the control.
     Valid values are the GUI keys (wcsALT_A, etc.) and function keys (wcsF01,
     etc.).
     For Pushbuttons (ftPB) and Radiobuttons (ftRB), the hotkey (if any) is
     embedded within the text of the control, so for those control types, the
     'hkey' value is ignored.

     While direct specification of hotkeys is valid for all other control
     types, this is recommended _only_ for Menu controls because Menu controls
     have no label.
     For all other control types it is recommended that if a hotkey is
     desired, it should be embedded in the field label.
     *Note SetFieldLabel:: and *note SetFieldHotkey:: methods for details.

   — grp
     Optional parameter, default: noGROUP i.e. null character ('\0')
     For Radiobuttons, Menus and other control types which can be grouped.
     Group members are identified by their shared use of this character. Any
     wchar_t (wide) character may be specified as the group indicator. This
     value is set during initialization and may not be modified afterward.

   — mrptr
     This is a public const pointer to the protected MRParse object defined
     within this class. Because it is a “const MRParse*”, this means that the
     application layer may VIEW BUT NOT MODIFY the text-parsing data. Please
     study the MRParse class for a description of these data.
     Please *note GetFieldData:: for accessing these data.
     See also the *note dumpMrp2Log:: method.


                            ────────────────────

Protected Data Members
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

   — mrp (‘protected’ member, internal use only)
     The MRParse object contains analytical data on the field contents
     including the number of text rows and the relative display position of
     the data within the control. Also included is both the logical and
     physical cursor position within the field.
     These data are primarily for multi-row text fields; however, the
     information is also used to initialize the data contained by other
     control types.
     To examine how this analysis is performed in the source code, see the
     private method: 'parseFieldText'.
     Please *note GetFieldData:: for accessing a copy of these data.

   — lab (‘protected’ member, internal use only)
     This member contains the label text (if any) for the control.
     Please *note SetFieldLabel:: for initializing a control label.

   — lpos (‘protected’ member, internal use only)
     This is the display position for the control label relative to the
     container window.

   — lattr (‘protected’ member, internal use only)
     Color attributes for the label text (if any).
     Please *note SetFieldLabel:: for initializing a control label.

   — battr (‘protected’ member, internal use only)
     Color attributes for the control outline (if any).
     Please *note SetFieldOutline:: for initializing a control outline.

   — cur (‘protected’ member, internal use only)
     This is a WinPos object and contains the 0-based offset from the
     control's 'orig' coordinates which defines the position of the visible
     cursor. This value is dynamically calculated from the 'ip' (insertion
     point) member.

   — btype (‘protected’ member, internal use only)
     If an outline for the control has been specified, this is the outline
     type, a member of enum LineType, either ltSINGLE or ltDUAL.
     Please *note SetFieldOutline:: for initializing a control outline.

   — sitem (‘protected’ member, internal use only)
     For Menu (ftMB) controls and Scrollbox (ftSB) control only, the index of
     the ‘selected’ item.
     Please *note GetFieldItem:: for retrieving this value.

   — iAttr (‘protected’ member, internal use only)
     By default, text data within a control is displayed using a single color
     attribute. For item-oriented data however, (specifically menu items),
     each item may be displayed in a different color. Both menus (ftMB) and
     scrollbox (ftSB) controls support item-oriented, multi-color data.
     Please *note SetFieldAttr:: or the *note colorConfig:: skField-class
     method for details.

   — rbch (‘protected’ member, internal use only)
     For Radiobutton (ftRB) controls only, the display character used to
     indicate the “set” state of the control. Note that this character is
     extracted from the initialization text for the Radiobutton control.
     Example: "[♦] ^Authorize daily cookie delivery"

   — off (‘protected’ member, internal use only)
     Text Offset: Used when scrolling text vertically within a field to
     indicate the index of the first character of the top visible row.

   — shft (‘protected’ member, internal use only)
     Text Shift: Used when scrolling text horizontally within a field to
     indicate the offset from the beginning of the text row to the first
     (leftmost) visible character.

   — sela and selb (‘protected’ members, internal use only)
     These members are delimeters (indices) for “selected” text within the
     field. Selected text is identified by being _underlined_ within the
     control.
     Selecting text is related to copy-and-paste operations. Text selection
     and the Copy, Cut and Paste operations are performed within Textbox
     (ftTB) controls only. Please *note test T:: for functional examples of
     these operations.
     Invoke this test using: ./epts --test=Tea



File: ansicmd.info,  Node: UI Control Types,  Next: skForm Initialization,  Prev: skField Data Members,  Up: skForm Class

UI Control Types
----------------

Field Types
▔▔▔▔▔▔▔▔▔▔▔

The types of user-interface controls "fields" are defined by the FldType
enumerated type.

     // Field Type for controls defined by the skField class
     enum FldType : short
     {
        ftPB,          // PushButton (select)
        ftRB,          // Radio Button (on/off)
        ftTB,          // Text Box (edit text)
        ftSB,          // ScrollBox (view and scroll text)
        ftMB,          // Menu Box (select item)
     } ;

The data for each control type is initialized as an instance of the skField
class.
*Note skField Data Members:: for a discussion of each data member.

   "Your focus determines your reality."
   -- Qui-Gon Jinn

To understand input fields, it is important to understand the concept of
“input focus”. Input focus, or just “focus” can be defined as the point where
keyboard input is received and processed.

Just at the terminal's 'stdin' stream receives key input from the user, the
control which is currently monitoring the stdin stream (the control with
focus) receives the key input and decides whether to process it directly
(retain focus), or pass it on to another control (transfer focus).

In general focus is transferred in response to one of the cursor keys:
Tab, Shift+Tab, Up/Down/Right/Left Arrow, PageUp, PageDown, Home, End; or by
receipt of the “hotkey” assigned to a control. Under some circumstances, the
Enter or Space keys can also trigger a shift in focus.

   ♦ Pushbutton (ftPB):
     The most simple type of control is the "Pushbutton".
     Pusbutton controls process only two keycodes: 'Enter' and 'Space'. Thus
     to “push” a Pushbutton means to press the Enter or Space key while the
     control has focus. The application will then determine what action is
     taken in response.
        ▒▒▒OK▒▒▒  ▒▒CANCEL▒▒

   ♦ Radiobutton (ftRB):
     Radiobuttons are very similar in function to Pushbuttons in that they
     respond directly only to the 'Enter' and 'Space' keys.

     Radiobuttons are so called because their function resembles that of the
     buttons on archaic car radios. They have two states: either “ON” or
     “OFF”.

     A Radiobutton can be a stand-alone control, or can be configured as a
     member of an XOR Radiobutton group. The term“XOR” is nerd-speak for
     “Exclusive OR”, meaning that exacty one button of the group may be ON at
     any given moment. All other buttons of the group are reset (OFF) when any
     member of the group is set (ON).
        [ ] Small
        [◆] Medium
        [ ] Large
        [ ] Extra Large
        [ ] XX Large
        [ ] XXX Large

     If an application-level callback function is active, it can immediately
     respond to the control's change in state, or action can be deferred until
     the window or dialog is closed, or until some other criteria are met.

   ♦ Textbox (ftTB):
     Textbox controls are as the name implies a way to collect text data from
     the user. The input can be monitored on a per-character basis or
     collected as a unit when user shifts the focus to another control.
     Textbox controls may optionally be outlined.
          ┌─────────────────┤ ZMail - Create ├─────────────────┐
          │Dear Mom and Dad,                                   │
          │Sorry I won't be able to make it home for Christmas │
          │this year, but if you could send me $500, I'd be    │
          │happy to get you a Christmas gift.                  │
          │ -- Your loving daughter, Anita                     │
          └────────────────────────────────────────────────────┘

     One special characteristic of Textbox controls is that they can receive
     data directly from the clipboard or send data to the clipboard.
     *Note Communicate With System Clipboard:: for more information.

   ♦ Scrollbox (ftSB):
     The function of a Scrollbox control depends upon the type of data it
     contains. The Scrollbox can display plain, paragraph-oriented text data,
     _or_ it can be configured as a scrolling list of items. Scrollbox
     controls may optionally be outlined.

     When configured to display ordinary text, the user may scroll upward and
     downward through the data. Horizontal scrolling is not supported.
          ┌─────────────────────────────────────────────────────┐
          │ There once was a man from Kirkuk,                   │
          │ Who was known far and wide for his luck,            │
          │ Till while jogging one day, he looked the wrong way,│
          │ Whereupon he was hit by a truck.                    │
          └─────────────────────────────────────────────────────┘

     When configured as a list of individual item (one per line), then the
     user can scroll through the data and “select” any item, just as an item
     is selected from a Menu control (see below).
          ┌Select Your Ride────────────────────┐
          │  1951 Studebaker Starlight Coupe   │
          │▶ 1967 Chevy Camero                 │
          │  1971 Dodbge Super Bee             │
          │  1977 Ford Bronco                  │
          └────────────────────────────────────┘

   ♦ Menu (ftMB):
     Menu controls are a special case in that there are three distinct types
     of menus, each performing a different task:

       1. Menubar: The Menubar is a single-row menu that acts as a anchor
          point for a group of menus which are functionally tied together.
          This is a common construct used in almost every GUI application.
          A Menubar may be initially invisible, but if desired, can be locked
          in the visible state.
          The Firefox browser menubar is:
          File  Edit  View  History  Bookmarks  Tools  Help
          ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
          Each item in the Menu bar is associated with at least one sub-menu,
          which together form the menu system for the application.

       2. Sub-menu:
          Sub-menus are menus attached to a Menubar (as described above). A
          sub-menu is invisible by default, and is opened by an action taken
          on the Menubar, or in combination with the Menubar via an
          application-defined hotkey.
               FILE   EDIT   HELP
               ▔▔▔▔▔▔▔│▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔│▔▔▔▔▔▔▔▔
                      │Copy Selection   (C-c)│
                      │Cut Selection    (C-x)│
                      │Paste Clipboard  (C-v)│
                      │Find Text        (C-f)│
                      └──────────────────────┘

       3. Context Menu
          A “Context menu” is a stand-alone menu that operates in a specific
          “context”. (duh!)

          A context menu is generally defined as invisible until it is needed;
          and becomes invisible again after a selection is made. It is
          possible, however, to lock a context menu in the visible state.
               ┌─────────────────┐
               │View Contents    │
               │View file Stats  │
               │Open (execute)   │
               │Find Link Target │
               │Cancel           │
               └─────────────────┘

          The context menu shown is from the author's FileMangler application
          *Note By the Same Author:: for a description.

Numerous functional examples of these controls are available throughout the
test applications included in the AnsiCmd library.
Please *note Development and Testing:: for a general description of the tests
available. Specifically, the tests listed under *note test W:: and *note test
D::, which contain subtests for Windows, skForm/skField and Dialogs invoked
with:
   ./epts --test=W
   ./epts --test=D
The AcEdit application includes a functional set of controls in an (almost)
real-world context.
   cd AcEdit
   ./ace



File: ansicmd.info,  Node: skForm Initialization,  Prev: UI Control Types,  Up: skForm Class

skForm Initialization
---------------------

To create an skForm template, allocate a new object specifying the number of
fields, the global parameters and the definition for each field.

   ┌─────────┤ ACWin-class Window ├─────────┐
   │ ┌────────────────────────────────────┐ │
   │ │▒▒▒▒▒▒Me love cookies! Cookie!▒▒▒▒▒▒│ │
   │ └────────────────────────────────────┘ │
   │                                        │
   │  [◆] Authorize daily cookie delivery   │
   │      ▔                                 │
   │            ▒▒Close Window▒▒            │
   │              ▔                         │
   └────────────────────────────────────────┘

Define the skForm template:
This example creates an skForm object with three(3) fields: a Textbox (ftTB),
a Radiobutton control (ftRB) and a Pushbutton control (ftPB).

Note that many parameters of these constructors have default values, but for
clarity, they are explicity initialized here. See skForm and skField
initialization constructors, above for details.

The working code for this example can be found in the 'Test_Cookie' method in
AnsiCmdTest.cpp.

     //* Focus Color: for controls which can change color when *
     //* they have input focus. (Pushbuttons, Radiobuttons)    *
     acAttr focusAttr = acAttr(acaFGb_GREY | acaBG_RED) ;
     //* Non-Focus (embedded) color for Pushbuttons and Radiobuttons. *
     acAttr nonFocus  = acAttr(acaFG_BLACK | acaBG_RED) ;
     WinPos wpul( 1, 2 ) ;                  // vertical/horizontal offsets
     const short pbFIELD   = 2 ;            // index of pushbutton field
     const short FLD_COUNT = 3 ;            // number of fields

     skForm *skfPtr = new skForm
     (
        FLD_COUNT,                 // number of skField objects in 'fldArray'
        new skField[FLD_COUNT]     // array of field definitions
        {
           //* Field index 0: ftTB (Textbox) *
           {
           ftTB,                            // field type
           1,                               // field height (in rows)
           winWIDTH - 6,                    // field width (in columns)
           wpul.row, wpul.col,              // Y/X offset in window
           "      Me love cookies! Cookie!",// initial field text
           acAttr(acaFG_DFLT | acaBG_CYAN), // color attributes for text
           floShift,               // text formatting option (text-editor mode)
           ZERO,                            // insertion point (cursor offset)
           false,                           // user accessible (not read-only)
           true,                            // field outline enabled
           false,                           // field is visible (not hidden)
           true,                            // access lock enabled
           false,                  // binary state not applicable to ftTB
           NULLCHAR,                        // no hotkey specified
           noGROUP                          // not a group member
           },
           //* Field index 1: ftRB (Radiobutton) *
           {
           ftRB,                            // field type
           1,                               // field height (in rows)
           winWIDTH - 6,                    // field width (in columns)
           short(wpul.row += 3), wpul.col,  // Y/X offset in window
                                            // field text with Hotkey '^A'
           "[♦] ^Authorize daily cookie delivery",
           acAttr(acaFG_BLUE | acaBG_GREY), // color attributes (non-focus)
           floShift,                        // text formatting option
           ZERO,                            // insertion point (cursor offset)
           false,                           // user accessible (not read-only)
           false,                           // field outline enabled
           false,                           // field is visible (not hidden)
           true,                            // access lock enabled
           true,                            // initial binary state: 'set'
           NULLCHAR,                        // no hotkey (embedded in text)
           noGROUP                          // not a group member
           },
           //* Field index 2: ftPB (Pushbutton) *
           {
           ftPB,                            // field type
           1,                               // field height (in rows)
           16,                              // field width (in columns)
           short(wpul.row += 2),            // Y/X offset in window
           short(winWIDTH / 2 - 9),
           "  ^Close Window  ",             // field text with Hotkey '^C'
           nonFocus,                        // color attributes
           floShift,                        // text formatting option
           ZERO,                            // insertion point (cursor offset)
           false,                           // user accessible (not read-only)
           false,                           // field outline enabled
           false,                           // field is visible (not hidden)
           true,                            // access lock enabled
           false,                           // initial binary state: 'reset'
           NULLCHAR,                        // no hotkey (embedded in text)
           noGROUP                          // not a group member
           }
        },
        //* Optional skForm arguments *
        // 'fldIndex'  index of field with initial focus (the Pushbutton)
        pbFIELD,
        // 'fldAttr'   color attributes for control with focus
        focusAttr,
        // 'noisy'     beep on unhandled keycode received
        true,
        // 'ioFlag'    initial state of Insert/Overstrike flag
        true,
        // 'ioToggle'  user access to Insert/Overstrike mode
        true,
        // 'ioCursor'  enable cursor shape change for Insert/Overstrike
        true,
        // 'insCursor' cursor shape when Insert mode
        csBblock,
        // 'ovrCursor' cursor shape when Overstrike mode
        csBuline
     ) ;

The initialized skForm template is then passed as a parameter for the ACWin
constructor. *Note ACWin constructor::.

     ACWin *winPtr = new ACWin
           ( winROW, winCOL,
             winHEIGHT, winWIDTH,
             ltSINGLE,
             acAttr(acaFGb_BROWN | acaBG_BLUE),
             acAttr(acaFG_RED | acaBG_GREY),
             " ACWin-class Window ",
             skfPtr  // partially-initialized skForm object
           ) ;

     //* The setup data may now be safely deleted. (prevent memory leaks) *
     delete skfPtr ; skfPtr = NULL ;

     //* Open the window (make it visible) *
     winPtr->OpenWindow () ;

     //* Get User Input : Returns when Pushbutton control is selected,*
     //* either by "pressing it" (Enter/Space) or via hotkey (ALT+C). *
     short fieldIndex ;   // on return contains index of exit field
     winPtr->EditForm ( fieldIndex, pbFIELD ) ;

     //* Close the window and delete the ACWin object.*
     winPtr->CloseWindow ();
     delete winPtr;

Note that the example above does not specify a callback function. The
'EditForm' method returns when user the selects the Pushbutton control. In the
more sophisticated examples, the callback function determines when the edit
loop should be terminated.
Please *note EstablishCallback:: for more information.

User Interaction - the skForm class and skField class
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

Initialization of an skForm object as a parameter for creating an ACWin window
is shown above.

Accessing the form provides a user interface, via the fields defined by the
skForm object.

After the ACWin object has been created, and the window has been opened, the
*note EditForm:: method is called to give the user access to the field(s).

Example of calling the EditForm method. This is a copy of the code used in the
*note Test_Cookie:: test method. See screenshot above.

  //* Define an ACWin object *
  ACWin *winPtr = new ACWin
        ( winROW, winCOL, 
          winHEIGHT, winWIDTH,
          ltSINGLE,
          acAttr(acaFGb_BROWN | acaBG_BLUE),
          acAttr(acaFG_RED | acaBG_GREY),
          "  Window Formatted With \"skForm\" ",
          skfPtr  // partially-initialized skForm object
        ) ;

  //* Open the window (make it visible) *
  winPtr->OpenWindow () ;

  //* Get User Input : Returns when enter key is pressed.*
  short fieldIndex ;   // on return contains index of exit field
  winPtr->EditForm ( fldIndex, wcsENTER ) ;

  //* Get a pointer to final field configuration, *
  //* and retrive final text and button state.    *
  const skForm* skfp = winPtr->GetForm () ;
  gString finalText = skfp->fld[0].txt ; // contexts of textbox
  bool finalRadio = skfp->fld[1].state ; // state of radiobutton flag

  //* Close the window and delete the object.*
  winPtr->CloseWindow () ;
  delete winPtr ;


--- --- --- --- ---
The skForm object is fully integrated into the ACWin-class window; however, it
is possible to make it visually _appear_ that the fields defined within the
skForm object are independent from the enclosing window.
If desired, the skForm object can be displayed in an “_invisible_”
(borderless) window. In fact, many of the skForm tests included with the
AnsiCmd library use a borderless window. See the Test_SoftEcho tests for
examples of this usage.



File: ansicmd.info,  Node: Dialog sub-Windows,  Prev: skForm Class,  Up: ACWin Class

Dialog sub-Windows
==================


What is a Dialog?
.................

A “window”, (*note ACWin Class::) is a sub-window within the terminal window.
In turn, a “dialog”, as defined within this project, is a sub-window created
within the ACWin parent window.

Dialog sub-windows are based on the ACDlg class. The ACDlg class is
constructed as a simplified version of the ACWin class and shares many
characteristics with ACWin.

The greatest difference is that all methods and data of the ACDlg class are
“protected”. This means that it's methods and data are not directly available
at the application level. All access is through specialized methods of the
ACWin parent class.

A dialog may be invoked to alert the user to some issue or to gather
information from the user which it would be inconvenient for the parent window
to request directly.

Dialogs are self-contained objects—that is, there are no post-launch methods
for modification of the displayed data, and for the “quick” dialog, there is
no callback method for monitoring user activity within the dialog.
This is in contrast to the ACWin-class window which may be updated at any time
under application control.

Two types of dialogs are defined:
  1) the “quick” dialog, and
  2) the “full initialization” dialog.

A common type of information dialog is to alert the user that she has made an
invalid request.
      ┌───────────────────────────────────────────────┐
      │ You may not delete the boot partition, Dummy! │
      │                                               │
      │                     CLOSE                     │
      └───────────────────────────────────────────────┘

A common type of decision dialog is to ask the user a yes-or-no question.
     ┌───────────────────────────────────────────────┐
     │ Are you sure you want to discard your changes │
     │ to this document?                             │
     │               DISCARD   CANCEL                │
     └───────────────────────────────────────────────┘

It is of course possible to configure the dialog to ask more complex
questions, such as:
     ┌───────────────────────────────────────────────┐
     │    >>>  When will you pay your taxes?  <<<    │
     │                                               │
     │      [◆] April 15th   [ ] December 31st       │
     │      [ ] When Hell Freezes Over               │
     │                                               │
     │      ASK_AGAIN_TOMORROW    BUZZ_OFF!          │
     └───────────────────────────────────────────────┘

Please refer to the chapter describing Dialog testing *note test D:: for
functional dialog examples.

The user interface for a dialog is an skForm structure, the same type of
structure used by the parent window; however, for Quick dialogs, the skForm
structure is automatically generated. For the full-initialization dialog, the
application designer may specify all user-interface configuration parameters.
Please *note skForm Class:: for a discussion of configuring the user
interface.


Technical Info About Dialog Objects
-----------------------------------


Size and position of the dialog:
................................

Three factors determine the dimensions of the dialog:
 1) the dimensions of the parent window
 2) the space needed to display the static text and dialog controls
 3) the position of the dialog (offset within the parent window)

Validating the Parameters: A significant amount of defensive programming is
needed to ensure that the dialog does not extend into or beyond the borders of
the parent window. Even so, the application programer could trash the display
if determined to do so. (Your mother would be so proud...)

Dialog height, width, vertical offset and horizontal offset may be specified
directly as invocation parameters, or may be dynamically calculated based upon
the dimensions of the static text to be displayed.

  1. A height of zero (0) indicates that the vertical dimension should be
     derived from the height of the static text plus top and bottom borders
     (plus one row which is assumed to be occupied by one or more controls).
       a. If the dimensions of the received text will not fit within the
          available space, the text will be automatically reformatted based on
          the specified dialog width and vertical/horizontal offsets (if
          specified) and the space available for the dialog.
  2. If a VALID height is specified (ZERO < dlgHgt < maxHgt), then that value
     will anchor the dimensioning calculations.
       a. If specified height is out-of-range, it will be set to the available
          height.
  3. A width of zero (0) indicates that the horizontal dimension should be
     derived from the width of the static text plus left and right borders
     (plus 2 columns for left/right indentation).
  4. If a VALID width is specified (ZERO < dlgWid < maxWid), the static text
     will be automatically reformatted as necessary to fit the specified
     dimension.
  5. The number, width and position of the controls are also factors in
     determining the height and width of the dialog.
     Note that it is impractical to programatically resize the dialog to
     accomodate the defined controls. The only check is whether the size and
     position of controls violate the borders of the dialog object. Please use
     care in specifying the dialog dimensions to contain the defined controls.
  6. Yes, there is method to this madness. This design fascilitates automatic
     resizing of the dialog (if necessary) while maintaining the relative
     positions of the dialog controls.

     If neither positioning nor dimensioning adjustments will keep the dialog
     within the available space, then the static text will be truncated and if
     necessary, the controls will be discarded. This guarantees that the
     dialog will open successfully, although its appearance may come as a
     surprise.


Positioning of Dialog Controls:
...............................

  A. Vertical offset: orig.row
       a. Positive values specify an offset from the top border of the dialog.
          Range: 1 through dialog height minus one
          A value of zero(0) is not valid, and will be converted to 1.
          Example: For a dialog of 12 rows, the range would be:
                1 <= offset <= 10

       b. Negative values specify an offset from the bottom border of the
          dialog.
          Range: -1 through negative dialog height minus one
          Example: For a dialog of 12 rows, the range would be:
                -1 >= offset >= -10

  B. Horizontal offset: orig.col
     This value represents the offset in columns from the center of the
     dialog.
       a. A zero(0) indicates that the control is centered between the left
          and right borders.
       b. A positive value is a rightward offset from the center.
       c. A negative value is a leftward offset from the center.
          Example: 
          For a dialog with a width of 31 columns, the range would be:
          -14 <= offset <= 14 
            11111987654321012345678911111 
            43210         -         01234 
          
          For a dialog of 30 columns, the range would be: 
          -14 <= offset <= 13 
            1111198765432101234567891111 
            43210         -         0123


                            ────────────────────


Quick Dialog Configuration
..........................

bool QuickDialog ( const gString& gsMsg, bool query,
                   const char* title = NULL,
                   short height = 0, short width = 0,
                   short vOff = 0, short hOff = -1,
                   short timeout = 0, bool dbg = false );

Description of Parameters
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

  A. Only two(2) parameters are required:
       1) the message to be displayed
       2) the type of user interaction: informational or query.
     All other parameters are optional.

  B. A title for the dialog window may optionally be specified.
     If specified, the dialog title will be displayed in the top border of the
     dialog and horizontally centered. See example below.

  C. The dimensions (height and width) of the dialog are based on the text
     rows and columns required to display the formatted message data
      _unless_
     text would extend beyond the available vertical or horizontal space _or_
     would extend beyond the dimensions specified by the optional dimension
     parameters, in which case, the text will be automatically reformatted.
       - Note that if the text must be reformatted, the flag enabling
         line breaks on hyphen-like characters is set.
     Please *note acFormatParagraph:: for a discussion of automatic text
     formatting.

     The optional 'height' and 'width' may be used to override the formatting
     of the message text 'gsMsg'.

  D. Minimum Dimensions:
        — The dialog height must be at least four(4) rows: top border, text
          row, pushbutton row and bottom border.
        — The dialog width must be at least four(4) columns PLUS the width of
          the pushbutton(s). The width of the pushbuttons is determined by the
          the label text and whether there is one pushbutton (info dialog) or
          two (decision dialog). The default (English) label text is of the
          form:
           "__OK__ _CANCEL_"
          (16 columns for a decision dialog, or six columns for an info
          dialog)

  E. Maximum Dimensions:
        — The width of the dialog plus the horizontal offset must not cause
          the dialog to extend into the border of the parent window.
        — The height of the dialog plus the vertical offset must not cause the
          dialog to extend into the border of the parent window.

  F. Dialog offset from from origin (upper-left corner) of parent window.
     The 'vOff' parameter is the vertical offset from the top of the parent
     window.
     By default, 'vOff' is set to zero, which means that the dialog is
     positioned at the top row of the parent window.
     The special value of -1 indicates that the dialog is to be vertically
     centered in the parent window.

     The 'hOff' parameter is the horizontal offset from the left edge of the
     parent window.
     By default, 'hOff' is set to -1 indicating that the dialog is to be
     horizontally centered in the parent window.

     If the combined offset and dialog dimension would obscure the parent
     window's border, the dialog offset and/or dialog dimensions will be
     adjusted so that the dialog will be displayed entirely within the parent
     window.
        — In no case will the parent window's border be obscured.
        — In no case will the dialog be less than minimum size in either
          dimension.
        — In no case will the dialog fail to open.

  G. A QuickDialog window has either one or two Pushbutton controls which are
     automatically generated by the call.

     The language for the text of the pushbutton controls is matched to the
     active "locale" (at least for the languages we know): English, Spanish,
     Chinese (simplified) and Vietnamese. The language defaults to English if
     the locale is not one of the recognized locales.
         Our ancient Greek and Sanskrit would probably be worthless
         here, as they are under most circumstances. :-)
               संस्कृतं भव्यं लिखितभाषा अस्ति

       const short LANGS = 4 ;
       const wchar_t *ymsg[LANGS] =  // default pushbutton messages
       {
          L"  ^OK  ",                // English
          L" ^.好的 ",               // Zhongwen (Hǎo de)
          L" De ^Acuerdo ",          // Español
          L" ^Tốt "                  // Tieng Viet
       } ;
       const wchar_t *nmsg[LANGS] = 
       {
          L" ^CANCEL ",              // English
          L"  ^,取消  ",             // Zhongwen (Qǔxiāo)
          L" ^Cancelar ",            // Español
          L" ^Hủy Bỏ  "              // Tieng Viet
       } ;
     Support for additional languages may be added easily by extending these
     arrays; testing for the associated system locale, and setting the
     language index accordingly.

     A special case of the information dialog is the “automatic-timeout”
     dialog which has no user-interface controls. It is displayed for a
     specified amount of time, then closes automatically.

  H. The dialog's message text (gsMsg) is positioned vertically at the top
     interior row of the dialog, and is indented horizontally by one column
     from the left edge of the dialog interior.



                            ────────────────────


Full-initialization Dialog Configuration
........................................

bool Dialog ( short dlgHgt, short dlgWid,
              skForm* formDef,
              const char* sTxt = NULL,
              const char* tTxt = NULL,
              short vOff = -1, short hOff = -1,
              LineType ltype = ltSINGLE,
              acAttr bdrAttr = acaUSEDFLT,
              acAttr txtAttr = acaUSEDFLT,
              short tvOff = 0, short thOff = 1,
              CUPTR callbk = NULL,
              bool dbg = false );

Description of Parameters
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

Three(3) parameters are required: dlgHgt, dlgWid and formDef.
All other parameters are optional, and if not specified, receive default
values as described above.

  A. ‘dlgHgt’ Dialog Height
     An absolute height (number of display rows) may be specified by setting
     the 'dHgt' parameter to a value >= the arbitrary minimum of four(4) rows
     and less than the height of the parent window MINUS 'vOff'.

     Automatic calculation of the dialog height is specified by setting
     the 'dHgt' parameter to zero.
     - If the display text is pre-formatted, then the height of the text
        (plus padding) determines the height of the dialog.
        - "padding" includes the upper and lower borders plus one(1)
           internal row.
     - If the dialog height cannot be determined directly from the source
        text, or if the source text is taller than the available space,
        then the text may be automatically reformatted (and if necessary,
        truncated) to fit within the available space.
        The dialog height will then be the height of the reformatted text
        plus padding.
     - See also the note below about dialog controls.

  B. ‘dlgWid’ Dialog Width
     An absolute width number of display columns) may be specified by setting
     the 'dlgWid' parameter to a value >= the arbitrary minimum of eight(8)
     columns and no larger than the interior width of the parent window
     _MINUS_ 'hOff'.

     Automatic calculation of the dialog width is specified by setting the
     'dWid' parameter to zero.
     - If the display text is pre-formatted, then the width of the text
        (plus padding) determines the width of the dialog.
        - "padding" includes the left and right borders plus two(2)
           internal columns.
     - If the dialog width cannot be determined directly from the source
        text, or if the source text is wider than the available space,
        then the text may be automatically reformatted to fit within
        the available space.
        The dialog width will then be the width of the reformatted text
        plus padding.
     - See also the note below about dialog controls.

  C. ‘formDef’ Controls defined by an skForm object
     For a detailed discussion of the skForm class and its skField-class
     array, please *note skForm Class::.

     All control types defined by *note enum FldType:: are supported within a
     dialog window, with the following limitations:

        ▫ Although the skForm class does not place an upper limit on the
          number of controls, the range of controls in a dialog is limited to:

              1 <= count <= MAX_DLG_CTRLS

        ▫ At least one defined control must be a Pushbutton (ftPB)
          To exit the dialog, the user must select any defined Pushbutton
          control, either by placing focus on the control and pressing the
          Enter (or Space) key, or via the hotkey defined for the control.
          Optionally, exiting the dialog can be signalled from within the
          callback function if specified. In that case, dialog exit via
          Pushbutton is not mandatory.

        ▫ Textbox control (ftTB) height is limited to one row.
          (Although Textbox controls are designed as multi-row controls, the
          decision was made to limit the height within dialog windows in order
          to greatly simplify the user-interface algorithm. We may revisit
          this decision in a later release.)

        ▫ Menu controls (ftMB) are supported, but are limited to 'context'
          menus (multi-item stand-alone menus) only; AND unlike context menus
          defined in the parent window, the menu will automatically be set as
          always visible.
          (Enforcing menu visibility in this way significantly enhances the
          efficiency of the display refresh routine. We may revisit this
          decision in a later release.)

        ▫ Control outlines and external labels:
          Within a dialog, the data members that define outlines and labels
          are ‘protected’ members; that is, they may not be directly modified
          at the application level. Two specialized public methods of the
          skField class are available to configure these options:

            bool outlineConfig ( LineType lType, acAttr lAttr );
            bool labelConfig ( const char* labText, acAttr labAttr, bool center );

          Please *note skField Public Methods:: for details.

        ▫ Color attribute customization:
          Customization of text color attributes is often useful to enhance
          readability. For multi-row controls which contain fixed display
          text, color attributes for each individual display row may be
          specified. These are multi-row Menu controls (ftMB) and Scrollbox
          controls (ftSB) _only_.

          Within a dialog, the data member which defines per-item color
          attributes is ‘protected’, that is, it may not be directly modified
          at the application level. A specialized method of the skField class
          is available to configure this option:
            bool colorConfig ( const acAttr* rowAttr, short rowCnt );
          Please *note skField Public Methods:: for details.


  D. ‘sTxt’ Static text within the dialog
     Static text is any text written directly to the dialog interior and that
     is not within any dialog control object.

     The static text and the controls may occupy the same space without error.
     For instance the text may be above, below and on either side of a
     control. Just be sure that the text is not obscured by the control. To do
     this, the static text should contain only spaces (or newlines '\n') under
     the area occupied by the control and the control label (if any).

     For example, the following static text data will be rendered in a dialog
     with two Pushbutton controls as shown.

           "This application cannot honor your request\n"
           "for cookie delivery. Use DoorDash, OR:\n"
           "\n"
           "You may actually need to leave your parents'\n"
           "basement to find them. Sorry about that...\n"
           " " ;

          ┌──────────────┤ ACWin-class Window ├──────────────┐
          │                                                  │
          │ ┌──────────────┤  Nerd Alert!  ├───────────────┐ │
          │ │ This application cannot honor your request   │ │
          │ │ for cookie delivery. Use DoorDash, OR:       │ │
          │ │             ▒▒Call A Therapist▒▒             │ │
          │ │ You may actually need to leave your parents' │ │
          │ │ basement to find them. Sorry about that...   │ │
          │ │                                              │ │
          │ │               ▒▒Exit Dialog▒▒                │ │
          │ └──────────────────────────────────────────────┘ │
          │                                                  │
          │           ▒▒▒▒▒▒Me love cookies!▒▒▒▒▒▒           │
          │                                                  │
          │       [◆] Authorize daily cookie delivery        │
          │                                                  │
          │                 ▒▒Close Window▒▒                 │
          └──────────────────────────────────────────────────┘

  E. ‘tTxt’ Text of dialog title
     If specified, the dialog title will be displayed in the top border of the
     dialog and horizontally centered.

     For optimal display, it is recommended that the first and last characters
     of the title text be spaces, although this is not enforced.
        Example: " Nerd Alert! ".
     The text will be truncated if necessary to fit within the width of the
     dialog.

     The title text will be bracketed by delimiter characters corresponding to
     the border style and color specified for the dialog as shown in the
     example above.

  F. ‘vOff’ Vertical offset of dialog in parent window
     This is the (0-based) offset in rows from top of parent window. This
     parameter is optional, and the default value is minus one (-1),
     indicating that the dialog is to be centered vertically in the parent
     window.

  G. ‘hOff’ Horizontal offset of dialog in parent window
     This is the (0-based) offset in columns, from left edge of the parent
     window. This parameter is optional, and the default value is minus one
     (-1), indicating that the dialog is to be centered horizontally in the
     parent window.

  H. ‘lType’ Border style
     This optional parameter specifies the border style as a member of enum
     LineType. By default, the border is drawn with a single-width line
     (ltSINGLE), but a dual-width line (ltDUAL) may be specified.

  I. ‘bAttr’ Border color
     This optional parameter specifies the border color attributes.
     By default, the dialog inherits the border colors from the parent window;
     however, any foreground/background color attribute may be specified.
     *Note acAttr Enumerated Type: enum acAttr, for more information on color
     attribute specification.

  J. ‘tAttr’ Interior text color
     This optional parameter specifies the color attributes for the interior
     of the dialog (static text and dialog background).
     By default, the dialog inherits the interior color attributes from the
     parent window; however, any foreground/background color attribute may be
     specified.
     *Note acAttr Enumerated Type: enum acAttr, for more information on color
     attribute specification.

  K. ‘tvOff’ Vertical offfset for static text
     This optional parameter specifies the vertical offset at which to draw
     the dialog static text.
     By default, 'tvOff' is set to zero, indicating that the static text is to
     be drawn starting on the top row of the dialog interior.
     A positive value indicates an additional vertical offset.

  L. ‘thOff’ Horizontal offfset for static text
     This optional parameter specifies the horizontal offset at which to draw
     the dialog static text.
     By default, 'thOff' is set to one(1), indicating that the static text is
     to be drawn starting at one column from the left edge of the dialog
     interior. A positive value indicates an additional horizontal offset.

  M. ‘callbk’ Pointer to a non-member callback function.
     The full-initialization dialog supports an external callback function
     which can be used to monitor user activity within the dialog window.

     The callback functionality for a dialog is identical in most respects to
     a callback function for the the parent window.

       a. The callback is invoked using the same CUPTR template (macro), but
          instead of calling the *note EstablishCallback:: method, the CUPTR
          is passed as a parameter to the Dialog method.
          The callback function is based on the the following template:
            typedef wchar_t (*CUPTR)( short ctrlIndex, 
                                      wchar_t wkey, bool firstTime );

       b. User interactions with the dialog's controls can be monitored and
          directed just as they are in the parent window; however,
          window-specific methods of the ACWin class are not applicable to
          dialogs.

       c. For this reason, the ACWin class defines several dialog-specific
          methods for use by dialog callback functions:
               Dialog_GetText
               Dialog_SetText
               Dialog_GetItem
               Dialog_GetState
               Dialog_GetStateXOR
               Dialog_GetField
               Dialog_Write
               Dialog_Refresh
          Please *note Dialog-Oriented Methods:: for details.

       d. Each of these methods is demonstrated in the *note AcEdit Demo App::
          utility. The developer may find it instructive to study this method;
          therefore, the full callback source (version 0.0.04) is presented
          below: (*note example callback::).

  N. ‘dbg’ (for debugging only) If this flag is set, it allows the dialog
     window to remain open after control is returned to the application. This
     is useful during testing for verification that the reported results
     correspond to the visual data.


Example Dialog Callback
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

The working code for this example is located in the AcEditMenu.cpp module,
sfaCallback method. This callback monitors user specification of a filename
for the save-file-as operation. The user may traverse the the filesystem tree
to select the target directory and specify a filename for the data to be
written to that directory.

//***** Static, non-member function directing *****
//***** callback to member method.            *****
static wchar_t nonmember_dlgCallback ( short ctrlIndex, wchar_t wkey, 
                                       bool firstTime )
{
   return ( (aceditPtr->sfaCallback ( ctrlIndex, wkey, firstTime )) ) ;
}  //* End nonmember_dlgCallback() *

//***** AcEdit member method invoked as the *****
//***** Callback method for saveFileAs()    *****
wchar_t AcEdit::sfaCallback ( short ctrlIndex, wchar_t wkey, 
                              bool firstTime )
{
   static const char* Warn_Dupe[uilENV] =
   { // Warn field width is 28 columns.
      "Error, file already exists.",   // English
      "错误，文件已存在。",               // Zhongwen
   } ;
   static const char* Warn_Name[uilENV] = 
   {
      "Invalid filename characters.",  // English
      "错误，文件名中包含无效字符。",      // Zhongwen
   } ;
   static const char* Warn_Access[uilENV] =
   {
      "Unable to access target dir!",  // English
      "无法访问目标目录！",               // Zhongwen
   } ;
   static const char* noName[uilENV] = 
   {
      "  Filename not specified.",     // English
      "       未指定文件名。",           // Zhongwen
   } ;
   static const char* Cancel_Msg[uilENV] = 
   {
      "    Operation Cancelled.",      // English
      "      重命名操作已取消。",         // Zhongwen
   } ;

   // dialog row where filter message is displayed
   const short filterMsgRow = 10 ;
   // set if warning message is visible
   static bool warnMsg = false ;
   gString gs, gsCwd, gsName, gsList ;
   const skField* skfPtr = NULL ;// pointer to a control within the dialog
   acAttr* acArray = NULL ;   // pointer to array of Scrollbox attributes
   short itemCnt ;            // number of items in Scrollbox control
   short item ;               // Scrollbox item selected
   bool  vfat ;               // state of text filter Radiobutton
                              // (set==VFAT compatible)

   //*------------*
   //* First call *
   //*------------*
   if ( firstTime )
   { /* Nothing to do at this time. */ }

   //* If a warning message is currently displayed, erase it. *
   if ( warnMsg )
   {
      gs.clear() ;
      this->win->Dialog_SetText( sfaWARN, gs ) ;
      warnMsg = false ;
   }

   //* Note that the hotkey for a field has been automagically  *
   //* converted to wcsENTER.                                   *
   if ( (wkey == wcsENTER) || (wkey == wcsSPACE) )
   {
      switch ( ctrlIndex )
      {
         case sfaSAVE:
            // retrieve filename data
            this->win->Dialog_GetText ( sfaTEXT, gsName ) ;
            if ( (gsName.gschars()) > 1 )
            {
               //* Validate the filename characters.                *
               //* Radiobutton state determines which filter to use.*
               this->win->Dialog_GetState ( sfaVFAT, vfat ) ;
               if ( !(this->isFilename ( gsName, false, vfat )) )
               {
                  //* Warn of invalid filename character(s) *
                  gs = Warn_Name[this->lang] ;
                  this->win->Dialog_SetText( sfaWARN, gs ) ;
                  warnMsg = true ;  // remember that warning was posted
                  wkey = NULLCHAR ; // keycode handled
               }
               else
               {
                  // Get Scrollbox text. Compare user-provided filename
                  // with each filename in the array of filenames in CWD.
                  this->win->Dialog_GetField ( sfaCWD, skfPtr ) ;
                  gsCwd = skfPtr->txt ;
                  // pointer to source data
                  const wchar_t* wsrc = gsCwd.gstr() ;
                  wchar_t wtrg[MAX_FNAME] ;      // filename target buffer
                  int   wchars = gsCwd.gschars(),// source characters
                        si = ZERO,
                        ti = ZERO ;              // target index
                  bool match = false ;           // set if duplicate name
                  //* Step over the "parent-dir" item at top of list.*
                  while ( (si < wchars) && (wsrc[si] != NEWLINE) )
                     ++si ;
                  ++si ;

                  //* Extract each filename *
                  for( ; si < wchars ; ++si )
                  {
                     while ( (wsrc[si] != NEWLINE) && 
                             (wsrc[si] != NULLCHAR) )
                        wtrg[ti++] = wsrc[si++] ;
                     wtrg[ti] = NULLCHAR ; // terminate the string
                     ti = ZERO ;           // reset target index
                     gs = wtrg ;           // load raw data item
                     gs.shiftChars( -3 ) ; // discard item prefix
                     gs.strip() ; // strip leading/trailing whitespace
                     //* Compare with user's filename *
                     if ( (gsName.compare( gs )) == ZERO )
                     { match = true ; break ; }
                  }

                  //* If user's data matches an existing    *
                  //* filename in CWD, warn of duplication. *
                  if ( match )
                  {
                     gs = Warn_Dupe[this->lang] ;
                     this->win->Dialog_SetText( sfaWARN, gs ) ;
                     warnMsg = true ;  // remember that warning was posted
                     wkey = NULLCHAR ; // keycode handled
                  }

                  //* Else, a valid, non-duplicate filename    *
                  //* specified. Signal that dialog s/b closed.*
                  //* Filename is in Textbox control.          *
                  else
                     wkey = wcsCTL_4 ;
               }
            }
            else     // empty filename string
            {
               gs = noName[this->lang] ;
               this->win->Dialog_SetText( sfaWARN, gs ) ;
               this->win->nsleep ( 20 ) ;
               wkey = wcsCTL_4 ;
            }
            break ;

         case sfaCANCEL:                  // Cancel pushbutton
            gs = Cancel_Msg[this->lang] ;
            this->win->Dialog_SetText( sfaWARN, gs ) ;
            this->win->nsleep ( 16 ) ;
            wkey = wcsCTL_4 ;
            break ;

         case sfaCWD:         // Scrollbox display of CWD files
            //* Get a copy of "selected" item *
            if ( (this->win->Dialog_GetItem ( sfaCWD, gs, item )) )
            {
               // isolate indicator character
               wchar_t indyChar = *gs.gstr() ;
               gsName = &gs.gstr()[2] ;    // item text without prefix

               //* Move to parent directory or subdirectory *
               if ( (indyChar == PCHAR) || (indyChar == DCHAR) )
               {
                  //* Get filespec of CWD *
                  if ( !(this->getCWD ( gsCwd )) ) { gsCwd = L"." ; }
                  if ( indyChar == PCHAR )   // moving to parent directory
                  {
                     gs = gsCwd ;
                     this->ExtractPathname ( gsCwd, gs ) ;
                  }
                  else                       // moving to subdirectory
                     gsCwd.append( "/%S", gsName.gstr() ) ;

                  if ( (this->setCWD ( gsCwd )) )
                  {
                     //* Scan new CWD and format the entries.  *
                     // Create an array of color attributes to *
                     //* match the records                     *
                     this->win->Dialog_GetField ( sfaCWD, skfPtr ) ;
                     itemCnt = this->readCwd ( gsList, acArray, 
                                               skfPtr->wid ) ;
                     // Update text data, and array of color attributes.
                     // Programmer's Note: Refresh is not performed after
                     // text update, but is performed only after attribute
                     // update.
                     this->win->Dialog_SetText ( ctrlIndex, gsList, 
                                                 acaUSEDFLT, false ) ;
                     this->win->Dialog_SetAttr ( ctrlIndex, acArray, 
                                                 itemCnt ) ;

                     // release the dynamic allocation
                     if ( acArray != NULL )
                     { delete[] acArray ; acArray = NULL ; }
                     //* Signal caller that operation is compete.*
                     wkey = NULLCHAR ;
                  }
                  else
                  { //* Malformed filespec OR user lacks read access *
                     gs = Warn_Access[this->lang] ;
                     this->win->Dialog_SetText( sfaWARN, gs ) ;
                     warnMsg = true ;  // remember that warning was posted
                     wkey = NULLCHAR ; // keycode handled
                  }
               }
               else                    // non-directory filename
                  this->win->Dialog_SetText ( sfaTEXT, gsName ) ;
            }
            // else(call is unlikely to fail)
            break ;

         case sfaVFAT:
            //* State of Radiobutton is being toggled.          *
            //* Match the filter message with Radiobutton state *
            //* NOTE: The state flag has not yet been updated   *
            //* at this point, so the sense is reversed.        *
            this->win->Dialog_GetState ( sfaVFAT, vfat ) ;
            gs = sfaFilterMsg[this->lang][(vfat ? 0 : 1)] ;
            this->win->Dialog_Write ( gs.gstr(), filterMsgRow, 0, true ) ;
            break ;
      } ;
   }
   return wkey ;

}  //* End sfaCallback() *




File: ansicmd.info,  Node: Development and Testing,  Next: Building from Source,  Prev: ACWin Class,  Up: Top

Development and Testing
***********************

The methods described in this chapter test all major functionality of the
AnsiCmd class and the AnsiCmd library as a whole.

These methods are not required for application development, and are therefore
under a conditional compile directive so they can be disabled in a production
build. The EarthPoints test application includes these tests in order to
demonstrate all AnsiCmd functionality.
Please *note Build Options:: for more information on conditional compilation
options.

Each test may be invoked through a command line option.
Please *note Invoking - AnsiCmd Tests:: for a list of available options.

The following is a list of the primary test methods found in the
AnsiCmdTest.cpp source file.
Each method header contains detailed information about that test, and
exhaustive comments are sprinkled throughout the test code to indicate _what_
is being tested, _how_ it is being tested, and _why_ it is being tested. These
comments should answer most questions about the AnsiCmd library, and at the
very least, they offer an example of how code should be commented.

     ┌─────────────────────────────────────────────────────────────────┐
     │ Editorial:                                                      │
     │ Many students misunderstand the purpose of comments within the  │
     │ source code. Comments DO NOT explain what your code does; the   │
     │ the code explains itself.                                       │
     │ Rather, comments describe what your code is _intended_ to do.   │
     │ That is why comments are (nearly) always written before the     │
     │ code itself. Comments explain to _you_ what needs to be done,   │
     │ so that after the code is written and fully functional, you can │
     │ compare the code with the comments to see if they agree; and    │
     │ if not, adjust the one that is incomplete.                      │
     │   — Software Sam                                                │
     └─────────────────────────────────────────────────────────────────┘

Many of these methods also invoke support methods for user interface duties or
for various often-used calculations.

Note also that many of these test methods write diagnostic data to the
debugging log: "dbg.log" created in the source code directory.

   ▪ void ansiTest_Menu ( dbgArgs& args );
          *Note Invoking - AnsiCmd Tests::

     This method is called from the application layer by the public method:
     *note ansiTest:: which determines whether the conditionally-compiled test
     code is present in the library.

     ansiTest_Menu is the entry point for invoking the individual tests.
     The command-line arguments are validated and formatted as call
     parameters, and the appropriate test (or test sub-menu) is invoked.

   ▪ void Test_4Bit ( void );
          *Note test C:: (f) invocation option.

   ▪ void Test_Bg ( void );
          *Note test C:: (b) invocation option.

   ▪ void Test_8bitColor ( void );
          *Note test C:: (t) invocation option.

   ▪ void Test_RGB ( wchar_t rgbTest );
          *Note test C:: (r) invocation option.

   ▪ void Test_Greyscale ( void );
          *Note test C:: (g) invocation option.

   ▪ void Test_AixFgBg ( void );
          *Note test C:: (a) invocation option.

   ▪ void Test_acaExpand ( void );
          *Note test C:: (d) invocation option.

   ▪ void Test_acaExpandSwap ( void );
          *Note test C:: (s) invocation option.

   ▪ void Test_AltFonts ( aeSeq fg );
          *Note test F:: invocation option.

   ▪ void Test_CursorPos ( aeSeq fg );
          *Note test P:: invocation option.

   ▪ void Test_Erasures ( aeSeq fg );
          *Note test E:: invocation option.

   ▪ void Test_AsciiCodes ( aeSeq fg );
          *Note test A:: invocation option.

   ▪ void Test_Ideogram ( aeSeq fg );
          *Note test I:: invocation option.

   ▪ void Test_UnbufferedInput ( aeSeq fg );
          *Note test T:: (i) invocation option.

   ▪ void Test_TermFlags ( aeSeq fg );
          *Note test T:: (t) invocation option.

   ▪ void Test_ModFlags ( aeSeq fg );
          *Note test T:: (m) invocation option.

   ▪ void Test_NonBlock ( aeSeq fg );
          *Note test T:: (b) invocation option.

   ▪ void Test_RawInput ( aeSeq fg );
          *Note test T:: (r) invocation option.

   ▪ void Test_OutputStream ( aeSeq fg );
          *Note test T:: (o) invocation option.

   ▪ void Test_SoftEcho ( wchar_t eOpt, aeSeq fg );
          *Note test T:: (e) invocation option.

   ▪ void Test_Write ( aeSeq fg );
          *Note test T:: (f) invocation option.

   ▪ void Test_Window ( aeSeq fg );
          *Note test W:: (w) invocation option.

   ▪ void Test_Form ( aeSeq fg );
          *Note test W:: (f) invocation option.

   ▪ void Test_Wrap ( aeSeq fg );
          *Note test W:: (t) invocation option.

   ▪ void Test_WinDefault ( aeSeq fg );
          *Note test W:: (d) invocation option.

   ▪ void Test_Fifo ( aeSeq fg );
          *Note test W:: (s) invocation option.

   ▪ void Test_Menu ( aeSeq fg );
          *Note test W:: (m) invocation option.

   ▪ void Test_Hilite ( aeSeq fg );
          *Note test W:: (h) invocation option.

   ▪ void Test_Cookie ( aeSeq fg );
          *Note test W:: (e) invocation option.

   ▪ void Test_Box ( aeSeq fg );
          *Note test W:: (b) invocation option.

   ▪ void Test_Line ( aeSeq fg );
          *Note test W:: (l) invocation option.

   ▪ void Test_Clipboard_API ( aeSeq fg );
          *Note test W:: (x a) invocation option.

   ▪ void Test_Clipboard_Win ( aeSeq fg );
          *Note test W:: (x w) invocation option.

   ▪ void Test_Tfman ( aeSeq fg );
          *Note test W:: (x t) invocation option.

   ▪ void Test_LaunchExt ( wchar_t opt, aeSeq fg );
          *Note test W:: (x) invocation option.

   ▪ void Test_Dialog ( wchar_t tst );
          *Note test D:: invocation option.

   ▪ void Test_Sandbox ( wchar_t parmA, wchar_t parmB );
          *Note test S:: invocation option.

     This method is provided so that the application developer can write
     experimental code and test it before moving it to the application.
     Because this is an AnsiCmd-class member method, the test code has access
     to all the internal functionality of the library.

     The Test_Sandbox method is presented here in its entirety.
     This is the best ride in the amusement park. Have fun!!

     void AnsiCmd::Test_Sandbox ( wchar_t parmA, wchar_t parmB )
     {
        gString gsOut( "Welcome to the Sandbox!\n" ) ;
        this->ttyWrite ( gsOut ) ;
     
        //* Create Tests Here... *
     
     
     
     
        //* --- End of Sandbox Area - Do Not Modify This Line --- **
        this->acSetCursor ( aesCUR_ABSPOS, (this->termRows - 1), 1 ) ;
     
     }  //* End Test_Sandbox() *



File: ansicmd.info,  Node: Building from Source,  Next: gString Text Tool,  Prev: Development and Testing,  Up: Top

Building from Source
********************

Tools
=====

The AnsiCmd library and the EarthPoints test application are written in C++
and are built with the GNU C++ compiler and linker. No additional link
libraries or third-party tools are needed.

   ▪ GCC (G++) version 8 and above, (support for C++17 or greater).


Compiling
=========

The AnsiCmd library is compiled using the GNU/G++ compiler which is invoked
through the 'gmake' ('make') utility. The compile and linking instructions are
contained in the file named 'Makefile'.

     Examples:
           gmake all
           gmake clean
           gmake
           gmake buildlib    # build the AnsiCmd library only


Build Options
=============

Conditional compilation directives control the build options, both for the
AnsiCmd class library and the EarthPoints application.

Four major conditional-compilation directives control most, if not all the
sub-directives. The first is the INCLUDE_API directive which enables or
disables inclusion of the high-level constructs related to the creation of
window objects and user-interface controls.
The second is the DEBUG_ANSICMD_TEST directive which enables the test suite
located in AnsiCmdTest.cpp.
The other two directives manage the debugging code embedded within the AnsiCmd
library methods. These embedded tests are used to verify algorithm design and
functionality for the library as a whole.
These are the DEBUG_ANSICMD and DEBUG_LOG directives. All other debugging code
is designed to be subordinate to these. If these two are enabled, debugging
code (other than the test suite) is potentially enabled. If these two
directives are disabled, then all debugging code is disabled.

Because the AnsiCmd class as well as the EarthPoints application are primarily
experimental in design, a large number of conditional-compilation directives
are defined to assist in development and debugging of the code. The following
is a list of the directives which persist beyond the immediate needs of the
programming day.

Please *note Development and Testing:: for more information.


AnsiCmd Class Directives
------------------------

  1. DEBUG_ANSICMD
     This directive is defined in AnsiCmd.hpp, and is the master directive for
     all debugging code within the AnsiCmd class.
         #define DEBUG_ANSICMD (1) debugging code is compiled.
         #define DEBUG_ANSICMD (0) debugging code is excluded.

     All other debugging directives in the AnsiCmd source code are nested
     within this directive. Setting the definition to zero _SHOULD_ disable
     all debugging code within the AnsiCmd class, _including_ all the testing
     methods (grouped under DEBUG_ANSICMD_TEST).

  2. DEBUG_ANSICMD_TEST
     This directive is defined in AnsiCmd.hpp, and controls whether the test
     suite is included in the library build. This directive should be enabled
     when linking with the EarthPoints application, so that all tests and
     diagnostic code will be available. The test suite is optional when
     linking the library with the other demo apps. If present, it will not
     affect the functionality of those apps; however, disabling the test suite
     will reduce the size of the compiled library by approximately 500Kb.

  3. DEBUG_LOG
     This directive is defined in AnsiCmd.hpp, and controls whether a log file
     will be created to contain miscellaneous debugging information.

     If enabled (1), the file will be created in the source code directory
     with the name: “dbg.log”. If a file of that name already exists, it will
     be overwritten. The file is closed before the program exits.

     The log file contains detailed data on the program execution sequence and
     the results of specific operations. For instance it can report
     configuration data or interim results of binary operations such as:
        decode( fgIndex:04 hue:00 shade:00 r:0 g:0 b:0 )
              ( bgIndex:02 hue:00 shade:00 r:0 g:0 b:0 )
                ---r brfc --mods--- --bgnd--- --fgnd---
               b0000-0000-0000-0111-0000-0010-0000-0100

  4. Default Configuration
     As distributed, the package should have INCLUDE_API directive, as well as
     the DEBUG_ANSICMD, DEBUG_LOG and DEBUG_ANSICMD_TEST directives enabled,
     which in turn enables the tests of library functionality in the
     EarthPoints application.
     To verify this, after unpacking the archive, use the 'grep' utility to
     display the debugging directives:
        grep -n '#define DEBUG_' *.[hc]pp | grep '[(]1[)]' 
        (This is why OCD is not really a “disorder” at all. :-)

     As a convenience, a small Perl utility, 'report.pl' is included in the
     distribution archive. This utility will report the current state of the
     conditional-compile directives described above.
     This utility is also invoked by the Makefile when performing a clean
     build:
           gmake all

  5. Embedded Debugging Directives
     These directives may be enabled temporarily to verify intermediate states
     of data and execution flow for a particular section of the code. These
     directives typically affect only one method, or a small group of related
     methods. These directives may affect overall library functionality and so
     should be disabled when not being directly monitored.

                                 ──────────

        ▫ DEBUG_CURPOS
        ▫ DEBUG_SEQUENCE
          These directives are defined within the acGetCursor method, in the
          AnsiCmd.cpp module.

          The test code uses the debugging log file (see above) to report the
          transmission of the ANSI escape sequence commands and the capture of
          the response.

          The ANSI escape sequence for _get-cursor-position_ is the most
          complex of the escape sequences defined by the standard. This is
          because after issuing the command, the response is returned to the
          application as an escape sequence via 'stdin'. This opens the
          possibility of trashing the display.

          For this reason, special attention is given to the algorithm used to
          capture the incomming data. — It works, but keep an eye on it.

        ▫ DEBUG_SOFTKEY
          This directive is defined within the specialkeyDecode method, in the
          AnsiCmd.cpp module.

          The test code uses the debugging log file (see above) to report the
          captured byte sequences, convert them to standard keycodes and
          determine whether the keycode belongs to the group of “special” i.e.
          cursor-control keys.

        ▫ DEBUG_FI
          Located in the acFlushIn method in AnsiCmd.cpp to verify terminal
          configuration flags for flusing the input stream.
        ▫ DEBUG_BSR
          Located in the breaksignalReceived method in AnsiCmd.cpp, this
          enables monitoring of the break signal (Ctrl+C key) capture and
          processing.
        ▫ DEBUG_SSR
          Located in the suspendsignalReceived method in AnsiCmd.cpp, this
          enables monitoring of the suspend signal (Ctrl+Z key) capture and
          processing.

        ▫ DEBUG_skForm
          This directive is defined within the init_skForm method, in the
          AnsiCmdWin.cpp module.

          The test code uses the debugging log file (see above) to report the
          contents of the the skForm object's data members.

        ▫ DEBUG_SHIFT_TEXT
          This directive is defined within the shiftFieldText method, in the
          AnsiCmdWin.cpp module. This method implements block-shift of text
          within the target field.

        ▫ DEBUG_skpInterRow
        ▫ DEBUG_skpDeleteChar
          These directives report intermediate processing of the “special”
          keycodes.

        ▫ DEBUG_normalkeyProc
          This directive reports intermediate processing of the “normal”
          (graphing) keycodes.

        ▫ DEBUG_wpos2tpos
          This directive is located in the wpos2tpos method which converts
          window-relative coordinates to terminal-relative coordinates.
          (currently unused)

        ▫ DEBUG_SA
          This directive is located in the acSetAttributes method and
          validates decoding of color-attribute bitfields and transmitting the
          corresponding ANSI escape sequences to set the attributes.

        ▫ DEBUG_TERMSETUP
        ▫ DEBUG_TS_PAUSE
          These directives are defined in the ansicmdSetup method which parses
          command-line arguments related to terminal configuration.

        ▫ DEBUG_EOTOFF
        ▫ DEBUG_ipOffset
          These directives are defined within the eotOffset and ipOffset
          methods, respectively, and report the interim results when
          calculating the cursor position within a field under edit.

        ▫ DEBUG_RGB_WEB
          This directive is defined within the trgbStepWeb method, in the
          AnsiCmdTest.cpp module.

          This method displays the supported “web-safe” colors by setting the
          background color attribute. The directive is used to temporarily
          render the web-safe colors by setting the _foreground_ instead of
          the background.

        ▫ DEBUG_TestWindow
          This directive is defined within the Test_Window method, in the
          AnsiCmdTest.cpp module. (currently unused)

        ▫ DEBUG_TEXTBOX
          This directive is defined within the ddzCallback method, in the
          AnsiCmdTest.cpp module. This is the callback method which monitors
          real-time user interaction within an ACDlg class window—specifically
          for testing scrolling of text data within a field.

        ▫ DEBUG_TFBDR
          This directive is defined within the Test_Form method, in the
          AnsiCmdTest.cpp module. Optionally test field outline for
          Radiobutton controls.(currently unused)

        ▫ DEBUG_ACWCB
          This directive is defined at the top of the AnsiCmdApi.cpp module.
          Report the intermediate results of interaction with the system
          clipboard.

        ▫ DEBUG_decode
        ▫ DEBUG_update
        ▫ DEBUG_modify
        ▫ DEBUG_compose
        ▫ DEBUG_swap
        ▫ DEBUG_buildRgb
        ▫ DEBUG_build8bit
          This group of directives manages debugging information for the
          acaExpand class which is used to encode, decode and apply
          color-attribute data.

  6. INCLUDE_API
     This directive controls compilation of methods and data for the
     high-level functionality of the AnsiCmd library.

     The API methods are used by the EarthPoints application for optional
     output of the coordinate reports to an ACWin-class object; however,
     EarthPoints will build successfully even when this directive is disabled
     (set to zero). But in this case, the windowed output option will not be
     available.

     The API methods are required by the AcEdit application which integrates
     both ACWin-class and ACDlg-class objects into the application design.

     The API methods are not used in the CsvView application which is
     implemented using only the low-level AnsiCmd methods.

     Therefore, when building the AnsiCmd library, keep in mind the
     application to which the library will be linked, and set or reset this
     directive as needed.

        ▫ INCLUDE_WAYLANDCB
          This is a sub-directive under control of the INCLUDE_API directive
          and is defined in AnsiCmd.hpp.
          The INCLUDE_API directive enables the _local clipboard_ which is
          available only within the application itself.
          When INCLUDE_WAYLANDCB is enabled, access to the Wayland (system)
          clipboard becomes available through the WaylandCB class, assuming
          the connection with the system can be established.
          The system clipboard connection requires installation of the Linux
          utility: 'wl-clipboard'.
             sudo dnf install 'wl-clipboard'
             sudo apt-get install 'wl-clipboard'
          For details, please see the documentation included as part of the
          standalone WaylandCB package.
          (*Note By the Same Author::.)
          Please *note AnsiCmd Clipboard Access:: which describes the
          clipboard interaction methods.


     ACWin-class and ACDlg-class Directives
     --------------------------------------

     Within the API group of methods, some additional directives are defined.
     All debugging directives in this group are contained within the global
     DEBUG_ANSICMD directive, so disabling this global debugging directive
     will also disable all API debugging code.

        ▫ DEBUG_WDUMP — enable write of config data to log
        ▫ DEBUG_FDUMP — enable write of field data members to log
        ▫ DEBUG_MDUMP — enable write of field MRParse data to log
        ▫ DEBUG_FIFO — enable write of BlockFifo data to log
        ▫ DEBUG_PHOTO — enable screenshot (for documentation)
          These directives are defined within the AnsiCmdWin.hpp module and
          control output of various groups of ACWin configuration information
          to the debugging log file.
        ▫ DEBUG_PHOTO2 — located in the Screenshot method. Supports screenshot
          capture.

        ▫ DEBUG_KPUSH — enable support methods of KeycodePush group
        ▫ DEBUG_GFD — request copy of skField data structure
        ▫ DEBUG_PFT — parsing algorithm for field text
        ▫ DEBUG_SKP — special-key processing for 'flowing' text
        ▫ DEBUG_skpST — special-key processing for 'shifted' text
        ▫ DEBUG_skpInterRow — calculate inter-row offset
        ▫ DEBUG_DELCHAR — algorithm for deleting a character
        ▫ DEBUG_NKP — filter and process 'normal' keycodes
          These directives are defined within the AnsiCmdWin.cpp module and
          are related to identification and processing of “special” keycodes
          received from the user.

        ▫ DEBUG_CBGET_FLOW — paste to control with 'flowing' text
        ▫ DEBUG_CBGET_SHFT — paste to control with 'shifting' text
        ▫ DEBUG_CBGET_OVER — overflow of field during paste
          These directives are defined within the AnsiCmdSkf.cpp module and
          are used to validate the functionality of the local clipboard
          “paste” operation for Textbox fields.

        ▫ DEBUG_skForm — range-check top-level skForm members
        ▫ DEBUG_IMF — verify array of skField objects
        ▫ DEBUG_IMM — validate data for Menubox controls
        ▫ DEBUG_ISB — validate data for Scrollbox controls
          These directives are defined within the AnsiCmdSkf.cpp module and
          validate initialization of the skForm and skField objects.

        ▫ DEBUG_CCFG —
        ▫ DEBUG_SB —
        ▫ DEBUG_MB — These directives are defined within the AnsiCmdSkf.cpp
          module and validate per-row color attribute configuration for Menu
          and Scrollbox controls.

        ▫ DEBUG_SA — color attribute bitfield initialization
        ▫ DEBUG_TERMSETUP — display terminal setup options
        ▫ DEBUG_TS_PAUSE — after report, pause for user response
          These directives are defined within the AnsiCmdApi.cpp module and
          validate terminal window color-attribute initialization and parsing
          of command-line parameters for terminal configuration, respectively.

        ▫ DEBUG_QDialog
          This directive is defined within the AnsiCmdDlg.cpp module and
          validates configuration of the *note QuickDialog:: invocation.

        ▫ DEBUG_Dialog
        ▫ DEBUG_ADJ
          These directives are defined within the AnsiCmdDlg.cpp module and
          validate configuration of the full-initialization dialog.
          *note Dialog:: invocation.

        ▫ DEBUG_ED_CLIP
          This directive is defined within the AnsiCmdDlg.cpp module and
          monitors user interaction within the editDialog method.


EarthPoints Application Directives
----------------------------------

  1. DEBUG_EPNTS
     This directive is defined in the EarthPoints.hpp module.
     It controls debugging code specifically designed to test parsing of GPS
     data and calculation of arc distances.

  2. DEBUG_PARSE
     This directive is defined in the EarthPoints.hpp module.
     It controls debugging code for parsing the user's command line input.

  3. DEBUG_PVALUE
     This directive is defined in the EarthPoints.hpp module.
     It controls debugging code for parsing GPS values in degrees and radians.

  4. DEBUG_VERBOSE
     This directive is defined in the EarthPoints.hpp module.
     As the name implies, it enables additional debugging information for
     verification of data operations.

  5. DEBUG_GCLA
     This directive is defined within the GetCommandLineArgs method, in the
     EpParse.cpp module.

     The results of parsing the command-line arguments are written to the
     terminal window, and the application then waits for the user to press the
     ENTER key before continuing program execution.

Testing the Build
=================

To test the build, invoke with a request for the EarthPoints version number.
You should get something similar to the following:

     ./epts --version

     EarthPoints (epts) v:0.0.07 Copyright(c) 2022-2026  The Software Samurai
     ========================================================================
     License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>
     This is free software: you are free to modify and/or redistribute it
     under the terms set out in the license.
     There is NO WARRANTY, to the extent permitted by law.



Installing the Documentation
----------------------------

Documentation for the AnsiCmd library is provided in both Texinfo (info)
format and HTML format.

To view the HTML-format documentation, navigate to:
    AnsiCmd/Texinfo
then load the 'ansicmd.html' document into your favorite browser. Note that
the 'infodoc-styles.css' CSS style definition file must be in the same
directory as the HTML document.

To view the Texinfo (info) documentation, navigate to:
    AnsiCmd/Texinfo
then view the documentation using the following command:
    info -f ansicmd.info

Follow these steps to install the AnsiCmd documentation into the ‘info’
database.

  1. Note that installing the documentation is not necessary, but is
     recommended. Not only is it convenient to have the documentation always
     available, but it is a useful skill for when you begin installing
     documentation for your own applications!

  2. Adding an ‘info’ document to the info-reader database (or removing a
     document from the database) is easy, but it does require ‘SUPERUSER’
     (‘root’) user privilege. If this makes you nervous, please make a backup
     copy of the ‘dir’ (info directory) file before modifying it.

  3. Open a terminal window.

  4. Navigate to the directory which contains the 'ansicmd.info'
     documentation.

          Example:
            cd ~/MySoftware/AnsiCmd/Texinfo

            (substitute your actual installation path)

  5. Locate the master Info system directory file: 'dir'.
     For local users, this is typically:
           /usr/local/share/info/dir

     For global system users, this is typically:
           /usr/share/info/dir

  6. Copy the document to the directory where you found the info 'dir' file.
          Example:
          sudo cp −−preserve=timestamps ansicmd.info /usr/local/share/info/.

          (substitute the actual path to the directory containing the 'dir' file)
          Enter your password when prompted.

  7. Navigate to the Info target directory.
           cd /usr/local/share/info

  8. Verify that the document was copied correctly.
           ls -l ansicmd.info

  9. Add the menu entry.
          sudo install-info
                  −−dir-file=dir −−info-file=ansicmd.info
                  −−name='AnsiCmd-class Library' −−debug

          Note that this is a single command, typed all on one line
          even though it may look strange as printed here.

          Enter your password when prompted.

  10. Verify the install.
          Type the following command:
             info

     This will open the top-level menu of the Info system.
     Verify that your new entry is beautifully displayed and that the new Info
     document is accessible:

     First, press the forward-slash key '/'  (search)
     Then, type: AnsiCmd-class Library       (and press ENTER)
     The highlight should now be on the menu entry.
     Press ENTER (RET) key again, and verify that the main page of the AnsiCmd
     documentation is displayed.
     Then, exit the Info system: 'q' (quit).

  11. If the menu item is not present OR if the new Info document is not
     accessible, then try the installation again.

     If you want to remove the menu entry, use the command:
          sudo install-info
              −−dir-file=dir −−info-file=ansicmd.info
              −−name='AnsiCmd-class Library' −−remove −−debug

          Again, this is a single command, typed all on one line.

          Enter your password when prompted.



File: ansicmd.info,  Node: gString Text Tool,  Next: CsvView Demo App,  Prev: Building from Source,  Up: Top

gString Text Tool
*****************

'gString' is a small, fast and flexible way to seamlessly convert, format and
analyze both UTF-8 and wchar_t ('wide') text.

* Menu:

* Introduction to gString::   An overview of gString-class functionality
* gString Public Methods::    A list of all public methods
* gString Instantiation::     How to create a new gString-class object
* Assignment Operators::      Overloaded assignment operators
* Formatted Assignments::     Data formatting (like swprintf, but better)
* Integer Formatting::        Formatting and sizing integer display
* Data Access::               Referencing the 'const' data of gString
* Copying Data::              Exporting gString contents
* Modifying Existing Data::   Add to, subtract from, shift or replace data
* Comparisons::               Compare gString contents to other data
* Extract Formatted Data::    Scan data and extract formatted info (swscanf)
* Statistical Info::          Report statistics on gString contents
* gString Miscellaneous::     Get class version, reinitialize data
* gString Examples::          Examples of using gString methods
* gsmeter Test App::          Testing gString functionality


File: ansicmd.info,  Node: Introduction to gString,  Next: gString Public Methods,  Up: gString Text Tool

Introduction to gString
=======================


Introduction to a Wider World
-----------------------------

Modern applications must be designed for a worldwide audience, and for this
reason, the application designer must plan for multi-language support.

Fortunately, the Universal Character Set standard ISO/IEC 10646 and UTF-8, the
most popular and flexible method of character-encoding smoothly provide all
the character sets, alphabets and special characters which are currently in
general use.

Unfortunately, the C and C++ languages offer only minimal support for
internationalization. std::string and std::wstring are nothing more than a
cruel joke to a serious application designer. The GTK+ toolkit's Glib::ustring
class is an excellent internationalization tool, but it requires installation
of the GTK+ toolkit's 'glib' and 'glibmm' libraries.
For more information on Glib::ustring, see: https://developer.gnome.org/

'gString' falls halfway between the full feature set of Glib::ustring and the
meaningless garbage that is std::string. 'gString' consists of one C++ header
file and one C++ source code module. 'gString' is integrated into the NcDialog
API library, but may also be compiled independently as a small (16Kb) link
library or the source may be embedded directly into your application.


Preparing to Support Multiple Languages
---------------------------------------

Here are the basic ideas you will need to understand in order for your
application to smoothly support multiple languages.

  1. ASCII (American Standard Code for Information Interchange) is only the
     very first step in character encoding. It is an ancient and venerable
     encoding, but supports only the 95 printable characters of the basic
     Latin alphabet.
     If you think you can say "你是在欺骗自己！" in ASCII, you're just
     deluding yourself!

  2. NEVER assume that one character can be represented with one byte.

  3. NEVER assume that one character is one display column in width.

  4. The idea that text flows from left-to-right, may only be PROVISIONALLY
     assumed, because again: "!איר זענט נאָר דילוזינג זיך" you're just deluding
     yourself.

  5. NEVER assume that "everyone reads English, so why bother?". Native
     speakers of Spanish, French, Chinese, the various flavors of Arabic and
     others (i.e. your potential customers) all have a significant impact on
     the daily events of our planet, so include them when planning for your
     next killer app.

See also a discussion of multiple-language support in the NcDialog API.



File: ansicmd.info,  Node: gString Public Methods,  Next: gString Instantiation,  Prev: Introduction to gString,  Up: gString Text Tool

gString Public Methods
======================

What follows is a list of all public methods of the gString class.
Methods are arranged in functional groups.

        gString Method Name               Chapter Reference    
                                       
----------------------------------------------------------------------------
 gString [constructor]                  *note gString Instantiation::
 ~gString [destructor]                  
 operator=                              *note Assignment Operators::
                                        
 compose                                *note Formatted Assignments::
                                        
 formatInt                              *note Integer Formatting::
                                        
 gstr                                   *note Data Access::
 ustr                                   
                                        
 copy                                   *note Copying Data::
 operator<<                             
 substr                                 
                                        
 append                                 *note Modifying Existing Data::
 insert                                 
 limitChars                             
 limitCols                              
 shiftChars                             
 shiftCols                              
 padCols                                
 strip                                  
 erase                                  
 replace                                
 loadChars                              
 textReverse                            
 formatParagraph                        
                                        
 compare                                *note Comparisons::
 compcoll                               
 operator==                             
 operator!=                             
 find                                   
 findlast                               
 after                                  
 findr                                  
 findx                                  
 scan                                   
                                        
 gscanf                                 *note Extract Formatted Data::
                                        
 gschars                                *note Statistical Info::
 gscols                                 
 utfbytes                               
 isASCII                                
                                        
 clear                                  *note gString Miscellaneous::
 wAlloc                                 
 uAlloc                                 
 freeSpace                              
 reAlloc                                
 Get_gString_Version                    
 dumpGstring                            
 dbMsg                                  



File: ansicmd.info,  Node: gString Instantiation,  Next: Assignment Operators,  Prev: gString Public Methods,  Up: gString Text Tool

gString Instantiation
=====================

The following are the 'constructors' for the gString class.

For those new to C++, a constructor creates an 'instance' of the class. An
instance is a particular, named object, and can be thought of as a complex
variable.

   ▪ gString ( void ) ;

       Input  :
          none
       Returns:
          nothing

     Constructor: Initialize members to default values (NULL string).


   ▪ gString ( int32_t charAlloc );

       Input  :
          charAlloc : storage capacity
             interpreted as the maximum number of wchar_t (32-bit) characters 
             for the storage buffer.
             Range: gsALLOCMIN <= charAlloc <= gsALLOCMAX
             -- The minimum allocation of gsALLOCDMIN will result in the
                same storage capacity at the default constructor.
             -- The maximum allocation of gsALLOCMAX is 1000 times the
                minimum allocation.
             The specified value is normalized by rounding upward to the
             nearest multiple of gsALLOCMIN.
     
       Returns: nothing

     Constructor: Initialize members to default values with empty string.

     This constructor is used to specify the initial storage capacity for the
     gString object. This may be useful if it is known that the data the
     object will hold will be larger than the default storage capacity.
     For more information, *note Dynamic Memory Allocation::.


   ▪ gString ( const char* usrc, int32_t charLimit = -1 ) ;

       Input  :
          usrc     : pointer to a UTF-8-encoded, null-terminated string
          charLimit: (optional, -1 by default) maximum number of source
                     characters to be stored (not including nullchar).
                     This is the number of characters (NOT the number of
                     UTF-8 bytes).
                     If not specified, then all source data will be stored
                     up to the maximum storage limit.
     
       Returns: nothing

     Constructor: Convert specified UTF-8-encoded source to gString.


   ▪ gString ( const wchar_t* wsrc, int32_t charLimit = -1 ) ;

       Input  :
          wsrc      : pointer to a wchar_t-encoded, null-terminated string
          charLimit : (optional, -1 by default)
                      maximum number of characters from source array to 
                      convert
     
       Returns: nothing

     Constructor: Convert specified wchar_t ('wide') source to gString.


   ▪ gString ( short iVal, short fWidth, bool lJust = false,
      bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
   ▪ gString ( unsigned short iVal, short fWidth, bool lJust = false,
      bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
   ▪ gString ( int iVal, short fWidth, bool lJust = false,
      bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
   ▪ gString ( unsigned int iVal, short fWidth, bool lJust = false,
      bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
   ▪ gString ( long int iVal, short fWidth, bool lJust = false,
      bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
   ▪ gString ( unsigned long int iVal, short fWidth, bool lJust = false,
      bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
   ▪ gString ( long long int iVal, short fWidth, bool lJust = false,
      bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
   ▪ gString ( unsigned long long int iVal, short fWidth, bool lJust = false,
      bool sign = false, bool kibi = false, fiUnits units = fiK ) ;

       Input  :
          iVal  : value to be converted
                  Supported value range: plus/minus 9.999999999999 terabytes
          fWidth: field width (number of display columns)
                  range: 1 to FI_MAX_FIELDWIDTH
          lJust : (optional, false by default)
                  if true, strip leading spaces to left-justify the value
                  in the field. (resulting string may be less than fWidth)
          sign  : (optional, false by default)
                  'false' : only negative values are signed
                  'true'  : always prepend a '+' or '-' sign.
          kibi  : (optional, false by default)
                  'false' : calculate as a decimal value (powers of 10)
                            kilobyte, megabyte, gigabyte, terabyte
                  'true'  : calculate as a binary value (powers of 2)
                            kibibyte, mebibyte, gibibyte, tebibyte
          units  : (optional) member of enum fiUnits (fiK by default)
                   specifies the format for the units suffix.
                   Note that if the uncompressed value fits in the field,
                   then this parameter is ignored.
     
       Returns: nothing
          Note: if field overflow, field will be filled with '#' characters.

     Constructor: Convert specified integer value to gString.
     Please *note Integer Formatting:: 'formatInt' method group for formatting
     details.


   ▪ gString ( const char* fmt, const void* arg1, ... )
      __attribute__ ((format (gnu_printf, 2, 0))) ;

       Input  :
          fmt       : a format specification string in the style of 
                      sprintf(), swprintf() and related formatting 
                      C/C++ functions.
          arg1      : pointer to first value to be converted by 'fmt'
          ...       : optional arguments (between ZERO and gsfMAXARGS - 1)
                      Each optional argument is a POINTER (address of) the 
                      value to be formatted.
       Returns:
          nothing

     Constructor: Convert formatting specification and its arguments to
     gString. Please refer to the compose() method:
     (*note Formatted Assignments::) for more information.

     Technical Note: There is no constructor using a “const wchar_t* fmt”
     format specification because it would conflict with the constructor which
     limits the number of characters used to initialize the instance.


   ▪ ~gString ( void ) ;

       Input  :
          none
       Returns:
          nothing

     Destructor: Release all resources associated with the gString object.

     Object is destroyed either when it goes out of scope, or by explicitly
     deleting the object.

     For those new to C++, please note that if you use the 'new' keyword to
     create objects, then those objects persist (take up space) until you
     explicitly delete them or until the application is closed, even if the
     pointer to the object has gone out-of-scope. See examples below.


     Examples
     ........
     void calling_method ( void )
     {
        gString *gsPtr = playful_kitten ( "Hello World!" ) ;
     
        // report contents of object created by called method
        wcout << gsPtr->gstr() << endl ;
        delete gsPtr ; // delete object created by called method
     }
     
     gString* playful_kitten ( const char* msg )
     {
        gString gs_local( "I love tuna!" ) ;  // local object
        gString *gsPtr1 = new gString,        // global object
                *gsPtr2 = new gString(msg) ;  // global object (initialized)
        gString *gsArray = new gString[4] ;   // global array
     
        *gsPtr1 = gs_local ;   // be a kitten: play with the strings...
        gsArray[2] = *gsPtr2 ;
        gsArray[3] = "Scratch my belly!" ;
        gsArray[1] = gsArray[3] ;
     
        delete gsPtr1 ;      // delete object referenced by gsPtr1
        delete [] gsArray ;  // delete object array referenced by gsArray
        return gsPtr2 ;      // return pointer to object referenced by gsPtr2
                             // (caller is responsible for deleting object)
     }           // 'gs_local' goes out of scope and is destroyed here
     _____________________________________________________________________



Dynamic Memory Allocation
.........................

   ♦ During instantiation of a gString object, a dynamic memory allocation
     occurs; that is, memory is allocated from the “heap” which is RAM memory
     not directly controlled by the application.

     This is in contrast to the “stack” memory which is assigned to the
     application on startup.

   ♦ The dynamic allocation is initially the default value: gsALLOCDFLT. This
     is the number of UTF-32 (wchar_t) characters the object can hold.

     Storage capacity is automatically expanded as necessary to accomodate the
     size of the data assigned to the object.

   ♦ The exception to the default allocation is the gString constructor which
     takes as it argument a specific storage capacity, expressed as the number
     of UTF-32 (wchar_t) characters. Examples:
        gString gs( gsALLOCMED );   gString gs( 2500 );
     This constructor is described above.

   ♦ The DEFAULT storage capacity is the minimum capacity:
           (gsALLOCDFLT == gsALLOCMIN)
     Total dynamic allocation for the default storage capacity will be:
        1K UTF-32 characters + 4K UTF-8 bytes + 1K 16-bit integers,
        or 4Kb + 4Kb + 2Kb == 10Kb (approximately).

   ♦ The “medium” capacity, gsALLOCMED is four(4) times the minimum capacity,
     i.e. 4,096 wchar_t characters.
     This should handle all but the most extreme circumstances. Total dynamic
     allocation will be:
        4K UTF-32 characters + 16K UTF-8 bytes + 4Kb 16-bit integers,
        or 16Kb + 16Kb + 8Kb == 40Kb (approximately).

   ♦ The MAXIMUM storage capacity is one thousand (1,000) times the minimum
     allocation.
     This is 1,024,000 wchar_t characters. (Note the mixture of Kilo-byte and
     Kibi-byte math.) Total dynamic allocation will be:
        1000K UTF-32 characters + 4000K UTF-8 bytes + 1000K 16-bit integers,
        or 1Mb + 1Mb + 500Kb == 2.5Mb (approximately).
     This is enough memory to hold a short novel, and so the maximum
     allocation will be needed in only the most extreme cicumstances.

   ♦ The “reAlloc” method described in the chapter,
     *note gString Miscellaneous::, may be used to manually increase or
     decrease the size of the storage buffers in increments of gsALLOCMIN.

   ♦ All methods which set or modify the stored text data implement automatic
     re-sizing of the data buffers.

     The ‘gsmeter’ test application reports all these methods to be fully
     functional; however, be aware that the allocation/reallocation algorithm
     is still young, relatively speaking, (about eight months as of May 2025);
     so if a problem arises, please drop the author a note.

     Please *note gsmeter Test App:: for additional information; specifically
     the R[a|b] (reallocate) tests which exercise all methods that perform
     modifications to the size of the storage buffers.



File: ansicmd.info,  Node: Assignment Operators,  Next: Formatted Assignments,  Prev: gString Instantiation,  Up: gString Text Tool

Assignment Operators
====================

For those new to C++, an assignment operator assigns (initializes) the object
to the left of the '=' using the data on the right of the '='. You may also
hear the term 'overloaded operator'. This just means that the '=' assignment
operator may be defined in more than one way, so it will perform different
tasks according to the context or circumstance.

   ▪ void operator = ( const char* usrc ) ;
   ▪ void operator = ( const uint8_t* usrc ) ;

       Input  :
          usrc  : pointer to an array of UTF-8-encoded characters
       Returns:
          nothing

     Assignment operator: converts UTF-8-encoded source to gString.

   ▪ void operator = ( const wchar_t* wsrc ) ;

       Input  :
          wsrc  : pointer to an array of wchar_t 'wide' characters
       Returns:
          nothing

     Assignment operator: converts wchar_t ('wide') source to gString.

   ▪ void operator = ( const gString& gssrc ) ;

       Input  :
          gssrc : gString object to be copied (by reference)
       Returns:
          nothing

     Assignment operator. Copies one gString object to another.


Examples
........

char utf8Data[] = { "Youth is wasted on the young." } ;
gString gs1, gs2 ;

gs1 = utf8Data ;
gs2 = gs1 ;
wcout << gs2 << endl ;
 - - -> Youth is wasted on the young.



File: ansicmd.info,  Node: Formatted Assignments,  Next: Integer Formatting,  Prev: Assignment Operators,  Up: gString Text Tool

Formatted Assignments
=====================

   ▪ const wchar_t* compose ( const wchar_t* fmt, ... )
      __attribute__ ((format (gnu_wprintf, 2, 0))) ;
   ▪ const wchar_t* compose ( const char* fmt, ... )
      __attribute__ ((format (gnu_printf, 2, 0))) ;

       Input  :
          fmt  : a format specification string in the style of sprintf(),
                 swprintf() and related formatting C/C++ functions.
          ...  : optional arguments (between ZERO and gsfMAXARGS)
                 Each optional argument is a POINTER (address of) the value
                 to be formatted.
                 - Important Note: There must be AT LEAST as many optional
                   arguments as the number of format specifiers defined in
                   the formatting string. Excess arguments will be ignored;
                   HOWEVER, too few arguments will result in an application
                   crash. You have been warned.
       Returns:
          const wchar_t* to formatted data

     Create formatted text data from a format specification string including
     between ZERO and gsfMAXARGS format specifications and their corresponding
     argument pointers.

     Supported data types:
      %d, %i  integer (decimal)
      %o      integer (octal)
      %u      integer (unsigned)
      %x, %X  integer (hex lower or upper case)
      %f      floating point (fixed point)
      %e, %E  floating point (scientific notation, lower/uppercase)
      %g, %G  floating point (normal/exponential, lower/uppercase)
      %a, %A  floating point (hex fraction)
      %c      character
      %C      character (alias for %lc)
      %s      string
      %S      string (alias for %ls)
      %p      pointer
      %b, %B  (extension to swprintf - see description below)
      %m      capture 'errno' description string (see /usr/include/errno.h)
      %n      number of characters printed so far
              (value written to corresponding argument's location)
      %%      literal '%'
     
     See man pages for the C/C++ function 'swprintf' or
     'Table of Output Conversions' for additional details.


Examples
........

char      Greeting[] = { "Hello!" } ;
int       iValue = 27064 ;
long long int qValue = 7842561 ;
long int  lValue = 485772 ;
short int sValue1 = 28875, sValue2 = -261, sValue3 = 529 ;
bool      flagValue = true ;
float     fltValue = 278.5610234 ;
double    dblValue = 9982.5610234 ;
gString gs ;
gs.compose( "%s - %d %12hd, %-hi, %#hx %08lXh %lld %hhd",
            Greeting, &iValue, &sValue1, &sValue2, &sValue3,
            &lValue, &qValue, &flagValue ) ;
wcout << gs << endl ;
 - - -> Hello! - 27064        28875, -261, 0x211 0007698Ch 7842561 1
gs.compose( "floating downstream:%10.2f and doubling our pace:%.4lf",
            &fltValue, &dblValue ) ;
wcout << gs << endl ;
 - - -> floating downstream:    278.56 and doubling our pace:9982.5610

See also formatted instantiation: *note gString Instantiation::.


Important Note on Formatting
............................

Because THE PARAMETERS ARE POINTERS TO THEIR DATA, similar to the C/C++
library function 'sscanf' and friends, the compiler cannot perform automatic
promotions from short int* to int* or from float* to double*, and so-on as it
would for swprintf.

This implementation was selected because a) it eliminates data-width conflicts
when moving among hardware platforms, and b) it reduces code size while
increasing performance.

This implementation relies on you, the designer, to use care that the data
type you specify in the formatting string matches the data type of the
variable referenced by its parameter pointer AND that you use the 'address-of'
('&') operator to reference non-pointer variables. Note also that 'literal'
values may not be used as parameters because literals have no address.

The following constructs will produce errors:
gString gs ;
char   grade = 'A' ;
short  age   = 21 ;
int    sat   = 1550 ;
double gpa   = 3.75 ;

   // These examples fail to use the 'address-of' operator for the 
   // referenced variables, and will cause a 'segmentation fault' 
   // i.e. an application crash.
   gs.compose( "My grade is an %c", grade ) ;
   gs.compose( "I got a %d on my SAT.", sat ) ;
   // The above should be:
   gs.compose( "My grade is an %c", &grade ) ;
   gs.compose( "I got a %d on my SAT.", &sat ) ;

   // These examples use mismatched format-specification/variable 
   // reference. This will result in either bad data out OR will 
   // cause a memory-access violation.
   gs.compose( "I can't wait to be %d.", &age ) ;
   gs.compose( "My GPA is %1.3f", &gpa ) ;
   gs.compose( "The hex value of %c is: %#x", &grade, &grade ) ;
   gs.compose( "My GPA is %1.3lf", 3.88 ) ; // (literal value)
   // The above should be:
   gs.compose( "I can't wait to be %hd.", &age ) ;
   gs.compose( "My GPA is %1.3lf", &gpa ) ;
   gs.compose( "The hex value of %c is: %#hhx", &grade, &grade ) ;

Parameter Type Checking:
Unfortunately, type-checking of wchar_t formatting strings is not yet
supported by the gnu (v:4.8.0) compiler, (but see wchar.h which is preparing
for the future). Thus, use care when constructing your 'wchar_t fmt'
formatting string. The 'char fmt' string IS type-checked.

IMPORTANT NOTE:
Depending on your compiler version, you may get a warning when using the '%b'
binary format specification (described below):
   "warning: unknown conversion type character ‘b’ in format [-Wformat=]"
This is because the preprocessor does not recognize our custom format
specifier. If this happens, use a 'wchar_t' (wide) formatting template to
avoid the preprocessor type checking.

Instead of:
      gs.compose( "bitmask: %b", &wk.mevent.eventType );
Use this (not type checked by the preprocessor):
      gs.compose( L"bitmask: %b", &wk.mevent.eventType );



Formatted binary output (extension to swprintf)
...............................................

We implement an extension to the swprintf output-conversion-specifiers for
binary formatted output. We have found this formatting option useful when
working with bit masks, for verifying bit-shifting operations during
encryption/decryption and other uses.

   ⚬ Base formatting specifier:
          %b , %B

          Note that the lower-case / upper-case variants have identical
          function, and indicate only the case of the identifier character.
          See format modifiers for data size.

   ⚬ Format modifiers for data size are the same as for swprintf:
          hh , h , l , ll , L , q
          Examples: %hhb  %hB  %llB  %qb

   ⚬ Format modifier for prepending of a data-type indicator.
          '#' (hash character)
          This is the same principle as for prepending a '0x' indicator
          to hex output, and will place either a 'b' or 'B' character at
          the beginning of the output.
          Examples:  %#hhb -> b0101.1010   %#hhB -> B0101.1010

   ⚬ Format modifier for appending of a data-type indicator.
          '-#' (minus sign and hash character)
          Rather than prepending the indicator, the indicator will be
          append to the end of the output.
          Examples: %-#hhb -> 0101.1010b   %-#hhB -> 0101.1010B

   ⚬ Format modifier for specifying the group-seperator character.
          By default, the bit groups are seperated by a '.' (fullstop)
          character. To specify an alternate seperator character:
          % hB   -> 0111 0101 1010 0001   (' ' (space) as seperator)
          %_hB   -> 0111_0101_1010_0001   ('_' (underscore) as seperator)
          %#/hB  -> B0111/0101/1010/0001  ('/' (slash) as seperator)
          %-#-hB -> 0111-0101-1010-0001B  ('-' (dash) as seperator)

          Valid seperator characters are any printable ASCII character that
          IS NOT alphabetical, IS NOT a number, and IS NOT a '.'(fullstop)

   ⚬ Format modifier for specifying bit grouping.
          By default, bits are formatted in groups of four (4 nybble); however,
          if desired, bits can be formatted in groups of eight (8 byte):
          %.8hB    -> 01110101.10100001
          %-.8hB   -> 01110101-10100001
          %# .8hB  -> B01110101 10100001
          %-#`.8hb -> 01110101`10100001b


Field-width specification (swprintf bug fix)
............................................

The standard library 'swprintf' function has a design flaw for format
specifications that include a field-width specifier.

'swprintf' pads the string to the specified number of CHARACTERS, not the
number of COLUMNS as it should do. For ASCII numeric source values this is not
a problem because one character equals one display column. For string source
data, however, if the source string contains characters that require more than
one display column each, then the output may be too wide.

Therefore, for string-source-formatting specifications ONLY:
 (examples: "%12s" "%-6s" "%16ls" "%5S" "%-24S")
we compensate for this ethnocentric behavior by interpreting the field-width
specifier as number-of-columns, NOT number-of-characters. For non-ASCII string
data, this will result in output that appears different (and better) than
output created directly by the 'swprintf' function.


Unsupported format specifications
.................................

Conversion modifiers that are not fully supported at this time:
 'j', 'z', 't', '%['
Also, the '*' field-width specification or precision specification which uses
the following argument as the width/precision value IS NOT supported.




File: ansicmd.info,  Node: Integer Formatting,  Next: Data Access,  Prev: Formatted Assignments,  Up: gString Text Tool

Integer Formatting
==================

   ▪ bool formatInt ( short iVal, short fWidth,
      bool lJust = false, bool sign = false,
      bool kibi = false, fiUnits units = fiK ) ;

   ▪ bool formatInt ( unsigned short iVal, short fWidth,
      bool lJust = false, bool sign = false,
      bool kibi = false, fiUnits units = fiK ) ;

   ▪ bool formatInt ( int iVal, short fWidth,
      bool lJust = false, bool sign = false,
      bool kibi = false, fiUnits units = fiK ) ;

   ▪ bool formatInt ( unsigned int iVal, short fWidth,
      bool lJust = false, bool sign = false,
      bool kibi = false, fiUnits units = fiK ) ;

   ▪ bool formatInt ( long iVal, short fWidth,
      bool lJust = false, bool sign = false,
      bool kibi = false, fiUnits units = fiK ) ;

   ▪ bool formatInt ( unsigned long iVal, short fWidth,
      bool lJust = false, bool sign = false,
      bool kibi = false, fiUnits units = fiK ) ;

   ▪ bool formatInt ( long long iVal, short fWidth,
      bool lJust = false, bool sign = false,
      bool kibi = false, fiUnits units = fiK ) ;

   ▪ bool formatInt ( unsigned long long iVal, short fWidth,
      bool lJust = false, bool sign = false,
      bool kibi = false, fiUnits units = fiK ) ;

  Input  :
     iVal  : value to be converted
             Supported value range: plus/minus 9.999999999999 terabytes
     fWidth: field width (number of display columns)
             range: 1 to FI_MAX_FIELDWIDTH
     lJust : (optional, false by default)
             if true, strip leading spaces to left-justify the value
             in the field. (resulting string may be less than fWidth)
     sign  : (optional, false by default)
             'false' : only negative values are signed
             'true'  : always prepend a '+' or '-' sign.
     kibi  : (optional, false by default)
             'false' : calculate as a decimal value (powers of 10)
                       kilobyte, megabyte, gigabyte, terabyte
             'true'  : calculate as a binary value (powers of 2)
                       kibibyte, mebibyte, gibibyte, tebibyte
     units  : (optional) member of enum fiUnits (fiK by default)
              specifies the format for the units suffix.
              Note that if the uncompressed value fits in the field,
              then this parameter is ignored.

  Returns:
     'true' if successful
     'false' if field overflow (field will be filled with '#' chars)
             See notes below on field overflow.


Convert an integer value into a formatted display string of the specified
width. Value is right-justified in the field, with leading spaces added if
necessary (but see 'lJust' parameter).

Maximum field width is FI_MAX_FIELDWIDTH. This is wide enough to display a
18-digit, signed and comma-formatted value: '+9,876,543,210,777'

Actual formatting of the value depends on the combination of:
  a) magnitude of the value
  b) whether it is a signed value
  c) the specified field-width
  d) the specified suffix format
  e) locale-specific grouping of digits according the LC_NUMERIC locale
     environment variable
     Important Note: the 'C' (default) locale defines an empty string
     as the grouping separator character. Therefore, the locale should
     be explicitly set before calling this method. (This is done
     automatically when the NcDialog API is initialized.)
  f) See notes below on the possible reasons for field overflow:
     *note field overflow::

The following examples are based on the U.S. English locale: ‘en_US.utf8’.



Examples
........

1) Simple comma formatted output if specified field-width is sufficient.
   345    654,345    782,654,345    4,294,967,295

2) Output with values compressed to fit a specified field width.
   12.3K    999K    12.345M    1.234G    4.3G

   
gString gs ;      // gString object

3) Convert a signed integer value:
   int iValue = 28954 ;

   // field width == 8, right justified (note: compression unnecessary)
   gs.formatInt( iValue, 8 ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :  28,954:

   // field width == 8, left justified (note: compression unnecessary)
   gs.formatInt( iValue, 8, true ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :28,954:

   // field width == 6
   gs.formatInt( iValue, 6 ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :28.95K:

   // field width == 6 with forced sign
   gs.formatInt( iValue, 6, false, true ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :+29.0K:

   // field width == 5
   gs.formatInt( iValue, 5 ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :29.0K:

   iValue = -28954 ;    // convert negative source value

   // field width == 8, right justified (note: compression unnecessary)
   gs.formatInt( iValue, 8 ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  : -28,954:

   // field width == 8, left justified (note: compression unnecessary)
   gs.formatInt( iValue, 8, true ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :-28,954:

   // field width == 6
   gs.formatInt( iValue, 6 ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :-29.0K:

   // field width == 5
   gs.formatInt( iValue, 5 ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  : -29K:

4) Convert an unsigned long long integer value (field width == 11):
   unsigned long long int qValue = 39000009995 ;

   // decimal compression (gigabytes) with "official" IEC suffix
   gs.formatInt( qValue, 11, false, false, false, fikB ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :39.000010gB:

   // binary compression (gibibytes) with "official" IEC suffix
   gs.formatInt( qValue, 11, false, false, true, fiKiB ) ;
   wcout << ':' << gs << ':' << endl ;
    - - >  :38.08595GiB:

Please see (NcDialog test application, 'Dialogw' for more examples.)


Notes on the formatInt group
............................

Optional specification of the units suffix for the 'formatInt' methods.
Units are specified using the optional 'units' parameter, which
is a member of the 'fiUnits' enumerated type..

enum fiUnits : short
{
   fiK,     // 'K'   'M'   'G'   'T'   (default)
   fik,     // 'k'   'm'   'g'   't'
   fiKb,    // 'Kb'  'Mb'  'Gb'  'Tb'
   fikB,    // 'kB'  'mB'  'gB'  'tB'  ("official" metric 'kilo' designation)  
   fiKiB,   // 'KiB' 'MiB' 'GiB' 'TiB' ("official" binary 'kibi' designation)
} ;

The 'formatInt' methods use decimal (powers of 10) compression
calculations by default. To use binary (powers of 2) compression,
use the optional 'kibi' parameter.

   DECIMAL                      BINARY
   kilobytes (x/1000)           kibibytes (x/1024)
   megabytes (x/1000000)        mibibytes (x/1024000)
   gigabytes (x/1000000000)     gibibytes (x/1024000000)
   terabytes (x/1000000000000)  tebibytes (x/1024000000000)


The kilo/kibi controversy
.........................

The IEC (International System of Quantities) recommends lower-case for metric
(powers of 10) and upper-case for binary (powers of 2). However, unless you
must be accurate in presenting the data according to IEC standard, it is
recommended that you choose the format according to: your space requirements,
visual appeal, and clear communication with your users.
If you blindly follow style standards against your own better judgement, then
be forever labelled as a weenie.


formatInt field overflow
........................

As described above, the actual formatting of a fixed-width integer field
depends on a number of factors. Every effort is made to compress the data to
fit within the field while retaining an accurate representation of the numeric
value.

There are cases, however, where it is not possible to represent the data
within the specified field width. When this occurs, the entire field will be
filled with HASH characters '#'.

The specified field must be wide enough to accomodate either the entire,
uncompressed value, _or_ the combination of compressed value, units designator
and sign (if any). The following situations may cause field overflow.

 a) Values <= -10.0 Tbytes or >= 10.0 Tbytes cannot be represented
    by 'formatInt' methods.
 b) One-column fields can display values between 0 and 9.
    Values outside this range will cause overflow.
 c) Two-column fields can display values between -9 and 99.
    Values outside this range will cause overflow.
 d) Three-column fields can display _compressed_ data
    only if the combined width of value, sign and units require
    no more than three(3) columns.
 e) Four-column fields can display _compressed_ data
    only if the combined width of value, sign and units require
    no more than four(4) columns.
 f) Five-column fields can accurately display any value _IF_
    the units designator requires only one(1) column.
 g) Six-column fields can accurately display any value _IF_
    the units designator requires no more than two(2) columns.

Fields of seven(7) or more columns can display any formatted value without
danger of overflow.

                                 ──────────


How To Set the Application Locale In C++
........................................

The NcDialogAPI library automatically sets the application locale according to
the console window environment. Please see the NcDialog documentation,
chapter: Multi-language Support for details.

In brief, the “locale” specifies the upper-/lower-case text rules, numeric
formatting, language-specific punctuation, currency symbols and so on.

The application locale should be taken from the terminal environment if
possible, This is done by creating an instance of the "std::locale" structure
referencing the empty string ("").
   locale* locptr = new locale("");
The captured locale is then made “global”, that is it replaces the so-called
"classic" (C/C++ language) locale with the specified locale definition.
   locptr->global( *locptr );
Please see the C++ documentation for "std::locale" for details.



File: ansicmd.info,  Node: Data Access,  Next: Copying Data,  Prev: Integer Formatting,  Up: gString Text Tool

Data Access
===========

   ▪ const wchar_t* gstr ( void ) const ;

       Input  :
          none
       Returns:
          const pointer to array of wchar_t characters

     Return a const pointer to the wchar_t (wide) character array.


   ▪ const wchar_t* gstr ( int32_t& charCount ) const ;

       Input  :
          charCount : (by reference, initial value ignored)
                      receives number of characters in array, 
                      including null terminator
       Returns:
          const pointer to array of wchar_t characters

     Return a const pointer to the wchar_t (wide) character array, along with
     the number of characters in the array (including the null terminator).


   ▪ const char* ustr ( void ) const ;

       Input  :
          none
       Returns:
          const pointer to array of UTF-8 characters

     Return a const pointer to the char (UTF-8) character array.


   ▪ const char* ustr ( int32_t& charCount, int32_t& byteCount ) const;

       Input  :
          charCount : (by reference, initial value ignored)
                      receives number of characters in array, 
                      including null terminator
          byteCount : (by reference, initial value ignored)
                      receives number of bytes in array, 
                      including null terminator
       Returns:
          const pointer to array of UTF-8 characters

     Return a const pointer to the char (UTF-8) character array, along with
     the number of characters _and_ the number of bytes in the array
     (including the null terminator).



Examples
........

int32_t charCount, byteCount ;
gString gs( "Wherever you go, there you are!" ) ;

const wchar_t* wPtr = gs.gstr() ;
const wchar_t* wPtr = gs.gstr( charCount ) ;
const char* utf8Ptr = gs.ustr() ;
const char* utf8Ptr = gs.ustr( charCount, byteCount ) ;



File: ansicmd.info,  Node: Copying Data,  Next: Modifying Existing Data,  Prev: Data Access,  Up: gString Text Tool

Copying Data
============

   ▪ int32_t copy ( char* uTarget, int32_t maxBytes,
                    int32_t maxCols = -1 ) const ;

       Input  :
          uTarget  : pointer to target array to receive UTF-8-encoded text
          maxBytes : maximum number of bytes to copy (incl. NULL terminator)
          maxCols  : (optional, default: -1, count bytes only)
                     maximum number of display-columns to copy
       Returns:
          number of bytes copied (incl. NULL terminator)

     Copy gString text to specified target buffer.

            ┌─────────────────────────────────────────────────────────┐
            │ Important Note: It is the caller's responsibility to    │
            │ specify a target buffer large enough to hold the data.  │
            │ Be safe: char ubuff[gs.utfbytes()];                     │
            └─────────────────────────────────────────────────────────┘

     Technical Note: If source data bytes greater than specified 'maxBytes',
     then copy data up to the complete UTF-8 character <= byte limit.
     This avoids writing an invalid character into the target array.


   ▪ int32_t copy ( wchar_t* wTarget, int32_t maxChars,
                    int32_t maxCols = -1 ) const ;

       Input  :
          wTarget  : pointer to target array to receive wchar_t 'wide' text
          maxChars : maximum number of characters to copy (incl. NULL)
          maxCols  : (optional, default: -1, count characters only)
                     maximum number of display-columns to copy
       Returns:
          number of characters copied (incl. NULL terminator)

     Copy gString text to specified target buffer.
            ┌─────────────────────────────────────────────────────────┐
            │ Important Note: It is the caller's responsibility to    │
            │ specify a target buffer large enough to hold the data.  │
            │ Be safe:  wchar_t wbuff[gs.gschars()];                  │
            └─────────────────────────────────────────────────────────┘


   ▪ std::wostream& operator<< ( std:wostream& os, const gString& gs2 );

       Input  :
          IMPLIED reference to the output stream
          IMPLIED reference to the gString object
       Returns: reference to the specified output stream

     !! NON-MEMBER METHOD !!
     Insertion operator: Copies the contents of the gString object into the
     'wcout' (wide) standard output stream.

     Note that due to the way the output stream is defined, you cannot mix
     'cout' (narrow) and 'wcout' (wide) output streams indiscriminately.
       −− If 'wcout' is called first, then 'cout' is disabled.
       −− If 'cout' is called first, then both narrow and wide
          channels are active.
       −− 'wcout' handles both narrow and wide data, however,
          'cout' handles ONLY narrow data.
     This is not related to gString, but is a characteristic of the default
     C++ output stream itself. We recommend that you always use the 'wcout'
     stream in console applications for both narrow and wide text data.

   ▪ std::ostream& operator<< ( std:ostream& os, const gString& gs2 );

       Input  :
          IMPLIED reference to the output stream
          IMPLIED reference to the gString object
       Returns: reference to the specified output stream

     !! NON-MEMBER METHOD !!
     Insertion operator: Copies the contents of the gString object into the
     'cout' (narrow) standard output stream.

          IMPORTANT NOTE: Access to the narrow output stream is
          provided for convenience only. It is recommended that the
          wide stream version (above), if available on your system,
          be used exclusively.


   ▪ int32_t substr ( char* uTarget, int32_t offset,
                      int32_t charCnt ) const;
   ▪ int32_t substr ( wchar_t* wTarget, int32_t offset,
                      int32_t charCnt ) const;
   ▪ int32_t substr ( gString& wTarget, int32_t offset,
                      int32_t charCnt ) const;

       Input  :
          targ    : (by reference, initial contents ignored)
                    receives null-terminated contents of specified
                    character range
                    -- If target buffer is a char*, then data returned is 
                       a UTF-8 text string.
                    -- If target buffer is a wchar_t*, then data returned is 
                       a wchar_t (wide) text string.
                    -- If target buffer is a gString object, then both 
                       UTF-8 and wchar_t data are returned 
          offset  : character index at which substring begins
                    (this IS NOT a byte index)
          charCnt : number of characters to copy (not incl. NULL terminator)
       Returns:
          if target is a wchar_t* or gString object, then returns number of
            characters written to target (not including the NULL terminator)
          if target is a char*, then returns number of bytes written to
            target (not including the NULL terminator)
     
          Note: returns ZERO if either 'offset' or 'charCnt' out of range
          Note: If 'charCnt' extends beyond the end of the source data, 
                then returns the available data.

     Copy the specified character range to target buffer.
     These methods copy the indicated substring (null terminated) to the
     target buffer, leaving the original data unchanged.

     If you have a fixed-format field, then the offset and character count
     will be known in advance. Otherwise you can use the 'find()' method to
     locate the substring to be copied.

            ┌─────────────────────────────────────────────────────────┐
            │ Important Note: It is the caller's responsibility to    │
            │ specify a target buffer large enough to hold the data.  │
            │ If size of substring is unknown, be safe:               │
            │    wchar_t wbuff[gs.gschars()];   or                    │
            │    char ubuff[gs.utfbytes()];                           │
            └─────────────────────────────────────────────────────────┘

          Please Note: The number of bytes can _NEVER_ be assumed to be the
          same as the number of characters.
          Please refer to the 'Multi-language Support' chapter of the
          'NcDialog API' documentation.


Examples
........

gString gs( "That's not flying, that's falling -- with style!\n"
            "Buzz Lightyear" ) ;
char    utf8Data[gs.gs.utfbytes()] ;
wchar_t wideData[gs.gschars()] ;

gs.copy( utf8Data, gs.utfbytes() ) ;
gs.copy( wideData, gs.gschars() ) ;

gString gstream( "You're a child's TOY! -- Woody" ) ;
wcout << gstream << endl ;

// get a copy of the first word starting with 'c'
gString AusAnimal( "Aardvark Kangaroo Cockatoo Dingo Wombat " ) ;
gString gsc ;
int b = AusAnimal.find( " c" ) ;
if ( b >= 0 )
{
   int e = AusAnimal.find( L' ', b + 1 ) ;
   if ( e > b )
   {
      AusAnimal.substr( gsc, (b + 1), (e - b - 1) ) ;
      wcout << gsc << endl ;
   }
}
 - - -> Cockatoo



File: ansicmd.info,  Node: Modifying Existing Data,  Next: Comparisons,  Prev: Copying Data,  Up: gString Text Tool

Modifying Existing Data
=======================

   ▪ int32_t append ( const wchar_t* wPtr ) ;
   ▪ int32_t append ( const char* uPtr ) ;
   ▪ int32_t append ( const wchar_t wChar ) ;

       Input  :
          wPtr  : pointer to array of wchar_t 'wide' text to be appended
                  OR
          uPtr  : pointer to array of char UTF-8 text to be appended
                  OR
          wChar : a single, 'wide' character
       Returns:
          number of characters in resulting string (incl. NULL terminator)
          Note: if value returned equals gsALLOCMAX, then 
                some data MAY HAVE BEEN discarded.

     Append text to existing gString text data up to a combined length of
     gsALLOCMAX. Characters in excess of the maximum will not be appended.


     Example
     .......

     gString gs( L"Be kind to your manager." ) ;
     gs.limitChars( gs.gschars() - 2 ) ;
     gs.append( L", and other lower forms of life." ) ;
     wcout << gs << endl ;
      - - -> Be kind to your manager, and other lower forms of life.


   ▪ int32_t append ( const wchar_t* fmt, const void* arg1, ... )
                      __attribute__ ((format (gnu_wprintf, 2, 0)));
   ▪ int32_t append ( const char* fmt, const void* arg1, ... )
                      __attribute__ ((format (gnu_printf, 2, 0)));

       Input  :
          fmt  : a format specification string in the style of sprintf(),
                 swprintf() and related formatting C/C++ functions.
          arg1 : pointer to first value to be converted by 'fmt'
          ...  : optional arguments (between ZERO and gsfMAXARGS - 1)
                 Each optional argument is a POINTER (address of) the value
                 to be formatted.
     
       Returns:
          number of characters in resulting string (incl. NULL terminator)
          Note: if return equals gsALLOCMAX, then
                some data MAY HAVE BEEN discarded.

     Append formatted text data to existing gString text data up to a combined
     length of gsALLOCMAX. Characters in excess of the maxmum will not be
     appended.

     Please refer to the 'compose' method (*note Formatted Assignments::) for
     more information on converting data using a format specification string.


     Example
     .......

     short gaddress = 2840 ;
     wchar_t gdirection = L'E' ;
     const wchar_t* gstreet = L"Colorado Blvd." ;
     double gcost = 29.95 ;
     gString gs( "Gorilla Men's Clothing" ) ; // existing text
     
     gs.append( ", %hd %C %S\n  Dress shirts on sale, $%.2lf.", 
                &gaddress, &gdirection, gstreet, &gcost ) ;
     
     wcout << gs << endl ;
      - - -> Gorilla Men's Clothing, 2840 E Colorado Blvd.
               Dress shirts on sale, $29.95.


   ▪ int32_t insert ( const wchar_t* wPtr, int32_t offset = 0 ) ;
   ▪ int32_t insert ( const char* uPtr, int32_t offset = 0 ) ;
   ▪ int32_t insert ( wchar_t wChar, int32_t offset = 0 ) ;

       Input  : 
          wPtr  : pointer to array of wchar_t 'wide' text to be inserted
                  OR
          uPtr  : pointer to array of char UTF-8 text to be inserted
                  OR
          wChar : a single wchar_t 'wide' character
          offset: (optional, ZERO by default)
                  character offset at which to insert specified text into
                  existing text.
                  Note: if specified 'offset' > number of characters in
                        existing text, then acts like 'append' method.
       Returns:
          number of characters in resulting string (incl. NULL terminator)
          Note: if value returned equals gsALLOCMAX, then 
                some data MAY HAVE BEEN discarded.

     Insert text into existing gString text data up to a combined length of
     gsALLOCMAX. Characters in excess of the maximum will be truncated.


     Example
     .......

     gString gs( L"Remember to hurt people!" ) ;
     gs.insert( L"NOT ", 9 ) ;
     wcout << gs << endl ;
      - - -> Remember NOT to hurt people!


   ▪ int32_t insert( int32_t offset, const char* fmt, const void* arg1, ... );
   ▪ int32_t insert( int32_t offset, const wchar_t* fmt,
                     const void* arg1, ... );

       Input  :
          offset: character offset at which to insert specified text into
                  existing text.
                  Note: if specified 'offset' > number of characters in
                        existing text, then data will be appended to existing text.
          fmt   : a format specification string in the style of sprintf(),
                  swprintf() and related formatting C/C++ functions.
                  Format spec may be either char data or wchar_t data.
          arg1  : pointer to first value to be converted by 'fmt'
          ...   : optional arguments (between ZERO and gsfMAXARGS - 1)
                  Each optional argument is a POINTER (address of) the value
                  to be formatted.
     
       Returns:
          number of characters in resulting string (incl. NULL terminator)
          Note: if value returned equals gsALLOCMAX, then 
                some data MAY HAVE BEEN discarded.

     Insert formatted text data into existing text data at the specified
     offset.

     Please refer to compose() method for more information on converting data
     using a format-specification string.


     Example
     .......

     const char* Month = "April" ;
     short       Date  = 28 ;
     gString gs( L"We have a date on to see the Yankees." ) ;
     int off = gs.find( "to see" ) ; // index insertion point
     gs.insert( off, "%s %hd ", Month, &Date ) ;
     wcout << gs << endl ;
      - - -> We have a date on April 28 to see the Yankees.
     
     gString gs( "drive above 90 kph!" ) ;
     gs.insert( ZERO, "%S", L"Don't " ) ; // insert at head of text
     int off   = gs.gschars() ; // index end-of-text
     int Speed = 55 ;
     gs.insert( off, L" Stay under %02d kph in the city.", &Speed ) ;
      - - -> Don't drive above 90 kph! Stay under 55 kph in the city.


   ▪ int32_t limitChars ( int32_t charCount ) ;

       Input  :
          charCount : maximum number of characters allowed in formatted data 
                      (not including NULL) Range: 1 to storage limit.
       Returns:
          number of characters in the adjusted data (including NULL)

     Truncate the data to no more than charCount display characters.
     Insert a null terminator after the specified number of characters.


     Example
     .......

     gString gs( "This shirt is available in yellow or red." ) ;
     gs.limitChars( 34 ) ;
     gs.append( "only." ) ;
     wcout << gs << endl ;
      - - -> This shirt is available in yellow only.


   ▪ int32_t limitCols ( int32_t colCount ) ;

       Input  :
          colCount : maximum number of display columns allowed in formatted data
                     Range: 1 to storage capacity.
       Returns:
          number of columns needed to display the adjusted data
          Note: If specified column count occurs in mid-character, then the 
                partial character will be removed from the string.

     Truncate the data to no more than colCount display columns. Insert a null
     terminator after the number of characters required to fill the specified
     number of display columns.


     Example
     .......

     gString gs( "The manual is located at:\n"
                 "http://cdn.funcom.com/aoc/pdf/aoc_manual.pdf" ) ;
     gs.limitCols( 55 ) ;
     wcout << gs << endl ;
      - - -> The manual is located at:
             http://cdn.funcom.com/aoc/pdf/
     
     Note that there are 25 display columns for the first line, (the newline 
     character requires no column), and 30 columns remain on the second line.


   ▪ int32_t shiftChars ( int32_t shiftCount, wchar_t padChar = L' ' ) ;

       Input  :
          shiftCount: < ZERO: shift data to the left, discarding the
                              specified number of characters from the
                              beginning of the array
                      > ZERO: shift data to the right, padding the vacated
                              positions on the left with 'padChar'
                      ==ZERO: do nothing
          padChar   : (optional, SPACE character, 0x20 by default)
                      when shifting data to the right, use this character
                      to fill the vacated character positions
                      NOTE: Specify a one-column character ONLY as the
                      padding character. (multi-column characters ignored)
       Returns:
          number of characters in adjusted array

     Shift text data by the specified number of characters.

     Note for writers of RTL (right-to-left) languages:
      In the above descriptions, the terms 'left' and 'right' are used for 
      convenience, but actually 'left' refers to the head of the data 
      and 'right' refers to the tail.


     Example
     .......

     gString gs( "Your balance is: 2,521,697.56 USD" ) ;
     gs.shiftChars( -17 ) ;
     wcout << gs << endl ;
      - - -> 2,521,697.56 USD
     gs.shiftChars( 5, L'#' ) ;
     wcout << gs << endl ;
      - - -> #####2,521,697.56 USD
     
     Note: For this example, the optional fill character used for 
     right-shift is L'#'. The default fill character is space (L' ').


   ▪ int32_t shiftCols ( int32_t shiftCount, wchar_t padChar = L' ' ) ;

       Input  :
          shiftCount: < ZERO: shift data to the left, discarding the
                              number of characters equivalent to the
                              specified number of display columns
                              NOTE: May discard one extra column if count
                              falls within a multi-column character.
                      > ZERO: shift data to the right, padding the vacated
                              positions on the left with 'padChar'
                      ==ZERO: do nothing
          padChar   : (optional, SPACE character, U+0020 by default)
                      when shifting data to the right, use this character
                      to fill the vacated column positions
                      NOTE: Specify a one-column character ONLY as the
                      padding character. (multi-column characters ignored)
       Returns:
          number of display columns in adjusted array

     Shift text data by the specified number of display columns.

     Note for writers of RTL (right-to-left) languages:
      In the above descriptions, the terms 'left' and 'right' are used for 
      convenience, but actually 'left' refers to the head of the data 
      and 'right' refers to the tail.


     Example
     .......

     gString gs( "您的帐户余额是500元" ) ; // "Your account balance is 500 yuan"
     gs.shiftCols( -14 ) ;
     wcout << gs << endl ;
      - - -> 500元
     gs.shiftCols( 5, L'.' ) ;
     wcout << gs << endl ;
      - - -> .....500元
     
     Note: Most Chinese characters are two display columns wide, 
     therefore we shift 14 columns (7 characters) out on the left.
     For this example, the optional fill character used for 
     right-shift is L'.' (U+002E, ASCII full stop). 
     The Chinese full-stop (U+3002) MAY NOT be used as a fill 
     character because it is a two-column character.


   ▪ int32_t padCols ( int32_t fieldWidth, wchar_t padChar = L' ',
                       bool centered = false );

       Input  :
          fieldWidth: number of columns for the adjusted data array
          padChar   : (optional, ASCII space 0x20 by default)
                      character with which to pad the data
                      Note: Specify a one-column character ONLY.
                            Multi-column characters will be ignored.
          centered  : (optional, 'false' by default)
                      if 'false', all padding will be appended at the end 
                                  of the existing data
                      if 'true',  padding will be equally divided between 
                                  the beginning and end of the existing data
     
       Returns:
          number of display columns in the adjusted array
     

     Append padding to the existing string data to achieve the specified
     number of display columns.

     If the 'centered' flag is set, the padding will be divided equally
     between the beginning and end of the data to achieve the specified field
     width. Note that if an odd number of columns is to be added, then the odd
     column will be placed at the end of the data.

     The ‘padCols’ method calculates the number of padding characters needed
     to fill out the specified field width.

     The default padding character is the ASCII space character (20 hex).
     Any single-column character may be specified as an alternate padding
     character.

     Padding will be added until either the specified number of columns is
     reached, _OR_ until the array contains the maximum number of characters
     (storage limit).

     If the fieldWidth specified is <= the current width of the data, then the
     data will not be modified.


     Example
     .......

     gString gs( "This is a test." );
     
     gs.padCols( 30 );              ==> "This is a test.               "
     gs.padCols( 30, L'#' );        ==> "This is a test.###############"
     gs.padCols( 30, L'#', true );  ==> "#######This is a test.########"
     
     // To create a right-justified field, use 'shiftCols' (see above):
     gs.shiftCols( (30 - gs.gscols()) );
                                    ==> "               This is a test."
     gs.shiftCols( (30 - gs.gscols()), L'#' );
                                    ==> "###############This is a test."


   ▪ int32_t strip ( bool leading = true, bool trailing = true );

       Input  :
          leading  : (optional, 'true' by default)
                     if 'true', strip leading whitespace
                     if 'false', leading whitespace unchanged
          trailing : (optional, 'true' by default)
                     if 'true', strip trailing whitespace
                     if 'false', trailing whitespace unchanged
     
       Returns:
          number of characters in modified string (incl. NULL terminator)

     Strip (remove) leading and/or trailing whitespace from the string data.

     Whitespace characters are defined as:
     0x0020 single-column ASCII space
     0x3000 two-column CJK space
     0x0A linefeed character
     0x0D carriage-return character
     0x09 horizontal-tab character
     0x0B vertical-tab character
     0x0C formfeed character

     “Leading” whitespace is space characters from the beginning of the data
     to the first non-space character. “Trailing” whitespace is from after the
     last non-space character through the end of the data.

     By default, _both_ leading and trailing whitespace will be removed;
     however, this action may be modified by resetting the appropriate
     parameter to ‘false’.


   ▪ int32_t erase ( const gString& src, int32_t offset = 0,
                     bool casesen = false, bool all = false );
   ▪ int32_t erase ( const wchar_t* src, int32_t offset = 0,
                     bool casesen = false, bool all = false );
   ▪ int32_t erase ( const char* src, int32_t offset = 0,
                     bool casesen = false, bool all = false );
   ▪ int32_t erase ( wchar_t src, int32_t offset = 0,
                     bool casesen = false, bool all = false );

       Input  :
          src    : source data to be matched, one of the following:
                   -- pointer to a UTF-8 string
                   -- pointer to a wchar_t string
                   -- a gString object containing the source (by reference)
                   -- a single, wchar_t character
          offset : (optional, ZERO by default)
                   character index at which to begin search
                   NOTE: This is a character index, NOT a byte offset.
          casesen: (optional, 'false' by default)
                   if 'false', then scan IS NOT case sensitive
                   if 'true, then scan IS case sensitive
          all    : (optional, 'false' by default)
                   if 'false', then only the first instance of the substring
                               will be deleted
                   if 'true',  then all instances of the specified substring
                               from 'offset' forward will be deleted
     
       Returns:
          index of first character following the deleted sequence
          Note: This is the wchar_t character index, NOT a byte index
          Returns (-1) if:
            a) no matching substring found
            b) 'offset' out-of-range
            c) 'src' is an empty string or a NULL character
     

     Scan the data for a matching substring, and if found, erase (delete) the
     first occurance of the substring, or optionally all instances of the
     substring from 'offset' onward.

     Actual comparison is always performed against the 'wide' character array
     using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included
     in the comparison.


   ▪ int32_t erase ( int32_t offset = 0, int32_t length = gsALLOCMAX );

       Input  :
          offset : (optional, ZERO by default)
                   index of first character of sequence to be erased
                   NOTE: This is a character index, NOT a byte offset.
          length : (optional, gsALLOCMAX by default)
                   if not specified, then erase all characters from
                      'offset' to end of data
                   if specified, then erase the specified number of
                      characters beginning at 'offset'
     
       Returns:
          index of first character following the deleted sequence
          Note: This is the wchar_t character index, NOT a byte index
          Returns (-1) if:
            a) offset < ZERO
            b) offset >= number of characters in data
            c) length <= ZERO
          (data will not be modified)
     

     Erase (delete) the data sequence specified by 'offset' and 'length'.

     'offset' is the index of the first character to be deleted, and 'length'
     specifies the number of characters to delete.


     Example
     .......

        ● If the 'length' parameter specifies deletion of more characters than
          remain, then 'erase' has the same effect as calling the 'limitChars'
          method (i.e. truncates the string at 'offset').

        ● If the defaults for both 'offset' and length' are used, then the
          'erase' method has the same effect as calling the 'clear' method
          (gString data are reset to an empty string).

        ● Note that the NULL terminator will never be deleted.


     Examples for 'erase'
     ....................

     For the gString object containing the following verbal 
     exchange, erase all occurances of the word 'crapweasel'.
     
     gString gs( "Ross : Are you familiar with the word crapweasel?\n"
                 "Paolo: No, I don't know crapweasel.\n"
                 "Ross : You're a huge crapweasel!" );
     int index = ZERO ;
     while ( (index = gs.erase( " crapweasel", index )) >= ZERO ) ;
     
     Yields:
       "Ross : Are you familiar with the word?\n"
       "Paolo: No, I don't know.\n"
       "Ross : You're a huge!"
     
     Find the substring, "the the" and erase the extra "the".
     gString gs1( L"There are seven candidates in the the Primary Election." );
     gString gs2( L"the " );
     int index = gs1.find( "the the" );
     gs1.erase( index, (gs2.gschars() - 1) );
     
     Yields:
       "There are seven candidates in the Primary Election."


   ▪ int32_t replace ( const wchar_t* src, const wchar_t* newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );
   ▪ int32_t replace ( const wchar_t* src, const char* newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );
   ▪ int32_t replace ( const wchar_t* src, const wchar_t newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );
   ▪ int32_t replace ( const char* src, const wchar_t* newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );
   ▪ int32_t replace ( const char* src, const char* newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );
   ▪ int32_t replace ( const char* src, const wchar_t newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );
   ▪ int32_t replace ( const wchar_t src, const wchar_t* newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );
   ▪ int32_t replace ( const wchar_t src, const char* newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );
   ▪ int32_t replace ( const wchar_t src, const wchar_t newtxt,
                       int32_t offset = 0,
                       bool casesen = false, bool all = false );

       Input  :
          src    : source data to be matched
                   -- pointer to a UTF-8 string
                   -- pointer to a wchar_t string
                   -- a single, wchar_t character
          newtxt : data to overwrite existing text
                   -- pointer to a UTF-8 string
                   -- pointer to a wchar_t string
                   -- a single, wchar_t character
          offset : (optional, ZERO by default)
                   character index at which to begin search
                   NOTE: This is a character index, NOT a byte offset.
          casesen: (optional, 'false' by default)
                   if 'false', then scan IS NOT case sensitive
                   if 'true, then scan IS case sensitive
          all    : (optional, 'false' by default)
                   if 'false', then replace only the first occurance found
                   if 'true',  then replace all occurances of the specified
                               substring
     
       Returns:
          'true' if successful
          returns 'false' if error (existing data not modified):
            a) no matching source substring found
            b) 'src' is a empty string or a null character
            c) offset < ZERO or offset is beyond existing data
            d) modifying the data would cause buffer overflow

     Replace the specified source substring, or optionally all matching
     substrings with the provided substring.

     Actual comparison is always performed against the 'wide' character array
     using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included
     in the comparison.


     Examples for 'replace'
     ......................

     Correct the spelling errors in the following data:
     gString gs( "The land near hare is full of Heres, hoping her and ther." ) ;
     
     bool okiday = gs.replace( L"hare", L"here" ) ;
     Yields:
       "The land near here is full of Heres, hoping her and ther."
     
     okiday = gs.replace( "Here", "Hare", ZERO, true ) ;
     Yields:
       "The land near here is full of Hares, hoping her and ther."
     
     okiday = gs.replace( L'p', L"pp" ) ;
     Yields:
       "The land near here is full of Hares, hopping her and ther."
     
     int index = gs.find( "her " ) ;
     okiday = gs.replace( "her", L"here", index, true, true ) ;
     Yields:
       "The land near here is full of Hares, hopping here and there."
     
     Then, replace all spaces ' ' with underscores '_'.
     okiday = gs.replace( L' ', L'_', ZERO, false, true ) ;
     Yields:
       "The_land_near_here_is_full_of_Hares,_hopping_here_and_there."


   ▪ int32_t loadChars ( const wchar_t* wsrc, int32_t charLimit,
                         bool append = false );
   ▪ int32_t loadChars ( const char* usrc, int32_t charLimit,
                         bool append = false );

     Load the specified number of characters from the source data. This is
     useful for extracting data from fixed-width fields when the contents of
     the field is unknown.
        gs.loadChars( StreetAddress1, 48 );

     By default, the new text REPLACES the existing text; however, the
     'append' parameter allows the new text to be appended to the existing
     text.

     The functionality is equivalent to the gString constructor which loads
     only the specified number of characters.
     *Note gString Instantiation::.


       Input  :
          usrc     : pointer to a UTF-8 encoded string
          wsrc     : pointer to a wchar_t encoded string
          charLimit: maximum number of characters (not bytes) from source
                     array to load. Range: 1 through target storage capacity.
                     The count should not include the NULL terminator
          append   : (optional, 'false' by default)
                     if 'false', replace existing text with specified text
                     if 'true', append new text to existing text
     
       Returns:
          number of characters in modified string (incl. NULL terminator)


     Examples for 'loadChars'
     ........................

     Replace the existing text with the specified number of characters 
     from the source text.
     
     const char* Piggy =  // (56 characters)
                "Spider-pig, Spider-pig does whatever a Spider-pig does." ;
     gString gs( "Existing text." ) ;
     gs.loadChars( Piggy, 36 ) ;
     Yields:
       "Spider-pig, Spider-pig does whatever"
     
     Append specified number of characters from the source text to the 
     existing text.
     
     gs.loadChars( " it's told, because it's stupid.", 11, true ) ;
     Yields:
       "Spider-pig, Spider-pig does whatever it's told,"


   ▪ int32_t textReverse ( bool punct = false,
                           bool para = false, bool rjust = false );

     Reverse the order of characters in the text string.

     If RTL text data displayed by your application is not formatted as
     desired, then this method may be used to reverse the character order
     before writing to the display. This is useful for manipulating both RTL
     (Right-To-Left) language text and mixed RTL/LTR text.

     The 'para' parameter is useful for outputting columns of numeric data or
     when the column labels are in an RTL language (see example below).

     Although modern web browsers (Firefox, Opera, Chromium, etc.) _usually_
     handle RTL text correctly, other applications often do not. This is
     especially true of terminal emulator software.

     See also a discussion of multiple-language support in the NcDialog API.

       Input  :
          punct : (optional, 'false' by default)
                  if 'false', invert entire string
                  if 'true' AND if a punctuation mark is seen at either end
                     of the string, invert everything except the punctuation
                     mark(s). typically one of the following:
                     '.' ',' '?' '!' ';' ':' but see note below.
          para  : (optional, 'false' by default)
                  if 'false', invert data as a single character stream
                  if 'true',  invert data separately for each logical line
                              (line data are separated by newlines ('\n')
          rjust : (optional, 'false' by default)
                  if 'false', do not insert right-justification padding
                  if 'true',  insert padding for each logical line to
                              right-justify the data
                              (used to right-justify LTR output)
                              Note that right-justification is performed
                              ONLY if the 'para' parameter is true.
                              Otherwise, 'rjust' will be ignored.
     
       Returns:
          number of wchar_t characters in gString object
          (if return value >= storage limit, data may have been truncated)


     Examples for 'textReverse'
     ..........................

     Note that the const Hebrew strings are written canonically in the source,
     but are displayed incorrectly in the terminal window by the info reader
     and by the HTML browser (sorry about that).

     // Hebrew: "Are you ready for lunch?"
     // Sometimes the terminal will inappropriately move the punctuation 
     // to the opposite end of the string.
     // To prevent this, use the 'punct' option.
     const wchar_t* const Lunch = L"?םיירהצ תחוראל ןכומ התא םאה" ;
     
     gString gs( Lunch ) ;
     gs.textReverse() ;
     wcout << gs.gstr() << endl ;
     
     OUTPUT (correct except punctuation) : האם אתה מוכן לארוחת צהריים?
     
     gs = Lunch ;
     gs.textReverse( true ) ;
     wcout << gs.gstr() << endl ;
     
     OUTPUT (correct): ?האם אתה מוכן לארוחת צהריים
     
     // When the 'punct' flag is set, both leading and trailing punctuation 
     // are identified.
     // Questions in Spanish use a leading inverted question mark (U+00BF), 
     // and a trailing ASCII question mark (U+003F).
     // Reverse the internal text but do not reverse the terminal punctuation.
     gs = "¿ozreumla le arap atsil sátsE?" ;
     gs.textReverse( true ) ;
     wcout << gs.gstr() << endl ;
     
     OUTPUT : ¿Estás lista para el almuerzo?
     
      = = = = =
      
     // Reverse multi-line text (paragraph formatting).
     // Ordinary ASCII text is used for this example 
     // to demonstrate the reversal.
     // The example outputs to an NcDialog window referenced by NcDialog *dp
     const char* Vaccine = "Have you received your covid-19 vaccination yet?\n
                           "Protect yourself and others,\n"
                           "get your vaccination today!" ;
     gs = Vaccine ;
     // Write unmodified text as LTR data:
     dp->WriteParagraph ( 1, 1, gs, nc.grR, true, false ) ;
     
     OUTPUT: Have you received your covid-19 vaccination yet?
             Protect yourself and others,
             get your vaccination today!
     
     // Reverse the data, without punctuation processing or 
     // right-justification. (Note: all parameters are optional, 
     // but are shown here for clarity.)
     gs.textReverse( false, true, false ) ;
     
     // Write reversed text as LTR data:
     dp->WriteParagraph ( 1, 1, gs, nc.grR, true, false ) ;
     
     OUTPUT: ?tey noitaniccav 91-divoc ruoy deviecer uoy evaH
             ,srehto dna flesruoy tcetorP
             !yadot noitaniccav ruoy teg
     
     // Write the same data as RTL (note the X origin of 48):
     dp->WriteParagraph ( 1, 48, gs, nc.grR, true, true ) ;
     OUTPUT: ?tey noitaniccav 91-divoc ruoy deviecer uoy evaH
                                 ,srehto dna flesruoy tcetorP
                                  !yadot noitaniccav ruoy teg
     
     // Reload the source data and reverse it without punctuation processing,
     // but WITH right-justification padding.
     gs = Vaccine ;
     gs.textReverse( false, true, true ) ;
     
     // Write reversed text as LTR data.
     // Note that the padding character is ASCII space ' ',
     // however the '-' character is used here to show the padding position.
     dp->WriteParagraph ( 1, 1, gs, nc.grR, true, false ) ;
     
     OUTPUT: ?tey noitaniccav 91-divoc ruoy deviecer uoy evaH
             --------------------,srehto dna flesruoy tcetorP
             ---------------------!yadot noitaniccav ruoy teg
     
     // Write the same data as RTL (note the X origin of 48):
     dp->WriteParagraph ( 1, 48, gs, nc.grR, true, true ) ;
     
     OUTPUT: ?tey noitaniccav 91-divoc ruoy deviecer uoy evaH
             --------------------,srehto dna flesruoy tcetorP
             ---------------------!yadot noitaniccav ruoy teg
     
     // Combine RTL text with numeric (LTR) data.
     // Create an ASCII numeric time string.
     // Reverse the numeric string.
     // Insert a Hebrew label: "The current time is: "
     const wchar_t *timeLabel = L"השעה הנוכחית היא: " ; //(displayed incorrectly)
     short hours = 12, minutes = 32, seconds = 45 ;
     gs.compose( "%02hd:%02hd:%02hd", &hours, &minutes, &seconds ) ;
     gs.textReverse( false, true, false ) ;
     gs.insert( timeLabel ) ;
     
     // Write the data as RTL (note the X origin of 26):
     dp->WriteParagraph ( 1, 26, gs, nc.grR, true, true ) ;
     
     OUTPUT:
        12:32:45 :השעה הנוכחית היא
     

     Technical Note On Punctuation
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

     Determining which characters are and are not punctuation is locale
     specific (see the 'ispunct()' C-language function).
     Rather than rely on the locale used by the application calling this
     method, we test against a list of the most common punctuation characters
     used in modern languages. If a punctuation character used by your
     application is not recognized as punctuation, please send us a note
     including the Unicode codepoint and we will add it to the list.


   ▪ int32_t formatParagraph ( int32_t maxRows, int32_t maxCols,
                               bool trunc = true, bool hypenbrk = false,
                               int32_t *truncIndex = NULL );

       Input  : maxRows  : maximum rows for message (>= 1)
                maxCols  : maximum columns on any message row (>= 4)
                trunc    : (optional, 'true' by default)
                           if 'true',  truncate the data if necessary to ensure
                                       that the data do not extend beyond the
                                       specified target area
                           if 'false', format the entire source text array, even
                                       if doing so requires violating the specified
                                       height of the target area (maxRows).
                                       (see also 'truncIndex' parameter)
                hyphenbrk: (optional, 'false' by default)
                           if 'false', automatic line breaks occur at space ' '
                                       characters only (20h)
                                       Special Case: the following CJK ideographs
                                       are also recognized as whitespace for
                                       purposes of line formatting (see below)
                                        '、' comma U+3001 and
                                        '。' full stop U+3002
                           if 'true',  in addition to the space ' ' characters,
                                       enable line break at:
                                        ASCII hyphen    '-' (2dh)
                                        Unicode &mdash; '—' (2014h)
                                        Unicode &ndash; '–' (2013h)
                                        Unicode &minus; '−' (2212h)
                                        Unicode &shy;       (00ADh) (soft hyphen)
                truncIndex: (optional, null pointer by default)
                            (referenced _only_ when the 'trunc' flag is reset)
                            If specified, points to a variable to receive the
                            index at which the data _would_have_been_ truncted to
                            fit the specified height of the target area if the
                            'trunc' flag had been set.
                            a) A positive value indicates that the data have not
                               been truncated, AND that the data extend beyond
                               the specified target area.
                            b) A negative value indicates that it was not necessary
                               to truncate the data i.e. the data fit entirely
                               within the target area.
     
       Returns: number of text rows in the formatted output


     Reformat the text so that when written to the display, it will fit within
     the specified rectangular area.

     The dimensions of the formatted text is specified as the number of text
     rows and columns, with a minimum of one(1) row by four(4) columns.


     Technical Description of the Line Break Algorithm
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

     Formatting is done in three steps:
       1. Remove all newlines from the text.
       2. Perform word wrap to limit the width of each row of the paragraph.
       3. If necessary, truncate the text to limit the height of the
          paragraph. (but see the 'trunc' and 'truncIndex' parameters)

     Token: A ‘token’ as used here is a series of printing characters
     delimited by whitespace characters. If line breaks on hyphen-like
     characters is enabled, those characters are also interpreted as token
     delimiters.

       1. Line breaks occur _after_ the space character at the end of a token,
          i.e. a word. This means that the line is broken by placing the
          newline _after_ the identified space character.
          Note: Currently the ASCII space character (20h) and the two-column
          CJK space (U+3000) are the only whitespace characters recognized.

          Special Case: CJK text seldom contains any spaces at all within a
          sentence, or even between sentences. Two-column punctuation is
          designed to provide a visual spacing effect. For this reason, we
          have made the design decision to process the following CJK
          ideographs as whitespace:
                     '、' comma U+3001  and '。' full stop U+3002

          Caution: Tab characters ('\t') _are not_ recognized as whitespace
          characters because they are effectively variable width characters.
          Don't use them!
          For safety, if Tab characters are present in the text, they are
          silently removed.

          Optionally, the ASCII hyphen and the Unicode hyphen-like characters
          can be treated as if they were whitespace characters for purposes of
          the algorithm. (see the 'hyphenbrk' parameter.) The characters
          included within this group are:
                NAME        HTML TAG  GLYPH  UNICODE CODEPOINT
               ASCII hyphen            '-'    U+002D
               mDASH        &mdash;    '—'    U+2014
               nDASH        &ndash;    '–'    U+2013
               minus        &minus;    '−'    U+2212
               soft hyphen  &shy;             U+00AD

       2. When reformatting the data, it is possible that the text will be
          pushed beyond the specified number of rows. In this case, we have
          two options:
          a) Truncate the text after the last specified row is filled.
          b) Alert the caller about the number of rows actually required.
          Optionally, we can indicate the index of where we _would have_
          truncated the text so that caller can manually truncate the text if
          desired. (see the 'trunc' and 'truncIndex' parameters)

       3. It is possible that a single token (word) will be longer than the
          width of the target area. Handling this (unlikely) scenario
          complicates the line-break algorithm, but could come into play; for
          instance: filespecs, URLs, or some German words. :-)

          Filespecs and URLs should be parsed using specialized formatting
          methods.
          Long words can be a challenge during parsing of the data. Our
          solution is to define “long” tokens as those which are more than
          half the specified area width ('maxCols').

          This method can optionally break after hyphens, but this may
          sometimes cause unintended breaks or confusing output. Use the
          'hyphenbrk' option wisely.

       4. Notes on automatic hyphenation:
          Technically, hyphens should be placed between syllables, but that
          would require a full dictionary of the target language.
          “Can open... worms everywhere.” (Thank you, Chandler Bing.)
             − The hyphen used is the the Unicode &ndash; U+2013. This
               facilitates stripping them from the text if the text is copied
               and pasted elsewhere.
               Note that ideally we would use the "soft hyphen," Unicode &shy;
               U+00AD, but unfortunately most non-word procesing applications
               interpret this as a zero-width character making it invisible
               under most circumstances.
             − Programmer's Note: If the current character is the same width
               as the hyphen, then the hyphen will be at the right edge of the
               target area. Otherwise there will be a one-column gap at the
               end of the line.
             − Special case: For multi-column characters, it is assumed that
               the characters belong to the CJK character groups. (This may
               not be true, but multi-column characters seldom appear in
               Romance languages. Therefore, for multi-column characters only,
               hyphens _are not_ inserted after mid-token line breaks because
               there is no way of knowing if we are breaking in mid-word or
               between words unless we have access to dictionaries for those
               languages. Again, “...worms everywhere.”




File: ansicmd.info,  Node: Comparisons,  Next: Extract Formatted Data,  Prev: Modifying Existing Data,  Up: gString Text Tool

Comparisons
===========

   ▪ int32_t compare ( const char* uStr, bool casesen = true,
                       int32_t length = -1, int32_t offset = 0 ) const;
   ▪ int32_t compare ( const uint8_t* uStr, bool casesen = true,
                       int32_t length = -1, int32_t offset = 0 ) const;
   ▪ int32_t compare ( const wchar_t* wStr, bool casesen = true,
                       int32_t length = -1, int32_t offset = 0 ) const;
   ▪ int32_t compare ( const gString& gs, bool casesen = true ) const;

       Input  :
          uStr     : (UTF-8 string) to be compared
            OR
          wStr     : (wchar_t string) to be compared
            OR
          gs       : (by reference) gString object containing
                     data to be compared
          casesen  : (optional, 'true' by default)
                     if 'true' perform case-sensitive comparison
                     if 'false' perform case-insensitive comparison
          length   : (optional, -1 by default. i.e. compare to end)
                     maximum number of characters to compare
          offset   : (optional, ZERO by default)
                     If specified, equals the character offset into the
                     gString character array at which to begin comparison.
     
       Returns: 
          return value uses the rules of the 'wcsncmp' (or 'wcsncasecmp') 
          library function (see string.h):
            ZERO, text data are identical
          > ZERO, first differing char of gString object is numerically larger.
          < ZERO, first differing char of gString object is numerically smaller.

     Compares the text content of the gString object with the specified text.

     The comparison is performed against the gString objects' wchar_t
     character arrays. The character comparisons are _numerical_, not
     locale-based. This includes the relationship between upper-case and
     lower-case characters.
     For locale-specific comparisons, please *note compcoll:: method below.


   ▪ int32_t compare ( const gString& gs, bool casesen = true ) const ;

       Input  :
          gs       : (by reference) object whose text is to be compared
          casesen  : (optional, 'true' by default)
                     if 'true' perform case-sensitive comparison
                     if 'false' perform case-insensitive comparison
     
       Returns:
          return value uses the rules of the 'wcsncmp' (or 'wcsncasecmp') 
          library function (see string.h):
            ZERO, text data are identical
          > ZERO, first differing char of gString object is numerically larger.
          < ZERO, first differing char of gString object is numerically smaller.

     Compares the text content of two gString objects.

     The comparison is performed against the gString objects’ wchar_t
     character arrays. The character comparisons are _numerical_, not
     locale-based. This includes the relationship between upper-case and
     lower-case characters.
     For locale-specific comparisons, please see the compcoll method below.


   ▪ int32_t compcoll ( const wchar_t* wStr ) const;
   ▪ int32_t compcoll ( const char* uStr ) const;
   ▪ int32_t compcoll ( const gString& bs ) const;

       Input  : wStr     : (UTF-32 string) to be compared
                   OR
                uStr     : (UTF-8 string) to be compared
                   OR
                gs       : (gString object by reference) data to be compared
     
       Returns: using the rules of the 'wcscoll' library function (see wchar.h):
           ZERO, text data are identical
         > ZERO, first differing char of stored data is larger.
         < ZERO, first differing char of stored data is smaller.

     Compares the text content of the gString object with the specified text.

     The comparison is performed according to the active "locale" within the
     application. This comparison is known as the “collation order” or
     “dictionary order” comparison where lowercase letters are considered as
     less than their uppercase equivalents. Characters with diacritical
     markers and unitary character sequence (e.g. Spanish 'll') will also be
     sorted according to the rules of the active locale.

       a. If the application has set the locale, the rules of that locale will
          be used for the comparison.
          Note that the comparison is always case sensitive.
       b. If the application has not specified the locale, then the so-called
          POSIX C/C++ pseudo-locale will be used.
       c. Note that for some languages, Chinese and Japanese for instance,
          there is no "dictionary" order for the characters. Instead,
          dictionaries rely on sound markers, e.g. pinyin transliteration,
          stroke count, or other criteria. The 'compcoll' method is not
          effective for these languages.
       d. Note that if the source data contain mixed languages, the 'wcscoll'
          function will be ineffective and misleading.
       e. Technical Note: The 'wcscoll' librarary function is also
          _considerably_ slower than the 'wcscmp' (numeric comparison)
          function because it scans the data multiple times.


          Please *note how to set locale:: for additional information.
          Note: Regardless of source data format, this method uses the
          C-library 'wcscoll' function exclusively to perform the comparison.


          Technical Note:
          ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
          In the ASCII world, the letter 'A' is numerically less than the
          letter 'a'; however, in the world of locale-specific comparison,
          English lowercase is “less than” uppercase, so 'a' is less than 'A'.

          Examples of string comparison using the collation algorithm:
                'abc'  ==  'abc'
                'abc'   <  'ABC'
                'ABC'   <  'abc'
                'abc'   <  'aBc'
                'abc'   <  'abC'
                'abc'   <  'abcd'
                'abcd'  >  'abC'
                'abcd'  <  'abCd'
                'abC'   <  'abcd'
               This would suggest that the collation algoorithm is essentially
               useless unless your project is to create a dictionary.


   ▪ bool operator == ( const gString& gs2 ) const ;

       Input  :
          gs2   : (by reference)
                  gString object containing string to be compared
       Returns:
          'true' if the strings are identical, else 'false'

     Comparison operator: Compares the text content of two gString objects.

     The comparison is performed against the wchar_t character arrays of the
     two objects. The comparison _is_ is case-sensitive.


   ▪ bool operator != ( const gString& gs2 ) const ;

       Input  :
          gs2   : (by reference)
                  gString object containing string to be compared
       Returns:
          'true' if the strings are different, else 'false'

     Comparison operator: Compares the text content of two gString objects.

     The comparison is performed against the wchar_t character arrays of the
     two objects. The comparison _is_ case-sensitive.


   ▪ int32_t find ( const char* src, int32_t offset=0,
                    bool casesen=false, int32_t maxcmp= -1 ) const;
   ▪ int32_t find ( const wchar_t* src, int32_t offset=0,
                    bool casesen=false, int32_t maxcmp= -1 ) const ;
   ▪ int32_t find ( const gString& src, int32_t offset=0,
                    bool casesen=false, int32_t maxcmp= -1 ) const;
   ▪ int32_t find ( const wchar_t src, int32_t offset=0,
                    bool casesen=false ) const;

       Input  :
          src    : source data to be matched, one of the following:
                   -- pointer to a UTF-8 string
                   -- pointer to a wchar_t string
                   -- a gString object containing the source (by reference)
                   -- a single, wchar_t character
          offset : (optional, ZERO by default)
                   character index at which to begin search
                   -- if out-of-range, then same as if not specified
          casesen: (optional, 'false' by default)
                   if 'false', then scan IS NOT case sensitive
                   if 'true, then scan IS case sensitive
          maxcmp : (optional, (-1) by default)
                   -- if not specified, then scan for a match of all
                      characters in 'src' (not including null terminator)
                   -- if specified, then scan for a match of only the first
                      'maxcmp' characters of 'src'
                   -- if out-of-range, then same as if not specified
       Returns:
          index of matching substring or (-1) if no match found
          Note: This is the wchar_t character index, NOT a byte index

     Scan the data for a matching substring and if found, return the index at
     which the first substring match begins.

     Actual comparison is always performed against the 'wide' character array
     using wcsncasecmp (or wcsncmp). Null terminator character is not included
     in the comparison.

   ▪ int32_t findlast ( const char* src, bool casesen=false ) const;
   ▪ int32_t findlast ( const wchar_t* src, bool casesen=false ) const;
   ▪ int32_t findlast ( const gString& src, bool casesen=false ) const;
   ▪ int32_t findlast ( const wchar_t src, bool casesen=false ) const;

       Input  :
          src    : source data to be matched, one of the following:
                   -- pointer to a UTF-8 string
                   -- pointer to a wchar_t string
                   -- a gString object containing the source (by reference)
                   -- a single, wchar_t character
          casesen: (optional, 'false' by default)
                   if 'false', then scan IS NOT case sensitive
                   if 'true, then scan IS case sensitive
     
       Returns:
          index of last matching substring or (-1) if no match found
          Note: This is the wchar_t character index, NOT a byte index

     Scan the data for the last occurance of the matching substring and if
     found, return the index at which the substring match occurs.

     Actual comparison is always performed against the 'wide' character array
     using wcsncasecmp (or wcsncmp). Null terminator character is not included
     in the comparison.

   ▪ int32_t after ( const char* src, int32_t offset=0,
                     bool casesen=false ) const;
   ▪ int32_t after ( const wchar_t* src, int32_t offset=0,
                     bool casesen=false ) const;
   ▪ int32_t after ( const gString& src, int32_t offset=0,
                     bool casesen=false ) const;

       Input  :
          src    : source data to be matched, one of the following:
                   -- pointer to a UTF-8 string
                   -- pointer to a wchar_t string
                   -- a gString object containing the source (by reference)
          offset : (optional, ZERO by default)
                   character index at which to begin search
                   -- if out-of-range, then same as if not specified
          casesen: (optional, 'false' by default)
                   if 'false', then scan IS NOT case sensitive
                   if 'true, then scan IS case sensitive
       Returns:
          index of the character which follows the matching substring
            or (-1) if no match found
          Note: This is the wchar_t character index, NOT a byte index

     This method is very similar to the 'find()' method above, but instead of
     returning the index to the beginning of the substring, returns the index
     of the character which FOLLOWS the substring.

   ▪ int32_t findr ( const gString& src, int32_t offset = -1,
                     bool casesen = false ) const;
   ▪ int32_t findr ( const wchar_t *src, int32_t offset = -1,
                     bool casesen = false ) const;
   ▪ int32_t findr ( const char *src, int32_t offset = -1,
                     bool casesen = false ) const;
   ▪ int32_t findr ( const wchar_t& src, int32_t offset = -1,
                     bool casesen = false ) const;

       Input  : src    : source data to be matched, one of the following:
                         -- pointer to a UTF-8 string
                         -- pointer to a wchar_t string
                         -- a gString object containing the source (by reference)
                         -- a single, wchar_t character (by reference)
                offset : (optional, by default: index of null terminator minus one)
                         character index at which to begin search
                         -- if out-of-range, then same as if not specified
                casesen: (optional, 'false' by default)
                         if 'false', then scan IS NOT case sensitive
                         if 'true, then scan IS case sensitive
     
       Returns: index of the first character (closest to head of data) of the 
                matching substring or (-1) if no match found
                Note: This is the wchar_t character index, NOT a byte index

     Scan the data beginning at the specified offset and moving toward the
     head of the string (toward offset zero). Locate the matching substring
     and if found, return the index of the first match.

     Actual comparison is always performed against the 'wide' character array
     using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included
     in the comparison.

   ▪ int32_t findx ( wchar_t srcChar = L' ', int32_t offset=0 ) const;

       Input  :
          srcChar: (optional, L' ' by default) character to be skipped over
          offset : (optional, ZERO by default)
                   if specified, equals the character offset into the 
                   character array at which to begin the scan.
       Returns:
          a) If successful, returns the index of first character which 
             DOES NOT match specified character.
          b) If the scan finds no character which is different from the 
             specified character, OR if 'offset' is out of range, OR if the 
             specified character is the null character, the return value 
             indexes the null terminator of the array.
          Note: This is the wchar_t character index, NOT a byte index

     Scan the text and locate the first character which DOES NOT match the
     specified character.

     This method is used primarily to scan past the end of a sequence of space
     (' ') characters (0x0020), but may be used to skip over any sequence of a
     single, repeated character. Note that the character specified must be a
     ‘wide’ (wchar_t) character.

     See also the 'scan' method below which scans to the first non-whitespace
     character.


   ▪ int32_t scan ( int32_t offset=0 ) const ;

       Input  :
          offset : (optional, ZERO by default)
                   if specified, equals the character offset into the 
                   character array at which to begin the scan.
       Returns:
          a) If successful, returns the index of first non-whitespace 
             character
          b) If the scan finds no non-whitespace character OR if 'offset' 
             is out of range, the return value indexes the null terminator 
             of the array.
          Note: This is the wchar_t character index, NOT a byte index.

     Scans the text array and returns the index of the first non-whitespace
     character found.

     Whitespace characters are defined as:
     0x0020 single-column ASCII space
     0x3000 two-column CJK space
     0x0A linefeed character
     0x0D carriage-return character
     0x09 horizontal-tab character
     0x0B vertical-tab character
     0x0C formfeed character



Examples
........

gString str1( "Toys for Tots" ) ;
gString str2( "The Tin Drum" ) ;

// compare with UTF-8 string
int result = str1.compare( "Toys for Tots" ) ;

// compare with wchar_t string
int result = str2.compare( L"The Tin Drum" ) ;

// compare gString objects
if ( str1 == str2 ) { /* do stuff */ }
if ( str1 != str2 ) { /* do stuff */ }


gString gs( L"Tiny Tim had a titillating tour of Times Square." ) ;

// find first instance of substring "tim" (not case sensitive)
int tIndex = gs.find( "tim" ) ;
wcout << &gs.gstr()[tIndex] << endl ;
 - - -> Tim had a titillating tour of Times Square.

// find the next instance of "tim"
gString gsSub( "tim" ) ;      // search string in a gString object
tIndex = gs.find( gsSub, tIndex + 1 ) ;
wcout << &gs.gstr()[tIndex] << endl ;
 - - -> Times Square.

// find first instance of substring "ti" (case sensitive)
tIndex = gs.find( L"ti", 0, true ) ;
wcout << &gs.gstr()[tIndex] << endl ;
 - - -> titillating tour of Times Square.

// match the first three characters of the search string
tIndex = gs.find( L"squirrel", 0, false, 3 ) ;
wcout << &gs.gstr()[tIndex] << endl ;
 - - -> Square.

// find first instance of L'R' (not case sensitive)
tIndex = gs.find( L'R' ) ;
wcout << &gs.gstr()[tIndex] << endl ;
 - - -> r of Times Square.

// extract the filename from path/filename string
gString gs( "/home/sam/SoftwareDesign/NcDialog/Dialog1/gString.hpp" ) ;
if ( (tIndex = gs.findlast( L'/' )) >= 0 )
   wcout << &gs.gstr()[tIndex + 1] << endl ;
 - - -> gString.hpp

// insert text after first instance of substring
gString gs( "I think that a parrot would be an ideal pet." ) ;
int pIndex = gs.after( L"would" ) ;
gs.insert( " NOT", pIndex ) ;
 - - -> I think that a parrot would NOT be an ideal pet.

For more examples of using gString-class methods, please refer to Test #6 of
the 'Dialogw' test application.




File: ansicmd.info,  Node: Extract Formatted Data,  Next: Statistical Info,  Prev: Comparisons,  Up: gString Text Tool

Extract Formatted Data
======================

   ▪ int32_t gscanf ( const wchar_t* fmt, ... ) const ;
   ▪ int32_t gscanf ( const char* fmt, ... ) const ;

       Input  :
          fmt  : a format specification template in the style of swscanf()
                 or sscanf() and related C/C++ functions
                 Template may be either a const char* OR a const wchar_t*
     
          ...  : optional arguments
                 Each optional argument is a POINTER to (address of) the
                 variable to receive the formatted data.
                 - Important Note: There must be AT LEAST as many optional
                   arguments as the number of format specifiers defined in
                   the formatting template. Excess arguments will be
                   ignored; however, too few arguments will return an
                   error condition. (see below)
     
       Returns: 
          number of items captured and converted
          returns 0 if:
            a) number of format specifications in 'fmt' > gsFormMAXARGS
            b) number of format specifications in 'fmt' > number of
               optional arguments (pointers to target variables) provided

     Scan the text data contained in the gString object and extract data
     according to the specified formatting template.
     (This is an implementation of the standard C-library 'swscanf' function.)

     The formatting template may be either a 'const wchar_t*' as in a call to
     'swscanf', _or_ a 'const char*' as in a call to 'sscanf'.

     The formatting template may contain between zero(0) and gsFormMAXARGS
     format specifiers.

     The optional arguments are _pointers_ to the target variables which will
     receive the formatted data.

     As with 'swscanf', the number of optional arguments must be equal to or
     greater than the number of format specifiers:
           (%d, %63s, %X %lld, %24lls, %[, etc.).
     Excess arguments will be ignored; however, unlike the 'swscanf' function,
     'gscanf' counts the number of format specifiers and optional arguments,
     and if there are too few arguments, the scan will be aborted to avoid an
     application crash due to memory-access violation. (You're welcome :-)


   ▪ int32_t gscanf ( int32_t offset, const wchar_t* fmt, ... ) const ;
   ▪ int32_t gscanf ( int32_t offset, const char* fmt, ... ) const ;

       Input  :
          offset: wide-character offset at which to begin the scan
                  Important Note: This IS NOT a byte offset.
                  If offset < 0 || offset > length of data, offset will
                  be silently set to 0.
     
          fmt   : a format specification template in the style of swscanf()
                  or sscanf() and related C/C++ functions
                  Template may be either a const char* OR a const wchar_t*
     
          ...   : optional arguments
                  Each optional argument is a POINTER to (address of) the
                  variable to receive the formatted data.
                  - Important Note: There must be AT LEAST as many optional
                    arguments as the number of format specifiers defined in
                    the formatting template. Excess arguments will be
                    ignored; however, too few arguments will return an
                    error condition. (see below)
     
       Returns: 
          number of items captured and converted
          returns 0 if:
            a) number of format specifications in 'fmt' > gsFormMAXARGS
            b) number of format specifications in 'fmt' > number of
               optional arguments (pointers to target variables) provided

     This is the same method as described above _except_ that the scan of the
     data begins at the specified character offset.



     Examples
     ........

     int  sval1, sval2, sval3, sval4 ;
     int  ival ;
     long long int llval ;
     double dval ;
     char   str1[64], str2[16], str3[16], ch1 ;
     gString gs( "17 % 18 21 22 48A2B 720451 24.325 A country song "
                 "is three chords and the truth. - Willie Nelson" ) ;
     int32_t cnt = 
        gs.gscanf( L"%d %% %d %d %d %X %lld %lf %63[^-] %c %16s %16s", 
                   &sval1, &sval2, &sval3, &sval4, &ival, &llval, 
                   &dval, str1, &ch1, str2, str3 ) ;
     
     gString gsOut( "items    : %d\n"
                    "numeric  : %d  %d  %d  %d  0x%04X  %lld  %4.6lf\n"
                    "text data: \"%s\" %c %s %s\n",
                    &cnt, &sval1, &sval2, &sval3, &sval4, &ival, &llval, &dval, 
                    str1, &ch1, str2, str3 ) ;
     dp->WriteParagraph ( 1, 1, gsOut, dColor ) ;
     
     This yields:
     items    : 11
     numeric  : 17  18  21  22  0x48A2B  720451  24.325000
     text data: "A country song is three chords and the truth. " - Willie Nelson
     
     A working example may be found in the NcDialog API package, 
     (Dialogw test application, Test #6).
     
      - - - - -
     
     To begin the scan from a particular offset into the text, the unneeded 
     initial data may either be scanned into a throw-away buffer or the 
     scan offset may be specified directly. For example, to discard the 
     first sixteen(16) characters:
     
     wchar_t junk[gsALLOCMIN] ;
     gs = "Useless garbage: 17 21 34" ;
     
     gs.gscanf( L"%16C %d %d %d", junk, &sval1, &sval2, &sval3 ) ;
       _or_
     gs.gscanf ( 16, L"%d %d %d", &sval1, &sval2, &sval3 ) ;
     

     Programmer's Note: It is good practice to specify a maximum length
     for all scanned strings in order to avoid overrun of the target buffer.
         THIS: %64s   %128lls   %256S   %32[a-z]
     NOT THIS: %s     %lls      %S      %[a-z]




File: ansicmd.info,  Node: Statistical Info,  Next: gString Miscellaneous,  Prev: Extract Formatted Data,  Up: gString Text Tool

Statistical Info
================

   ▪ int32_t gString::gschars ( void ) const ;

       Input  :
          none
       Returns:
          number of characters in the string

     Returns the number of characters in the string including the null
     terminator.


   ▪ int32_t utfbytes ( void ) const ;

       Input  :
          none
       Returns:
          number of bytes in UTF-8 string

     Returns the number of bytes in the UTF-8-encoded string including the
     null terminator.


   ▪ int32_t gscols ( void ) const ;

      Input  :
         none
      Returns:
         number of columns needed to display the data

     Returns the number of columns required to display the string.


   ▪ const short* gscols ( short& charCount ) const ;

       Input  :
          charCount : (by reference, initial value ignored)
                      on return, contains number of characters in 
                      the string including the null terminator.
       Returns:
          pointer to number of columns needed for display of each character

     Returns a pointer to an array of column counts, one for each character of
     the text data. Note that number of array elements equals number of
     characters (plus meta-characters, if any).


     Example
     .......

     This example is from the FileMangler utility. It trims the head of 
     the provided path/filename string to fit within a dialog window.
     
     void FmConfig::ecoPathFit ( gString& gsPath, short colsAvail )
     {
        if ( (gsPath.gscols()) > colsAvail )
        {
           gString gst = gsPath ;
           int32_t width = gst.gscols(),
                   offset = ZERO,
                   charCount ;
           const short* colArray = gst.gscols( charCount ) ;
     
           while ( width > (colsAvail - 3) )
              width -= colArray[offset++] ;
           gsPath.compose( L"...%S", &gst.gstr()[offset] ) ;
        }
     }  //* End ecoPathFit() *


   ▪ bool isASCII ( void ) ;

       Input  :
          none
       Returns:
          'true' if data are pure, 7-bit ASCII, else 'false'

     Scan the data to determine whether it is pure, 7-bit ASCII.



File: ansicmd.info,  Node: gString Miscellaneous,  Next: gString Examples,  Prev: Statistical Info,  Up: gString Text Tool

gString Miscellaneous
=====================

   ▪ void gString::clear ( void );

       Input  : none
       Returns: nothing

     Reset contents to an empty string i.e. "". The data will consist of a
     single, NULLCHAR character (L'\0').
     The character and byte counts are set to 1 (one), and the column count is
     zero.


   ▪ int32_t wAlloc ( void ) const;
   ▪ int32_t uAlloc ( void ) const;
       Input  : none
     
       Returns: size of dynamic storage allocation in wchar_t words
                OR
                size of dynamic storage allocation in uint8_t (char) bytes

     Report data storage allocation for the gString object:
     Note that this the maximum UTF-32 (wchar_t) characters,
     (or UTF-8 byte) capacity, NOT the current number of
     characters or bytes stored.
       wAlloc : returns the storage allocation for
                UTF-32 (wchar_t) characters
       uAlloc : returns the storage allocation for UTF-8 bytes


   ▪ int32_t freeSpace ( void ) const;
       Input  : none
     
       Returns: available buffer space
                Note: If zero(0) is returned, data may have been
                      truncated to fit.

     Reports the amount of free buffer space available, expressed as a count
     of UTF-32 (wchar_t) characters.


   ▪ int32_t reAlloc ( int32_t steps, bool clear = false );
       Input  :
          steps : number of steps to increase or decrease in buffer size.
                  Range: +/-999
                  If value out of range, will be set to upper/lower limit.
          clear : (optional, 'false' by default)
                  if 'false', if possible, retain the existing contents
                              of the buffer. (Note that if buffer size is
                              reduced, some data may be truncated.)
                  if 'true',  erase any existing text in the buffer
                              (same as 'clear' method, above)
     
       Returns: new buffer capacity expressed as the number of wchar_t characters

     Increase or decrease the size of storage buffer by the specified number
     of gsALLOCMIN increments.

     The buffer is sized in multiples of gsALLOCMIN in the range:
              gsALLOCMIN <= size <= gsALLOCMAX
              1024 chars            1,024,000 chars


   ▪ const char* Get_gString_Version ( void ) const ;
       Input  :
          none
       Returns:
          pointer to version string

     Return a pointer to gString class version number string.


   ▪ void gString::dbMsg ( gString& gsmsg ) const;
       Input  :
          gsmsg : (caller's object, by reference)
                  receives most recent debug message
       Returns:
          nothing

     FOR DEBUGGING ONLY! Application can retrieve most recent debug message.
     Note: This method is visible only if the DEBUG_GSTRING flag is set in
     gString.hpp.


   ▪ void dumpGstring ( const wchar_t*& gstr, const char*& ustr,
                        const short*& cwid, int32_t& gsw,
                        int32_t& gsu, int32_t& bsch, int32_t& bsco,
                        int32_t& utfb, bool& isas ) const;
       Input  :
          gstr   : array of wchar_t characters
          ustr   : array of UTF-8 bytes
          cwid   : array of column widths
          gsw    : size of gstr array
          gsu    : size of ustr array
          bsco   : number of display columns required for stored data
          bsch   : number of wchar_t characters stored (incl. nullchar)
          utfb   : number of UTF-8 bytes stored (incl.nullchar)
          isas   : set if stored data are pure ASCII data
     
       Returns: nothing

     FOR DEBUGGING ONLY! Get a snapshot of the private gString data members.
     Note: This method is visible only if the DEBUG_GSTRING flag is set in
     gString.hpp.



File: ansicmd.info,  Node: gString Examples,  Next: gsmeter Test App,  Prev: gString Miscellaneous,  Up: gString Text Tool

gString Examples
================

The NcDialog API test application 'Dialogw' contains _extensive_ examples of
gString usage, including working copies of the examples used in this chapter.
The other NcDialog API test applications also use gString in various ways.

Here, we show just a sample of some basic uses for the gString class.

  1. Convert a UTF-8 (8-bit) character string to a wchar_t (32-bit) character
     string.

     const char* some_UTF-8_data = "I want to buy an hamburger." ;
     wchar_t some_wide_data[gsALLOCDFLT] ;
     
     gString gs( some_UTF-8_data ) ;
     gs.copy( some_wide_data, gsALLOCDFLT ) ;

  2. Convert a wchar_t (32-bit) character string to a UTF-8 (8-bit) character
     string.

     const wchar_t* some_wide_data = L"I want to buy an hamburger." ;
     char some_UTF-8_data[gsALLOCDFLT] ;
     
     gString gs( some_wide_data ) ;
     gs.copy( some_UTF-8_data, gsALLOCDFLT ) ;

  3. Concatenate strings.

     const char* Head = "Where" ;
     const wchar_t* Tail = L"is Carmen Sandiego?" ;
     gString gs( L" in the world " ) ;
     gs.insert( Head, ZERO ) ;
     gs.append( Tail ) ;
     wcout << gs << endl ;
      - - ->  Where in the world is Carmen Sandiego?

  4. Create formatted string data.

     const char* utf8String = "We present" ;
     const wchar_t* wideString = L"for your enjoyment:" ;
     const char utf8Char = 'W' ;
     const wchar_t wideChar = L'C' ;
     short int ways = 100 ;
     double dish = 17.57 ;
     gString gs ;
     
     gs.compose( "%s %S %hd %cays to %Cook %Chicken,\n"
                 "and %.2lf side dishes and beverages!",
                 utf8String,
                 wideString,
                 &ways,
                 &utf8Char,
                 &wideChar, &wideChar,
                 &dish ) ;
     
     wcout << gs << endl ;
      - - ->  We present for your enjoyment: 100 Ways to Cook Chicken,
              and 17.57 side dishes and beverages!

       ┌────────────────────────────────────────────────────────────┐
       │ Important Note: All parameters are _pointers_ to the data: │
       │ For strings (and pointers), the _address_ is the name of   │
       │ the variable. For all other data types, including single   │
       │ characters, use the address-of ('&') operator.             │
       └────────────────────────────────────────────────────────────┘

  5. Count display columns to make data fit the window.

     This is a formatting method taken from the 'Dialogx' test application. It
     breaks a text stream into lines which fit within the dianostic window.
     It's not speedy (or particularly smart), but it demonstrates the use of
     'gString' to calculate the space needed to display text data and then
     formatting the data to fit the space.

     //*  FormatOutput   *
     //* Input  : gsOut     : semi-formatted source data
     //*          wpos      : start position for display
     //*          lineCount : maximum display lines before truncation
     //* Returns: nothing
     
     void dXClip::FormatOutput ( const gString& gsOut, 
                                 winPos& wpos, int32_t lineCount )
     {
        int tWidth = (ddCOLS - 2),        // inside width of target window
            maxWidth = tWidth * lineCount,// max columns for message
            tLines = ZERO ;               // loop counter
     
        gString gsw( gsOut.gstr() ), gso ;
        if ( gsw.gscols() > maxWidth )
        { // truncate the string if necessary
           gsw.limitCols ( maxWidth - 3 ) ;
           gsw.append( L"..." ) ;
        }
        do
        {  // break the source into convenient widths
           gso = gsw ;
           gso.limitCols( tWidth ) ;
           gso.append( L'\n' ) ;
           gsw.shiftCols( -tWidth ) ;
           this->dpd->ClearLine ( wpos.ypos ) ; // clear target display line
           wpos = this->dpd->WriteParagraph ( wpos, gso, 
                                              dxPtr->dColor, true ) ;
        }
        while ( ++tLines <= lineCount && gsw.gschars() > 1 ) ;
     
     }  //* End FormatOutput() *

     The example above is just a simple demonstration of using column widths.
     To see it in action, please refer to the 'Dialogw' NcDialog API Test
     Application, test seven (7).

     For a more sophisticated text-parsing algorithm, *note formatParagraph::
     which parses text data by _token_ rather than simply counting columns.



File: ansicmd.info,  Node: gsmeter Test App,  Prev: gString Examples,  Up: gString Text Tool

gsmeter Test App
================

                 GSMETER
                 
     ---------------------------------
          *note gsmeter Introduction::
          
          *note gsmeter Options::
          
          *note Building gsmeter::
          


'gsmeter' Introduction
--------------------

The original design of the gString class was based upon a fixed buffer size of
PATH_MAX, which is the maximum length of a file specification under the POSIX
standard. This is is defined as s GNU compiler constant, (4096 bytes), which
is greater-than-or-equal-to the number of bytes (or characters), depending on
the character set used for filespecs.
This buffer size was chosen specifically to balance storage capacity with
performance. The original gString design has performed far beyond expectations
for over fifteen years, and it is expected to meet or exceed most daily needs
of applications into the future.

In October of 2024, a beta-test branch of the gString class, bString was
created. The design critera for this class were to retain the original
functionality of the gString class with as few modifications as possible,
while converting the static character buffers to dynamically-resized character
and byte buffers.

This compares favorably with std::string and std::wstring which are cute in
their own way and semi-functional; but _seriously_ overweight. While it is not
our intention to be fat-shaming the C++ language, std::string support for text
data is functionally inconvenient, entirely too English-centric and
practically-speaking, is often mis-used (or ignored completely) by developers
due to its opaque implementation, which is based on a solid idea, but clearly,
was designed by committee.

Because this new design touches every aspect of the original gString
functionality, the 'gsmeter' test utility was created to perform exhaustive
regression testing, with a special focus on the algorithms for allocation and
re-allocation of dynamic memory.

The beta branch has now been re-integrated into the mainline gString class, so
the test application is now being included as part of the gString
distribution. Have fun!


                            ────────────────────


'gsmeter' Command-line Options
------------------------------

While this application lacks professional polish, it does provide a simple
menu structure and the usual --help and --version options.

gsmeter: version:0.0.05  gString v:0.0.37 - (c) 2024-2025 The Software Samurai
------------------------------------------------------------------------------
Test Suite for gString Class  Usage: gsmeter TEST [SUBTEST]
   C[a|b] --------- Constructors  :  S ------- Statistics   
   I[a|b] --------- Initializers  :  O ------- Output group 
   M[a|b|c|d]------ Modifiers     :  B[a|b] -- Buffer size 
   A[a|b|c|d|e|f]-- Analyzers     :  R[a|b] -- Reallocation
   --help  --version              :  P ------- Playground

      Example Invocations:
         gsmeter              # No arguments, invokes the options menu
         gsmeter Ca           # Constructor Group, section 'a'
         gsmeter Ac           # Analyzer Group, section 'c'
         gsmeter --version    # Report version numbers, current locale
                              # and copyright info

The tests are grouped according to functionality, and are sub-divided into
smaller groups so that each test run will fit within one terminal window of 39
rows x 150 columns.

There are seven(7) test groups with eighteen(18) tests, plus a “_Sandbox_” for
creating ad-hoc tests.


Test Groups
...........
  1. Constructors
          A: Constructors A, default, specify allocation, char*,
             wchar_t*, format specification
          B: Constructors B: integer-formatting constructors
  2. Initializers
          A: Initializers A, and basic reporting methods:
             wAlloc(), uAlloc(), gstr(), ustr(), gschars(), uftbytes(), gscols(),
             isASCII(), operator=, loadChars(), formatInt()
          B: Initializers B: compose(format, ...), compose(binary extension)
  3. Modifiers
          A: append(), limitChars(), limitCols(), insert(), erase()
          B: replace(), shiftChars(), shiftCols()
          C: rightJustify(), padCols(), strip(), textReverse()
          D: formatParagraph(), clear()
  4. Analyzers
          A: operator==, operator!=, compare(gString&), compare()
          B: compcoll(), find()
          C: findlast(), findx(), scan()
          D: after()
          E: findr()
          F: gscanf()
  5. Statistics
          Info Dump, Public Stats, Character Widths, Class Version Number
  6. Output group
          "operator<<" for both UTF-32 (wide) and UTF-8 (narrow) streams
  7. Reallocation tests
          A: Reallocation tests, Group A
          B: Reallocation tests, Group B
  8. Buffer Size/Resize (attempted overflow) tests
          A: Constructors and Assignments Overflow tests
          B: Insert and Append Overflow tests

Reporting of test results is split between the terminal window and a file
(gsmdbg.txt) created in the current working directory.


Note on Application Locale
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
gsmeter automatically enables the “locale” specified in the terminal
environment. While the gString class is written to be locale-independent, some
of the gsmeter tests rely upon the locale to function properly.
Specifically, the gString compcoll (compare-collated) method invokes the
locale-aware C-language function,'wcscoll'. This function uses a
dictonary-style comparison which is dependent on the language and locale
involved. Please *note compcoll:: method for details.


                            ────────────────────


Building 'gsmeter'
------------------

gsmeter is a very simple application, so building it is also simple.

There are four(4) ways to invoke the Makefile:
     gmake            # compile the application module and link
                          # to the existing gString library

     gmake buildlib   # delete the existing gString.lib link library
                          # and rebuild it

     gmake clean      # Remove the object files, the gString library
                          # and the executable

     gmake all        # Execute the 'clean', 'buildlib' and
                          # 'gmake' options

     ┌───────────────────────────────────────────────────────────────┐
     │ Important Note: Some tests include a snapshot of the gString  │
     │ object's internal configuration. This report requires that a  │
     │ conditional-compile declaration be enabled:                   │
     │       #define DEBUG_GSTRING (1)                               │
     │ This declaration is located near the top of gString.hpp.      │
     │ This declaration should be enabled only for use by gsmeter,   │
     │ and should be disabled for all other applications.            │
     │       #define DEBUG_GSTRING (0)                               │
     └───────────────────────────────────────────────────────────────┘




File: ansicmd.info,  Node: CsvView Demo App,  Next: AcEdit Demo App,  Prev: gString Text Tool,  Up: Top

CsvView Demo App
****************

'CsvView' (csvv) reads any Comma-Seperated-Values file and formats the data
for viewing in the terminal window.

* Menu:

* Introduction to CsvView::   A description of basic functionality
* Invoking CsvView::          Command line options
* CSV Encoding::              Examples of CSV-encoding formats
* Build CsvView from Source:: Building CsvView from Source



File: ansicmd.info,  Node: Introduction to CsvView,  Next: Invoking CsvView,  Up: CsvView Demo App

Introduction to CsvView
=======================


What Is CSV?
------------

Comma-Seperated-Values files are plain-text files commonly used for
transferring tabular data between applications or accross the web. The format
is very simple and supported by many applications such as LibreOffice,
Excel(tm), as well as various email platforms and database applications.

While there is no formal specification for CSV data, several groups have
worked toward a normalized format, most notably the World Wide Web Consortium
(W3C).
   <https://www.w3.org/TR/tabular-data-primer/>
   <https://www.w3.org/2013/csvw/wiki/Main_Page.html>

Additional information (and the opinions of various parties) are available:
Internet Engineering Administration, Research Task Force (IRTF):
   <https://datatracker.ietf.org/doc/html/rfc4180>
FileFormat.com:
   <https://docs.fileformat.com/spreadsheet/csv/>
Wikipedia:
   <https://en.wikipedia.org/wiki/Comma-separated_values>

For examples of CSV files, please *note CSV Encoding::, and the sample CSV
files included with this distribution.


The CsvView Application
-----------------------

The CsvView application (csvv) reads any CSV-formatted file and reformats it
for viewing, either directly in the terminal window or through the 'less'
utility. CsvView supports source files in any of the four(4) authorized
encodings:
   UTF-8
   UTF-8 with byte-order mark (BOM)
   UTF-16LE (little-endian)
   UTF-16BE (big-endian)

It is important to note that the 'less' can display _some_ CSV files without
the need for reformatting; however, 'less' will often complain that the target
file is a "binary" file, and cannot display the data as text, even though the
file does not actually contain binary data.

For this reason, CsvView reformats the source data into pure UTF-8 encoding
before display. This re-encoding also vertically aligns the fields to present
the data in an orderly manner. CsvView can format the output in any of
three(3) ways.

Horizontal Format: one record per line
NAME              TITLE                PHONE        EMAIL
Helena Handbasket Queen of the Castro  415-654-3210 Yaz-Queen@TwinPeaks.com

Vertical Format : one field per line
NAME     Helena Handbasket 
TITLE    Queen of the Castro
PHONE    415-654-3210
EMAIL    Yaz-Queen@TwinPeaks.com

Quick Format : horizontal format, truncated to width of window
┌───────────────────────────────────────────────────────┐
│NAME              TITLE                PHONE        EMA│
│Helena Handbasket Queen of the Castro  415-654-3210 Yaz│
└───────────────────────────────────────────────────────┘

Please *note csv display option:: for selection of the display format.

CsvView may also be used to _create_ files in CSV format using any of the
encoding methods described above.
Please *note csv create option:: for details.



File: ansicmd.info,  Node: Invoking CsvView,  Next: CSV Encoding,  Prev: Introduction to CsvView,  Up: CsvView Demo App

Invoking CsvView
================

This chapter lists the command-line options for invoking the CsvView (csvv).
The 'help' and 'version' options override all other specified options.

The CsvView application is intentionally very simple — built without support
for direct user-configuration of the AnsiCmd library. The only available
terminal configuration option is for selection of the color attributes used
for text output.
Please *note Invoking - Terminal Setup:: for a detailed discussion of the
AnsiCmd terminal setup options used for the EarthPoints and AcEdit
applications,


Summary of Options
------------------

       OPTION                           DESCRIPTION
     ------------------------------------------------------------------
       *note csv filespec option::     Specify the source CSV file
       *note csv display option::      Specify the display format
       *note csv fgndattr option::     Foreground color attribute
       *note csv bgndattr option::     Background color attribute
                                       to a file
       *note csv language option::     Specify user-interface
                                       language
       *note csv header option::       Specify whether source file
                                       includes a header record
       *note csv saveas option::       Save formatted display data
       *note csv stats option::        Report source file stats
       *note csv dimensions option::   Report dimensions of terminal
                                       window
       *note csv help option::         Display all application
                                       options
       *note csv helpless option::     Same as '--help' option
                                       except pipe through 'less'
       *note csv version option::      Reports CsvView version
                                       number and copyright info.
       --- Development Options ---         ------------------
       *note csv create option::       Create a CSV file
       *note csv capture option::      Capture a range of records
       *note csv terminfo option::     Report the current  terminal
                                      configuration
       *note csv pause option::        Pause before display of
                                       formatted data

Options may be specified in any order.

For each option that requires one or more arguments, the option name and its
argument(s) may be separated by either '=' or ' ' (space).
Note that if the argument contains whitespace, then the entire argument
sequence must be enclosed within single-quotes or double-quotes.
This prevents the terminal's shell program from “interpreting” (trashing) your
argument formatting.

Multiple instances of an option will result in unpredictable results, so don't
do it.

Examples:
    --filespec=Contacts.csv
    --filespec Contacts.csv
    --create=Sample.txt,utf8bom,crlf
    --create "Sample Records.txt, utf16le, crlf"

Note: As a convenience, the options may be uniquely specified in a truncated
form. At least six (6) characters of the option must be specified. This
consists of the two 'dash' characters, plus the first four characters of the
option name. Example: The “--filespec” option may be uniquely specified as
“--file”.



Invocation Options
------------------

 −−filespec Specify the source CSV file.

     Specify the file to be displayed.
     The source file may be specified as a filename in the current directory,
     as a relative path, or as an absolute path. Special characters such as
     '.' '..' '~' are recognized, and symbolic links in the path will be
     followed. The filename must include the ".csv" filename extension.

     The file must be in Comma-Seperated-Values (CSV) format, and encoded as
     UTF-8, UTF-8 with byte-order-mark, UTF-16LE or UTF-16BE.
     If the file cannot be verified as containing valid CSV data, a warning
     will be displayed and the application will exit.
     Important Note: Because there is no formal standard for the CSV format,
     it is possible that a non-CSV file will be accepted for processing. If
     this happens, then as the saying goes: “Garbage in, garbage out.”

        EXAMPLES:  csvv --filespec=Contacts.csv
                   csvv --filespec='Company Employee Info.csv'
                   csvv --filespec "Fred's Extended Family.csv"
                   csvv --file=Contacts.csv
        Although it is not recommended, CsvView will accept a source
        filename WITHOUT the "--filespec" option:
                   csvv Contacts.csv --display=v --stats


 −−display Specify the display format.

     The display option specifies the type of formatting to be used for
     display of the CSV records. The options are:
      h — Horizontal (default)
          Display one record per line.
          The record fields are aligned vertically for ease of viewing.
          The data are displayed using the 'less' utility to fascilitate
          both vertical and horizontal scrolling.
      v — Vertical
          Display one field per line. This is useful if the record
          is wider than the width of the terminal window.
          The data are displayed using the 'less' utility to fascilitate
          both vertical and horizontal scrolling.
      q — Quick
          The Quick output format is the same as the Horizontal format except:
          a) The data are written directly into the terminal window,
             one page at a time.
             This is similar to viewing data using the 'cat' utility.
          b) The data are truncated at the right edge of the terminal window
             to prevent the terminal from inserting automatic line breaks.

     Please *note Output Formats:: for further information.

        EXAMPLE: csvv --display=v


 −−fgndattr Set foreground color attribute.

     Specify the foregroud (text) attribute used for display of the data.
     By default, the text data are displayed using _blue_ text.

     The available attributes are the eight(8) basic colors and their
     “intense” (bold) variants, or the terminal-default attribute.

        BASIC    INTENSE
        -----    -------
        black    blacki
        red      redi
        green    greeni
        brown    browni
        blue     bluei
        magenta  magentai
        cyan     cyani
        grey     greyi
        dflt
     
        EXAMPLES:  csvv --fgndattr=green
                   csvv --fgndattr red
                   csvv --fgndattr=redi


 −−bgndattr Set background color attribute.

     Specify the backgroud attribute used for display of the data.
     By default, the background attribyte is the terminal default (_dflt_).

     The available attributes are the same as those listed for the foreground
     attributes above.
     Note: Avoid using the same attribute for both foreground and background.

     [** THE bgndattr OPTION IS CURRENTLY IGNORED **]
        EXAMPLES:  csvv --bgndattr=magenta
                   csvv --bgndattr brown
                   csvv --bgndattr=bluei


 −−language Specify the user interface language.

     Specify the language used by the application's user interface.

     Options:
        EN — ENglish
        ZH — ZHongwen (中文) Simplified Chinese
        tenv — Terminal EnVironent (default)

     By default, the user interface language used is derived from the locale
     used by the system. If the system locale is one of the Zhōngwén variants,
     the Chinese interface will be used; otherwise, the English interface will
     be used.
     *Note Terminal Configuration:: for a discussion of locale.

     To override the automatic language selection, use the '--language' option
     to select the desired user-interface language.

     Note that the 'EN' and 'ZH' designators are the internationally accepted
     language designators.
     Please refer to Library Of Congress document:
     <https://www.loc.gov/standards/iso639-2/>,
     or to the Wikipedia article which describes the ISO 639 standard:
     <https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes>

        EXAMPLES:  csvv --language=ZH
                   csvv --lang en
                   csvv --language tenv

          Note: This application is designed to be as simple as possible, so
          we have implemented only our two(2) best languages. Other UI
          languages may be added in a later release.


 −−header Specify whether source contains header record.

     Override the application's determination of whether the source file
     contains a header record.
     A header record contains column headings for the remainder of the
     records.

     During the initial scan of the source file, the application tries to
     determine whether the first record of the file is a header record. The
     criteria for this test are:
        1) Is the first line of the file terminated by a newline?
        2) Does the record include at least one comma (',') delimeter?
        3) Do all fields of the record contain text data, (non-empty)?

     Clearly, the first record of a CSV file may meet all these criteria and
     still not be a header record—or may be a header record without meeting
     these criteria. If this happens, the program's scan results may be
     overridden using the '--header' option to specify whether the file does,
     in fact include a header record.

     Note that if a CSV file does not contain a header record, then horizontal
     output formatting will simply have no column headings; however, for
     vertical output formatting, generic column headings will be used.
     Example:
        Field # 1  : Helena Handbasket
        Field # 2  : Queen of the Castro
        Field # 3  : 415-654-3210
        Field # 4  : Yaz-Queen@TwinPeaks.com

        EXAMPLE:  csvv --filespec='Contacts.csv' --header=y

                            ────────────────────
          Note that the MIME-type database for the system may optionally
          specify whether CSV files on the system include header records;
          however, this information is not just optional, it is unreliable and
          is not referenced by this application. In a corporate setting, CSV
          files that are routinely used to transfer company data may adhere to
          the specified MIME type; however, a CSV file created by a
          non-corporate application (e.g. an email application), or a file
          randomly downloaded from the web are not likely to conform to the
          system's MIME-type database.


 −−saveas Save reformatted display data.

     When specified, the '--saveas' option saves a copy of the displayed data
     to a file in the current working directory. Specify the filename only.

     The saved data will be plain text in the same format used to display the
     data in the terminal window.

     The data format is determined by the '--display' option described above,
     either 'Horizonal' or 'Vertical'.
     (For the “Quick” output format, the data are not saved.)

        EXAMPLE:  csvv --filespec='contacts.csv' --saveas='formatted_data.txt'


 −−help (or −h) Display command-line help.

     Command-line Help. Display a brief summary of command-line usage and
     options.
     (overrides everything on command line except '--version')

        EXAMPLES:  csvv --help
                   csvv -h


 −−helpless (or −hl) Display command-line help.

     Display command-line help. Same as the '--help' option above except that
     the help menu will be piped through the 'less' utility.

        EXAMPLES:  csvv --helpless
                   csvv -hl


 −−version Report CsvView version number.

     Display the CsvView version number and copyright information.
     (overrides everything else on the command line)
     The AnsiCmd-class and gString-class version numbers are also reported.

        EXAMPLE:  csvv --version

                            ────────────────────


 −−create Create a CSV file from plain text.

     Create a Comma-Seperated-Values (CSV) file using a plain-text file as the
     source data.

          ┌───────────────────────────────────────────────────────┐
          │ During development, this option was used to create    │
          │ various test files to exercise the functionality      │
          │ and general syntax checking of the application.       │
          │                                                       │
          │ The test files included in this distribution were all │
          │ created from the plain-text file, 'csvsource.txt'     │
          │ using the --create option. Study this file for more   │
          │ information.                                          │
          └───────────────────────────────────────────────────────┘

     The create option takes two or three arguments:
       1) source filename
       2) UTF encoding (utf8, utf8bom, utf16le, or utf16be)
       3) newline format (optional) lf    linefeed only, or
                                    crlf  carriage-return/linefeed pairs

     The CSV file created through this option takes the name of the source
     file, but with the ".csv" filename extension. Example:
        csvsource.txt --> csvsource.csv
        csvsource     --> csvsource.csv

     Although the source file is technically a plain-text file, it could also
     be described as a _pure UTF-8_ encoded CSV file.


     Exception:
     .........

     The newline character, (either a linefeed '\n' or a
     carriage-return/linefeed pair "\r\n") is a special character which
     signals the end of a record within a CSV file. However, it is fairly
     common to use newlines within a long, free-form field to indicate line
     breaks, so long as the field is enclosed within secondary-delimeter
     pairs.

     To test this functionality, a special two-character sequence within the
     source file: “\n” is recognized by the 'createCsvFile' method as an
     _embedded newline_ character. This allows for testing embedded newlines
     within a field.

     Please *note CSV Encoding:: for additional information about newlines and
     commas embedded within a CSV record.


        EXAMPLES:  csvv --create=source_data.txt,utf16le
                   csvv --create="source data.txt,utf16be,crlf"
                   csvv --create="source data.txt, utf8bom, crlf"


 −−capture Capture a range of records.

     Extract a range of records from the source file, and if the records are
     UTF-16 encoded, convert them to UTF-8.

     Format the data for analysis, and write the formatted data to a file in
     the current working directory.
     The name of the target file is: "captured_records.txt"

     The --capture option takes three(s) parameters:
       a) the source filename,
       b) the index of the first record to be captured (>=0), and
       c) the index of the last record to be captured (>first record)
     Note that the header record (index 0) is always captured.

     During development, certain records in the source files may either be
     malformed or, _gasp_ the application may have parsed the record
     incorrectly. This option may be used to isolate the suspected range of
     records and format them as both text and ASCII hex, which may then be
     used to visually analyze the data. See example output below.

        EXAMPLE:  csvv --capture="SourceRecords.csv,5,6"

     Sample Output:
     --------------
     HEADER RECORD - index:00 
     -------------------------
       N  A  M  E  ,  A  G  E  ,  O  C  C  U  P  A  T  I  O  N \n
      4E 41 4D 45 2C 41 47 45 2C 4F 43 43 55 50 41 54 49 4F 4E 0A
     
     RECORD INDEX :05 
     -----------------
        成   吉   思   汗  ,  9  6  2  ,   马   语   者  ,  "   蒙   古  ,
      6210 5409 601D 6C57 2C 39 36 32 2C 9A6C 8BED 8005 2C 22 8499 53E4 2C
        肯   特   山   脊  " \n
      80AF 7279 5C71 810A 22 0A
      
     RECORD INDEX :06 
     -----------------
       "  B  o  n  d  ,     J  a  m  e  s  "  ,  3  6  ,  w  o  m  e  n \n 
      22 42 6F 6E 64 2C 20 4A 61 6D 65 73 22 2C 33 36 2C 77 6F 6D 65 6E 0A
     


 −−stats Report statistics for source file.

     Display information about the specified source file.
     This information includes basic information about the file itself, as
     well as information about the CSV data contained in the file.

     The following example illustrates the type of information reported.
     This test file shown here is included as part of the distribution
     package.

     Source File Stats
     ------------------------------------
     Filename   : utf8bom_cr.csv            # Name of the source file
     File type  : REG                       # File type (must be Regular)
     File bytes : 388                       # Size of the file in bytes
     Mod time   : 2024-02-15T19:09:30       # Timestamp (modification time)
     Permissions: r:1 w:1                   # Read and Write permission flags
     Encoding   : UTF-8bom Cr:yes Hdr:yes   # Type of character encoding
                                            # Type of newline: Linefeed only,
                                            #  or Carriage-return/Linefeed pairs
                                            # Report whether file includes a
                                            #  header record
     Records    : 9        Fields : 4       # Number of records (not incl. header)
                                            # Number of fields per record
     
     
        EXAMPLE:  csvv --stats --filespec='utf8bom_cr.csv'


 −−dimensions Report terminal window dimensions.

     Report the size of the terminal window expressed as the number of rows
     and columns.

     When deciding how to format the CSV data to fit within the terminal
     window, the window dimensions must first be calculated. This option
     simply reports the results of that calculation.

     The following example shows how the report is written to the display.
     The report preceeds the formatted output of the CSV file data.

     ┌───────────────────────────────────────┐
     │ Terminal Size: 39 rows x 154 columns  │
     └───────────────────────────────────────┘
     Press Any Key To Continue...
     
     
     
        EXAMPLES:  csvv --dimensions
                   csvv --dime --filespec=Contacts.csv


 −−terminfo Report terminal configuration.

     Used during development, this option reports the current terminal window
     configuration data as reported by the AnsiCmd link library.
     Please *note acGetTermInfo:: for further information about terminal
     configuration.

     Terminal Configuration Flags
     ---------------------------------------------
     istrip : 7-bit input                 disabled
     opost  : output flags                enabled 
     onlcr  : convert newlines to cr/lf   enabled 
     xtabs  : convert tabs to spaces      disabled
     cread  : read terminal input         enabled 
     csize  : character width             8 bits
     icanon : enable canonical input      disabled
     echo   : echo character input        disabled
     echonl : echo newlines               disabled
     echoctl: echo control chars as (^x)  enabled 
     iexten : posix extensions            enabled 
     
     
        EXAMPLE:  csvv --terminfo


 −−pause Pause before display of formatted data.

     This option is included primarily for use during development.
     When debugging output is enabled, it is written to the display during
     startup and during analysis of the source file. This option causes the
     program to wait for a keypress before the debugging information is
     overwritten by the formatted CSV records.

        EXAMPLE:  csvv --pause --filespec='Contacts.csv'



File: ansicmd.info,  Node: CSV Encoding,  Next: Build CsvView from Source,  Prev: Invoking CsvView,  Up: CsvView Demo App

CSV Encoding
============

This chapter provides a practical, (but not official) description of
Comma-Seperated-Values (CSV) formatting and example data for each of the
recognized UTF encodings.

  1. A CSV file consists of a list of "records", one record per line of the
     file. Any reasonable number of records is supported.
     Technical Note: This application uses 16-bit indices, so the practical
     record limit is 32,768 data records.

  2. Each record consists of a series of "fields" seperated by the ASCII
     comma: ',' (2C hex).
       a. Each record must have the same number of fields.
       b. Any reasonable number of fields is allowed.
       c. A field may contain any reasonable number of characters, (including
          zero characters).
       d. A field may contain any text character _except_ commas and newline
          characters, (but see note about secondary delimeters, below).
       e. The first field of a record _does not_ have a leading comma.
       f. The last field of a record _does not_ have a trailing comma.

  3. Each line is terminated by a newline. For purposes of this discussion, a
     "newline" is either a single linefeed character: '\n' or a
     carriage-return/linefeed pair: "\r\n".

     In UTF-8 encoded data the newline is represented as:
        0A   or   0D0A   hex
        \n   or   \r\n

     In UTF-16LE (little-endian) encoded data the newline is represented as:
        0A00   or   0D000A00   hex
        \n\0   or   \r\0\n\0

     In UTF-16BE (big-endian) encoded data the newline is represented as:
        000A   or   000D000A   hex
        \0\n   or   \0\r\0\n

  4. Secondary Field Delimeters:
     The double-quotation character: '"' (22 hex) may be used in conjunction
     with the basic comma delimeter to create pairs of secondary field
     delimeters. This is useful (and necessary) if the field contains either
     commas or newlines (as defined above). An example of a record using a
     secondary-delimeter pair for the second field of the three-field record
     is given:
      Hello!,"When, where\nand why",vape?
      48656C6C6F212C225768656E2C2077686572652C0A616E6420776879222C766170653F0A
       H e l l o ! , " W h e n ,   w h e r e ,\n a n d   w h y " , v a p e ?\n
                   └──        ┴┴              ┴┴               ──┘
               opening        embedded        embedded     closing
             delimeter        comma           newline    delimeter

     The secondary delimeters enclose the data of the field: ,".....", and
     have the effect of dereferencing those special characters, which are then
     interpreted as plain text within the field.


A Note On Creating CSV Files With Secondary Delimeters
......................................................

The CsvView application includes the functionality to create CSV files from a
plain-text source file. (*note csv create option::) The CSV file is created
using the desired UTF encoding and newline format.

Commas and newlines within a CSV file are interpreted as field-delimeter and
end-of-record, respectively. However, these characters may be interpreted as
ordinary text _IF_ they are enclosed within secondary delimeters as described
above.

Within the source file used to create CSV output, a comma embedded within
secondary delimeters is automatically identified during conversion; however,
because the newline character is a “special” character (i.e. a control
character) within a plain-text file, it must be handled as a special case.

The design decision was made that within a source file used to generate CSV
files, _embedded newlines_ are designated using a sequence of two ordinary
ASCII characters:
   backstroke: '\' plus a lower case n: 'n'
During creation of the CSV file, this sequence is converted to a newline
character as defined above.

Comment lines may be used within the source file and will be ignored by the
conversion algorithm. Comments are identified by using the hash character
('#') as the first character of the line. When the hash character is
encountered, the entire source line will be discarded.

Technical Note: Secondary delimeters must not be used in the first record of
the source file (header record). This is because when scanning the first
record of a CSV file, the type of encoding has not yet been determined.

                            ────────────────────
Technical Note: It is possible that some designers of CSV files will attempt
to be “creative” by using a character other than the double-quote character to
create secondary-delimeter pairs. Some examples would be the astrisk '*' or
the semicolon ';'. CsvView does not support this kind of “creativity”, but if
you often encounter such constructs, the 'convertDoubleQuotes' and
'dqDelimeterCount' methods could be generalized to accomodate such constructs.



File: ansicmd.info,  Node: Build CsvView from Source,  Prev: CSV Encoding,  Up: CsvView Demo App

Build CsvView from Source
=========================


Tools
-----

The CsvView demonstration application and the AnsiCmd library upon which it is
built, are written in C++ and are built with the GNU C++ compiler and linker.
No additional link libraries or third-party tools are needed.

GCC (G++) version 7 and above with support for C++17 (gnu++17) or greater.


Compiling
---------

The make file, 'Makefile' includes several options for building the
application.

     Examples:
       gmake all          — Execute all other options in sequence
       gmake clean        — Delete the executable and object files
       gmake refreshlib   — Copy the necessary files from parent directory
       gmake              — Build out-of-date source files and re-link


Build Options
-------------

The AnsiCmd library has two(2) global directives which affect conditional
compilation of the library.
  1) DEBUG_ANSICMD Enable or disable debugging methods and data.
  2) INCLUDE_API   Include the high-level API methods and data.

Both of these conditional-compile directives should be set to zero ('0') when
building the AnsiCmd library (gmake buildlib).
While neither directive affects the functionality of the CsvView application,
disabling them will reduce the size of the executable by approximately 600
Kbytes.
Please *note Build Options:: for the AnsiCmd library for more information
about conditional compilation.

  1. DEBUG_CSVV – Global control of debugging code for the application.
     Various condition-compilation directives for debugging are defined for
     individual methods, and when the DEBUG_CSVV directive is set to zero
     ('0'), all of the following directives will also be disabled.

       a. DEBUG_PF – Defined in the 'SrcScan' method and used to control code
          for parsing the fields of a record.
       b. DEBUG_RR – Defined in the 'readRecord' method, this directive
          controls debugging output for the rather complex task of reading a
          single record from a CSV-formatted file.
       c. DEBUG_isUTF16 – As the name implies, this directive is defined in
          the 'isUTF16' method which scans the first record of the source file
          to determine whether the file is encoded as UTF-16 data.
       d. DEBUG_B2W – Defined in the 'convert2UTF16' method, this directive
          reports intermediate information for conversion from UTF-8 to UTF-16
          data.
       e. DEBUG_CNL – Defined in the 'convertNewlines' method, this directive
          reports on the process of converting linefeed characters to
          carriage-return/linefeed pairs.
       f. DEBUG_DNL – Defined in the 'deflateNewlines' method which
          complements the 'convertNewlines' method by converting
          carriage-return/linefeed pairs to linefeed characters.
       g. DEBUG_isUTF8b – Defined in the 'isUTF8bom' method, this directive
          reports the intermediate steps in determining whether the source CSV
          file contains a UTF-8 byte-order mark (BOM).
       h. DEBUG_CDQ – Defined in the 'convertDoubleQuotes' method, this
          directive reports the intermediate steps in processing
          double-quotation-mark characters which are used as secondary
          delimeters within a field.
          Please *note Secondary Field Delimeters:: for more information on
          secondary delimeters.
       i. DEBUG_GCLA – Defined in the 'GetCommandLineArgs' method, this
          directive enables reporting on parsing of the application's command
          line arguments.
       j. DEBUG_VP – Defined in the 'DisplayData' method, this directive
          inserts visible characters ('-') instead of whitespace for padding
          fields to their full width.


Testing the Build
-----------------

To test the build, invoke with a request for the CsvView version number. You
should get something similar to the following:

     ./csvv --version

     CsvView (csvv) v:0.0.06 Copyright(c) 2024-2026  The Software Samurai
     =======================================================================
     AnsiCmd Link Library v:0.0.07  (gString v:0.0.37)
     -----------------------------------------------------------------------
     License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>
     This is free software: you are free to modify and/or redistribute it
     under the terms set out in the license.
     There is NO WARRANTY, to the extent permitted by law.

If you have forgotten to disable the AnsiCmd library debugging code, and/or
the AnsiCmd API-level code (see above), a warning message will be appended to
the above output.





File: ansicmd.info,  Node: AcEdit Demo App,  Next: TFMTest Demo App,  Prev: CsvView Demo App,  Up: Top

AcEdit Demo App
***************

* Menu:

* Introduction to AcEdit::    A description of basic functionality
* Invoking AcEdit::           Command line options
* AcEdit Menu System::        Menus and the user interface
* AcEdit Dialogs::            User Interface Dialogs
* AcEdit Configuration::      Customizing the configuration file
* Build AcEdit from Source::  Building AcEdit from Source



File: ansicmd.info,  Node: Introduction to AcEdit,  Next: Invoking AcEdit,  Up: AcEdit Demo App

Introduction to AcEdit
======================

*Documentation for the 'AcEdit' demo application is under construction.*

The AcEdit application is designed as a platform for testing the high-level
functionality of the AnsiCmd library, and for demonstrating various approaches
to building applications based on the AnsiCmd library.
For details, *note AnsiCmd Link Library: Top. at the top of this document.

AcEdit is a console application, meaning that it runs within a terminal
window.

AcEdit is not designed to be a full-featured text editor, although subsequent
releases may approach full functionality.


AcEdit Features
---------------

  1. AcEdit is invoked like any command-line utility, although the data are
     not displayed as TTY output. Instead, AcEdit is a windowed application,
     visually similar to an application built on the "ncurses" library, but
     vastly more simple in design and execution than an ncurses application.
     Please visit the author's website for wide variety of applications which
     _are_ built on the ncurses library.

     Please *note Invoking AcEdit:: for a discussion of all command-line
     options.

  2. Configuration of AcEdit is performed by reading the ace.cfg configuration
     file on startup.
     Please *note AcEdit Configuration:: for more information.

  3. Multiple files may be edited simultaneously, so copy and paste among the
     files via a “local” (application-specific) clipboard is straightforward.

     Access to the system clipboard is enabled by default, so data may be
     seamlessly transferred between AcEdit and other active applications.
     *Note AnsiCmd Clipboard Access:: for a discussion of the system clipboard
     interface.

  4. AcEdit is designed as a multi-language application. Two languages are
     initially supported: English and Chinese (simplified). All LTR
     (left-to-right) character sets are supported.

     Support for RTL languages is too complex for this demonstration app;
     sorry about that. Please see the author's NcDialog API which includes
     full support for both LTR and RTL languages.


Building the Application
------------------------

The application is based on the author's AnsiCmd link library. The library is
fully self-contained and the build requires only the GNU compiler and its
standard dynamic-load libraries.
(The compiler version must support the C++17 functionality which became
available in GCC v:7.
*Note Build AcEdit from Source:: for details.

A local clipboard is built into the library; however, access to the system
clipboard requires the wl-clipboard package which is available for downlad on
most distribution sites.



File: ansicmd.info,  Node: Invoking AcEdit,  Next: AcEdit Menu System,  Prev: Introduction to AcEdit,  Up: AcEdit Demo App

Invoking AcEdit
===============

This chapter lists the command-line options for invoking the AcEdit (ace). The
'help' and 'version' options override all other specified options.

For a detailed discussion of the AnsiCmd terminal setup options used for
applications based on the AnsiCmd link library. please *note Invoking -
Terminal Setup::.


Summary of Options
------------------

       OPTION                           DESCRIPTION
     ------------------------------------------------------------------
       *note ace color option::        application color attributes
       *note ace language option::     user interface language
       *note ace dimensions option::   application height/width
       *note ace help option::         Display all application
                                       options
       *note ace helpless option::     Same as '--help' option
                                       except pipe through 'less'
       *note ace version option::      Reports AcEdit version
                                       number and copyright info.
       --- Development Options ---         ------------------
       *note ace test option::         Sandbox (testing only)

All parameters are optional, and may be specified in any order.

For each option that requires one or more arguments, the option name and its
argument(s) may be separated by either '=' or ' ' (space).
Note that if the argument contains whitespace, then the entire argument
sequence must be enclosed within single-quotes or double-quotes.
This prevents the terminal's shell program from “interpreting” your argument
formatting.

Parsing of command line options requires at least the first six(6) characters
of the option token.
For instance, the "--language" token is fully identified by the first six
characters: --lang".

Avoid specifying the same option multiple times. Multiple instances of an
option may cause unpredictable results.



Invocation Options
------------------

     Specify file(s) to be edited:
     ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  1. Any parameter that does not begin with a dash, ‘–’ character) is
     interpreted as a filename specification.
       a. Specify the filename only, which will be interpreted as a file
          located in the current working directory (CWD).
          Example: ace strip_cr.pl

       b. Specify a path relative to the CWD.
          Example: ace "../../Perl Utilities/strip_cr.pl"

       c. Specify a full filespec.
          Example: ace "/home/sam/Documents/Perl Utilities/strip_cr.pl"

  2. Environment variable substitutions and special filespec characters are
     supported.
     Example: ace ~/Videos/DVD_List.txt
              ace '${HOME}/Videos/Blu-ray/Videos With Subtitles.txt'
              ace ./Subtitles.txt

  3. Symbolic links are followed. Example: ace WkExer.lnk
     with the link referencing ~/Documents/Weekly_Exercise.txt.

  4. Note that the names of files edited in previous sessions will have been
     stored in the configuration file.
     If the file was open for editing when the application was closed, it will
     automatically be re-opened on application startup.

  5. If a filename specified on the command line duplicates a filename saved
     in the configuration file, the duplicate name will be discarded.

  6. Only “regular” text files may be edited using AcEdit. For example: Bash
     scripts, Perl, C, C++, HTML, XML, etc.
     Binary files and complex files such as LibreOffice documents will be
     rejected for edit.


 −−color=BORDER_FG:BORDER_BG
         [,TEXT_FG:TEXT_BG[,HILITE_FG:HILITE_BG]

       a. Border attributes must be specified.
       b. Text-field and cursor-row attributes are optional
       c. Application's default value is indicated by zeros for both
          foreground and background values:
          Example: --color=f00:f00,f10:f04

     Note that selecting a color scheme should normally be done in the
     configuration file. *Note AcEdit Configuration::.

     Command line specification of color attributes mirrors the syntax of the
     config file; and while this makes for efficient coding, it is certainly
     not user friendly. The option sequence is as follows:

     --color=Border_FG:Border_BG, Text_FG:Text_BG, Hilite_FG:Hilite_BG
        │     │         │          │       │        │         │
        │     │         │          │       │        │         │
        │     │         │          │       │        │         └ cursor row background
        │     │         │          │       │        └ cursor row foreground
        │     │         │          │       └ text field background
        │     │         │          └ text field foreground
        │     │         └ border background
        │     └ border foreground
        └ option name

     The color options correspond to the terminal color registers for 4-bit
     palette (16 colors), 8-bit palette (256 colors) and 24-bit palette (RGB).

     Each specified attribute consists of a single character (case
     insensitive), followed by an integer value.
     Foreground/Background pairs are seperated by a colon ':'.
     Color pairs are seperated by a comma ',' (and optional whitespace).

        Palette:  Character:  Value Range:
        --------  ----------  ------------
        4-bit       f         00 - 15
        8-bit       e         16 - 231
        24-bit      r         00 - 252
     
        EXAMPLES:  ace --color="f12:f03"
                   ace --color="f00:e38, e16:e21"
                   ace --color="f12:f03, r108:r216, r108:r252"

     Please refer to the color chart in the configuration file, or
     *note AcEdit Configuration:: for additional information.


 −−language=[en | zh | te] User Interface Language
     Specify the user interface language for the application.

     AcEdit is designed specifically for multi-language support. The menus,
     dialogs and most informational messages are provided in each supported
     language. An example would be the “Help About” dialog.

     ┌────────────────────────────────────────────────────────────────┐
     │ AcEdit (ace): Copyright (c) 2023-2026 v:0.0.05                 │
     │               The Software Samurai                             │
     │               http://www.SoftwareSam.us/                       │
     │                                                                │
     │ This application is based upon the author's AnsiCmd library    │
     │ which implements the ANSI escape sequences available within a  │
     │ Linux terminal window. It is not intended as a full-featured   │
     │ text editor; but rather is a testing platform for the AnsiCmd  │
     │ library and the ACWin and ACDlg classes within the library.    │
     │              AnsiCmd v:0.0.07  WaylandCB    v:0.0.06           │
     │              gString v:0.0.37  wl-clipboard v:2.2.1            │
     │                             ▒▒OK▒▒                             │
     └────────────────────────────────────────────────────────────────┘
     
     ┌─────────────────────────────────────────────────────────┐                                       
     │ AcEdit (ace): 版权 (c) 2023-2026 版:0.0.05              │
     │               The Software Samurai (软件武士)           │
     │               http://www.SoftwareSam.us/                │
     │                                                         │
     │   该应用程序基于同一作者的 AnsiCmd 库。该库实现了       │
     │   Linux 终端窗口内可用的 ANSI 转义序列。它并非一个      │
     │   全功能的文本编辑器；而是一个 AnsiCmd 功能的测试平台。 │
     │        AnsiCmd 版:0.0.07  WaylandCB    版:0.0.06        │
     │        gString 版:0.0.37  wl-clipboard 版:2.2.1         │
     │                        ▒▒.好的▒▒                        │
     └─────────────────────────────────────────────────────────┘

     The current release supports two languages:
      1) English
      2) Zhōngwén, 中文 (Chinese, simplified)
     By default, the application uses the language specified in the terminal
     environment if that language is supported. If the language specified in
     the environment is unsupported, English will be the fall-back language.

     Hooks for additional languages are provided, so additional languages may
     be added as desired.

        EXAMPLES:  ace --language=zh     // Zhōngwén interface language
                   ace --language=en     // English interface language
                   ace --language=te     // Use language specified in 
                                         // terminal environment
                   ace                   // language automatically taken
                                         // from terminal environment

     Technical Note: The command-line code for taking the language from the
     terminal environment is "te". This is technically the code for Telugu, a
     Dravidian language of south-eastern India. If an enterprising programmer
     from Telangana builds an application that supports Telugu, then we will
     be happy to assist in making modifications to our code.
                 తెలుగు ఒక అందమైన లిఖిత భాష.



 −−dimensions   Report dimensions of terminal window.

     Report the terminal window dimensions (rows and columns), then exit.

     This option can be used when updating the configuration file to specify
     the application dimensions to be used on startup.

The “Sandbox” is the traditional name for a section of the application code
which can be used for testing new functionality without disturbing the
functional code.

The AcEdit application accesses code within the Sandbox using the --test
command-line option. To invoke a specific test, provide the test number: ace
--test=[0|1|2|3]. These tests numbers are reserved for ad-hoc tests.

Depending on build options, the Sandbox may also contain several
pre-constructed test routines for use during regression testing.
For a list of available tests, invoke without specifying a test number: ace
--test

     Example:

     Development Test Menu
     00, 01, 02. 03 - Temporary Tests
     11 - Test updateFocus/updateText methods
     12 - Timestamp Formatting
     13 - Terminal Configuration
     14 - skField Text Formatting Options
     15 - Report locale settings
     99 - This Menu
          Press any key to exit...


 −−help (or −h) Display command-line help.

     Command-line Help. Display a brief summary of command-line usage and
     options.
     (overrides everything on command line except '--version')

        EXAMPLES:  ace --help
                   ace -h


 −−helpless (or −hl) Display command-line help.

     Display command-line help. Same as the '--help' option above except that
     the help menu will be piped through the 'less' utility.

        EXAMPLES:  ace --helpless
                   ace -hl


 −−version Report AcEdit version number.

     Display the AcEdit version number and copyright information.
     (overrides everything else on the command line)
     The AnsiCmd-class and gString-class version numbers are optionally
     reported by appending the letter 'V' (verbose) to the command.

     EXAMPLE:  ace -version
            AcEdit (ace) v:0.0.05 (c) 2023-2026  The Software Samurai
     =========================================================================
     License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>
     This is free software: you are free to modify and/or redistribute it
     under the terms set out in the license.
     There is NO WARRANTY, to the extent permitted by law.

     EXAMPLE:  ace -versionv
            AcEdit (ace) v:0.0.05 (c) 2023-2026  The Software Samurai
     =========================================================================
            AnsiCmd Link Library v:0.0.07  (gString v:0.0.37)
     -------------------------------------------------
     License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>
     This is free software: you are free to modify and/or redistribute it
     under the terms set out in the license.
     There is NO WARRANTY, to the extent permitted by law.

                            ────────────────────



File: ansicmd.info,  Node: AcEdit Menu System,  Next: AcEdit Dialogs,  Prev: Invoking AcEdit,  Up: AcEdit Demo App

AcEdit Menu System
==================


TEMP - EXPERIMENTAL
-------------------

Documentation for the 'AcEdit' demo application is under construction.




File: ansicmd.info,  Node: AcEdit Dialogs,  Next: AcEdit Configuration,  Prev: AcEdit Menu System,  Up: AcEdit Demo App

AcEdit Dialogs
==============


TEMP - EXPERIMENTAL
-------------------

Documentation for the 'AcEdit' demo application is under construction.

User Interface Dialogs
----------------------

*CZONE - AcEdit User Interface Dialogs*

Crash Recovery
--------------

All applications, even you humble author's applications, will occasionally
experience an uncontrolled shutdown, either through a system error or (gasp!),
due to programmer error. This is primarily due to the developer
underestimating the absolute stupidity of the user.

When an application crashes for whatever reason, it is possible that it will
leave behind some potentially recoverable data. The AcEdit application is no
exception.

On the next startup following an uncontrolled exit, AcEdit scans for orphaned
temporary files and if found compares them with the associated source files
and asks the user how to handle the recovered data.

The following example demonstrates the dialog window used to obtain the user's
decision. In this case, an uncontrolled exit was simulated by manually
creating a temporary backup file associated with the file under edit, namely:
   Welcome_To_AcEdit.txt
The backup file is a “hidden” file located in the same directory as the file
under edit, and takes it name from the source file:
   .#Welcome_To_AcEdit.txt#
This naming convention is similar to that used by other text editors, and is
useful in recovering data abandoned in an application crash.

The dialog reports the names of the source and recovered files, as well as the
last modification timestamp and file size for each file.
In this example, the recovered file is about three minutes newer than the
source file and is a different size. This indicates that the recovered file
may contain useful data. The available options are shown.
First, select one of the four Radiobuttons and then press the CONTINUE
Pushbutton; or none of the options matches your needs, select the EXIT
Pushbutton to abandon the recovered file without modification.

  1. Compare the two files.
     Invoke the 'diff' utility to format the contents of the files for
     side-by-side display. The data are displayed using the 'less' utility.
     (Press 'q' key to close 'less' and return to the dialog.)

  2. Save the recovered file as "Recovered_nn.txt".
     Rename the recovered file. The original source file is not modified.
     Because multiple files may have been orphaned by the previous application
     crash, to prevent accidental overwrite of another file, a serialized
     filename format is used where the "nn" is replaced by a two-digit serial
     number: Recovered_01.txt, Recovered_02.txt, etc. The renamed file can
     then be moved, renamed or opened for editing if desired.

  3. Replace the source file with the recovered file.
     If it is determined that the recovered data are more complete than the
     source file, then the original source file will be renamed as a backup
     file, and the recovered file will be renamed as the source file.
        Welcome_To_AcEdit.txt     -->  Welcome_To_AcEdit.txt~
        .#Welcome_To_AcEdit.txt#  -->  Welcome_To_AcEdit.txt
     No data are lost. Note that the appended tilde character ('~') is
     recognized by Linux system as indicating a “backup” file.

     The recovered file will then be opened as if it were the original source
     file. The old source file remains in the current directory and can be
     saved or discarded, as desired.

  4. Discard the recovered temporary file.
     If it is determined that the data in the recovered file are of no
     practical value, use this option to delete the recovered file.

After the desired operation has been performed, a status message will be
displayed, and then the dialog will wait for the next keystroke before
closing.

┌────────────┤ Recover Data From Abnormal Shutdown ├───────────┐
│                                                              │
│ Source File    : Welcome_To_AcEdit.txt                       │
│   Last Modified: 18 Oct 2025 17:12:33  Size:    628 bytes    │
│ Recovered File : .#Welcome_To_AcEdit.txt#                    │
│   Last Modified: 18 Oct 2025 17:15:22  Size:    681 bytes    │
│ ─────────── ─────────── ─────────── ─────────── ───────────  │
│  [♦] Compare the two files.                                  │
│  [ ] Save the recovered file as "Recovered_nn.txt".          │
│  [ ] Replace the source file with the recovered file.        │
│  [ ] Discard the recovered temporary file.                   │
│                                                              │
│                 ==CONTINUE==   ====EXIT====                  │
│                                                              │
└──────────────────────────────────────────────────────────────┘


You can test this functionality without actually needing to cause a crash
simply by: 1)closing the application, 2)copying any file that was open for
edit using the filename format described above, and then 3)reopening the
application:
   ./ace MyApp.cpp
   Close the application
   cp --preserve=all 'MyApp.cpp' '.#MyApp.cpp#'
   ./ace
On startup, the backup file will be recognized, and the recovery dialog will
be automatically invoked as described above.


                            ────────────────────

FileMan - File Management Class
-------------------------------

While the AcEdit application is designed as a test and demonstration app for
the AnsiCmd library, and specifically for the ACWin and ACDlg classes, it
reaches a few centimeters into the realm of an actually useful console
application.

File management within the application is done through an array of FileMan
records, one for each file under edit.
While a large number of files can simultaneously be open for edit, the number
of files which are currently visible is limited by the number of _visible_
edit fields.
Full-window mode: The “active” FileMan record references the file displayed in
that field.
Dual-window mode: The “active” FileMan record references the file in the field
that has the input focus, and the “inactive” FileMan record references the
file displayed in the field which is visible, but does not have the input
focus.
Other open (or recently closed) files are reference by other members of the
FileMan array. Please *note AcEdit Menu System:: for information on navigating
among the files which are open for edit.


  FileMan Class Data Members
  ..........................
  1. tnFName tnf: Source file stats data.
     The data include owner of the file, file type, timestamps, access flags
     and other data which identify the file within the filesystem.
  2. char srcSpec — Source fileSpec:
     Filespec of source file. The file may currently be under edit, _OR_ may
     have recently been under edit.

  3. char wrkSpec — Working copy fileSpec
     Filespec for working copy of source file. This is a “hidden” file located
     in the same directory as the source file. It is an intermediate buffer
     between the text being edited and the source file. It is used for
     auto-save operations and miscellaneous updates; thus protecting the
     source file from possible corruption due to system problems or !gasp!,
     program error.

  4. fldIndex tindx — TextEdit Index
     Index of the TextEdit control in which file data are currently displayed.
     (Initialized only for “active” records.)

  5. fldIndex lindx — Line number Index
     Index of the LineNumber control associated with 'teindx'.
     (Initialized only for “active” records.)

  6. char* scr — Scratch buffer
     for tracking miscellaneous data during file edit.
     This is a pointer to dynamic allocation.
       a. [NOT YET DEFINED]
       b. [NOT YET DEFINED]
       c. [NOT YET DEFINED]
  7. int32_t scrCnt — Source Count
     Number of bytes allocated for the 'scr' buffer.

  8. int vtop — Vertical Top row:
     This is the (1-based) line number of top visible data row in TextEdit
     control.
       a. If the source file was referenced in config file, then this value is
          initialized from data in the config file.
       b. Afterwards, it tracks the line number of the data row displayed at
          the top of the field and when updating the LineNum field.
       c. When file is closed (or application is closed) this value is stored
          in the config file record for the file.
  9. int voff — Vertical Offset: Vertical offset from 'vtop' to cursor line.
     This value is used to indicate the cursor position when updating the
     gutter field.
       a. If the source file was referenced in config file, then this value is
          initialized from data in the config file.
       b. Afterwards, it tracks the offset from the top display row to the row
          containing the cursor.
       c. When file is closed (or application is closed) this value is stored
          in the config file record for the file.

  10. int hoff — Horizontal Offset:
     Character (not column) offset from first character of cursor row to IP
     (Insertion Point).
     This value is used to indicate the cursor position when updating the
     gutter field.

  11. int sindx — Source Index:
     Index of FileMan record from which the live FileMan data were retrieved.
     When the data are copied from one record to another, the index of the
     source record is stored in target record so that it can be copied back
     later, either when the file is closed by the user, or when the
     application exits.
     (Initialized only for “active” records.)

  12. bool open:
     Set if source file is currently open or is to be opened on startup.
     Note that “open” in this case does not mean that the source file is
     literally open. It means that the _data_ of the file are currently (or
     about to be) under edit. The source file is opened periodically, and only
     long enough to save updates and then is immediately closed to ensure data
     integrity.

  13. bool mods:
     Set if TextEdit field data are newer than working copy of the file
     ('wrkSpec'). This indicates that a save to target file is pending.

  14. bool wmods:
     Set if working copy of file ('wrkSpec') is newer than the source file
     ('srcSpec'). This indicates that a save to source is pending.

  15. bool active:
     Set when the data of the FileMan record is actively being used during
     file edit (dynamically updated in response to user interaction).

  16. int64_t extime — External access Time:
     Timestamp when file was most recently updated by the application.
     Used on startup to determine whether file has been modified by another
     application.

                            ────────────────────




File: ansicmd.info,  Node: AcEdit Configuration,  Next: Build AcEdit from Source,  Prev: AcEdit Dialogs,  Up: AcEdit Demo App

AcEdit Configuration
====================


Introduction
------------

The AcEdit application startup sequence is built around a configuration file,
ace.cfg by default. This file provides definitions for initialization of
application dimensions, position, color attributes, shortcut keycodes, a list
of previously open files and other setup information.

     ┌───────────────────────────────────────────────────────────┐
     │ The configuration algorithm is not yet fully implemented. │
     │ For the current release (0.0.05), the configuration       │
     │ file is read on startup, but is not updated on exit.      │
     └───────────────────────────────────────────────────────────┘


TEMP - EXPERIMENTAL
-------------------

Documentation for the 'AcEdit' demo application is under construction.




File: ansicmd.info,  Node: Build AcEdit from Source,  Prev: AcEdit Configuration,  Up: AcEdit Demo App

Build AcEdit from Source
========================


TEMP - EXPERIMENTAL
-------------------

Documentation for the 'AcEdit' demo application is under construction.






File: ansicmd.info,  Node: TFMTest Demo App,  Next: Technical Support,  Prev: AcEdit Demo App,  Up: Top

TFMTest Demo App
****************

'TFMTest' (tfmtest) is a simple test and demo application supporting the TFMan
(Temporary File Management) class.

* Menu:

* The TFMTest Application::   Testing platform for TFMan class
* TFMan Class::               Description of public methods


File: ansicmd.info,  Node: The TFMTest Application,  Next: TFMan Class,  Up: TFMTest Demo App

The TFMTest Application
=======================

TFMTest (tfmtest) demonstrates the use of the TFMan class, which encapsulates
creation and management of any temporary files required by an application.
The next chapter, *note TFMan Class:: describes the class itself.

   — TFMTest is a stand-alone utility designed for stress-testing the methods
     of the TFMan class.
   — This application _does not_ use the AnsiCmd library. Output is written
     directly to stdout.
   — Each of the public methods of the TFMan class is exercised by this
     application.
   — Text analysis and formatting within the application is done through the
     author's gString class.
     *Note gString Text Tool:: for more information.
   — Support for C++17 (g++ v:8 and higher) is required.
     Please *note Building TFMTest:: below for details on building the
     application.

                                 ──────────

Invoking TFMTest
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

TFMTest ('tfmtest') requires one option, either --basic or --full. Other
options are optional :-).

   ♦ --basic
     Perform basic tests of the temporary-file system. This ensures that the
     application and the TFMan class are functioning and communicating with
     the system as expected.

   ♦ --full
     First, the sequence of basic tests is performed, and then additional
     tests are performed to ensure that all public methods of the TFMan class
     are functional and that the C-standard library functions are interacting
     with the system as expected.

   ♦ --verbose
     Output verbose diagnostics for each non-trivial test.
     Significant redundancy is built into these tests to ensure that the
     system is not lying to us. Verbose output simply reports the information
     generated by this redundancy, for example, the timestamps of the files
     which are created.

   ♦ --redirect
     The application writes directly to stdout by default; however, the output
     may be rediected (piped) to the 'less' utility so that the data may be
     scrolled for easy viewing.

     This redirection is not actually necessary because the full, verbose
     report only requires approximately 25 lines, and should fit comfortably
     in a typical terminal window. The pipe mechanism is used here to fulfill
     a student request for a simple example of how pipes work. Enjoy, Sarah!

   ♦ --help (or -h)
     List the available command-line options, (this list).

   ♦ --version
     Report the application version number and copyright notice.
     The report also includes the version numbers of the TFMan class and the
     gString class.

                                 ──────────

Building TFMTest
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

Development Tools:
------------------
   g++ (GCC) 14.3.1 20251022 (C++17)
   Fedora Linux v:42
   GNOME Terminal v:3.54.5 (GNOME 47)

  1. Open a terminal window.
     The TFMTest application source is located in a subdirectory of the
     AnsiCmd library distribution archive. Download the archive, open a
     terminal window and navigate to the directory containing the archive.
     Example:
         cd ~/sam/Documents/Software
     Unpack the archive:
         tar -xjvf ansicmd-x.x.xx.tar.bz2

  2. Navigate to the directory containing the TFMTest source.
         cd AnsiCmd/TFMTest

  3. The directory should contain two files:
         TFMTest.cpp  // Application source code.
         Makefile     // Build the TFMTest application
         ls -l
     Additional files will be copied from the parent directory during the
     build sequence.

  4. Be sure that your compiler version is 8.0 or greater (or Clang v:5).
         g++ --version
         g++ (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4)

  5. Build the 'tfmtest' application.
         gmake all
     Three files will be copied from the parent directory:
         TFMan.hpp
         gString.cpp
         gString.hpp

     The TFMTest and gString modules will be compiled and then linked to
     create the 'tfmtest' executable.

     The build should be clean with no errors and no warnings. If there are
     errors, then the most likely cause would be that the compiler cannot find
     a necessary header file or library. Check your LIB_PATH and other
     environment variables.

  6. Once you have a clean build, invoke the application with a request for
     version number.
         ./tfmtest --version

       a. If the application successfully reports the version number and
          copyright notice, then the application has been built correctly.
       b. If the application does not run, then verify that all necessary
          libraries are installed on your system. Run the 'ldd' command to
          list the necessary libraries. The needed libraries will look
          something like the following. These are all standard libraries which
          should be installed on your system by default.

          [TFMan]$ ldd tfmtest
             linux-vdso.so.1 (0x00007f9ca33f5000)
             libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f9ca3000000)
             libm.so.6 => /lib64/libm.so.6 (0x00007f9ca32ef000)
             libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f9ca32c0000)
             libc.so.6 => /lib64/libc.so.6 (0x00007f9ca2e0d000)
             /lib64/ld-linux-x86-64.so.2 (0x00007f9ca33f7000)



File: ansicmd.info,  Node: TFMan Class,  Prev: The TFMTest Application,  Up: TFMTest Demo App

TFMan Class
===========

The TFMan (Temporary File Management) class is desigined to fascilitate
creation, deletion and general management of temporary files used within an
application.

Temporary files created by the system are defined as uniquely named files
created within the system's shared temporary-file directory. Standard library
functions are available for creating these files, but the author's experience
in the classroom setting has shown that application management of these files
can be haphazard (to put it politely). The TFMan class was created to inject a
bit of organization into this chaos.

System Interface
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

The system interface functions of the C++ standard library used by the TFMan
class require C++17 support. Be sure that your compiler version is 8.0 or
greater (or Clang v:5).

These functions are available in C++17 (released Jan. 2018):
   const char* fs::temp_directory_path ( void ) ;|{@*
@verb{|   const char* fs::temp_directory_path ( std::error_code& ec ) ;

These functions return the filespec of a directory suitable for temporary
files. The path is guaranteed to exist and to be a directory. The overload
that takes error_code& argument returns an empty path on error.

On POSIX systems, the path may be specified in an environment variable:
TMPDIR, TMP, TEMP, TEMPDIR, and, if none of them are specified, the path
"/tmp" is returned by the system call.

Please visit: <http://en.cppreference.com> for more information on the library
functions.

In the author's FileMangler application, which was developed well before C++17
was released, we implemented a _literal_ interpretaton of the above
description. Now that the development community has had time to upgrade their
compilers, (gcc v:8 and above) we are able to use the library function to
obtain the temp-directory path.

Note that the TFMan class does not accept the system's assurances that the
target exists and is a directory. That information, including user's
read/write access, is independently verified.
                            ────────────────────

Requesting a unique hack-resistant filename for a temporary file
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The library function:
   char * mkdtemp (char *TEMPLATE);
is used to create a subdirectory within the system temp-file directory. This
function returns the uniquely-named directory in which all other application
temporary files will be located.
This makes cleanup of temporary file during application exit as simple as
calling the TFMan destructor.

  a. The 'mkdtemp' function returns a random sequence of characters for the
     filename: Example: "sakJhr"
  b. A constant prefix may be attached to the provided character sequence to
     enable easy identification of the subdirectory during application
     development. Example: "ANSICMD_sakJhr".
  c. An alternate prefix string may be specified using the 'prefix' parameter.
     Example prefix: "SAM" would yield the subdirectory name: "SAMsakJhr".

The library function used to create the individual temp files is:
   int mkstemp (char *TEMPLATE);

Note that both mkdtemp and mkstemp are "atomic", that is, file creation by one
process may not be interrupted by another process.

Technical Note: It is assumed that only non-special filename characters will
be used on the temp-file-path. "Special characters" are those which may be
interpreted by the shell or other system functionality as requiring special
handling.

List of Special Characters:
  '\'  '"'  ''' '?'  ':'  ';'  '&'  '>'  '<'  '|'  '*'  '`'  '$',
  '#'  '+'  '=' '%'  '!'  '~'  '{'  '}'  '@'  '('  ')'  '['  ']',  ' '

These special character should not be used in filenames. The algorithm for
escaping these characters is slow and probably not worth the complexity in
this context.
Please see notes in the author's FileMangler application. FMgr-class on using
'rmdir' and 'unlink' on filenames which contain "special" characters.

Within the application's temp-file subdirectory, temporary files take the
form: "TF_xxxxxx" where "TF_" is the specified prefix and the "xxxxxx"
sequence is replaced by the unique system-provided sequence.
                            ────────────────────


Public Methods of the TFMan Class
.................................

TFMan is a very simple class with the following public methods.

   ⚬ TFMan ( void );
       Input  : none
       Returns: implicitly returns pointer to object

     Default constructor.
     Create a uniquely named temp-file subdirectory within the system's
     temp-file directory. (Prefix for temp-file subdirectory name is set to
     default value: "TFMAN_".)

     Example tree structure:   /tmp/TFMAN_sakJhr


   ⚬ TFMan ( const char* prefix );
       Input  : 
          prefix : pointer to a prefix for temp-file subdirectory name.
                   -- Valid filename characters only
                   -- Maximum of 16 bytes including null terminator
       Returns: implicitly returns pointer to object

     Initialization constructor.
     Create a uniquely named temp-file subdirectory within the system's
     temp-file directory using the provided prefix string for the subdirectory
     name.

     Example:
     instance: TFMan* tfm = new TFMan( "MYAPP" );
       yields: /tmp/MYAPPsakJhr


   ⚬ ~TFMan ( void );
       Input  : none
       Returns: nothing

     Destructor.
     Delete all temporary files located within the subdirectory created by the
     TFMan constructor, then delete the subdirectory itself.

     The destructor is invoked in different ways, depending upon whether the
     TFMan object was created in 'stack' (automatic) memory or from 'heap'
     memory.

     If the TFMan object is created on the 'stack', then the destructor is
     called implicitly when the object goes out-of-scope.

             int doStuff ( void ) ;

             int main ( int argc, char* argv[], char* argenv[] )
             {
                tfm = new TFMan ( "SAM_" ) ;

                doStuff () ;

                if ( tfm != NULL )
                   delete tfm ;
             }
             int doStuff ( void )
             {
                TFMan tfm ( "SAM_" ) ;
                int status = 0 ;
                . . .
                return status ;
                // (the object goes out-of-scope here)
             }
                                  ─ ─ ─ ─ ─

     If the TFMan object is created in 'heap' memory (dynamic allocation),
     then the object should be deleted explicity when it is no longer needed.

             int doStuff ( void ) ;
             static TFMan *tfm = NULL ;

             int main ( int argc, char* argv[], char* argenv[] )
             {
                tfm = new TFMan ( "SAM_" ) ;

                doStuff () ;

                if ( tfm != NULL )
                   delete tfm ;
             }

          ┌─────────────────────────────────────────────────────────────┐
          │ Teacher's Rant:                                             │
          │ Note that the application's heap memory is automatically    │
          │ returned to the system when the application exits; HOWEVER, │
          │ it is sloppy programming, indeed to simply abandon objects  │
          │ on the heap. Objects on the heap should always be deleted   │
          │ explicity before exiting the application.                   │
          └─────────────────────────────────────────────────────────────┘


   ⚬ bool createTempFile ( gString& tmpPath );

       Input  :
          tmpPath : (by reference) gString object to receive filespec
       Returns: 
          'true'  if file successfully created:
                  (file exists, and contains no data)
          'false' if system call failed

     Create a uniquely-named temporary file.
     The filename takes the form: "TF_xxxxxx" where xxxxxx is the
     six-character token which uniquely identifies the file created by the
     system.

          Example:
          If the TFMan constructor has created the application subdirectory:
             /tmp/TFMAN_rQabnE
          then the filespec of the temporary file would be of the form:
             /tmp/TFMAN_rQabnE/TF_saNAar

     The full filespec is then returned to caller in 'tmpPath'. The
     application can then open the file in the usual way and write data to the
     (empty) file.

          ofstream ofs ( tmpPath.ustr(), ofstream::out | ofstream::app ) ;
          if ( (ofs.is_open()) )
          {
             ofs << "Write some data to the temp file." << endl ;
             ofs.close() ;
          }

     Notice that the gString object's UTF-8 (byte-oriented) text is used for
     the system call. Note also that because the file has been created by the
     call, the file may be opened either for “append”, or for “trunc” output.
     Please *note gString Public Methods: Data Access. for a discussion of the
     string data stored in the gString class.

     Please see above for a description of how the system creates
     uniquely-named temporary files, or refer to the C standard library
     documentation for the 'mkstemp' function.


   ⚬ bool deleteTempFile ( const gString& tmpPath );

       Input  :
          tmpPath : (by reference) filespec of file to be deleted
       Returns:
          'true'  if target file successfully deleted
          'false' if library call failed (invalid filespec)

     Delete a previously created temporary file.

     deleteTempFile will delete the specified file _ONLY_ if the file resides
     within the temporary subdirectory created by the TFMan constructor.


   ⚬ bool clearTempFiles ( void );

       Input  : none
       Returns:
          'true'  if all target files successfully deleted
          'false' if unable to delete one or more target files

     Delete all files in the application's temp-file container subdirectory.
     Only files created within the subdirectory created by the TFMan-class
     constructor are affected. The application-specific subdirectory created
     by the TFMan constructor _IS NOT_ deleted by this method.


   ⚬ const char* getTempPath ( void );

       Input  : none
       Returns: pointer to const buffer containing filespec

     Returns a pointer to the filespec of temp-file subdirectory created by
     the TFMan constructor. This is a read-only pointer!

     This method may be used during application development to locate the
     application's temp files.


   ⚬ bool isActive ( void );

       Input  : none
       Returns:
          'true'  if temp-file manager initialized and functional
          'false' if initialization failed

     Report the active/inactive status of the TFMan object.
     Although it is unlikely that the constructor will fail to create the
     target subdirectory, if the system call fails, the constructor has no way
     to report the error. This method may be used to verify that the TFMan
     temp-file manager is active and functional.

     Example:
       gString gsFilespec ;
       TFMan* tfm = new TFMan( "MyApp" ) ;
       if ( (tfm->isActive()) )
       {
          tfm->createTempFile ( gsFilespec ) ;
          . . .
          tfm->deleteTempFile ( gsFilespec ) ;
       }
       delete tfm ;


   ⚬ const char* tfmVersion ( void );
       Input  : none
       Returns: pointer to constant string of the form: "M.m.ss"
                indicating the major/minor/step versions

     Report the TFMan-class version number.

     Example:
       TFMan* tfm = new TFMan( "SAM_" ) ;
       cout < "TFMan class version: " << (tfm->tfmVersion()) << endl ;
       . . .
       delete tfm ;
     
     Output:
       TFMan class version: 0.0.02






File: ansicmd.info,  Node: Technical Support,  Next: Copyright Notice,  Prev: TFMTest Demo App,  Up: Top

Technical Support
*****************

     Please Note: All trademarks and service marks mentioned in this
     document are the entirely-too-proprietary property of their
     respective owners, and this author makes no representation of
     affiliation with or ownership of any of the damned things.

Contact
=======

     AnsiCmd-class library, test applications, source code and associated
     Texinfo documentation were written and are maintained by:

                              Mahlon R. Smith,
                           The Software Samurai
                      Beijing University of Technology
                      on the web at: www.SoftwareSam.us

     For bugs, suggestions, periodic updates, or possible praise,
     please post a message to the author via website.

     The author wishes to thank everyone for their intelligent, kind
     and thoughtful responses.  (ranters I can live without)


By the Same Author
==================

   • NcDialog Application Programming Interface (API) library.
     The NcDialog API forms the basis for most of our other software projects.
     It provides the application developer with the tools to create
     dialog-based console applications, without the need to learn anything
     about the complexities of the underlying ‘ncurses’ C-language library.

     Console applications have always been the most efficient and
     easily-implemented of computer programs. What they lacked was a friendly
     and visually-pleasing user interface.

     With the NcDialog API, console applications can now be used and
     understood by experts and novice users alike.

   • FileMangler (fmg), is a compact, fast and flexible tool for handling all
     your file management needs.

     FileMangler performs all basic file management tasks, as well as
     performing scheduled and ad-hoc file backup and synchronization
     activities.

     FileMangler runs in a console window, and thus provides access to many
     system tools not available to a GUI application. FileMangler also
     provides full support for accessing the local Trashcan.

     FileMangler is based on the NcDialog API, and thus will run in almost any
     GNU/Linux or UNIX terminal environment.

   • Console Trashcan (ctrash) is a simple, console-based (command-line)
     utility for managing the contents of your local Trashcan. Send items to
     the trash, restore items from the trash, report the trashcan contents,
     and empty the trash. 'ctrash' is designed as a safer, and more flexible
     alternative to the 'rm' and 'rmdir' commands.

   • Infodoc, post-processing and CSS style for HTML documents created by the
     Texinfo (makeinfo) utility. If you write documentation using the
     Texinfo/makeinfo documentation engine, AND if you care at all about what
     your documentation looks like, then you really do need the
     ‘infodoc-styles.css‘ definition file and the ‘idpp’ HTML post-processor.

     The HTML version of this document was formatted using ‘idpp’ and is
     displayed using the ‘infodoc-styles.css‘ definition file. Many more
     examples are available on the author's website.

   • gString text internationalization tool.
     gString implements a C++ class that may be integraged into any
     application for smooth and painless text formatting, and for converting
     between UTF-8 and ‘wchar_t’ (wide) character encoding.

     The gString class is lightweight, consisting of one C++ source module and
     one header file. The gString class may be directly integrated into an
     application, or may be built as a link library.
     The gString class is also embedded within the NcDialog API library (see
     above).

   • Taggit (taggit) is a demonstration program written for students, or for
     anyone who wishes to create a console application with a multilingual
     user interface.

     Conceptually, Taggit is an audio-file tag editor (metadata editor), and
     is album oriented rather than file oriented so that all audio files in an
     album may be edited simultaneously.

     Taggit is not intended as a full-featured tag editor; for instance,
     Taggit does not access online databases of audio tag information. Taggit
     fully supports tag editing for audio formats: MP3, M4A, OGG/Vorbis and
     WMA.

     The OGG/Vorbis I specification is supported for all text tags in '.ogg'
     and '.oga' audio files.

     For MP3 audio files, all tag frames of the ID3v2.3 standard are
     supported, along with some features of ID3v2.4, such as support for UTF-8
     text encoding which enables writing text tags in any language.

     Taggit is implemented in four(4) user interface languages: Español
     (Spanish), Zhōngwén (中文) (Chinese, simplified), Tiếng Việt (Vietnamese)
     and English (U.S.). Additional user interface languages (both LTR and
     RTL) may be added with minimum effort.

   • Source Profiler (srcprof) is a source code analysis tool for determining
     the ‘maintainability’ of source code modules.

     ‘srcprof’ can be used to profile source code for high-level languages
     such as C, C++ and Java, as well as various assembly languages and
     scripting languages such as Python, Perl and Ruby. For a complete list of
     currently-supported source languages, please see the Source Profiler
     documentation.

     'srcprof' can be used both as a productivity-measurement tool and as a
     tool for testing source code quality based on an evaluation of its
     ‘maintainability’.

     Source Profiler is a console-based utility, which runs as either a pure,
     command-line utility, OR as a dialog application based on the NcDialog
     API.

   • WaylandCB, clipboard access for console applications.
     Access to the system clipboard under the Wayland communications protocol,
     leveraging Sergey Bugaev's "wl-clipboard" application suite.

     WaylandCB is a simple C++ class definition which provides console
     applications with seemless access to the system clipboard.

   • Exercalc (ecalc) is a utility for tracking daily exercise activity.
     Specify the type of exercise, walk/bike/run/cardio/free weights, etc. and
     either the elapsed time, distance travelled, or energy expended (KCal or
     METs). Exercalc then calculates the efficiency and progress over time.
     Archive the data, retrieve and analyze the data in various ways including
     tables, comparisons and bar charts.

     The application is specifically designed to be a student exercise in
     creating applications which incorporate a multi-language user interface.
     Exercalc is implemented in four(4) user interface languages: Español
     (Spanish), Zhōngwén (中文) (Chinese, simplified), Tiếng Việt (Vietnamese)
     and English (U.S.). Additional user interface languages (both LTR and
     RTL) may be added with minimum effort.

   • DVD Repair (dvdrep) is a utility for exploring the contents of a damaged
     DVD video disc and rescuing as much of the data as possible.

     ‘dvdrep’ can be used to rescue data from any non-encrypted DVD video
     source disc that is formatted using the Universal Disc Format (UDF)
     filesystem (as all commercially produced DVD movies are).

     ‘dvdrep’ takes a layered approach to the analysis of the source disc. A
     detailed log file is maintained for each step of the process in case
     manual intervention is needed at a later step.

     DVD Repair is based on the NcDialog API, and thus will run in almost any
     GNU/Linux or UNIX terminal environment.

   • crcPlus (crcplus) is a reference model and demonstration program for
     implementating CRC (Cyclic Redundancy Check) data error detection.
     crcPlus provides a reliable reference algorithm for verifying the
     function of other CRC generators and decoders as well as providing the
     tools to build a fully customizable hash table (lookup table) for
     creating your own high-speed CRC generator.

   • Various other Linux utilities designed as academic exercises are also
     available for student use. For example: interprocess communication pipes,
     FIFOs, sockets, shared memory blocks, multi-threading, the 'Sleeping
     Barber' problem and so on.
     These cannot be considered as production-worthy, but they demonstrate the
     concepts in simple terms.






File: ansicmd.info,  Node: Copyright Notice,  Next: Index,  Prev: Technical Support,  Up: Top

Copyright Notice
****************

The AnsiCmd library and source code are released under
the GNU General Public License (GPL 3+), and
the user documentation (this document) is released under
the GNU Free Documentation License (FDL 1.3+):

      Copyright © 2022-2026

      Mahlon R. Smith, The Software Samurai

      This manual describes version 0.0.07 of the AnsiCmd library.

       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.3
       or any later version published by the Free Software Foundation;
       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
       Texts.  A copy of the license is included in the section entitled 
       "GNU Free Documentation License".


* Menu:

* GNU General Public License::
* GNU Free Documentation License::


File: ansicmd.info,  Node: GNU General Public License,  Next: GNU Free Documentation License,  Up: Copyright Notice

GNU General Public License
==========================

                           Version 3, 29 June 2007

     Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>

     Everyone is permitted to copy and distribute verbatim copies of this
     license document, but changing it is not allowed.

Preamble
--------

The GNU General Public License is a free, copyleft license for software and
other kinds of works.

The licenses for most software and other practical works are designed to take
away your freedom to share and change the works. By contrast, the GNU General
Public License is intended to guarantee your freedom to share and change all
versions of a program--to make sure it remains free software for all its
users. We, the Free Software Foundation, use the GNU General Public License
for most of our software; it applies also to any other work released this way
by its authors. You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom to
distribute copies of free software (and charge for them if you wish), that you
receive source code or can get it if you want it, that you can change the
software or use pieces of it in new free programs, and that you know you can
do these things.

To protect your rights, we need to prevent others from denying you these
rights or asking you to surrender the rights. Therefore, you have certain
responsibilities if you distribute copies of the software, or if you modify
it: responsibilities to respect the freedom of others.

For example, if you distribute copies of such a program, whether gratis or for
a fee, you must pass on to the recipients the same freedoms that you received.
You must make sure that they, too, receive or can get the source code. And you
must show them these terms so they know their rights.

Developers that use the GNU GPL protect your rights with two steps: (1) assert
copyright on the software, and (2) offer you this License giving you legal
permission to copy, distribute and/or modify it.

For the developers' and authors' protection, the GPL clearly explains that
there is no warranty for this free software. For both users' and authors'
sake, the GPL requires that modified versions be marked as changed, so that
their problems will not be attributed erroneously to authors of previous
versions.

Some devices are designed to deny users access to install or run modified
versions of the software inside them, although the manufacturer can do so.
This is fundamentally incompatible with the aim of protecting users' freedom
to change the software. The systematic pattern of such abuse occurs in the
area of products for individuals to use, which is precisely where it is most
unacceptable. Therefore, we have designed this version of the GPL to prohibit
the practice for those products. If such problems arise substantially in other
domains, we stand ready to extend this provision to those domains in future
versions of the GPL, as needed to protect the freedom of users.

Finally, every program is threatened constantly by software patents. States
should not allow patents to restrict development and use of software on
general-purpose computers, but in those that do, we wish to avoid the special
danger that patents applied to a free program could make it effectively
proprietary. To prevent this, the GPL assures that patents cannot be used to
render the program non-free.

The precise terms and conditions for copying, distribution and modification
follow.

TERMS AND CONDITIONS
--------------------

  0. Definitions.

     "This License" refers to version 3 of the GNU General Public License.

     "Copyright" also means copyright-like laws that apply to other kinds of
     works, such as semiconductor masks.

     "The Program" refers to any copyrightable work licensed under this
     License. Each licensee is addressed as "you". "Licensees" and
     "recipients" may be individuals or organizations.

     To "modify" a work means to copy from or adapt all or part of the work in
     a fashion requiring copyright permission, other than the making of an
     exact copy. The resulting work is called a "modified version" of the
     earlier work or a work "based on" the earlier work.

     A "covered work" means either the unmodified Program or a work based on
     the Program.

     To "propagate" a work means to do anything with it that, without
     permission, would make you directly or secondarily liable for
     infringement under applicable copyright law, except executing it on a
     computer or modifying a private copy. Propagation includes copying,
     distribution (with or without modification), making available to the
     public, and in some countries other activities as well.

     To "convey" a work means any kind of propagation that enables other
     parties to make or receive copies. Mere interaction with a user through a
     computer network, with no transfer of a copy, is not conveying.

     An interactive user interface displays "Appropriate Legal Notices" to the
     extent that it includes a convenient and prominently visible feature that
     (1) displays an appropriate copyright notice, and (2) tells the user that
     there is no warranty for the work (except to the extent that warranties
     are provided), that licensees may convey the work under this License, and
     how to view a copy of this License. If the interface presents a list of
     user commands or options, such as a menu, a prominent item in the list
     meets this criterion.

  1. Source Code.

     The "source code" for a work means the preferred form of the work for
     making modifications to it. "Object code" means any non-source form of a
     work.

     A "Standard Interface" means an interface that either is an official
     standard defined by a recognized standards body, or, in the case of
     interfaces specified for a particular programming language, one that is
     widely used among developers working in that language.

     The "System Libraries" of an executable work include anything, other than
     the work as a whole, that (a) is included in the normal form of packaging
     a Major Component, but which is not part of that Major Component, and (b)
     serves only to enable use of the work with that Major Component, or to
     implement a Standard Interface for which an implementation is available
     to the public in source code form. A "Major Component", in this context,
     means a major essential component (kernel, window system, and so on) of
     the specific operating system (if any) on which the executable work runs,
     or a compiler used to produce the work, or an object code interpreter
     used to run it.

     The "Corresponding Source" for a work in object code form means all the
     source code needed to generate, install, and (for an executable work) run
     the object code and to modify the work, including scripts to control
     those activities. However, it does not include the work's System
     Libraries, or general-purpose tools or generally available free programs
     which are used unmodified in performing those activities but which are
     not part of the work. For example, Corresponding Source includes
     interface definition files associated with source files for the work, and
     the source code for shared libraries and dynamically linked subprograms
     that the work is specifically designed to require, such as by intimate
     data communication or control flow between those subprograms and other
     parts of the work.

     The Corresponding Source need not include anything that users can
     regenerate automatically from other parts of the Corresponding Source.

     The Corresponding Source for a work in source code form is that same
     work.

  2. Basic Permissions.

     All rights granted under this License are granted for the term of
     copyright on the Program, and are irrevocable provided the stated
     conditions are met. This License explicitly affirms your unlimited
     permission to run the unmodified Program. The output from running a
     covered work is covered by this License only if the output, given its
     content, constitutes a covered work. This License acknowledges your
     rights of fair use or other equivalent, as provided by copyright law.

     You may make, run and propagate covered works that you do not convey,
     without conditions so long as your license otherwise remains in force.
     You may convey covered works to others for the sole purpose of having
     them make modifications exclusively for you, or provide you with
     facilities for running those works, provided that you comply with the
     terms of this License in conveying all material for which you do not
     control copyright. Those thus making or running the covered works for you
     must do so exclusively on your behalf, under your direction and control,
     on terms that prohibit them from making any copies of your copyrighted
     material outside their relationship with you.

     Conveying under any other circumstances is permitted solely under the
     conditions stated below. Sublicensing is not allowed; section 10 makes it
     unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

     No covered work shall be deemed part of an effective technological
     measure under any applicable law fulfilling obligations under article 11
     of the WIPO copyright treaty adopted on 20 December 1996, or similar laws
     prohibiting or restricting circumvention of such measures.

     When you convey a covered work, you waive any legal power to forbid
     circumvention of technological measures to the extent such circumvention
     is effected by exercising rights under this License with respect to the
     covered work, and you disclaim any intention to limit operation or
     modification of the work as a means of enforcing, against the work's
     users, your or third parties' legal rights to forbid circumvention of
     technological measures.

  4. Conveying Verbatim Copies.

     You may convey verbatim copies of the Program's source code as you
     receive it, in any medium, provided that you conspicuously and
     appropriately publish on each copy an appropriate copyright notice; keep
     intact all notices stating that this License and any non-permissive terms
     added in accord with section 7 apply to the code; keep intact all notices
     of the absence of any warranty; and give all recipients a copy of this
     License along with the Program.

     You may charge any price or no price for each copy that you convey, and
     you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

     You may convey a work based on the Program, or the modifications to
     produce it from the Program, in the form of source code under the terms
     of section 4, provided that you also meet all of these conditions:

       a. The work must carry prominent notices stating that you modified it,
          and giving a relevant date.

       b. The work must carry prominent notices stating that it is released
          under this License and any conditions added under section 7. This
          requirement modifies the requirement in section 4 to "keep intact
          all notices".

       c. You must license the entire work, as a whole, under this License to
          anyone who comes into possession of a copy. This License will
          therefore apply, along with any applicable section 7 additional
          terms, to the whole of the work, and all its parts, regardless of
          how they are packaged. This License gives no permission to license
          the work in any other way, but it does not invalidate such
          permission if you have separately received it.

       d. If the work has interactive user interfaces, each must display
          Appropriate Legal Notices; however, if the Program has interactive
          interfaces that do not display Appropriate Legal Notices, your work
          need not make them do so.

     A compilation of a covered work with other separate and independent
     works, which are not by their nature extensions of the covered work, and
     which are not combined with it such as to form a larger program, in or on
     a volume of a storage or distribution medium, is called an "aggregate" if
     the compilation and its resulting copyright are not used to limit the
     access or legal rights of the compilation's users beyond what the
     individual works permit. Inclusion of a covered work in an aggregate does
     not cause this License to apply to the other parts of the aggregate.

  6. Conveying Non-Source Forms.

     You may convey a covered work in object code form under the terms of
     sections 4 and 5, provided that you also convey the machine-readable
     Corresponding Source under the terms of this License, in one of these
     ways:

       a. Convey the object code in, or embodied in, a physical product
          (including a physical distribution medium), accompanied by the
          Corresponding Source fixed on a durable physical medium customarily
          used for software interchange.

       b. Convey the object code in, or embodied in, a physical product
          (including a physical distribution medium), accompanied by a written
          offer, valid for at least three years and valid for as long as you
          offer spare parts or customer support for that product model, to
          give anyone who possesses the object code either (1) a copy of the
          Corresponding Source for all the software in the product that is
          covered by this License, on a durable physical medium customarily
          used for software interchange, for a price no more than your
          reasonable cost of physically performing this conveying of source,
          or (2) access to copy the Corresponding Source from a network server
          at no charge.

       c. Convey individual copies of the object code with a copy of the
          written offer to provide the Corresponding Source. This alternative
          is allowed only occasionally and noncommercially, and only if you
          received the object code with such an offer, in accord with
          subsection 6b.

       d. Convey the object code by offering access from a designated place
          (gratis or for a charge), and offer equivalent access to the
          Corresponding Source in the same way through the same place at no
          further charge. You need not require recipients to copy the
          Corresponding Source along with the object code. If the place to
          copy the object code is a network server, the Corresponding Source
          may be on a different server (operated by you or a third party) that
          supports equivalent copying facilities, provided you maintain clear
          directions next to the object code saying where to find the
          Corresponding Source. Regardless of what server hosts the
          Corresponding Source, you remain obligated to ensure that it is
          available for as long as needed to satisfy these requirements.

       e. Convey the object code using peer-to-peer transmission, provided you
          inform other peers where the object code and Corresponding Source of
          the work are being offered to the general public at no charge under
          subsection 6d.

     A separable portion of the object code, whose source code is excluded
     from the Corresponding Source as a System Library, need not be included
     in conveying the object code work.

     A "User Product" is either (1) a "consumer product", which means any
     tangible personal property which is normally used for personal, family,
     or household purposes, or (2) anything designed or sold for incorporation
     into a dwelling. In determining whether a product is a consumer product,
     doubtful cases shall be resolved in favor of coverage. For a particular
     product received by a particular user, "normally used" refers to a
     typical or common use of that class of product, regardless of the status
     of the particular user or of the way in which the particular user
     actually uses, or expects or is expected to use, the product. A product
     is a consumer product regardless of whether the product has substantial
     commercial, industrial or non-consumer uses, unless such uses represent
     the only significant mode of use of the product.

     "Installation Information" for a User Product means any methods,
     procedures, authorization keys, or other information required to install
     and execute modified versions of a covered work in that User Product from
     a modified version of its Corresponding Source. The information must
     suffice to ensure that the continued functioning of the modified object
     code is in no case prevented or interfered with solely because
     modification has been made.

     If you convey an object code work under this section in, or with, or
     specifically for use in, a User Product, and the conveying occurs as part
     of a transaction in which the right of possession and use of the User
     Product is transferred to the recipient in perpetuity or for a fixed term
     (regardless of how the transaction is characterized), the Corresponding
     Source conveyed under this section must be accompanied by the
     Installation Information. But this requirement does not apply if neither
     you nor any third party retains the ability to install modified object
     code on the User Product (for example, the work has been installed in
     ROM).

     The requirement to provide Installation Information does not include a
     requirement to continue to provide support service, warranty, or updates
     for a work that has been modified or installed by the recipient, or for
     the User Product in which it has been modified or installed. Access to a
     network may be denied when the modification itself materially and
     adversely affects the operation of the network or violates the rules and
     protocols for communication across the network.

     Corresponding Source conveyed, and Installation Information provided, in
     accord with this section must be in a format that is publicly documented
     (and with an implementation available to the public in source code form),
     and must require no special password or key for unpacking, reading or
     copying.

  7. Additional Terms.

     "Additional permissions" are terms that supplement the terms of this
     License by making exceptions from one or more of its conditions.
     Additional permissions that are applicable to the entire Program shall be
     treated as though they were included in this License, to the extent that
     they are valid under applicable law. If additional permissions apply only
     to part of the Program, that part may be used separately under those
     permissions, but the entire Program remains governed by this License
     without regard to the additional permissions.

     When you convey a copy of a covered work, you may at your option remove
     any additional permissions from that copy, or from any part of it.
     (Additional permissions may be written to require their own removal in
     certain cases when you modify the work.) You may place additional
     permissions on material, added by you to a covered work, for which you
     have or can give appropriate copyright permission.

     Notwithstanding any other provision of this License, for material you add
     to a covered work, you may (if authorized by the copyright holders of
     that material) supplement the terms of this License with terms:

       a. Disclaiming warranty or limiting liability differently from the
          terms of sections 15 and 16 of this License; or

       b. Requiring preservation of specified reasonable legal notices or
          author attributions in that material or in the Appropriate Legal
          Notices displayed by works containing it; or

       c. Prohibiting misrepresentation of the origin of that material, or
          requiring that modified versions of such material be marked in
          reasonable ways as different from the original version; or

       d. Limiting the use for publicity purposes of names of licensors or
          authors of the material; or

       e. Declining to grant rights under trademark law for use of some trade
          names, trademarks, or service marks; or

       f. Requiring indemnification of licensors and authors of that material
          by anyone who conveys the material (or modified versions of it) with
          contractual assumptions of liability to the recipient, for any
          liability that these contractual assumptions directly impose on
          those licensors and authors.

     All other non-permissive additional terms are considered "further
     restrictions" within the meaning of section 10. If the Program as you
     received it, or any part of it, contains a notice stating that it is
     governed by this License along with a term that is a further restriction,
     you may remove that term. If a license document contains a further
     restriction but permits relicensing or conveying under this License, you
     may add to a covered work material governed by the terms of that license
     document, provided that the further restriction does not survive such
     relicensing or conveying.

     If you add terms to a covered work in accord with this section, you must
     place, in the relevant source files, a statement of the additional terms
     that apply to those files, or a notice indicating where to find the
     applicable terms.

     Additional terms, permissive or non-permissive, may be stated in the form
     of a separately written license, or stated as exceptions; the above
     requirements apply either way.

  8. Termination.

     You may not propagate or modify a covered work except as expressly
     provided under this License. Any attempt otherwise to propagate or modify
     it is void, and will automatically terminate your rights under this
     License (including any patent licenses granted under the third paragraph
     of section 11).

     However, if you cease all violation of this License, then your license
     from a particular copyright holder is reinstated (a) provisionally,
     unless and until the copyright holder explicitly and finally terminates
     your license, and (b) permanently, if the copyright holder fails to
     notify you of the violation by some reasonable means prior to 60 days
     after the cessation.

     Moreover, your license from a particular copyright holder is reinstated
     permanently if the copyright holder notifies you of the violation by some
     reasonable means, this is the first time you have received notice of
     violation of this License (for any work) from that copyright holder, and
     you cure the violation prior to 30 days after your receipt of the notice.

     Termination of your rights under this section does not terminate the
     licenses of parties who have received copies or rights from you under
     this License. If your rights have been terminated and not permanently
     reinstated, you do not qualify to receive new licenses for the same
     material under section 10.

  9. Acceptance Not Required for Having Copies.

     You are not required to accept this License in order to receive or run a
     copy of the Program. Ancillary propagation of a covered work occurring
     solely as a consequence of using peer-to-peer transmission to receive a
     copy likewise does not require acceptance. However, nothing other than
     this License grants you permission to propagate or modify any covered
     work. These actions infringe copyright if you do not accept this License.
     Therefore, by modifying or propagating a covered work, you indicate your
     acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

     Each time you convey a covered work, the recipient automatically receives
     a license from the original licensors, to run, modify and propagate that
     work, subject to this License. You are not responsible for enforcing
     compliance by third parties with this License.

     An "entity transaction" is a transaction transferring control of an
     organization, or substantially all assets of one, or subdividing an
     organization, or merging organizations. If propagation of a covered work
     results from an entity transaction, each party to that transaction who
     receives a copy of the work also receives whatever licenses to the work
     the party's predecessor in interest had or could give under the previous
     paragraph, plus a right to possession of the Corresponding Source of the
     work from the predecessor in interest, if the predecessor has it or can
     get it with reasonable efforts.

     You may not impose any further restrictions on the exercise of the rights
     granted or affirmed under this License. For example, you may not impose a
     license fee, royalty, or other charge for exercise of rights granted
     under this License, and you may not initiate litigation (including a
     cross-claim or counterclaim in a lawsuit) alleging that any patent claim
     is infringed by making, using, selling, offering for sale, or importing
     the Program or any portion of it.

  11. Patents.

     A "contributor" is a copyright holder who authorizes use under this
     License of the Program or a work on which the Program is based. The work
     thus licensed is called the contributor's "contributor version".

     A contributor's "essential patent claims" are all patent claims owned or
     controlled by the contributor, whether already acquired or hereafter
     acquired, that would be infringed by some manner, permitted by this
     License, of making, using, or selling its contributor version, but do not
     include claims that would be infringed only as a consequence of further
     modification of the contributor version. For purposes of this definition,
     "control" includes the right to grant patent sublicenses in a manner
     consistent with the requirements of this License.

     Each contributor grants you a non-exclusive, worldwide, royalty-free
     patent license under the contributor's essential patent claims, to make,
     use, sell, offer for sale, import and otherwise run, modify and propagate
     the contents of its contributor version.

     In the following three paragraphs, a "patent license" is any express
     agreement or commitment, however denominated, not to enforce a patent
     (such as an express permission to practice a patent or covenant not to
     sue for patent infringement). To "grant" such a patent license to a party
     means to make such an agreement or commitment not to enforce a patent
     against the party.

     If you convey a covered work, knowingly relying on a patent license, and
     the Corresponding Source of the work is not available for anyone to copy,
     free of charge and under the terms of this License, through a publicly
     available network server or other readily accessible means, then you must
     either (1) cause the Corresponding Source to be so available, or (2)
     arrange to deprive yourself of the benefit of the patent license for this
     particular work, or (3) arrange, in a manner consistent with the
     requirements of this License, to extend the patent license to downstream
     recipients. "Knowingly relying" means you have actual knowledge that, but
     for the patent license, your conveying the covered work in a country, or
     your recipient's use of the covered work in a country, would infringe one
     or more identifiable patents in that country that you have reason to
     believe are valid.

     If, pursuant to or in connection with a single transaction or
     arrangement, you convey, or propagate by procuring conveyance of, a
     covered work, and grant a patent license to some of the parties receiving
     the covered work authorizing them to use, propagate, modify or convey a
     specific copy of the covered work, then the patent license you grant is
     automatically extended to all recipients of the covered work and works
     based on it.

     A patent license is "discriminatory" if it does not include within the
     scope of its coverage, prohibits the exercise of, or is conditioned on
     the non-exercise of one or more of the rights that are specifically
     granted under this License. You may not convey a covered work if you are
     a party to an arrangement with a third party that is in the business of
     distributing software, under which you make payment to the third party
     based on the extent of your activity of conveying the work, and under
     which the third party grants, to any of the parties who would receive the
     covered work from you, a discriminatory patent license (a) in connection
     with copies of the covered work conveyed by you (or copies made from
     those copies), or (b) primarily for and in connection with specific
     products or compilations that contain the covered work, unless you
     entered into that arrangement, or that patent license was granted, prior
     to 28 March 2007.

     Nothing in this License shall be construed as excluding or limiting any
     implied license or other defenses to infringement that may otherwise be
     available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

     If conditions are imposed on you (whether by court order, agreement or
     otherwise) that contradict the conditions of this License, they do not
     excuse you from the conditions of this License. If you cannot convey a
     covered work so as to satisfy simultaneously your obligations under this
     License and any other pertinent obligations, then as a consequence you
     may not convey it at all. For example, if you agree to terms that
     obligate you to collect a royalty for further conveying from those to
     whom you convey the Program, the only way you could satisfy both those
     terms and this License would be to refrain entirely from conveying the
     Program.

  13. Use with the GNU Affero General Public License.

     Notwithstanding any other provision of this License, you have permission
     to link or combine any covered work with a work licensed under version 3
     of the GNU Affero General Public License into a single combined work, and
     to convey the resulting work. The terms of this License will continue to
     apply to the part which is the covered work, but the special requirements
     of the GNU Affero General Public License, section 13, concerning
     interaction through a network will apply to the combination as such.

  14. Revised Versions of this License.

     The Free Software Foundation may publish revised and/or new versions of
     the GNU General Public License from time to time. Such new versions will
     be similar in spirit to the present version, but may differ in detail to
     address new problems or concerns.

     Each version is given a distinguishing version number. If the Program
     specifies that a certain numbered version of the GNU General Public
     License "or any later version" applies to it, you have the option of
     following the terms and conditions either of that numbered version or of
     any later version published by the Free Software Foundation. If the
     Program does not specify a version number of the GNU General Public
     License, you may choose any version ever published by the Free Software
     Foundation.

     If the Program specifies that a proxy can decide which future versions of
     the GNU General Public License can be used, that proxy's public statement
     of acceptance of a version permanently authorizes you to choose that
     version for the Program.

     Later license versions may give you additional or different permissions.
     However, no additional obligations are imposed on any author or copyright
     holder as a result of your choosing to follow a later version.

  15. Disclaimer of Warranty.

     THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
     APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
     HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
     OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
     IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
     ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

     IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
     WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
     THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
     ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
     THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
     LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
     OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
     PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
     POSSIBILITY OF SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

     If the disclaimer of warranty and limitation of liability provided above
     cannot be given local legal effect according to their terms, reviewing
     courts shall apply local law that most closely approximates an absolute
     waiver of all civil liability in connection with the Program, unless a
     warranty or assumption of liability accompanies a copy of the Program in
     return for a fee.

END OF TERMS AND CONDITIONS
---------------------------

How to Apply These Terms to Your New Programs
---------------------------------------------

If you develop a new program, and you want it to be of the greatest possible
use to the public, the best way to achieve this is to make it free software
which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach
them to the start of each source file to most effectively state the exclusion
of warranty; and each file should have at least the "copyright" line and a
pointer to where the full notice is found.

     ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
     Copyright (C) YEAR NAME OF AUTHOR

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or (at
     your option) any later version.

     This program is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

If the program does terminal interaction, make it output a short notice like
this when it starts in an interactive mode:

     PROGRAM Copyright (C) YEAR NAME OF AUTHOR
     This program comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type ‘show c’ for details.

The hypothetical commands ‘show w’ and ‘show c’ should show the appropriate
parts of the General Public License. Of course, your program's commands might
be different; for a GUI interface, you would use an "about box".

You should also get your employer (if you work as a programmer) or school, if
any, to sign a "copyright disclaimer" for the program, if necessary. For more
information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

The GNU General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General Public
License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


File: ansicmd.info,  Node: GNU Free Documentation License,  Prev: GNU General Public License,  Up: Copyright Notice

GNU Free Documentation License
==============================

                        Version 1.3, 3 November 2008

     Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
     <https://fsf.org/>

     Everyone is permitted to copy and distribute verbatim copies
     of this license document, but changing it is not allowed.

  0. PREAMBLE

     The purpose of this License is to make a manual, textbook, or other
     functional and useful document “free” in the sense of freedom: to assure
     everyone the effective freedom to copy and redistribute it, with or
     without modifying it, either commercially or noncommercially.
     Secondarily, this License preserves for the author and publisher a way to
     get credit for their work, while not being considered responsible for
     modifications made by others.

     This License is a kind of "copyleft", which means that derivative works
     of the document must themselves be free in the same sense. It complements
     the GNU General Public License, which is a copyleft license designed for
     free software.

     We have designed this License in order to use it for manuals for free
     software, because free software needs free documentation: a free program
     should come with manuals providing the same freedoms that the software
     does. But this License is not limited to software manuals; it can be used
     for any textual work, regardless of subject matter or whether it is
     published as a printed book. We recommend this License principally for
     works whose purpose is instruction or reference.

  1. APPLICABILITY AND DEFINITIONS

     This License applies to any manual or other work, in any medium, that
     contains a notice placed by the copyright holder saying it can be
     distributed under the terms of this License. Such a notice grants a
     world-wide, royalty-free license, unlimited in duration, to use that work
     under the conditions stated herein. The "Document", below, refers to any
     such manual or work. Any member of the public is a licensee, and is
     addressed as "you". You accept the license if you copy, modify or
     distribute the work in a way requiring permission under copyright law.

     A "Modified Version" of the Document means any work containing the
     Document or a portion of it, either copied verbatim, or with
     modifications and/or translated into another language.

     A "Secondary Section" is a named appendix or a front-matter section of
     the Document that deals exclusively with the relationship of the
     publishers or authors of the Document to the Document's overall subject
     (or to related matters) and contains nothing that could fall directly
     within that overall subject. (Thus, if the Document is in part a textbook
     of mathematics, a Secondary Section may not explain any mathematics.) The
     relationship could be a matter of historical connection with the subject
     or with related matters, or of legal, commercial, philosophical, ethical
     or political position regarding them.

     The "Invariant Sections" are certain Secondary Sections whose titles are
     designated, as being those of Invariant Sections, in the notice that says
     that the Document is released under this License. If a section does not
     fit the above definition of Secondary then it is not allowed to be
     designated as Invariant. The Document may contain zero Invariant
     Sections. If the Document does not identify any Invariant Sections then
     there are none.

     The "Cover Texts" are certain short passages of text that are listed, as
     Front-Cover Texts or Back-Cover Texts, in the notice that says that the
     Document is released under this License. A Front-Cover Text may be at
     most 5 words, and a Back-Cover Text may be at most 25 words.

     A "Transparent" copy of the Document means a machine-readable copy,
     represented in a format whose specification is available to the general
     public, that is suitable for revising the document straightforwardly with
     generic text editors or (for images composed of pixels) generic paint
     programs or (for drawings) some widely available drawing editor, and that
     is suitable for input to text formatters or for automatic translation to
     a variety of formats suitable for input to text formatters. A copy made
     in an otherwise Transparent file format whose markup, or absence of
     markup, has been arranged to thwart or discourage subsequent modification
     by readers is not Transparent. An image format is not Transparent if used
     for any substantial amount of text. A copy that is not "Transparent" is
     called "Opaque".

     Examples of suitable formats for Transparent copies include plain ASCII
     without markup, Texinfo input format, LaTeX input format, SGML or XML
     using a publicly available DTD, and standard-conforming simple HTML,
     PostScript or PDF designed for human modification. Examples of
     transparent image formats include PNG, XCF and JPG. Opaque formats
     include proprietary formats that can be read and edited only by
     proprietary word processors, SGML or XML for which the DTD and/or
     processing tools are not generally available, and the machine-generated
     HTML, PostScript or PDF produced by some word processors for output
     purposes only.

     The "Title Page" means, for a printed book, the title page itself, plus
     such following pages as are needed to hold, legibly, the material this
     License requires to appear in the title page. For works in formats which
     do not have any title page as such, "Title Page" means the text near the
     most prominent appearance of the work's title, preceding the beginning of
     the body of the text.

     The "publisher" means any person or entity that distributes copies of the
     Document to the public.

     A section "Entitled XYZ" means a named subunit of the Document whose
     title either is precisely XYZ or contains XYZ in parentheses following
     text that translates XYZ in another language. (Here XYZ stands for a
     specific section name mentioned below, such as "Acknowledgements",
     "Dedications", "Endorsements", or "History".) To "Preserve the Title" of
     such a section when you modify the Document means that it remains a
     section "Entitled XYZ" according to this definition.

     The Document may include Warranty Disclaimers next to the notice which
     states that this License applies to the Document. These Warranty
     Disclaimers are considered to be included by reference in this License,
     but only as regards disclaiming warranties: any other implication that
     these Warranty Disclaimers may have is void and has no effect on the
     meaning of this License.

  2. VERBATIM COPYING

     You may copy and distribute the Document in any medium, either
     commercially or noncommercially, provided that this License, the
     copyright notices, and the license notice saying this License applies to
     the Document are reproduced in all copies, and that you add no other
     conditions whatsoever to those of this License. You may not use technical
     measures to obstruct or control the reading or further copying of the
     copies you make or distribute. However, you may accept compensation in
     exchange for copies. If you distribute a large enough number of copies
     you must also follow the conditions in section 3.

     You may also lend copies, under the same conditions stated above, and you
     may publicly display copies.

  3. COPYING IN QUANTITY

     If you publish printed copies (or copies in media that commonly have
     printed covers) of the Document, numbering more than 100, and the
     Document's license notice requires Cover Texts, you must enclose the
     copies in covers that carry, clearly and legibly, all these Cover Texts:
     Front-Cover Texts on the front cover, and Back-Cover Texts on the back
     cover. Both covers must also clearly and legibly identify you as the
     publisher of these copies. The front cover must present the full title
     with all words of the title equally prominent and visible. You may add
     other material on the covers in addition. Copying with changes limited to
     the covers, as long as they preserve the title of the Document and
     satisfy these conditions, can be treated as verbatim copying in other
     respects.

     If the required texts for either cover are too voluminous to fit legibly,
     you should put the first ones listed (as many as fit reasonably) on the
     actual cover, and continue the rest onto adjacent pages.

     If you publish or distribute Opaque copies of the Document numbering more
     than 100, you must either include a machine-readable Transparent copy
     along with each Opaque copy, or state in or with each Opaque copy a
     computer-network location from which the general network-using public has
     access to download using public-standard network protocols a complete
     Transparent copy of the Document, free of added material. If you use the
     latter option, you must take reasonably prudent steps, when you begin
     distribution of Opaque copies in quantity, to ensure that this
     Transparent copy will remain thus accessible at the stated location until
     at least one year after the last time you distribute an Opaque copy
     (directly or through your agents or retailers) of that edition to the
     public.

     It is requested, but not required, that you contact the authors of the
     Document well before redistributing any large number of copies, to give
     them a chance to provide you with an updated version of the Document.

  4. MODIFICATIONS

     You may copy and distribute a Modified Version of the Document under the
     conditions of sections 2 and 3 above, provided that you release the
     Modified Version under precisely this License, with the Modified Version
     filling the role of the Document, thus licensing distribution and
     modification of the Modified Version to whoever possesses a copy of it.
     In addition, you must do these things in the Modified Version:

       A. Use in the Title Page (and on the covers, if any) a title distinct
          from that of the Document, and from those of previous versions
          (which should, if there were any, be listed in the History section
          of the Document). You may use the same title as a previous version
          if the original publisher of that version gives permission.

       B. List on the Title Page, as authors, one or more persons or entities
          responsible for authorship of the modifications in the Modified
          Version, together with at least five of the principal authors of the
          Document (all of its principal authors, if it has fewer than five),
          unless they release you from this requirement.

       C. State on the Title page the name of the publisher of the Modified
          Version, as the publisher.

       D. Preserve all the copyright notices of the Document.

       E. Add an appropriate copyright notice for your modifications adjacent
          to the other copyright notices.

       F. Include, immediately after the copyright notices, a license notice
          giving the public permission to use the Modified Version under the
          terms of this License, in the form shown in the Addendum below.

       G. Preserve in that license notice the full lists of Invariant Sections
          and required Cover Texts given in the Document's license notice.

       H. Include an unaltered copy of this License.

       I. Preserve the section Entitled "History", Preserve its Title, and add
          to it an item stating at least the title, year, new authors, and
          publisher of the Modified Version as given on the Title Page. If
          there is no section Entitled "History" in the Document, create one
          stating the title, year, authors, and publisher of the Document as
          given on its Title Page, then add an item describing the Modified
          Version as stated in the previous sentence.

       J. Preserve the network location, if any, given in the Document for
          public access to a Transparent copy of the Document, and likewise
          the network locations given in the Document for previous versions it
          was based on. These may be placed in the "History" section. You may
          omit a network location for a work that was published at least four
          years before the Document itself, or if the original publisher of
          the version it refers to gives permission.

       K. For any section Entitled "Acknowledgements" or "Dedications",
          Preserve the Title of the section, and preserve in the section all
          the substance and tone of each of the contributor acknowledgements
          and/or dedications given therein.

       L. Preserve all the Invariant Sections of the Document, unaltered in
          their text and in their titles. Section numbers or the equivalent
          are not considered part of the section titles.

       M. Delete any section Entitled "Endorsements". Such a section may not
          be included in the Modified Version.

       N. Do not retitle any existing section to be Entitled "Endorsements" or
          to conflict in title with any Invariant Section.

       O. Preserve any Warranty Disclaimers.

     If the Modified Version includes new front-matter sections or appendices
     that qualify as Secondary Sections and contain no material copied from
     the Document, you may at your option designate some or all of these
     sections as invariant. To do this, add their titles to the list of
     Invariant Sections in the Modified Version's license notice. These titles
     must be distinct from any other section titles.

     You may add a section Entitled "Endorsements", provided it contains
     nothing but endorsements of your Modified Version by various parties--for
     example, statements of peer review or that the text has been approved by
     an organization as the authoritative definition of a standard.

     You may add a passage of up to five words as a Front-Cover Text, and a
     passage of up to 25 words as a Back-Cover Text, to the end of the list of
     Cover Texts in the Modified Version. Only one passage of Front-Cover Text
     and one of Back-Cover Text may be added by (or through arrangements made
     by) any one entity. If the Document already includes a cover text for the
     same cover, previously added by you or by arrangement made by the same
     entity you are acting on behalf of, you may not add another; but you may
     replace the old one, on explicit permission from the previous publisher
     that added the old one.

     The author(s) and publisher(s) of the Document do not by this License
     give permission to use their names for publicity for or to assert or
     imply endorsement of any Modified Version.

  5. COMBINING DOCUMENTS

     You may combine the Document with other documents released under this
     License, under the terms defined in section 4 above for modified
     versions, provided that you include in the combination all of the
     Invariant Sections of all of the original documents, unmodified, and list
     them all as Invariant Sections of your combined work in its license
     notice, and that you preserve all their Warranty Disclaimers.

     The combined work need only contain one copy of this License, and
     multiple identical Invariant Sections may be replaced with a single copy.
     If there are multiple Invariant Sections with the same name but different
     contents, make the title of each such section unique by adding at the end
     of it, in parentheses, the name of the original author or publisher of
     that section if known, or else a unique number. Make the same adjustment
     to the section titles in the list of Invariant Sections in the license
     notice of the combined work.

     In the combination, you must combine any sections Entitled "History" in
     the various original documents, forming one section Entitled "History";
     likewise combine any sections Entitled "Acknowledgements", and any
     sections Entitled "Dedications". You must delete all sections Entitled
     "Endorsements."

  6. COLLECTIONS OF DOCUMENTS

     You may make a collection consisting of the Document and other documents
     released under this License, and replace the individual copies of this
     License in the various documents with a single copy that is included in
     the collection, provided that you follow the rules of this License for
     verbatim copying of each of the documents in all other respects.

     You may extract a single document from such a collection, and distribute
     it individually under this License, provided you insert a copy of this
     License into the extracted document, and follow this License in all other
     respects regarding verbatim copying of that document.

  7. AGGREGATION WITH INDEPENDENT WORKS

     A compilation of the Document or its derivatives with other separate and
     independent documents or works, in or on a volume of a storage or
     distribution medium, is called an "aggregate" if the copyright resulting
     from the compilation is not used to limit the legal rights of the
     compilation's users beyond what the individual works permit. When the
     Document is included in an aggregate, this License does not apply to the
     other works in the aggregate which are not themselves derivative works of
     the Document.

     If the Cover Text requirement of section 3 is applicable to these copies
     of the Document, then if the Document is less than one half of the entire
     aggregate, the Document's Cover Texts may be placed on covers that
     bracket the Document within the aggregate, or the electronic equivalent
     of covers if the Document is in electronic form. Otherwise they must
     appear on printed covers that bracket the whole aggregate.

  8. TRANSLATION

     Translation is considered a kind of modification, so you may distribute
     translations of the Document under the terms of section 4. Replacing
     Invariant Sections with translations requires special permission from
     their copyright holders, but you may include translations of some or all
     Invariant Sections in addition to the original versions of these
     Invariant Sections. You may include a translation of this License, and
     all the license notices in the Document, and any Warranty Disclaimers,
     provided that you also include the original English version of this
     License and the original versions of those notices and disclaimers. In
     case of a disagreement between the translation and the original version
     of this License or a notice or disclaimer, the original version will
     prevail.

     If a section in the Document is Entitled "Acknowledgements",
     "Dedications", or "History", the requirement (section 4) to Preserve its
     Title (section 1) will typically require changing the actual title.

  9. TERMINATION

     You may not copy, modify, sublicense, or distribute the Document except
     as expressly provided under this License. Any attempt otherwise to copy,
     modify, sublicense, or distribute it is void, and will automatically
     terminate your rights under this License.

     However, if you cease all violation of this License, then your license
     from a particular copyright holder is reinstated (a) provisionally,
     unless and until the copyright holder explicitly and finally terminates
     your license, and (b) permanently, if the copyright holder fails to
     notify you of the violation by some reasonable means prior to 60 days
     after the cessation.

     Moreover, your license from a particular copyright holder is reinstated
     permanently if the copyright holder notifies you of the violation by some
     reasonable means, this is the first time you have received notice of
     violation of this License (for any work) from that copyright holder, and
     you cure the violation prior to 30 days after your receipt of the notice.

     Termination of your rights under this section does not terminate the
     licenses of parties who have received copies or rights from you under
     this License. If your rights have been terminated and not permanently
     reinstated, receipt of a copy of some or all of the same material does
     not give you any rights to use it.

  10. FUTURE REVISIONS OF THIS LICENSE

     The Free Software Foundation may publish new, revised versions of the GNU
     Free Documentation License from time to time. Such new versions will be
     similar in spirit to the present version, but may differ in detail to
     address new problems or concerns. See <https://www.gnu.org/licenses/>.

     Each version of the License is given a distinguishing version number. If
     the Document specifies that a particular numbered version of this License
     "or any later version" applies to it, you have the option of following
     the terms and conditions either of that specified version or of any later
     version that has been published (not as a draft) by the Free Software
     Foundation. If the Document does not specify a version number of this
     License, you may choose any version ever published (not as a draft) by
     the Free Software Foundation. If the Document specifies that a proxy can
     decide which future versions of this License can be used, that proxy's
     public statement of acceptance of a version permanently authorizes you to
     choose that version for the Document.

  11. RELICENSING

     "Massive Multiauthor Collaboration Site" (or "MMC Site") means any World
     Wide Web server that publishes copyrightable works and also provides
     prominent facilities for anybody to edit those works. A public wiki that
     anybody can edit is an example of such a server. A "Massive Multiauthor
     Collaboration" (or "MMC") contained in the site means any set of
     copyrightable works thus published on the MMC site.

     "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license
     published by Creative Commons Corporation, a not-for-profit corporation
     with a principal place of business in San Francisco, California, as well
     as future copyleft versions of that license published by that same
     organization.

     "Incorporate" means to publish or republish a Document, in whole or in
     part, as part of another Document.

     An MMC is "eligible for relicensing" if it is licensed under this
     License, and if all works that were first published under this License
     somewhere other than this MMC, and subsequently incorporated in whole or
     in part into the MMC, (1) had no cover texts or invariant sections, and
     (2) were thus incorporated prior to November 1, 2008.

     The operator of an MMC Site may republish an MMC contained in the site
     under CC-BY-SA on the same site at any time before August 1, 2009,
     provided the MMC is eligible for relicensing.

ADDENDUM: How to use this License for your documents
----------------------------------------------------

To use this License in a document you have written, include a copy of the
License in the document and put the following copyright and license notices
just after the title page:

       Copyright (C)  YEAR  YOUR NAME.
       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.3
       or any later version published by the Free Software Foundation;
       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
       Texts.  A copy of the license is included in the section entitled ``GNU
       Free Documentation License''.

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the "with...Texts." line with this:

         with the Invariant Sections being LIST THEIR TITLES, with
         the Front-Cover Texts being LIST, and with the Back-Cover Texts
         being LIST.

If you have Invariant Sections without Cover Texts, or some other combination
of the three, merge those two alternatives to suit the situation.

If your document contains nontrivial examples of program code, we recommend
releasing these examples in parallel under your choice of free software
license, such as the GNU General Public License, to permit their use in free
software.


File: ansicmd.info,  Node: Index,  Prev: Copyright Notice,  Up: Top

Index
*****

[index]
* Menu:

* 01.0.00 Introduction:                  Introduction.             (line    6)
* 02.0.00 Invoking:                      Invoking.                 (line    6)
* 02.1.00 Invoking - Terminal Setup:     Invoking - Terminal Setup.
                                                                   (line    6)
* 02.2.00 Invoking - AnsiCmd Tests:      Invoking - AnsiCmd Tests. (line    6)
* 02.3.00 Invoking - EarthPoints:        Invoking - EarthPoints.   (line    6)
* 03.0.00 AnsiCmd Library:               AnsiCmd Library.          (line    6)
* 03.1.00 Introductory Notes:            Introductory Notes.       (line    6)
* 03.2.00 ANSI Escape Sequences:         ANSI Escape Sequences.    (line    6)
* 03.3.00 Terminal Configuration:        Terminal Configuration.   (line    6)
* 03.4.00 AnsiCmd Class Methods:         AnsiCmd Class Methods.    (line    6)
* 03.4.01 Table of Public Methods:       Table of Public Methods.  (line    6)
* 03.4.02 Configuration Methods:         Configuration Methods.    (line    6)
* 03.4.03 Color Attributes:              Color Attributes.         (line    6)
* 03.4.04 Text Modifiers:                Text Modifiers.           (line    6)
* 03.4.05 Cursor Positioning:            Cursor Positioning.       (line    6)
* 03.4.06 Input Methods:                 Input Methods.            (line    6)
* 03.4.07 Output Methods:                Output Methods.           (line    6)
* 03.4.08 Text Erase:                    Text Erase.               (line    6)
* 03.4.09 Misc Methods:                  Misc Methods.             (line    6)
* 03.4.10 API Methods:                   API Methods.              (line    6)
* 03.4.11 Coding Example:                Coding Example.           (line    6)
* 03.4.11 Development Support:           Development Support.      (line    6)
* 04.0.00 ACWin Class:                   ACWin Class.              (line    6)
* 04.1.00 ACWin Public Methods:          ACWin Public Methods.     (line    6)
* 04.2.00 skForm Class:                  skForm Class.             (line    6)
* 04.2.01 User Interaction:              User Interaction.         (line    6)
* 04.2.02 skForm Public Methods:         skForm Public Methods.    (line    6)
* 04.2.03 skForm Data Members:           skForm Data Members.      (line    6)
* 04.2.04 skField Public Methods:        skField Public Methods.   (line    6)
* 04.2.05 skField Data Members:          skField Data Members.     (line    6)
* 04.2.06 UI Control Types:              UI Control Types.         (line    6)
* 04.2.07 skForm Initialization:         skForm Initialization.    (line    6)
* 04.3.00 Dialog sub-Windows:            Dialog sub-Windows.       (line    6)
* 05.0.00:                               Development and Testing.  (line    6)
* 06.0.00 Building from Source:          Building from Source.     (line    6)
* 07 gString Text Tool:                  gString Text Tool.        (line    6)
* 07.01 Introduction to gString:         Introduction to gString.  (line    6)
* 07.02 gString Public Methods:          gString Public Methods.   (line    6)
* 07.03 gString Instantiation:           gString Instantiation.    (line    6)
* 07.04 Assignment Operators:            Assignment Operators.     (line    6)
* 07.05 Formatted Assignments:           Formatted Assignments.    (line    6)
* 07.06 Integer Formatting:              Integer Formatting.       (line    6)
* 07.07 Data Access:                     Data Access.              (line    6)
* 07.08 Copying Data:                    Copying Data.             (line    6)
* 07.09 Modifying Existing Data:         Modifying Existing Data.  (line    6)
* 07.10 Comparisons:                     Comparisons.              (line    6)
* 07.11 Extract Formatted Data:          Extract Formatted Data.   (line    6)
* 07.12 Statistical Info:                Statistical Info.         (line    6)
* 07.13 gString Miscellaneous:           gString Miscellaneous.    (line    6)
* 07.14 gsmeter Test App:                gsmeter Test App.         (line    6)
* 07.14 gString Examples:                gString Examples.         (line    6)
* 08.0.00 CsvView Demo App:              CsvView Demo App.         (line    6)
* 08.01 Introduction to CsvView:         Introduction to CsvView.  (line    6)
* 08.02 Invoking CsvView:                Invoking CsvView.         (line    6)
* 08.03 CSV Encoding:                    CSV Encoding.             (line    6)
* 08.04 Build CsvView from Source:       Build CsvView from Source.
                                                                   (line    6)
* 09.0.00 AcEdit Demo App:               AcEdit Demo App.          (line    6)
* 09.01 Introduction to AcEdit:          Introduction to AcEdit.   (line    6)
* 09.02 Invoking AcEdit:                 Invoking AcEdit.          (line    6)
* 09.03 AcEdit Menu System:              AcEdit Menu System.       (line    6)
* 09.05 AcEdit Configuration:            AcEdit Configuration.     (line    6)
* 09.05 AcEdit Dialogs:                  AcEdit Dialogs.           (line    6)
* 09.06 Build AcEdit from Source:        Build AcEdit from Source. (line    6)
* 10.0.00 TFMTest Demo App:              TFMTest Demo App.         (line    6)
* 10.01 The TFMTest Application:         The TFMTest Application.  (line    6)
* 10.02 TFMan Class:                     TFMan Class.              (line    6)
* 11.0.00 Technical Support:             Technical Support.        (line    6)
* 12.0.00 Copyright Notice:              Copyright Notice.         (line    6)
* 12.1.00 GNU General Public License:    GNU General Public License.
                                                                   (line    6)
* 12.2.00 GNU Free Documentation License: GNU Free Documentation License.
                                                                   (line    6)
* ~skField:                              skField Public Methods.   (line   86)
* A option:                              Invoking - Terminal Setup.
                                                                   (line  106)
* acaExpand class:                       API Methods.              (line  268)
* acAttr, enum:                          API Methods.              (line  230)
* acBeep:                                Misc Methods.             (line    6)
* acBlockingInput:                       Configuration Methods.    (line  305)
* acBoxClear:                            API Methods.              (line 1103)
* acBoxDraw:                             API Methods.              (line 1031)
* acBoxErase:                            API Methods.              (line 1093)
* acBufferedInput:                       Configuration Methods.    (line  189)
* acCaptureBreakSignal:                  Configuration Methods.    (line  372)
* acCaptureQuitSignal:                   Configuration Methods.    (line  454)
* acCaptureSignals:                      Configuration Methods.    (line  323)
* acCaptureSuspendSignal:                Configuration Methods.    (line  494)
* acClearArea:                           API Methods.              (line  664)
* acClearScreen:                         API Methods.              (line  641)
* acClipboardByteCnt:                    API Methods.              (line 1451)
* acClipboardCharCnt:                    API Methods.              (line 1430)
* acClipboardDisable:                    API Methods.              (line 1365)
* acClipboardEnable:                     API Methods.              (line 1315)
* acClipboardGetText:                    API Methods.              (line 1393)
* acClipboardSetText:                    API Methods.              (line 1413)
* acClipboardTest:                       API Methods.              (line 1381)
* acComposeAttributes:                   API Methods.              (line  144)
* acCreateTempfile:                      API Methods.              (line 1270)
* acCreateTemppath:                      API Methods.              (line 1218)
* acDeleteTempfile:                      API Methods.              (line 1299)
* acDeleteTemppath:                      API Methods.              (line 1257)
* ACDlg class:                           Dialog sub-Windows.       (line    6)
* acDrawBox:                             API Methods.              (line  980)
* acDrawLine:                            API Methods.              (line  909)
* ace color option:                      Invoking AcEdit.          (line   89)
* ace dimensions option:                 Invoking AcEdit.          (line  199)
* ace help option:                       Invoking AcEdit.          (line  232)
* ace helpless option:                   Invoking AcEdit.          (line  242)
* ace language option:                   Invoking AcEdit.          (line  138)
* ace test option:                       Invoking AcEdit.          (line  207)
* ace version option:                    Invoking AcEdit.          (line  251)
* AcEdit invoking:                       Invoking AcEdit.          (line    6)
* acEraseArea:                           Text Erase.               (line    6)
* acEraseBox:                            API Methods.              (line 1013)
* acFlushIn:                             Input Methods.            (line  109)
* acFlushOut:                            Output Methods.           (line  199)
* acFlushStreams:                        Output Methods.           (line  216)
* acFormatParagraph:                     API Methods.              (line  703)
* acFullReset:                           Text Modifiers.           (line   68)
* acGetAttributes:                       API Methods.              (line  213)
* acGetCursor:                           Cursor Positioning.       (line   86)
* acGetEchoOption:                       Configuration Methods.    (line  294)
* acGetLocale:                           Configuration Methods.    (line  161)
* acGetTermDimensions:                   Configuration Methods.    (line   91)
* acGetTermInfo:                         Configuration Methods.    (line  102)
* acGetTermSize:                         Configuration Methods.    (line   58)
* acPause:                               Input Methods.            (line   60)
* acRead:                                Input Methods.            (line    6)
* acReleaseSignals:                      Configuration Methods.    (line  359)
* acReset:                               Color Attributes.         (line  321)
* acResetMods:                           Text Modifiers.           (line   23)
* acRestoreTermInfo:                     Configuration Methods.    (line  517)
* acSet8bitBg:                           Color Attributes.         (line  133)
* acSet8bitFg:                           Color Attributes.         (line  122)
* acSetAixBg:                            Color Attributes.         (line  311)
* acSetAixFg:                            Color Attributes.         (line  301)
* acSetAttributes:                       API Methods.              (line   42)
* acSetBg:                               Color Attributes.         (line   31)
* acSetCursor:                           Cursor Positioning.       (line   26)
* acSetCursorStyle:                      Cursor Positioning.       (line  122)
* acSetEchoOption:                       Configuration Methods.    (line  256)
* acSetFg:                               Color Attributes.         (line    6)
* acSetFgBg:                             Color Attributes.         (line   60)
* acSetFont:                             Misc Methods.             (line  170)
* acSetGreyscaleBg:                      Color Attributes.         (line  286)
* acSetGreyscaleFg:                      Color Attributes.         (line  271)
* acSetIdeogram:                         Misc Methods.             (line  194)
* acSetLocale:                           Configuration Methods.    (line  140)
* acSetMod:                              Text Modifiers.           (line    6)
* acSetRgbBg:                            Color Attributes.         (line  167)
* acSetRgbFg:                            Color Attributes.         (line  144)
* acSetStreamWidth:                      Configuration Methods.    (line  170)
* acSetWebBg:                            Color Attributes.         (line  244)
* acSetWebFg:                            Color Attributes.         (line  191)
* acShellOut:                            API Methods.              (line  850)
* acVersion:                             Misc Methods.             (line  151)
* acWait:                                Input Methods.            (line   89)
* ACWin constructor:                     ACWin Public Methods.     (line  112)
* ACWin derived class:                   ACWin Class.              (line    6)
* ACWin destructor:                      ACWin Public Methods.     (line  216)
* acWrite:                               Output Methods.           (line    6)
* AC_Box Class:                          API Methods.              (line 1027)
* aeSeq enumerated type:                 ANSI Escape Sequences.    (line   20)
* AIX extensions:                        Color Attributes.         (line   18)
* Aixterm, IBM:                          Color Attributes.         (line   18)
* AlertEnable:                           ACWin Public Methods.     (line  731)
* Alt keys:                              Terminal Configuration.   (line  478)
* ALT-key combo:                         Invoking - AnsiCmd Tests. (line  196)
* ANSI escape sequence:                  ANSI Escape Sequences.    (line   94)
* AnsiCmd constructor:                   Configuration Methods.    (line    6)
* AnsiCmd destructor:                    Configuration Methods.    (line   45)
* ansiTest:                              Development Support.      (line    6)
* ansiTest_Menu:                         Development and Testing.  (line   47)
* api methods:                           API Methods.              (line    6)
* application options:                   Invoking - EarthPoints.   (line    6)
* ASCII codes:                           Terminal Configuration.   (line  400)
* ascii test:                            Invoking - AnsiCmd Tests. (line  131)
* assignment, skField:                   skField Public Methods.   (line  101)
* assignment, skForm:                    skForm Public Methods.    (line  100)
* attributes, color:                     Color Attributes.         (line    6)
* B option:                              Invoking - Terminal Setup.
                                                                   (line  137)
* BiDi text:                             Modifying Existing Data.  (line  649)
* blink timeout:                         Invoking - Terminal Setup.
                                                                   (line  351)
* blink timeout <1>:                     Cursor Positioning.       (line  151)
* break signal:                          Terminal Configuration.   (line  200)
* breaksignalReceived:                   Configuration Methods.    (line  372)
* breaksignalReceived <1>:               Configuration Methods.    (line  545)
* buffered input:                        Configuration Methods.    (line  189)
* buffering, input:                      Terminal Configuration.   (line  100)
* build CsvView:                         Build CsvView from Source.
                                                                   (line    6)
* build options:                         Building from Source.     (line   30)
* C option:                              Invoking - Terminal Setup.
                                                                   (line   78)
* callback example:                      Dialog sub-Windows.       (line  548)
* callback function:                     ACWin Public Methods.     (line  745)
* callback, dialog:                      Dialog sub-Windows.       (line  506)
* chrono:                                Misc Methods.             (line   86)
* class, acaExpand:                      API Methods.              (line  268)
* class, ACDlg:                          Dialog sub-Windows.       (line    6)
* class, ACWin:                          ACWin Class.              (line    6)
* class, AnsiCmd:                        AnsiCmd Class Methods.    (line    6)
* class, skField:                        skField Public Methods.   (line    6)
* class, skForm:                         skForm Class.             (line    6)
* class, TermConfig:                     Terminal Configuration.   (line   18)
* class, TermSet:                        Terminal Configuration.   (line  520)
* ClearField:                            ACWin Public Methods.     (line 1723)
* ClearRow:                              ACWin Public Methods.     (line  365)
* ClearWin:                              ACWin Public Methods.     (line  349)
* clipboard directive:                   Building from Source.     (line  265)
* clipboard, copy/paste:                 API Methods.              (line 1531)
* CloseWindow:                           ACWin Public Methods.     (line  275)
* coa option:                            Invoking - EarthPoints.   (line  121)
* cob option:                            Invoking - EarthPoints.   (line  134)
* code example:                          Coding Example.           (line    6)
* codepoint, Unicode:                    ACWin Public Methods.     (line 2796)
* color attributes:                      Color Attributes.         (line    6)
* color option:                          Invoking - EarthPoints.   (line  260)
* color test:                            Invoking - AnsiCmd Tests. (line   85)
* colorConfig:                           skField Public Methods.   (line  260)
* colors, custom:                        skField Public Methods.   (line  260)
* command-line options:                  Invoking.                 (line    6)
* compilation, conditional:              Development and Testing.  (line    6)
* compile from source:                   Building from Source.     (line   15)
* conditional compilation:               Development and Testing.  (line    6)
* configuration, terminal:               Terminal Configuration.   (line    6)
* configuraton:                          Configuration Methods.    (line    6)
* contact info:                          Technical Support.        (line   10)
* control codes:                         Terminal Configuration.   (line  400)
* control types:                         UI Control Types.         (line    6)
* Control_C:                             Terminal Configuration.   (line  200)
* Control_Z:                             Configuration Methods.    (line  494)
* convert option:                        Invoking - EarthPoints.   (line  227)
* copy to cb:                            API Methods.              (line 1531)
* csv bgndattr option:                   Invoking CsvView.         (line  155)
* csv capture option:                    Invoking CsvView.         (line  347)
* csv create option:                     Invoking CsvView.         (line  292)
* csv dimensions option:                 Invoking CsvView.         (line  420)
* csv display option:                    Invoking CsvView.         (line  103)
* csv encoding:                          CSV Encoding.             (line    6)
* csv fgndattr option:                   Invoking CsvView.         (line  130)
* csv filespec option:                   Invoking CsvView.         (line   79)
* csv header option:                     Invoking CsvView.         (line  204)
* csv help option:                       Invoking CsvView.         (line  262)
* csv helpless option:                   Invoking CsvView.         (line  272)
* csv language option:                   Invoking CsvView.         (line  170)
* csv pause option:                      Invoking CsvView.         (line  468)
* csv saveas option:                     Invoking CsvView.         (line  247)
* csv stats option:                      Invoking CsvView.         (line  391)
* csv terminfo option:                   Invoking CsvView.         (line  443)
* csv version option:                    Invoking CsvView.         (line  281)
* csvview build:                         Build CsvView from Source.
                                                                   (line    6)
* CsvView invoking:                      Invoking CsvView.         (line    6)
* CTRL-key combo:                        Invoking - AnsiCmd Tests. (line  133)
* cursor offsets:                        Cursor Positioning.       (line    6)
* cursor position:                       Cursor Positioning.       (line    6)
* custom colors:                         skField Public Methods.   (line  260)
* cut to cb:                             API Methods.              (line 1531)
* database, GPS:                         Invoking - EarthPoints.   (line  179)
* delimeters, secondary:                 CSV Encoding.             (line   42)
* derived class, ACWin:                  ACWin Class.              (line    6)
* dialog callback:                       Dialog sub-Windows.       (line  506)
* Dialog method:                         ACWin Public Methods.     (line 2089)
* Dialog method <1>:                     Dialog sub-Windows.       (line  284)
* dialog test:                           Invoking - AnsiCmd Tests. (line  355)
* Dialog_GetField:                       ACWin Public Methods.     (line 2487)
* Dialog_GetItem:                        ACWin Public Methods.     (line 2305)
* Dialog_GetItem <1>:                    ACWin Public Methods.     (line 2389)
* Dialog_GetState:                       ACWin Public Methods.     (line 2440)
* Dialog_GetStateXOR:                    ACWin Public Methods.     (line 2460)
* Dialog_GetText:                        ACWin Public Methods.     (line 2222)
* Dialog_Hilite:                         ACWin Public Methods.     (line 2525)
* Dialog_Refresh:                        ACWin Public Methods.     (line 2716)
* Dialog_Scroll:                         ACWin Public Methods.     (line 2620)
* Dialog_SetAttr:                        ACWin Public Methods.     (line 2271)
* Dialog_SetFocus:                       ACWin Public Methods.     (line 2579)
* Dialog_SetReadOnly:                    ACWin Public Methods.     (line 2597)
* Dialog_SetText:                        ACWin Public Methods.     (line 2241)
* Dialog_Write:                          ACWin Public Methods.     (line 2671)
* directive, clipboard:                  Building from Source.     (line  265)
* documentation, installing:             Building from Source.     (line  402)
* DrawBox:                               ACWin Public Methods.     (line 2963)
* DrawLine:                              ACWin Public Methods.     (line 2993)
* dump option:                           Invoking - EarthPoints.   (line  389)
* dumpConfig2Log:                        ACWin Public Methods.     (line 3192)
* dumpField2Log:                         ACWin Public Methods.     (line 3192)
* dumpFifo2Log:                          ACWin Public Methods.     (line 3192)
* dumpFifoRecord2Log:                    ACWin Public Methods.     (line 3192)
* dumpMrp2Log:                           ACWin Public Methods.     (line 3192)
* dynamic alloc. gString:                gString Instantiation.    (line  193)
* echo options:                          Terminal Configuration.   (line  287)
* EditForm:                              ACWin Public Methods.     (line  535)
* EnableFootnotes:                       ACWin Public Methods.     (line 2851)
* encoding, csv:                         CSV Encoding.             (line    6)
* enum acAttr:                           API Methods.              (line  230)
* enum FldType:                          UI Control Types.         (line    6)
* enum FloType:                          ACWin Public Methods.     (line 1268)
* erase, text:                           Text Erase.               (line    6)
* erasure test:                          Invoking - AnsiCmd Tests. (line  121)
* EstablishCallback:                     ACWin Public Methods.     (line  745)
* example, coding:                       Coding Example.           (line    6)
* field types:                           UI Control Types.         (line    6)
* FIFO, input stream:                    ACWin Public Methods.     (line  865)
* file option:                           Invoking - EarthPoints.   (line  147)
* FileMan class:                         AcEdit Dialogs.           (line  120)
* fiUnits enumerated type:               Integer Formatting.       (line  167)
* Fnn-key combo:                         Invoking - AnsiCmd Tests. (line  167)
* Focus2NextField:                       ACWin Public Methods.     (line  645)
* Focus2PrevField:                       ACWin Public Methods.     (line  659)
* font test:                             Invoking - AnsiCmd Tests. (line  231)
* Footnote:                              ACWin Public Methods.     (line 2862)
* formatInt field overflow:              Integer Formatting.       (line  206)
* FormatParagraph:                       ACWin Public Methods.     (line 2744)
* formula option:                        Invoking - EarthPoints.   (line  208)
* getConfig:                             Development Support.      (line   40)
* GetCursorPos:                          ACWin Public Methods.     (line  421)
* getDataMembers:                        Development Support.      (line   22)
* GetFieldData:                          ACWin Public Methods.     (line 1668)
* GetFieldIP:                            ACWin Public Methods.     (line 1144)
* GetFieldItem:                          ACWin Public Methods.     (line 1161)
* GetFieldState:                         ACWin Public Methods.     (line 1222)
* GetFieldText:                          ACWin Public Methods.     (line  944)
* GetFifo:                               ACWin Public Methods.     (line 3184)
* GetForm:                               ACWin Public Methods.     (line  598)
* getHilite:                             skField Public Methods.   (line  589)
* GetInputFocus:                         ACWin Public Methods.     (line  619)
* getItem:                               skField Public Methods.   (line  411)
* GetWinAttributes:                      ACWin Public Methods.     (line 3168)
* GetWinConfig:                          ACWin Public Methods.     (line 3176)
* GPS database:                          Invoking - EarthPoints.   (line  179)
* gsettings, blink:                      Invoking - Terminal Setup.
                                                                   (line  351)
* gString:                               Introduction.             (line   50)
* gString memory alloc.:                 gString Instantiation.    (line  193)
* gString methods:                       gString Public Methods.   (line    6)
* gString text conversion:               gString Text Tool.        (line    6)
* GUI keys:                              Terminal Configuration.   (line  478)
* help option:                           Invoking - EarthPoints.   (line  431)
* helpless option:                       Invoking - EarthPoints.   (line  440)
* HideWin:                               ACWin Public Methods.     (line  314)
* HilightFieldText:                      ACWin Public Methods.     (line 1862)
* hotkeys, direct:                       skField Data Members.     (line  143)
* hotkeys, set:                          ACWin Public Methods.     (line 1478)
* i/o streams:                           Terminal Configuration.   (line  520)
* IBM Aixterm:                           Color Attributes.         (line   18)
* ideograph test:                        Invoking - AnsiCmd Tests. (line  253)
* info database:                         Building from Source.     (line  402)
* input buffering:                       Terminal Configuration.   (line  100)
* input methods:                         Input Methods.            (line    6)
* input stream FIFO:                     ACWin Public Methods.     (line  865)
* input, buffered:                       Configuration Methods.    (line  189)
* InsertKey:                             ACWin Public Methods.     (line  673)
* invoking:                              Invoking.                 (line    6)
* invoking AcEdit:                       Invoking AcEdit.          (line    6)
* invoking CsvView:                      Invoking CsvView.         (line    6)
* invoking TFMTest:                      The TFMTest Application.  (line   25)
* invoking, EarthPoints:                 Invoking - EarthPoints.   (line    6)
* invoking, term setup:                  Invoking - Terminal Setup.
                                                                   (line    6)
* invoking, test options:                Invoking - AnsiCmd Tests. (line    6)
* isCommandKey:                          API Methods.              (line 1163)
* isInsertMode:                          ACWin Public Methods.     (line  712)
* isPrint:                               ACWin Public Methods.     (line 2796)
* isSpecialKey:                          API Methods.              (line 1118)
* KeycodePush:                           ACWin Public Methods.     (line  865)
* L option:                              Invoking - Terminal Setup.
                                                                   (line  193)
* labelConfig:                           skField Public Methods.   (line  155)
* LaunchDefaultApp:                      ACWin Public Methods.     (line 3053)
* less utility:                          Introduction to CsvView.  (line   45)
* list of methods:                       Table of Public Methods.  (line    6)
* locale name:                           Terminal Configuration.   (line   47)
* locale, set:                           Integer Formatting.       (line  245)
* locale, specify:                       Invoking - Terminal Setup.
                                                                   (line  193)
* memory, alloc. gString:                gString Instantiation.    (line  193)
* menu item:                             skField Public Methods.   (line  411)
* method list:                           Table of Public Methods.  (line    6)
* methods, gString:                      gString Public Methods.   (line    6)
* misc methods:                          Misc Methods.             (line    6)
* modifiers, text:                       Text Modifiers.           (line    6)
* MoveWin:                               ACWin Public Methods.     (line  327)
* multi-threading:                       ANSI Escape Sequences.    (line  111)
* nanosleep:                             Misc Methods.             (line   86)
* nsleep:                                Misc Methods.             (line   50)
* offsets, cursor:                       Cursor Positioning.       (line    6)
* OpenWindow:                            ACWin Public Methods.     (line  246)
* option, A:                             Invoking - Terminal Setup.
                                                                   (line  106)
* option, ace color:                     Invoking AcEdit.          (line   89)
* option, ace dimensions:                Invoking AcEdit.          (line  199)
* option, ace help:                      Invoking AcEdit.          (line  232)
* option, ace helpless:                  Invoking AcEdit.          (line  242)
* option, ace language:                  Invoking AcEdit.          (line  138)
* option, ace test:                      Invoking AcEdit.          (line  207)
* option, ace version:                   Invoking AcEdit.          (line  251)
* option, B:                             Invoking - Terminal Setup.
                                                                   (line  137)
* option, C:                             Invoking - Terminal Setup.
                                                                   (line   78)
* option, coa:                           Invoking - EarthPoints.   (line  121)
* option, cob:                           Invoking - EarthPoints.   (line  134)
* option, color:                         Invoking - EarthPoints.   (line  260)
* option, convert:                       Invoking - EarthPoints.   (line  227)
* option, csv bgndattr:                  Invoking CsvView.         (line  155)
* option, csv capture:                   Invoking CsvView.         (line  347)
* option, csv create:                    Invoking CsvView.         (line  292)
* option, csv dimensions:                Invoking CsvView.         (line  420)
* option, csv display:                   Invoking CsvView.         (line  103)
* option, csv fgndattr:                  Invoking CsvView.         (line  130)
* option, csv filespec:                  Invoking CsvView.         (line   79)
* option, csv header:                    Invoking CsvView.         (line  204)
* option, csv help:                      Invoking CsvView.         (line  262)
* option, csv helpless:                  Invoking CsvView.         (line  272)
* option, csv language:                  Invoking CsvView.         (line  170)
* option, csv pause:                     Invoking CsvView.         (line  468)
* option, csv saveas:                    Invoking CsvView.         (line  247)
* option, csv stats:                     Invoking CsvView.         (line  391)
* option, csv terminfo:                  Invoking CsvView.         (line  443)
* option, csv version:                   Invoking CsvView.         (line  281)
* option, dump:                          Invoking - EarthPoints.   (line  389)
* option, file:                          Invoking - EarthPoints.   (line  147)
* option, formula:                       Invoking - EarthPoints.   (line  208)
* option, help:                          Invoking - EarthPoints.   (line  431)
* option, helpless:                      Invoking - EarthPoints.   (line  440)
* option, L:                             Invoking - Terminal Setup.
                                                                   (line  193)
* option, P:                             Invoking - Terminal Setup.
                                                                   (line  236)
* option, Q:                             Invoking - Terminal Setup.
                                                                   (line  278)
* option, S:                             Invoking - Terminal Setup.
                                                                   (line  320)
* option, verbose:                       Invoking - EarthPoints.   (line  294)
* option, version:                       Invoking - EarthPoints.   (line  449)
* option, W:                             Invoking - Terminal Setup.
                                                                   (line   53)
* option, window:                        Invoking - EarthPoints.   (line  329)
* option, Z:                             Invoking - Terminal Setup.
                                                                   (line  300)
* options, application:                  Invoking - EarthPoints.   (line    6)
* options, echo:                         Terminal Configuration.   (line  287)
* options, setup:                        Invoking - Terminal Setup.
                                                                   (line    6)
* options, testing:                      Invoking - AnsiCmd Tests. (line    6)
* outlineConfig:                         skField Public Methods.   (line  112)
* output formats:                        Introduction to CsvView.  (line   35)
* output methods:                        Output Methods.           (line    6)
* P option:                              Invoking - Terminal Setup.
                                                                   (line  236)
* ParagraphSize:                         ACWin Public Methods.     (line 2751)
* paste from cb:                         API Methods.              (line 1531)
* positioning test:                      Invoking - AnsiCmd Tests. (line  113)
* Q option:                              Invoking - Terminal Setup.
                                                                   (line  278)
* QuickDialog:                           ACWin Public Methods.     (line 2011)
* QuickDialog <1>:                       Dialog sub-Windows.       (line  166)
* quitsignalReceived:                    Configuration Methods.    (line  581)
* ram memory, gString:                   gString Instantiation.    (line  193)
* ReformatFieldText:                     ACWin Public Methods.     (line 1752)
* RefreshField:                          ACWin Public Methods.     (line 1688)
* RefreshWin:                            ACWin Public Methods.     (line  299)
* RTL text:                              Modifying Existing Data.  (line  649)
* S option:                              Invoking - Terminal Setup.
                                                                   (line  320)
* sandbox test:                          Invoking - AnsiCmd Tests. (line  428)
* Screenshot:                            ACWin Public Methods.     (line 3215)
* ScrollFieldText:                       ACWin Public Methods.     (line 1784)
* secondary delimeters:                  CSV Encoding.             (line   42)
* set locale:                            Integer Formatting.       (line  245)
* SetBorderAttr:                         ACWin Public Methods.     (line  478)
* SetCursorPos:                          ACWin Public Methods.     (line  430)
* SetFieldAttr:                          ACWin Public Methods.     (line  973)
* SetFieldData:                          ACWin Public Methods.     (line 1607)
* SetFieldFlow:                          ACWin Public Methods.     (line 1249)
* SetFieldHidden:                        ACWin Public Methods.     (line 1547)
* SetFieldHotkey:                        ACWin Public Methods.     (line 1478)
* SetFieldIP:                            ACWin Public Methods.     (line 1023)
* SetFieldLabel:                         ACWin Public Methods.     (line 1318)
* SetFieldOutline:                       ACWin Public Methods.     (line 1417)
* SetFieldState:                         ACWin Public Methods.     (line 1201)
* SetFieldText:                          ACWin Public Methods.     (line  913)
* SetHilightMod:                         ACWin Public Methods.     (line 1977)
* setHiliteMod:                          skField Public Methods.   (line  508)
* SetInputFocus:                         ACWin Public Methods.     (line  632)
* SetReadOnly:                           ACWin Public Methods.     (line 1592)
* SetTextAttr:                           ACWin Public Methods.     (line  467)
* SetTitle:                              ACWin Public Methods.     (line  446)
* setup options:                         Invoking - Terminal Setup.
                                                                   (line    6)
* ShellOut:                              ACWin Public Methods.     (line 3109)
* ShiftFieldText:                        ACWin Public Methods.     (line 1832)
* Sidebar:                               ACWin Public Methods.     (line 2898)
* skField class:                         skField Public Methods.   (line    6)
* skField constructor:                   skField Public Methods.   (line    6)
* skField operator=:                     skField Public Methods.   (line  101)
* skForm class:                          skForm Class.             (line    6)
* skForm constructor:                    skForm Public Methods.    (line   12)
* skForm operator=:                      skForm Public Methods.    (line  100)
* sleep_for:                             Misc Methods.             (line   86)
* soft-echo options:                     Terminal Configuration.   (line  287)
* source code:                           Building from Source.     (line    5)
* special keys:                          Terminal Configuration.   (line  329)
* streams, i/o:                          Terminal Configuration.   (line  520)
* support methods:                       Development Support.      (line    6)
* support, technical:                    Technical Support.        (line    6)
* suspendsignalReceived:                 Configuration Methods.    (line  565)
* swscanf emulation:                     Extract Formatted Data.   (line    6)
* technical support:                     Technical Support.        (line    6)
* temporary files:                       API Methods.              (line 1195)
* temporary files <1>:                   The TFMTest Application.  (line    6)
* temporary files <2>:                   TFMan Class.              (line    6)
* TermConfig class:                      Terminal Configuration.   (line   18)
* terminal configuration:                Terminal Configuration.   (line    6)
* terminal test:                         Invoking - AnsiCmd Tests. (line  273)
* TermSet class:                         Terminal Configuration.   (line  520)
* test methods:                          Development and Testing.  (line    6)
* test the build:                        Building from Source.     (line  385)
* test, ascii:                           Invoking - AnsiCmd Tests. (line  131)
* test, color:                           Invoking - AnsiCmd Tests. (line   85)
* test, dialog:                          Invoking - AnsiCmd Tests. (line  355)
* test, erasure:                         Invoking - AnsiCmd Tests. (line  121)
* test, font:                            Invoking - AnsiCmd Tests. (line  231)
* test, ideograph:                       Invoking - AnsiCmd Tests. (line  253)
* test, positioning:                     Invoking - AnsiCmd Tests. (line  113)
* test, sandbox:                         Invoking - AnsiCmd Tests. (line  428)
* test, terminal:                        Invoking - AnsiCmd Tests. (line  273)
* test, window:                          Invoking - AnsiCmd Tests. (line  307)
* testing options:                       Invoking - AnsiCmd Tests. (line    6)
* Test_4Bit:                             Development and Testing.  (line   58)
* Test_8bitColor:                        Development and Testing.  (line   64)
* Test_acaExpand:                        Development and Testing.  (line   76)
* Test_acaExpandSwap:                    Development and Testing.  (line   79)
* Test_AixFgBg:                          Development and Testing.  (line   73)
* Test_AltFonts:                         Development and Testing.  (line   82)
* Test_AsciiCodes:                       Development and Testing.  (line   91)
* Test_Bg:                               Development and Testing.  (line   61)
* Test_Box:                              Development and Testing.  (line  145)
* Test_Clipboard_API:                    Development and Testing.  (line  151)
* Test_Clipboard_Win:                    Development and Testing.  (line  154)
* Test_Cookie:                           Development and Testing.  (line  142)
* Test_CursorPos:                        Development and Testing.  (line   85)
* Test_Dialog:                           Development and Testing.  (line  163)
* Test_Erasures:                         Development and Testing.  (line   88)
* Test_Fifo:                             Development and Testing.  (line  133)
* Test_Form:                             Development and Testing.  (line  124)
* Test_Greyscale:                        Development and Testing.  (line   70)
* Test_Hilite:                           Development and Testing.  (line  139)
* Test_Ideogram:                         Development and Testing.  (line   94)
* Test_LaunchExt:                        Development and Testing.  (line  160)
* Test_Line:                             Development and Testing.  (line  148)
* Test_Menu:                             Development and Testing.  (line  136)
* Test_ModFlags:                         Development and Testing.  (line  103)
* Test_NonBlock:                         Development and Testing.  (line  106)
* Test_OutputStream:                     Development and Testing.  (line  112)
* Test_RawInput:                         Development and Testing.  (line  109)
* Test_RGB:                              Development and Testing.  (line   67)
* Test_Sandbox:                          Development and Testing.  (line  166)
* Test_SoftEcho:                         Development and Testing.  (line  115)
* Test_TermFlags:                        Development and Testing.  (line  100)
* Test_Tfman:                            Development and Testing.  (line  157)
* Test_UnbufferedInput:                  Development and Testing.  (line   97)
* Test_WinDefault:                       Development and Testing.  (line  130)
* Test_Window:                           Development and Testing.  (line  121)
* Test_Wrap:                             Development and Testing.  (line  127)
* Test_Write:                            Development and Testing.  (line  118)
* text conversion, gString:              gString Text Tool.        (line    6)
* text erase:                            Text Erase.               (line    6)
* text modifiers:                        Text Modifiers.           (line    6)
* TFMan:                                 Introduction.             (line   71)
* TFMTest app:                           The TFMTest Application.  (line    6)
* timeout, blink:                        Cursor Positioning.       (line  151)
* timeout, blinking:                     Invoking - Terminal Setup.
                                                                   (line  351)
* tseReport:                             Development Support.      (line   52)
* ttyWrite:                              Output Methods.           (line  121)
* Unicode codepoint:                     ACWin Public Methods.     (line 2796)
* user interface controls:               UI Control Types.         (line    6)
* verbose option:                        Invoking - EarthPoints.   (line  294)
* version option:                        Invoking - EarthPoints.   (line  449)
* W option:                              Invoking - Terminal Setup.
                                                                   (line   53)
* WaylandCB:                             Introduction.             (line   60)
* web-safe indices:                      API Methods.              (line  479)
* window option:                         Invoking - EarthPoints.   (line  329)
* window test:                           Invoking - AnsiCmd Tests. (line  307)
* WinInfo:                               ACWin Public Methods.     (line  493)
* Write:                                 ACWin Public Methods.     (line  384)
* Z option:                              Invoking - Terminal Setup.
                                                                   (line  300)




Tag Table:
Node: Top797
Node: Introduction2547
Ref: WaylandCB Class4923
Ref: ANSI5736
Ref: ASCII5992
Node: Invoking6179
Ref: invocation menu8266
Node: Invoking - Terminal Setup8513
Ref: W option10063
Ref: C option11081
Ref: A option12137
Ref: B option13468
Ref: L option16450
Ref: P option18110
Ref: Q option20203
Ref: Z option21083
Ref: S option21935
Node: Invoking - AnsiCmd Tests24129
Ref: test C27768
Ref: test P28873
Ref: test E29202
Ref: test A29674
Ref: test F34901
Ref: test I35838
Ref: test T36771
Ref: test W38361
Ref: test D40768
Ref: test S45348
Node: Invoking - EarthPoints46888
Ref: GPS Coordinate Records49667
Ref: coa option51933
Ref: cob option52316
Ref: file option52699
Ref: formula option55278
Ref: convert option56084
Ref: color option57264
Ref: verbose option58663
Ref: window option60280
Ref: dump option63580
Ref: help option65431
Ref: helpless option65688
Ref: version option65948
Node: AnsiCmd Library66288
Node: Introductory Notes66684
Node: ANSI Escape Sequences68188
Node: Terminal Configuration74009
Ref: TermConfig Class74652
Ref: bcAlert80627
Ref: Capturing the Break Signal83917
Ref: Soft Echo Options88445
Ref: Decoding the Special Keys90507
Ref: ASCII Control Codes94506
Ref: GUI Keys98426
Ref: TermSet Class100293
Node: AnsiCmd Class Methods106428
Node: Table of Public Methods107010
Node: Configuration Methods115550
Ref: AnsiCmd constructor115732
Ref: AnsiCmd destructor117293
Ref: acGetTermSize117638
Ref: acGetTermDimensions118926
Ref: acGetTermInfo119347
Ref: acSetLocale121000
Ref: acGetLocale121824
Ref: acSetStreamWidth121993
Ref: acBufferedInput122738
Ref: acSetEchoOption126378
Ref: acGetEchoOption128425
Ref: acBlockingInput128753
Ref: acCaptureSignals129497
Ref: acReleaseSignals131115
Ref: acCaptureBreakSignal131454
Ref: acCaptureQuitSignal135830
Ref: acCaptureSuspendSignal138018
Ref: acRestoreTermInfo139154
Ref: breaksignalReceived140634
Ref: suspendsignalReceived141708
Ref: quitsignalReceived142412
Node: Color Attributes143138
Ref: acSetFg143301
Ref: acSetBg144438
Ref: acSetFgBg145731
Ref: acSet8bitFg149509
Ref: acSet8bitBg149944
Ref: acSetRgbFg150379
Ref: acSetRgbBg151304
Ref: acSetWebFg152230
Ref: acSetWebBg155046
Ref: acSetGreyscaleFg156504
Ref: acSetGreyscaleBg157162
Ref: acReset158530
Node: Text Modifiers159097
Ref: acSetMod159253
Ref: acResetMods159925
Ref: acFullReset162031
Node: Cursor Positioning163574
Ref: cursor offsets163735
Ref: acSetCursor164833
Ref: acGetCursor167621
Ref: acSetCursorStyle169258
Node: Input Methods172418
Ref: acRead172569
Ref: acPause175011
Ref: acWait176405
Ref: acFlushIn177211
Node: Output Methods178144
Ref: acWrite178289
Ref: ttyWrite183682
Ref: acFlushOut187331
Ref: acFlushStreams187843
Node: Text Erase188469
Ref: acEraseArea188605
Node: Misc Methods190497
Ref: acBeep190634
Ref: nsleep192953
Ref: acVersion198189
Ref: acSetFont199019
Ref: acSetIdeogram200172
Node: API Methods201263
Ref: Color Attribute Methods203019
Ref: acSetAttributes203019
Ref: acComposeAttributes208122
Ref: acGetAttributes211994
Ref: List of Attribute Names212570
Ref: enum acAttr212570
Ref: Attribute Bitfield Definitions214603
Ref: acaExpand class214603
Ref: Display Formatting Methods233379
Ref: acClearScreen233379
Ref: acClearArea234275
Ref: acFormatParagraph236086
Ref: acShellOut244716
Ref: Line Drawing Methods247839
Ref: acDrawLine247839
Ref: acDrawBox251484
Ref: acEraseBox253039
Ref: AC_Box Class253561
Ref: acBoxDraw253607
Ref: acBoxErase256693
Ref: acBoxClear256981
Ref: Identify "Special" Keycodes257551
Ref: isSpecialKey257551
Ref: isCommandKey259651
Ref: Temporary File Management261227
Ref: acCreateTemppath262252
Ref: acDeleteTemppath264157
Ref: acCreateTempfile264540
Ref: acDeleteTempfile265591
Ref: Communicate With System Clipboard266091
Ref: acClipboardEnable266091
Ref: acClipboardDisable268341
Ref: acClipboardTest268778
Ref: acClipboardGetText269059
Ref: acClipboardSetText269906
Ref: acClipboardCharCnt270589
Ref: acClipboardByteCnt271327
Ref: AnsiCmd Clipboard Access272028
Node: Development Support278024
Ref: ansiTest278186
Ref: getDataMembers278823
Ref: getConfig279594
Ref: tseReport280023
Node: Coding Example280320
Node: ACWin Class286181
Node: ACWin Public Methods287355
Ref: ACWin constructor294522
Ref: ACWin destructor299636
Ref: OpenWindow300627
Ref: CloseWindow302024
Ref: RefreshWin303199
Ref: HideWin303676
Ref: MoveWin304108
Ref: ClearWin305179
Ref: ClearRow305824
Ref: Write306709
Ref: GetCursorPos308549
Ref: SetCursorPos308739
Ref: SetTitle309279
Ref: SetTextAttr310225
Ref: SetBorderAttr310541
Ref: WinInfo311176
Ref: EditForm312963
Ref: GetForm316484
Ref: GetInputFocus317176
Ref: SetInputFocus317575
Ref: Focus2NextField318007
Ref: Focus2PrevField318417
Ref: InsertKey318829
Ref: isInsertMode320897
Ref: AlertEnable321471
Ref: EstablishCallback321952
Ref: KeycodePush327573
Ref: SetFieldText329822
Ref: GetFieldText331273
Ref: SetFieldAttr332796
Ref: SetFieldIP335017
Ref: GetFieldIP340925
Ref: GetFieldItem341685
Ref: SetFieldState343717
Ref: GetFieldState344656
Ref: SetFieldFlow345924
Ref: SetFieldLabel349840
Ref: SetFieldOutline356400
Ref: SetFieldHotkey360373
Ref: SetFieldHidden363962
Ref: SetReadOnly366345
Ref: SetFieldData366953
Ref: GetFieldData369857
Ref: RefreshField370688
Ref: ClearField371865
Ref: ReformatFieldText373227
Ref: ScrollFieldText374761
Ref: ShiftFieldText376839
Ref: HilightFieldText378160
Ref: SetHilightMod383895
Ref: Dialog-Oriented Methods384901
Ref: QuickDialog385219
Ref: Dialog389548
Ref: Dialog_GetText397471
Ref: Dialog_SetText398148
Ref: Dialog_SetAttr399467
Ref: Dialog_GetItem400997
Ref: Dialog_SetItem405363
Ref: Dialog_GetState407929
Ref: Dialog_GetStateXOR408703
Ref: Dialog_GetField409882
Ref: Dialog_Hilite411600
Ref: Dialog_SetFocus414361
Ref: Dialog_SetReadOnly414991
Ref: Dialog_Scroll415954
Ref: Dialog_Write418496
Ref: Dialog_Refresh420853
Ref: FormatParagraph422108
Ref: ParagraphSize422385
Ref: isPrint424193
Ref: EnableFootnotes426932
Ref: Footnote427293
Ref: Sidebar429022
Ref: DrawBox432457
Ref: DrawLine433930
Ref: LaunchDefaultApp437889
Ref: ShellOut440905
Ref: GetWinAttributes443972
Ref: GetWinConfig444303
Ref: GetFifo444646
Ref: dumpConfig2Log444999
Ref: dumpField2Log444999
Ref: dumpMrp2Log444999
Ref: dumpFifo2Log444999
Ref: dumpFifoRecord2Log444999
Ref: Screenshot446035
Node: skForm Class450547
Node: User Interaction451910
Node: skForm Public Methods455229
Ref: skForm constructor455754
Ref: skForm operator=460460
Node: skForm Data Members464044
Node: skField Public Methods468129
Ref: skField Class468305
Ref: skField constructor468305
Ref: ~skField472547
Ref: skField operator=473011
Ref: outlineConfig473350
Ref: labelConfig475568
Ref: colorConfig480489
Ref: skField config example484602
Ref: getItem488335
Ref: setHiliteMod493423
Ref: getHilite496622
Node: skField Data Members498894
Node: UI Control Types511296
Ref: Field Types511456
Ref: enum FldType511456
Node: skForm Initialization520243
Node: Dialog sub-Windows530169
Ref: ACDlg Class530296
Ref: Dialog Callback555264
Ref: example callback557239
Node: Development and Testing567323
Ref: ansiTest_Menu570076
Ref: Test_4Bit570573
Ref: Test_Bg570654
Ref: Test_8bitColor570733
Ref: Test_RGB570819
Ref: Test_Greyscale570910
Ref: Test_AixFgBg570996
Ref: Test_acaExpand571080
Ref: Test_acaExpandSwap571166
Ref: Test_AltFonts571256
Ref: Test_CursorPos571341
Ref: Test_Erasures571427
Ref: Test_AsciiCodes571512
Ref: Test_Ideogram571599
Ref: Test_UnbufferedInput571684
Ref: Test_TermFlags571780
Ref: Test_ModFlags571870
Ref: Test_NonBlock571959
Ref: Test_RawInput572048
Ref: Test_OutputStream572137
Ref: Test_SoftEcho572230
Ref: Test_Write572333
Ref: Test_Window572419
Ref: Test_Form572506
Ref: Test_Wrap572591
Ref: Test_WinDefault572676
Ref: Test_Fifo572767
Ref: Test_Menu572852
Ref: Test_Hilite572937
Ref: Test_Cookie573024
Ref: Test_Box573111
Ref: Test_Line573195
Ref: Test_Clip573280
Ref: Test_Dialog573663
Ref: Test_Sandbox573749
Node: Building from Source574666
Ref: Build Options575461
Ref: installing the documentation592641
Node: gString Text Tool596193
Node: Introduction to gString597491
Node: gString Public Methods600205
Node: gString Instantiation603224
Ref: Dynamic Memory Allocation611275
Node: Assignment Operators614198
Node: Formatted Assignments615669
Node: Integer Formatting625288
Ref: field overflow632697
Ref: how to set locale634412
Node: Data Access635313
Node: Copying Data637309
Node: Modifying Existing Data645260
Ref: textReverse method671526
Ref: formatParagraph678929
Node: Comparisons687413
Ref: compcoll690628
Node: Extract Formatted Data705310
Node: Statistical Info711200
Node: gString Miscellaneous713511
Node: gString Examples717480
Node: gsmeter Test App722297
Ref: gsmeter Introduction722652
Ref: gsmeter Options724634
Ref: Building gsmeter728192
Node: CsvView Demo App729814
Node: Introduction to CsvView730320
Ref: Output Formats732154
Node: Invoking CsvView733481
Ref: csv filespec option736964
Ref: csv display option738243
Ref: csv fgndattr option739464
Ref: csv bgndattr option740174
Ref: csv language option740728
Ref: csv header option742096
Ref: csv saveas option744273
Ref: csv help option744852
Ref: csv helpless option745114
Ref: csv version option745374
Ref: csv create option745743
Ref: csv capture option748417
Ref: csv stats option750186
Ref: csv dimensions option751630
Ref: csv terminfo option752578
Ref: csv pause option753555
Node: CSV Encoding754007
Ref: Secondary Field Delimeters755770
Node: Build CsvView from Source759049
Node: AcEdit Demo App763816
Node: Introduction to AcEdit764319
Node: Invoking AcEdit767098
Ref: ace color option770815
Ref: ace language option773079
Ref: ace dimensions option777264
Ref: ace test option777532
Ref: ace help option778456
Ref: ace helpless option778716
Ref: ace version option778974
Node: AcEdit Menu System780350
Node: AcEdit Dialogs780623
Ref: AcEdit Crash Recovery780979
Ref: FileMan class786495
Node: AcEdit Configuration791945
Node: Build AcEdit from Source793137
Node: TFMTest Demo App793412
Node: The TFMTest Application793802
Ref: Invoking TFMTest794843
Ref: Building TFMTest796655
Node: TFMan Class799324
Node: Technical Support811649
Ref: By the Same Author812675
Node: Copyright Notice820207
Node: GNU General Public License821177
Node: GNU Free Documentation License858453
Node: Index883342

End Tag Table


Local Variables:
coding: utf-8
Info-documentlanguage: en_US
End:
