Application Interface to ANSI Escape Sequences

AnsiCmd Class Link Library

Copyright © 2022-2023 Mahlon R. Smith, The Software Samurai This manual describes version 0.0.04 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.


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 ANSI escape sequences and 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 the "break" signal (CTRL+C).

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.


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

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





Invoking

There are three (3) groups of command-line options for invoking the application (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 See Invoking - Terminal Setup.
  2. AnsiCmd-class Testing Options:
    These options specify a test of specific functionality within the AnsiCmd class. 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 (See Build Options), so all test code may be disabled without loss of application functionality.
    Please See 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 See Invoking - EarthPoints for more information.

       Invocation Options


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
  W option    stream Width
  C option    Color attributes
  A option    Ansi compliant
  B option    input Buffering
  L option    Locale name
  P option    Panic button
  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: 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: 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: 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. 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. See 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: 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. 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:t # Terminal handler (default)

Please see Capturing the Break Signal for additional information.

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



–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: 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.




Invoking - AnsiCmd Tests

Tests for the AnsiCmd library are specified as arguments to the "–ansi" command-line option.
epts --ansi=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 --ansi=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.

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 --ansi=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 --ansi=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 --ansi=Eb — Perform 'E'rasure test with 'b'lue text.
epts --ansi=Ac — Perform 'A'SCII code test with 'c'yan text.
epts --ansi=Tig — Perform 'T'erminal 'i'nput test with 'g'reen text.


Summary of Options

    OPTION          DESCRIPTION
  test C Color tests
  test P Positioning tests
  test E Erasure tests
  test A Ascii control code tests
  test F Font switch test
  test I Ideograph test
  test T Terminal setup tests
  test W Window tests
  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 see Development and Testing or study the AnsiCmdTest.cpp source file for more information about how the individual tests are constructed.



–C Color Attributes.

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


–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 Code Tests.

ASCII control codes (00h - 1Fh) were an important part of systems which used serial communication (e.g. Teletype machines) for user interaction. On modern systems, most of these codes are swallowed by the terminal software and never become available to the console application. A few 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.

This test transmits each of the ASCII control codes to the terminal and reports the terminal’s response (if any).



–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 see 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 indended 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. c : Cursor-movement special keys translated. e : Edit keys: Backspace/Del/Insert translated. d : Disable soft-echo special-key translation. 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' m : Modifiers: Bold, Italic, Underline, Reverse, Overline, etc. Examples: epts --ansi=T # Display the menu of sub-options epts --ansi=Tb # Test blocking vs. non-blocking input epts --ansi=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 which 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 acDrawLine method and the AC_Box Class, respectively.

At the higher level of abstraction is the ACWin Class which defines a relatively primitive dialog window which optionally contains a user-defined array of text fields (skForm Class), with more sophisticated input and output methods which may be used to display information or to interact with the user.

w : Window (ACWin) interactive tests f : Form: skForm class and skField class text fields d : Default AC_Win window constructor b : Box drawing tests l : Line drawing tests Examples: epts –ansi=W # Display the menu for the window group epts –ansi=Ww # Interactive test of ACWin functionality epts –ansi=Wf # Edit text in an skForm, multi-field structure epts –ansi=Wlg # Line-drawing tests with 'g'reen lines


–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.
See 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 --ansi=S # invoke the Sandbox with no arguments
epts --ansi=St # invoke the Sandbox with one argument
epts --ansi=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 () ; }



Invoking - EarthPoints

Summary of Options

  OPTION  DESCRIPTION
  coa option Specify the first set of  global coordinates.
  cob option Specify the second set of  global coordinates.
  file option Specify a file containing  global coordinate pairs.
  formula option Specify the formula to be  used to calculate distance.
  convert option Convert coordinate-pair  format to alternate formats
  color option Specify color attribute for  reporting results.
  verbose option Display verbose output for  results of calculation.
  window option Display the report within a  window object.
  dump option Display and verify contents  of a file of GPS records.
  version option Reports EarthPoints version  number and copyright info.
  help option Display all EarthPoints and  AnsiCmd options
  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 GPS Coordinate Records section, above.

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

Please See 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 GPS Coordinate Records section, above.

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

Please See 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 See 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. See 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. See 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 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 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



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, see Terminal Configuration.


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.

Wikipedia:   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 (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. (see nsleep)


Terminal Configuration

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

Subsequent modifications to the terminal environment are specified by calling the associated AnsiCmd-class method(s).
   See 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.
   See TermSet Class.


TermConfig Class

Initialization of the TermConfig object may be done directly by the application when invoking the AnsiCmd constructor:
   AnsiCmd constructor,
or may be performed by the user through command-line options:
   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.

  • 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|C|D|E]: the 'acRead' input methods echo (display) all graphing (printing) characters to the terminal window as they arrive. The “special” keys (cursor movement, backspace, delete, insert) are processed according to specified soft-echo sub-option.
      • softEchoA - All special keys are captured, decoded and available to the application.
      • 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 see 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 see 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 see 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.
    • cchtIgnore - Ignore (discard) the break signal.

    See 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.
  • 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 see 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 see 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 see TermConfig Class and 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 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 a private 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.
  • 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. (see 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 acBufferedInput method which disables input buffering and optionally specifys 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
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.
  • 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. 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 small subset of these escape sequences are captured and decoded. These include:

 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
   Note: Encoding of Backspace and Delete keys are specified in terminal settings.

The Copy/Cut/Paste keys (Ctrl+C, Ctrl+X, Ctrl+V) will be integrated into this group for a future release. Until then, the terminal equivalents, in concert with the system mouse, may be used: Ctrl+Shift+C, CtrL+Shift+V.

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 see skForm Class for a description of how these keycodes are interpreted within a form or a field.

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.
See 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 see 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 (see 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 See S option for specifying the cursor style as a command line option, and the 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 See 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 See Soft Echo Options and 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 See B option for specifying the input buffering option as a command line option, and the TermConfig Class for a description of input buffering. See also, the 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 (see 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 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 See Capturing the Break Signal, and also the acCaptureBreakSignal method for a discussion of the break-signal handlers.

  • 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




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 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 see By the Same Author for more information.

 Method Name Description
──── Configuration ────── ─────────────────────────────────────────
 AnsiCmd constructor Constructors
 AnsiCmd destructor Destructor
 acGetTermSize Calculate size of terminal window
 acGetTermDimensions Get a copy of stored terminal size
 acGetTermInfo Get current terminal configuration
 acSetLocale Specify a non-default locale
 acGetLocale Get current locale setting
 acSetStreamWidth Lock in wide or narrow I/O streams
 acBufferedInput Configure input-stream buffering
 acEchoOption Echo option (unbuffered input only)
 acBlockingInput Input blocking (unbuffered input only)
 acCaptureBreakSignal Enable/disable capture of Ctrl+C
 acRestoreTermInfo Set terminal configuration to defaults
  
──── Color Attributes ─── ─────────────────────────────────────────
 acSetFg Set text foreground (3-bit, 4-bit)
 acSetBg Set text background (3-bit, 4-bit)
 acSetFgBg Set text fgnd and bkgnd (3-bit, 4-bit)
 acSet8bitFg Set text foreground (8-bit color)
 acSet8bitBg Set text background (8-bit color)
 acSetRgbFg Set text foreground (r/g/b color)
 acSetRgbBg Set text background (r/g/b color)
 acSetWebFg Set text foreground (web-safe r/g/b)
 acSetWebBg Set text background (web-safe r/g/b)
 acSetGreyscaleFg Set text foreground (greyscale)
 acSetGreyscaleBg Set text background (greyscale)
 acSetAixFg Set text foreground (AIX Intel)
 acSetAixBg Set text background (AIX Intel)
 acReset Reset attributes and tracking data
  
──── Text Modifiers ───── ─────────────────────────────────────────
 acSetMod Set or reset a text modifier
 acResetMods Reset all text modifiers
 acFullReset Reset all colors and text modifiers
  
─── Cursor Position ───── ─────────────────────────────────────────
 acSetCursor Position the visible cursor
 acGetCursor Get current cursor position
 acSetCursorStyle Specify cursor shape
  
───── Input Methods ───── ─────────────────────────────────────────
 acRead Read from stdin
 acFlushIn Flush the input stream (stdin)
  
──── Output Methods ───── ─────────────────────────────────────────
 acWrite Write formatted data to stdout
 ttyWrite Write unformatted data (TTY style)
 acFlushOut Flush the output stream (stdout)
 acFlushStreams Flush both input and output streams
  
──── Text Erase ───────── ─────────────────────────────────────────
 acEraseArea Erase specified area of terminal window
  
──── Misc Methods ─────── ─────────────────────────────────────────
 acBeep Make some noise
 nsleep Put thread to sleep
 acVersion Get AnsiCmd class version number
 acSetFont Seldom supported alternate font
 acSetIdeogram Seldom supported line drawing
  
──── API Methods ──────── ─────────────────────────────────────────
 acSetAttributes Set bit-field color and text-mod data
 acComposeAttributes Encode bit-field color and text-mods
 acGetAttributes Get decoded bit-field color/text-mods
 acClearScreen Erase all data from terminal window
 acClearArea Erase specified area of terminal window
 acDrawLine Draw a horizontal or vertical line
 acDrawBox Draw a rectangle in the terminal window
 acEraseBox Erase a rectangular area of terminal
 acBoxDraw Display an AC_Box object in terminal
 acBoxErase Erase an AC_Box object from terminal
 acBoxClear Clear the interior of an AC_Box object
  
── Development Support ── ─────────────────────────────────────────
 ansiTest Manage AnsiCmd library testing
 getDataMembers Get a copy of internal data members



Configuration Methods

  • AnsiCmd ( void );
      Input  : none
    
      Returns: implicitly returns a pointer to object
    

    Default Constructor: Terminal configuration parameters are set to default values.
    Please See 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 See Invoking.

    Please See 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.
    see 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 (acEchoOption) and/or the input-blocking option (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 acEchoOption ( 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)
                         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 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 see Decoding the Special Keys for more information on the soft-echo options.

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


  • 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 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:
      1. the cursor will be placed on the bottom row of the terminal window,
      2. the terminal bell will sound,
      3. a short message will be displayed, and
      4. the application will be terminated with a minus-one (-1) exit code.
    • cchtUser : Ask the user if they really want to exit the application:
      1. the terminal bell will sound,
      2. 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.)
      3. Display a message asking the user to answer:
        Exit? 'y'es or 'n'o: _
      4. Wait for the user’s response.
    • cchtTerm : Local handler is disabled, so the local handler is not called.

  • 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:

    1. Buffering of input stream.
    2. Echo option (see enum EchoOpt).
    3. Blocking vs. non-blocking read of input stream.
    4. Disable local break-key handler, if active.
    5. Set cursor style to terminal default.



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).


  • 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).

    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).


    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 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 see 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.

    See 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)
    

    Set text foreground color using the non-standard AIX extensions.

    The members of enum aeSeq recognized by this method are:
    aesAIXFG_B_BLACK aesAIXFG_B_BLUE
    aesAIXFG_B_RED aesAIXFG_B_MAGENTA
    aesAIXFG_B_GREEN aesAIXFG_B_CYAN
    aesAIXFG_B_BROWN aesAIXFG_B_GREY

    The AIX color attributes were defined by IBM to provide interoperability of the terminal interface between their proprietary systems 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.
    See Development and Testing for more information.


  • 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)
    

    Set text background color using the non-standard AIX extensions.

    The members of enum aeSeq recognized by this method are:
    aesAIXBG_B_BLACK aesAIXBG_B_BLUE
    aesAIXBG_B_RED aesAIXBG_B_MAGENTA
    aesAIXBG_B_GREEN aesAIXBG_B_CYAN
    aesAIXBG_B_BROWN aesAIXBG_B_GREY


  • 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.




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 the list of valid text modifiers in the description of the acResetMods method below.


  • 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.

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




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 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-positioninng 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.

    See 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 see 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 “gsettings” 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.




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.

    Note that the gString object which receives the data can hold up to gsMAXCHARS (1024) characters.

    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 See 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,
    (see acBufferedInput)
    2) The active input echo option,
    (see Soft Echo Options)
    3) Whether input is configured for blocking or non-blocking read.
    (see 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.


  • 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 see acBufferedInput for more information.

    See also acFlushStreams, below.




Output Methods

  • WinPos  acWrite ( WinPos wp, const gString& gsTxt, bool flush, bool newln ) const;
  • WinPos  acWrite ( short row, short col, const gString& gsTxt, bool flush, bool newln ) const;
  • WinPos  acWrite ( WinPos wp, const wchar_t* wTxt, bool flush, bool newln ) const;
  • WinPos  acWrite ( short row, short col, const wchar_t* wTxt, bool flush, bool newln ) const;
  • WinPos  acWrite ( WinPos wp, const char* cTxt, bool flush, bool newln ) const;
  • WinPos  acWrite ( WinPos wp, wchar_t wchar, bool flush, bool newln ) const;
  • WinPos  acWrite ( short row, short col, wchar_t wchar, bool flush, bool newln ) const;
  • WinPos  acWrite ( WinPos wp, char cbyte, bool flush, bool newln ) const;
  • WinPos  acWrite ( short row, short col, char cbyte, bool flush, bool newln ) 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, 'true' by default)
                       if 'true,   flush the output buffer before return
                       if 'false', do not flush the output buffer
    
               newln : (optional, 'true' by default)
                       if 'true',  a newline will cause the following line to
                                   begin on the same column as the previous line
                       if 'false', a newline will cause the following line to
                                   begin at column one (left edge of window)
    
      Returns: current cursor position (WinPos object)
    

    Write text data (or ANSI escape sequences) to stdout beginning at the specified cursor position. The final cursor position is at the end of the output. This is the return value.

    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 wide-character array, 3) a byte (char) array, or 4) as a single character or single byte.

    Note that the length of the source data is limited by the size of the gString object: gsMAXCHARS (wchar_t characters), or gsMAXBYTES (bytes). For longer text strings, call the ttyWrite method which can handle arbitrary data length.

    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 DOES NOT check whether a line has automatically wrapped at the right edge of the terminal window. If a line wrap occurs, then the returned cursor position may be incorrect.

    Note also that this method will not cause displayed data to scroll upward when the bottom row of the window is reached. If scrolling is desired, then call the 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 see acSetStreamWidth, or the W option command-line option for more information on stream configuration.


  • void  ttyWrite ( const gString& gsTxt, bool flush ) const;
  • void  ttyWrite ( const wchar_t* wTxt, bool flush ) const;
  • void  ttyWrite ( wchar_t wchar, bool flush ) const;
  • void  ttyWrite ( const char* cTxt, bool flush ) const;
  • void  ttyWrite ( char cbyte, bool flush ) 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
                  wchar : a single wchar_t (wide) 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
    
      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 wide-character array, 3) a byte (char) array, or 4) as a single character or single byte.

    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 see acSetStreamWidth, or the 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 acWrite and 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 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 acFlushIn and 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.




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, acClearArea.




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 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: (see 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.

    See acDrawBox and acDrawLine methods for line drawing options.




API Methods

  • bool AnsiCmd::acSetAttributes ( acAttr newAttr, bool resetAll );
      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 See 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 );
      See 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 )
      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 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 acaExpand class data members for more information.


  • void acClearScreen ( wchar_t fillchar, acAttr fillattr );
      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, acAttr fillattr );
  • bool acClearArea ( WinPos wpOrig, short height, short width, wchar_t fillchar, acAttr fillattr );
      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.
    See 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 cursor offsets regarding 1-based vs. 0-based cursor positioning.


  • WinPos acDrawLine ( const WinPos& wpOrig, short length, bool vertical, LineType lType, wchar_t begChar, wchar_t endChar );
      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, const char *text );
      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.
    See 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 );
      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.
      1. Text will be written using the foreground and background attributes specified for the interior.
      2. 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.

    Technical Note on the acAttr Enumerated Type

    The acAttr (AnsiCmd Attributes) enumerated type provides application-level color-attribute and text-modifier configuration for terminal applications.

    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 AnsiCmdWin.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 see 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.

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

    acAttr modify ( acAttr acaValue, bool add, uint8_t webRGB = 0 ) ;
    Add (or remove) one or more elements to (from) the bitfield value.
    'acaValue' specifies the item(s) to be modified.
    'add' if true, add the ’acaValue’ items to the existing bitfield
    if false, remove (reset the specified items
    'webRGB' for R/G/B items only, this specifies the web-safe index

    void update ( aeSeq aesValue, uint8_t colorIndx = ZERO );
    Update attribute tracking data using a member of enum aeSeq.
    'aesValue' aeSeq item specifying attribute to be updated
    'colorIndx' for aeSeq items requiring a color-attribute index value

    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.
    See also the API-level method acComposeAttributes which calls this method with consistent formatting.

    aeSeq bits2aeseq ( acAttr acaBits, uint8_t byteIndx, bool isFgnd, bool isRgb );
    Convert between acAttr (bitfield) and aeSeq (ANSI escape sequence).
    'acaBits' acAttr bitfields to be converted
    'byteIndx' byte index value (either foreground or background index)
    '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.

    acAttr aeseq2bits ( aeSeq aesCmd, bool& setFlag );
    Convert between aeSeq (ANSI escape sequence) and acAttr (bitfield).
    'aesCmd' member of enum aeSeq to be converted
    'setFlag' (by reference) receives the state of the internal
    set/reset flag associated with the attribute

    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



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. See 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.




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() *



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 (see skForm Class), or both direct display and user interface fields. This table lists the public methods of the ACWin class.

 Method Name Description
 ACWin constructor Constructors
 ACWin destructor Destructor
 OpenWindow Open the window (make it visible)
 CloseWindow Close the window
 RefreshWin Redraw the window
 HideWin Erase window from display
 MoveWin Move window to another position
 ClearWin Erase interior of window
 ClearRow Erase specified interior row
 SetFieldText Replace text in specified field
 GetFieldText Get a copy of text in field
 ClearField Delete text in specified field
 SetFieldIP Position visible cursor in field
 RefreshField Redraw text in a field
 SetFieldAttr Set color attributes for a field
 SetInputFocus Set input focus to a field
 Focus2NextField Move input focus to next field
 Focus2PrevField Move input focus to prev field
 InsertKey Configure the Insert key
 EditForm User edit of skForm object
 EditField User edit of skField object
 SetTitle Specify window title text
 SetTextAttr Specify window interior colors
 SetBorderAttr Specify window border colors
 Write Write directly to window interior
 GetCursorPos Get cursor position in the window
 SetCursorPos Set cursor position in the window
 Write (field) Write text into a field
 DrawBox Draw a rectangle in text area
 DrawLine Draw a line in the window
 FieldOutline Draw a border around a field


  • 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.

    Notes:

    1. '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).
    2. 'winHeight' and 'winWidth' specify the number of rows and columns, respectively defining the dimensions of the window, including the border.
    3. '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.
    4. 'txtAttrib' defines the color attributes for the window interior, and accepts all foreground/background color attributes and text modifiers.
    5. '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.
    6. 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 see skForm Sample, below for more information.

  • ~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.


  • 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 data from 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. (see 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 text stored in the skForm object (if any) will be displayed.


  • 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.

    Data in the skForm object (if any) will be retained; however, any text previously written directly into the window interior will be lost.

    To make the window visible again, call 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' if specified position would place any part of the window
                       outside the visible area of the terminal display.
    

    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.

    Data in the skForm object (if any) will be redrawn as part of the move; however, any text previously written directly into the window interior will be lost. (see 'newText' parameter)

    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 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 ClearField method instead.


  • bool SetFieldText ( short fIndx, const gString& gsTxt );
      Input  : fIndx   : index of target field within the skForm object
               gsTxt : (by reference) new text data for field
    
      Returns: 'true'  if successful
               'false' if invalid field index specified
    

    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.


  • bool GetFieldText ( short fIndx, gString& gsTxt ) const;
      Input  : fIndx   : index of target field within the skForm object
               gsTxt : (by reference) receives a copy of field text
    
      Returns: 'true'  if successful
                       gsTxt contains field text data
               'false' if invalid field index specified
                       gsTxt cleared to empty string
    

    Get a copy of the current contents of the field.


  • bool ClearField ( short fIndx, acAttr txtAttr = acaUSEDFLT );
      Input  : fIndx   : index of target field
               txtAttr : (optional, acaUSEDFLT by default)
                         new color attributes for the target field
                         (logical OR of forground and background color)
                         (attributes and attribute modifiers          )
    
      Returns: 'true'  if target field cleared
               'false; if fldIndex out-of-range (data not modified)
    

    Erase text from the specified text field. The stored text is deleted, and the display area of the field is cleared.


  • bool SetFieldIP ( short fIndx, short newIp );
      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.
                         (A safe end-of-text value is: gsMAXCHARS.)
    
      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.

    If 'fIndx' references the field which has input focus, the visible cursor will also be updated.

    Special case: If 'newIp' is greater that the number of characters in the field, IP will be set to end-of-text (over the null terminator).


  • void RefreshField ( short fIndx );
      Input  : fIndx: index of target text field
                      If fIndx >= total of fields defined (fCnt),
                      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.


  • void RefreshField ( void );
      Input  : none
    
      Returns: nothing
    

    Refresh (erase and redraw) the contents of the field which has input focus.


  • 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
    
      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.


  • 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).


  • wchar_t EditForm ( wchar_t exitChar, short& focusFld );
      Input  : exitChar : when this character is received, return to caller
               focusFld : (by reference) receives the index of the field with
                          input focus on return to caller.
    
      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 See 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: skForm Class and skField Class.


  • wchar_t EditField ( short& fIndx, wchar_t exitChar = L’\n’, bool allChar = false );
      Input  : fIndx   : (by reference) index of target field
                         On entry, specifies the field to be edited.
                         On return, index of field with input focus.
               exitChar: (optional, NEWLINE '\n' by default)
                         This character terminates the input loop.
               allChar : (optional, 'false' by default)
                         if 'false', 'exitChar' controls the loop
                         if 'true',  return to caller after each
                                     iteration of the loop
      Returns: last keycode captured
    

    Interactively edit the text within the target field.

    Keyboard input is captured, formatted and written into the fields. Certain “special keys” are defined for navigating within the field or for signalling the move to a different field. These keycodes are discussed in the chapter on terminal configuration.
    Please See Soft Echo Options for more information.

    A technical description of the skField class as well as a discussion of user interaction with these objects can be found at: skField Class.


  • 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.


  • 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 );
      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
               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.

    To write text into one of the input fields within the window, csee Write (field) below.


  • 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.


  • short Write ( short fIndx, const wchar_t* txtData, short offset, bool clear, acAttr txtAttr );
  • short Write ( short fIndx, const gString& txtData, short offset, bool clear, acAttr txtAttr );
  • short Write ( short fIndx, const char* txtData, short offset, bool clear, acAttr txtAttr );
      Input  : fIndx  : index of target field
               txt    : text to write in one of the following formats:
                        -- gString object by reference
                        -- wchar_t pointer
                        -- char pointer
               offset : (optional, -1 by default, indicating that the current
                         insertion point 'ip' should be used)
                        character offset into existing text at which to insert
                        the new text
               clear  : (optional, 'false' by default)
                        if 'false', new text will be added to the existing text
                                    as described
                        if 'true',  new text will replace the existing text
               txtAttr: (optional, acaPLAINTEXT i.e. zero by default)
                        (existing text attributes will be used)
                        If specified, text attributes and text modifiers
    
      Returns: current insertion point ('ip'), that is, the character offset at
               which the cursor is positioned. This will be at the point following
               the inserted text, or at the last character cell of the field.
               (or zero if invalid field index specified)
    

    Write text to the specified field within the window.

    This group of methods inserts the specified text into the existing text of the target field at the specified offset ('ip'); or if the 'clear' flag is set, replaces the existing text. The field is then redrawn to display the updated data.


  • bool DrawBox ( WinPos wpOrig, short height, short width, LineType lType, acAttr bxAttr );
      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.
    
      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 ├────────╥───┐ ───┼──────────────────────────────────────╫─── │ ├──────────────────────┤ ║ │ ╠════════════════════════╣ ║ ═══╪══════════════════════════════════════╬═══ │ ┬ ╔════════════════════════╗ ╦ ║ │ │ ║ ║ ────────────────── │ ║ ║ ║ │ │ ║ ║ ══════════════════ │ ║ ║ ║ │ ┴ ╚════════════════════════╝ ╩ ║ └───┴──────────────────────────────────────╨───┘

  • bool FieldOutline ( 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 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 DrawBox method described above.

    Note: Potential incursion into the border is range checked; however, potential incursion into other fields is not tested. Beware!



Sample initialization of an skForm object:

Some developers will want to write directly into the window, while others will want to design an array of text-input fields for user interactions which are defined by Some Kind of Form i.e. the skForm class.

If the ACWin constructor is called without specifying an skForm object, a default skForm object is created based on the size of the window. If the window is small (less than 1,000 character cells), then the skForm object is created with one(1) skField. Else, the skForm will generate an array of skField objects, one per row of the window interior.

To achieve direct control over the way the skForm object is configured, a pointer to an skForm template object (’formDef’)is passed to the ACWin constructor.

The position and dimensions of each field must fall entirely within the text area of the window, and the fields may not overlap. Although range checking and automatic adjustments of these fields is performed, an over-caffinated developer could still cause chaos, so it is important to carefully verify the parameters which define the individual fields.

There are several ACWin objects created in the test code included with this library. 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 objects below (see skForm Class).

To create an skForm template, allocate a new object specifying the number of fields and the row/column offset from the upper left corner of the window interior to the upper left corner of the target area for the form.
Here we define an skForm object with two(2) fields with the form origin at offset 0,0. This is the upper left corner of the window interior space.

skForm *skfPtr = new skForm( 2, 0, 0 ) ;

┌───────┤ ACWin-class Window ├───────┐ Some text for field 0. Some text for field 1. └────────────────────────────────────┘

Initialize the FORM-LEVEL members. Note that ’fCnt’ (the number of elements in the array) is initialized during instantiation, and must not be changed. Also, the ’base’ value (offset) is overridden by the ACWin initialization.

skfPtr->ins = false ; // insert/overstrike flag
skfPtr->insc = false ; // cursor shape for insert/overstrike
skfPtr->togg = true ; // insert/overstrike lock
skfPtr->beep = true ; // make noise if invalid user input
skfPtr->fi = ZERO ; // initial field index

Initialize the FIELD-LEVEL members:
WinPos wpul(1,1) ;
short f = ZERO ;
skfPtr->fld[f].orig = wpul ; // origin (row/column offset) for field
skfPtr->fld[f].hgt = 1 ; // field height
skfPtr->fld[f].wid = winWIDTH - 4 ; // width of field
skfPtr->fld[f].ip = ZERO ; // text insertion point (offset into field)
skfPtr->fld[f].txt = "Some text for field 0." ;

wpul.row += 2 ; // position of next field==two rows below
++f ;

skfPtr->fld[f].orig = wpul ;
skfPtr->fld[f].hgt = 1 ;
skfPtr->fld[f].wid = winWIDTH - 4 ;
skfPtr->fld[f].ip = 5 ;
skfPtr->fld[f].txt = "Some text for field 1." ;

  • Note that the 'cur' member (physical cursor position) is dynamically calculated from the 'ip' (insertion point).
  • The 'aca' member (color attributes) is the logical OR of enum acAttr values. If not specified, the field colors will be the same as the colors of the window interior.
  • The 'insc' flag (change cursor style when insert/overstrike toggled) defaults to 'false'.
  • The 'icur' and 'ocur' members (cursor styles for Insert and Overstrike modes) default to 'csBblock' and 'csBuline', respectively, and are ignored when the 'insc' flag is reset.
  • The 'ro' (read-only) flag defaults to 'false'.
  • The 'off' (text positioning) member is defined for future development and is currently ignored.

The initialized skForm template is then passed as a parameter for the ACWin constructor.

User Interaction - the skForm class and skField class

Initialization of an skForm object as a parameter for creating a dialog window is shown above.

Accessing the form provides a user interface, either by editing the contents of the form as a whole EditForm, or by editing individual fields within the form EditField.

After the ACWin object has been created, and the window has been opened, The selected edit method is called to give the user access to the field(s).

Example of calling the EditForm method. This is a simplified version of the sequence used in the Test_Form test method.

  //* 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) *
  wpos = winPtr->OpenWindow ( " Edit the fields as desired." ) ;

  //* Configure the functionality of the "special" Insert key *
  winPtr->InsertKey ( true, true, true ) ;

  //* Get User Input *
  winPtr->EditForm ( NEWLINE, fldIndx ) ;

  //* Close the window and delete the object.*
  winPtr->CloseWindow () ;
  delete winPtr ;

Example of calling the EditField method in a loop:
In this example, EditField returns to caller after each keystroke so that the application can closely monitor user input. This is done by setting the 'allChar' flag as the third parameter for the call to EditField.
The loop terminates when the user presses the Enter key ('\n').

   while ( (wkey = winPtr->EditField ( fIndx, NEWLINE, true )) != NEWLINE )
   {
      //* Update Insert/Overstrike report *
      if ( skfp->ins != insFlag )
      {
         winPtr->Write ( wpIns, (skfp->ins ? L"<INS>" : L"<OVR>"), 
                         (skfp->ins ? acAttr(acaFG_GREEN | acaBG_DFLT) : 
                                      acAttr(acaFG_BLUE  | acaBG_DFLT)) ) ;
         insFlag = skfp->ins ;
      }
   
      //* Report the data members of each field *
      this->tseReport ( *skfp, wpRpt ) ;
      winPtr->RefreshField ( skfPtr->fi ) ;
   }

This loop is used in the "softEchoA" section of the Test_SoftEcho test method. Invoke the test to see this loop in action:
epts --ansi=Tea


--- --- --- --- ---
Note that it is possible to create a stand-alone skForm object outside the dialog window; however, doing so would require a deeper knowledge of the user-interface mechanics than most applications would need to have. Therefore, it is recommended that the windowed version of the skForm always be used. Note also that 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.




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 see Build Options for more information on conditional compilation options.

Each test may be invoked through a command line option. Please see 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. 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 );
         See Invoking - AnsiCmd Tests

    This method is called from the application layer by the public method: 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 );
         See test C (f) invocation option.
  • void Test_Bg ( void );
         See test C (b) invocation option.
  • void Test_8bitColor ( void );
         See test C (t) invocation option.
  • void Test_RGB ( wchar_t rgbTest );
         See test C (r) invocation option.
  • void Test_Greyscale ( void );
         See test C (g) invocation option.
  • void Test_AixFgBg ( void );
         See test C (a) invocation option.
  • void Test_acaExpand ( void );
         See test C (d) invocation option.
  • void Test_AltFonts ( aeSeq fg );
         See test F invocation option.
  • void Test_CursorPos ( aeSeq fg );
         See test P invocation option.
  • void Test_Erasures ( aeSeq fg );
         See test E invocation option.
  • void Test_AsciiCodes ( aeSeq fg );
         See test A invocation option.
  • void Test_Ideogram ( aeSeq fg );
         See test I invocation option.
  • void Test_UnbufferedInput ( aeSeq fg );
         See test T (i) invocation option.
  • void Test_TermFlags ( aeSeq fg );
         See test T (t) invocation option.
  • void Test_ModFlags ( aeSeq fg );
         See test T (m) invocation option.
  • void Test_NonBlock ( aeSeq fg );
         See test T (b) invocation option.
  • void Test_SoftEcho ( wchar_t eOpt, aeSeq fg );
         See test T (e) invocation option.
  • void Test_Window ( aeSeq fg );
         See test W (w) invocation option.
  • void Test_Form ( aeSeq fg );
         See test W (f) invocation option.
  • void Test_WinDefault ( aeSeq fg );
         See test W (d) invocation option.
  • void Test_Box ( aeSeq fg );
         See test W (b) invocation option.
  • void Test_Sandbox ( wchar_t parmA, wchar_t parmB );
         See 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() *
    



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 4.8.0 (C++11) and above,
    (Support for C++17 or greater recommended (g++ version 7 and above)).

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

Build Options

Conditional compilation directives control the build options, both for the AnsiCmd class library and the EarthPoints application.

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.

The two directives which are integral to the AnsiCmd design are the DEBUG_ANSICMD and DEBUG_LOG directives. Some, or all of the other directives and the code they control may be removed when the code has become more stable.

The names of all the conditional compile directives are very intentionally formatted in the same way. (This is a hint, dear student. :-)
To see all debugging directives in the code use the grep utility:
grep -n '[#]define DEBUG_' *.[hc]pp
Please see 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.

    As distributed, the package should have DEBUG_ANSICMD enabled, and all other debugging directives disabled. To test this, after unpacking the archive, use the 'grep' utility to test this:
    grep -n '#define DEBUG_' *.[hc]pp | grep '[(]1[)]'
    (This is why OCD is not really a “disorder” at all. :-)

  2. 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

  3. DEBUG_CURPOS
  4. 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 command 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.

  5. DEBUG_SOFTKEY
    This directive is defined within the decodeSpecialKey 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.

  6. 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.

  7. DEBUG_skpInterRow
  8. DEBUG_skpDeleteChar
    These directives report intermediate processing of the “special” keycodes.
  9. DEBUG_normalkeyProc
    This directive reports intermediate processing of the “normal” (graphing) keycodes.
  10. DEBUG_wpos2tpos
    This directive is located in the wpos2tpos method which converts window-relative coordinates to terminal-relative coordinates. (currently unused)
  11. 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.
  12. DEBUG_TERMSETUP
  13. DEBUG_TS_PAUSE
    These directives are defined in the ansicmdSetup method which parses command-line arguments related to terminal configuration.
  14. DEBUG_EOTOFF
  15. 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.
  16. 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.

  17. DEBUG_TestWindow
    This directive is defined within the Test_Window method, in the AnsiCmdTest.cpp module. (currently unused)
  18. DEBUG_decode
  19. DEBUG_update
  20. DEBUG_modify
  21. DEBUG_compose
    This group of directives manages debugging information for the acaExpand class which is used to encode, decode and apply color-attribute data.

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.04 Copyright(c) 2022-2023 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.



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.


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:
http://library.gnome.org/devel/glibmm/unstable/classGlib_1_1ustring.html

’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.




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] see gString Instantiation
 ~gString [destructor] 
 operator= see Assignment Operators
  
 compose see Formatted Assignments
  
 formatInt see Integer Formatting
  
 gstr see Data Access
 ustr 
  
 copy see Copying Data
 operator<< 
 substr 
  
 append see Modifying Existing Data
 insert 
 limitChars 
 limitCols 
 shiftChars 
 shiftCols 
 padCols 
 strip 
 erase 
 replace 
 loadChars 
 textReverse 
  
 compare see Comparisons
 operator== 
 operator!= 
 find 
 findlast 
 after 
 findx 
 scan 
  
 gscanf see Extract Formatted Data
  
 gschars see Statistical Info
 gscols 
 utfbytes 
 isASCII 
  
 clear see gString Miscellaneous
 Get_gString_Version 
 dbMsg 



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 ( const char* usrc, short charLimit=gsMAXCHARS ) ;
      Input  :
         usrc      : pointer to a UTF-8-encoded, null-terminated string
         charLimit : (optional, gsMAXCHARS by default)
                     maximum number of characters from source array to 
                     convert
      Returns:
         nothing
    

    Constructor: Convert specified UTF-8-encoded source to gString.


  • gString ( const wchar_t* wsrc, short charLimit=gsMAXCHARS ) ;
      Input  :
         wsrc      : pointer to a wchar_t-encoded, null-terminated string
         charLimit : (optional, gsMAXCHARS 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 see 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 (see 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 ( const gsForm& gsf, short charLimit=gsMAXCHARS ) ;
      Input  :
         gsf       : initialized gsForm class object containing parameters 
                     for creating a formatted text string.
         charLimit : (optional, gsMAXCHARS by default)
                     maximum number of characters from source array to 
                     convert
      Returns:
         nothing
    

    DEPRECATED: May be removed in a future release.
    This method seemed like a good idea back in 2011, but neither we, nor our beta testers have ever had a desire to use it.

    Constructor: Convert formatting instructions in gsForm class object to gString. See compose() for more information.


  • ~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
    



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 ) ;
      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.

  • void operator = ( const gsForm& gsf ) ;
      Input  :
         gsf   : an initialized gsForm object (by reference)
      Returns:
         nothing
    

    DEPRECATED: May be removed in a future release.
    Assignment operator: Converts gsForm-class instructions to gString.

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.



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: see 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.




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: see 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.




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 ( short& 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 ( short& charCount, short& 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

short 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 ) ;



Copying Data

  • short copy ( char* uTarget, short maxBytes,
       short maxCols=(gsMAXCHARS*2) ) 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 == gsMAXCHARS*2)
                    maximum number of display-columns to copy
      Returns:
         number of bytes copied (incl. NULL terminator)
    

    Copy gString text to specified target buffer.


  • short copy ( wchar_t* wTarget, short maxChars,
       short maxCols=(gsMAXCHARS*2) ) 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 == gsMAXCHARS*2)
                    maximum number of display-columns to copy
      Returns:
         number of characters copied (incl. NULL terminator)
    

    Copy gString text to specified target buffer.


  • 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.

  • short substr ( char* uTarget, short offset, short charCnt ) const ;
  • short substr ( wchar_t* wTarget, short offset, short charCnt ) const ;
  • short substr ( gString& wTarget, short offset, short 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.
                   IMPORTANT NOTE: It is the caller's responsibility to 
                   specify a target buffer large enough to hold the data.
                   Recommended: wchar_t wbuff[gsMAXCHARS]; or 
                                char ubuff[gsMAXBYTES];
                   -- If target buffer is a gString object, then both 
                      UTF-8 and wchar_t data are returned 
                      (with no chance of target buffer overflow).
    
         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.

    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 ’ncdialogapi’ documentation.


Examples

gString gs( "That's not flying, that's falling -- with style!\n"
            "Buzz Lightyear" ) ;
char utf8Data[gsMAXBYTES] ;
wchar_t wideData[gsMAXCHARS] ;

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 ;
short b = AusAnimal.find( " c" ) ;
if ( b >= 0 )
{
   short e = AusAnimal.find( L' ', b + 1 ) ;
   if ( e > b )
   {
      AusAnimal.substr( gsc, (b + 1), (e - b - 1) ) ;
      wcout << gsc << endl ;
   }
}
 - - -> Cockatoo



Modifying Existing Data

  • short append ( const wchar_t* wPtr ) ;
  • short append ( const char* uPtr ) ;
  • short 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 gsMAXCHARS, then 
               some data MAY HAVE BEEN discarded.
    

    Append text to existing gString text data up to a combined length of gsMAXCHARS. 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.
    


  • short append ( const wchar_t* fmt, const void* arg1, ... )
                   __attribute__ ((format (gnu_wprintf, 2, 0)));

  • short 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 gsMAXCHARS, then
               some data MAY HAVE BEEN discarded.
    

    Append formatted text data to existing gString text data up to a combined length of gsMAXCHARS. Characters in excess of the maxmum will not be appended.

    Please refer to the ’compose’ method (see 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.
    


  • short insert ( const wchar_t* wPtr, short offset = 0 ) ;
  • short insert ( const char* uPtr, short offset = 0 ) ;
  • short insert ( wchar_t wChar, short 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 gsMAXCHARS, then 
               some data MAY HAVE BEEN discarded.
    

    Insert text into existing gString text data up to a combined length of gsMAXCHARS. 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!
    


  • short limitChars ( short charCount ) ;
      Input  :
         charCount : maximum number of characters allowed in formatted data 
                     (not including NULL) Range: 1 to gsMAXCHARS-1
      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.
    


  • short limitCols ( short colCount ) ;
      Input  :
         colCount : maximum number of display columns allowed in formatted data
                    Range: 1 to (gsMAXCHARS * 2)
      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.
    


  • short shiftChars ( short 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' ').
    


  • short shiftCols ( short 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.
    


  • short padCols ( short 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 (gsMAXCHARS).

    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."
    


  • short 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’.



  • short erase ( const gString& src,
                  short offset = 0, bool casesen = false );

  • short erase ( const wchar_t* src,
                  short offset = 0, bool casesen = false );

  • short erase ( const char* src,
                  short offset = 0, bool casesen = false );

  • short erase ( const wchar_t src,
                  short offset = 0, bool casesen = false );
      Input  :
         src    : source data to be matched, one of the following:
                  -- pointer to a UTF-8 string (max length==gsMAXBYTES)
                  -- pointer to a wchar_t string (max length==gsMAXCHARS)
                  -- 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
                  The way upper/lowercase are related is locale dependent;
    
      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.

    Actual comparison is always performed against the ’wide’ character array using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included in the comparison. These comparisons ARE locale dependent.



  • short erase ( short offset = 0, short length = gsMAXCHARS ) ;
      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, gsMAXCHARS 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.
    • Programmer’s Note:
      Stubs with 'int' arguments are also defined, but are included only to silence a compiler warning that the prototype erase(short, short); is ’ambiguous’. Actually, it is not ambiguous at all, but we believe that the use of pragmas is bad design, so it’s easier to include the stubs than to argue with the compiler. Internally, gString uses ’short int’ exclusively.

    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!" );
    short 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 " );
    short index = gs1.find( "the the" );
    gs1.erase( index, (gs2.gschars() - 1) );
    
    Yields:
      "There are seven candidates in the Primary Election."
    


  • short replace ( const wchar_t* src, const wchar_t* newtxt,
                    short offset = 0,
                    bool casesen = false, bool all = false );

  • short replace ( const wchar_t* src, const char* newtxt,
                    short offset = 0,
                    bool casesen = false, bool all = false );

  • short replace ( const wchar_t* src, const wchar_t newtxt,
                    short offset = 0,
                    bool casesen = false, bool all = false );

  • short replace ( const char* src, const wchar_t* newtxt,
                    short offset = 0,
                    bool casesen = false, bool all = false );

  • short replace ( const char* src, const char* newtxt,
                    short offset = 0,
                    bool casesen = false, bool all = false );

  • short replace ( const char* src, const wchar_t newtxt,
                    short offset = 0,
                    bool casesen = false, bool all = false );

  • short replace ( const wchar_t src, const wchar_t* newtxt,
                    short offset = 0,
                    bool casesen = false, bool all = false );

  • short replace ( const wchar_t src, const char* newtxt,
                    short offset = 0,
                    bool casesen = false, bool all = false );

  • short replace ( const wchar_t src, const wchar_t newtxt,
                    short 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
                  The way upper/lowercase are related is locale dependent;
         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 (>gsMAXCHARS)
    

    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. These comparisons ARE locale dependent.

    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."
    
    short 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."
    


  • short loadChars ( const wchar_t* wsrc, short charLimit,
                      bool append = false );

  • short loadChars ( const char* usrc, short 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.
    See 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 gsMAXCHARS.
                    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,"
    


  • short 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 >= gsMAXCHARS, 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.




Comparisons

  • short compare ( const char* uStr, bool casesen = true,
                    short length = gsMAXCHARS, short offset = 0 ) const ;

  • short compare ( const wchar_t* wStr, bool casesen = true,
                    short length = gsMAXCHARS, short offset = 0 ) const ;
      Input  :
         uStr     : (UTF-8 string) to be compared
           OR
         wStr     : (wchar_t string) to be compared
         casesen  : (optional, 'true' by default)
                    if 'true' perform case-sensitive comparison
                    if 'false' perform case-insensitive comparison
         length   : (optional, gsMAXCHARS 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 object’s wchar_t character array. The relationship between upper-case and lower-case characters is locale dependent.



  • short 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 relationship between upper-case and lower-case characters is locale dependent.



  • 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 is case-sensitive.



  • short find ( const char* src, short offset=0,
                 bool casesen=false, short maxcmp= -1 ) const ;
  • short find ( const wchar_t* src, short offset=0,
                 bool casesen=false, short maxcmp= -1 ) const ;
  • short find ( const gString& src, short offset=0,
                 bool casesen=false, short maxcmp= -1 ) const ;
  • short find ( const wchar_t src, short offset=0,
                 bool casesen=false ) const ;
      Input  :
         src    : source data to be matched, one of the following:
                  -- pointer to a UTF-8 string (max length==gsMAXBYTES)
                  -- pointer to a wchar_t string (max length==gsMAXCHARS)
                  -- 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
                  The way upper/lowercase are related is locale dependent;
         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. These comparisons ARE locale dependent.


  • short findlast ( const char* src, bool casesen=false ) const ;
  • short findlast ( const wchar_t* src, bool casesen=false ) const ;
  • short findlast ( const gString& src, bool casesen=false ) const ;
  • short 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 (max length==gsMAXBYTES)
                  -- pointer to a wchar_t string (max length==gsMAXCHARS)
                  -- 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
                  The way upper/lowercase are related is locale dependent;
    
      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. These comparisons ARE locale dependent.


  • short after ( const char* src, short offset=0,
                  bool casesen=false ) const ;
  • short after ( const wchar_t* src, short offset=0,
                  bool casesen=false ) const ;
  • short after ( const gString& src, short offset=0,
                  bool casesen=false ) const ;
      Input  :
         src    : source data to be matched, one of the following:
                  -- pointer to a UTF-8 string (max length==gsMAXBYTES)
                  -- pointer to a wchar_t string (max length==gsMAXCHARS)
                  -- 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
                  The way upper/lowercase are related is locale dependent;
      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.


  • short findx ( wchar_t srcChar = L' ', short 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.


  • short scan ( short 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
short result = str1.compare( "Toys for Tots" ) ;

// compare with wchar_t string
short 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)
short 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." ) ;
short 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.




Extract Formatted Data

  • short gscanf ( const wchar_t* fmt, ... ) const ;
  • short 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 :-)



  • short gscanf ( short offset, const wchar_t* fmt, ... ) const ;
  • short gscanf ( short 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

    short 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" ) ;
    short cnt = 
       gs.gscanf( L"%hd %% %hd %hd %hd %X %lld %lf %63[^-] %c %16s %16s", 
                  &sval1, &sval2, &sval3, &sval4, &ival, &llval, 
                  &dval, str1, &ch1, str2, str3 ) ;
    
    gString gsOut( "items    : %hd\n"
                   "numeric  : %hd  %hd  %hd  %hd  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[gsMAXCHARS] ;
    gs = "Useless garbage: 17 21 34" ;
    
    gs.gscanf( L"%16C %hd %hd %hd", junk, &sval1, &svan2, &sval3 ) ;
      _or_
    gs.gscanf ( 16, L"%hd %hd %hd", &sval1, &svan2, &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]



Statistical Info

  • short 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.



  • short 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.



  • short 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 ;
          short 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.




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. The character and byte counts are set to 1 (one), and the column count is zero.



  • 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 ) ;
      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 ENABLE_GS_DEBUG flag is set in gString.hpp.




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[gsMAXCHARS] ;
    
    gString gs( some_UTF-8_data ) ;
    gs.copy( some_wide_data, gsMAXCHARS ) ;
    
  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[gsMAXBYTES] ;
    
    gString gs( some_wide_data ) ;
    gs.copy( some_UTF-8_data, gsMAXBYTES ) ;
    
  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, short lineCount )
    {
       short 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 one. To see it in action, please refer to the ’Dialogw’ NcDialog API Test Application, test seven (7). For a more sophisticated example, see the ’DialogTextbox::mlFmtDisplay’ automatic word-wrapping method in the NcDialog API source code.








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 application, 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.





Index

Jump to:   0  
A   B   C   D   E   F   G   H   I   L   M   N   O   P   R   S   T   V   W  
Index Entry  Section

0
01.0.00 Introduction: Introduction
02.0.00 Invoking: Invoking
02.1.00 Invoking - Terminal Setup: Invoking - Terminal Setup
02.2.00 Invoking - AnsiCmd Tests: Invoking - AnsiCmd Tests
02.3.00 Invoking - EarthPoints: Invoking - EarthPoints
03.0.00 AnsiCmd Library: AnsiCmd Library
03.1.00 Introductory Notes: Introductory Notes
03.2.00 ANSI Escape Sequences: ANSI Escape Sequences
03.3.00 Terminal Configuration: Terminal Configuration
03.4.00 AnsiCmd Class Methods: AnsiCmd Class Methods
03.4.01 Table of Public Methods: Table of Public Methods
03.4.02 Configuration Methods: Configuration Methods
03.4.03 Color Attributes: Color Attributes
03.4.04 Text Modifiers: Text Modifiers
03.4.05 Cursor Positioning: Cursor Positioning
03.4.06 Input Methods: Input Methods
03.4.07 Output Methods: Output Methods
03.4.08 Text Erase: Text Erase
03.4.09 Misc Methods: Misc Methods
03.4.10 API Methods: API Methods
03.4.11 Coding Example: Coding Example
03.4.11 Development Support: Development Support
04.0.00 ACWin Class: ACWin Class
05.0.00: Development and Testing
06.0.00 Building from Source: Building from Source
07 gString Text Tool: gString Text Tool
07.01 Introduction to gString: Introduction to gString
07.02 gString Public Methods: gString Public Methods
07.03 gString Instantiation: gString Instantiation
07.04 Assignment Operators: Assignment Operators
07.05 Formatted Assignments: Formatted Assignments
07.06 Integer Formatting: Integer Formatting
07.07 Data Access: Data Access
07.08 Copying Data: Copying Data
07.09 Modifying Existing Data: Modifying Existing Data
07.10 Comparisons: Comparisons
07.11 Extract Formatted Data: Extract Formatted Data
07.12 Statistical Info: Statistical Info
07.13 gString Miscellaneous: gString Miscellaneous
07.14 gString Examples: gString Examples
08.0.00 Technical Support: Technical Support
09.0.00 Copyright Notice: Copyright Notice
09.1.00 GNU General Public License: GNU General Public License
09.2.00 GNU Free Documentation License: GNU Free Documentation License

A
A option: Invoking - Terminal Setup
acaExpand class: API Methods
acAttr, enum: API Methods
acBeep: Misc Methods
acBlockingInput: Configuration Methods
acBoxClear: API Methods
acBoxDraw: API Methods
acBoxErase: API Methods
acBufferedInput: Configuration Methods
acCaptureBreakSignal: Configuration Methods
acClearArea: API Methods
acClearScreen: API Methods
acComposeAttributes: API Methods
acDrawBox: API Methods
acDrawLine: API Methods
acEchoOption: Configuration Methods
acEraseArea: Text Erase
acEraseBox: API Methods
acFlushIn: Input Methods
acFlushOut: Output Methods
acFlushStreams: Output Methods
acFullReset: Text Modifiers
acGetAttributes: API Methods
acGetCursor: Cursor Positioning
acGetLocale: Configuration Methods
acGetTermDimensions: Configuration Methods
acGetTermInfo: Configuration Methods
acGetTermSize: Configuration Methods
acRead: Input Methods
acReset: Color Attributes
acResetMods: Text Modifiers
acRestoreTermInfo: Configuration Methods
acSet8bitBg: Color Attributes
acSet8bitFg: Color Attributes
acSetAixBg: Color Attributes
acSetAixFg: Color Attributes
acSetAttributes: API Methods
acSetBg: Color Attributes
acSetCursor: Cursor Positioning
acSetCursorStyle: Cursor Positioning
acSetFg: Color Attributes
acSetFgBg: Color Attributes
acSetFont: Misc Methods
acSetGreyscaleBg: Color Attributes
acSetGreyscaleFg: Color Attributes
acSetIdeogram: Misc Methods
acSetLocale: Configuration Methods
acSetMod: Text Modifiers
acSetRgbBg: Color Attributes
acSetRgbFg: Color Attributes
acSetStreamWidth: Configuration Methods
acSetWebBg: Color Attributes
acSetWebFg: Color Attributes
acVersion: Misc Methods
ACWin derived class: ACWin Class
acWrite: Output Methods
AC_Box Class: API Methods
aeSeq enumerated type: ANSI Escape Sequences
ANSI escape sequence: ANSI Escape Sequences
AnsiCmd constructor: Configuration Methods
AnsiCmd destructor: Configuration Methods
ansiTest: Development Support
ansiTest_Menu: Development and Testing
api methods: API Methods
application options: Invoking - EarthPoints
ascii test: Invoking - AnsiCmd Tests
attributes, color: Color Attributes

B
B option: Invoking - Terminal Setup
BiDi text: Modifying Existing Data
blink timeout: Invoking - Terminal Setup
blink timeout: Cursor Positioning
break signal: Terminal Configuration
breaksignalReceived: Configuration Methods
buffered input: Configuration Methods
buffering, input: Terminal Configuration
build options: Building from Source

C
C option: Invoking - Terminal Setup
chrono: Misc Methods
class, acaExpand: API Methods
class, ACWin: ACWin Class
class, AnsiCmd: AnsiCmd Class Methods
class, skField: ACWin Class
class, skForm: ACWin Class
class, TermConfig: Terminal Configuration
class, TermSet: Terminal Configuration
coa option: Invoking - EarthPoints
cob option: Invoking - EarthPoints
code example: Coding Example
color attributes: Color Attributes
color option: Invoking - EarthPoints
color test: Invoking - AnsiCmd Tests
command-line options: Invoking
compilation, conditional: Development and Testing
compile from source: Building from Source
conditional compilation: Development and Testing
configuration, terminal: Terminal Configuration
configuraton: Configuration Methods
contact info: Technical Support
Control_C: Terminal Configuration
convert option: Invoking - EarthPoints
cursor offsets: Cursor Positioning
cursor position: Cursor Positioning

D
database, GPS: Invoking - EarthPoints
derived class, ACWin: ACWin Class
documentation, installing: Building from Source
dump option: Invoking - EarthPoints

E
echo options: Terminal Configuration
enum acAttr: API Methods
erase, text: Text Erase
erasure test: Invoking - AnsiCmd Tests
example, coding: Coding Example

F
file option: Invoking - EarthPoints
fiUnits enumerated type: Integer Formatting
font test: Invoking - AnsiCmd Tests
formatInt field overflow: Integer Formatting
formula option: Invoking - EarthPoints

G
getDataMembers: Development Support
GPS database: Invoking - EarthPoints
gsettings, blink: Invoking - Terminal Setup
gString: gString Examples
gString methods: gString Public Methods
gString text conversion: gString Text Tool

H
help option: Invoking - EarthPoints
helpless option: Invoking - EarthPoints

I
i/o streams: Terminal Configuration
ideograph test: Invoking - AnsiCmd Tests
info database: Building from Source
input buffering: Terminal Configuration
input methods: Input Methods
input, buffered: Configuration Methods
invoking: Invoking
invoking, EarthPoints: Invoking - EarthPoints
invoking, term setup: Invoking - Terminal Setup
invoking, test options: Invoking - AnsiCmd Tests

L
L option: Invoking - Terminal Setup
list of methods: Table of Public Methods

M
method list: Table of Public Methods
methods, gString: gString Public Methods
misc methods: Misc Methods
modifiers, text: Text Modifiers
multi-threading: ANSI Escape Sequences

N
nanosleep: Misc Methods
nsleep: Misc Methods

O
offsets, cursor: Cursor Positioning
option, A: Invoking - Terminal Setup
option, B: Invoking - Terminal Setup
option, C: Invoking - Terminal Setup
option, coa: Invoking - EarthPoints
option, cob: Invoking - EarthPoints
option, color: Invoking - EarthPoints
option, convert: Invoking - EarthPoints
option, dump: Invoking - EarthPoints
option, file: Invoking - EarthPoints
option, formula: Invoking - EarthPoints
option, help: Invoking - EarthPoints
option, helpless: Invoking - EarthPoints
option, L: Invoking - Terminal Setup
option, P: Invoking - Terminal Setup
option, S: Invoking - Terminal Setup
option, verbose: Invoking - EarthPoints
option, version: Invoking - EarthPoints
option, W: Invoking - Terminal Setup
option, window: Invoking - EarthPoints
options, application: Invoking - EarthPoints
options, echo: Terminal Configuration
options, setup: Invoking - Terminal Setup
options, testing: Invoking - AnsiCmd Tests
output methods: Output Methods

P
P option: Invoking - Terminal Setup
positioning test: Invoking - AnsiCmd Tests

R
RTL text: Modifying Existing Data

S
S option: Invoking - Terminal Setup
sandbox test: Invoking - AnsiCmd Tests
setup options: Invoking - Terminal Setup
skField class: ACWin Class
skForm class: ACWin Class
sleep_for: Misc Methods
soft-echo options: Terminal Configuration
source code: Building from Source
streams, i/o: Terminal Configuration
support methods: Development Support
swscanf emulation: Extract Formatted Data

T
TermConfig class: Terminal Configuration
terminal configuration: Terminal Configuration
terminal test: Invoking - AnsiCmd Tests
terminal test: Invoking - AnsiCmd Tests
TermSet class: Terminal Configuration
test methods: Development and Testing
test the build: Building from Source
test, ascii: Invoking - AnsiCmd Tests
test, color: Invoking - AnsiCmd Tests
test, erasure: Invoking - AnsiCmd Tests
test, font: Invoking - AnsiCmd Tests
test, ideograph: Invoking - AnsiCmd Tests
test, positioning: Invoking - AnsiCmd Tests
test, sandbox: Invoking - AnsiCmd Tests
test, terminal: Invoking - AnsiCmd Tests
test, terminal: Invoking - AnsiCmd Tests
testing options: Invoking - AnsiCmd Tests
Test_4Bit: Development and Testing
Test_8bitColor: Development and Testing
Test_acaExpand: Development and Testing
Test_AixFgBg: Development and Testing
Test_AltFonts: Development and Testing
Test_AsciiCodes: Development and Testing
Test_Bg: Development and Testing
Test_Box: Development and Testing
Test_CursorPos: Development and Testing
Test_Erasures: Development and Testing
Test_Form: Development and Testing
Test_Greyscale: Development and Testing
Test_Ideogram: Development and Testing
Test_ModFlags: Development and Testing
Test_NonBlock: Development and Testing
Test_RGB: Development and Testing
Test_Sandbox: Development and Testing
Test_SoftEcho: Development and Testing
Test_TermFlags: Development and Testing
Test_UnbufferedInput: Development and Testing
Test_WinDefault: Development and Testing
Test_Window: Development and Testing
text conversion, gString: gString Text Tool
text erase: Text Erase
text modifiers: Text Modifiers
timeout, blink: Cursor Positioning
timeout, blinking: Invoking - Terminal Setup
ttyWrite: Output Methods

V
verbose option: Invoking - EarthPoints
version option: Invoking - EarthPoints

W
W option: Invoking - Terminal Setup
web-safe indices: API Methods
window option: Invoking - EarthPoints

Jump to:   0  
A   B   C   D   E   F   G   H   I   L   M   N   O   P   R   S   T   V   W