Next: Introduction [Contents][Index]
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.
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 system signals such as "break" (CTRL+C), "suspend" (CTRL+Z),
and "quit" (CTRL+4).
See Terminal Configuration.
AnsiCmd captures all (or nearly all) keycodes which are passed from
the system as escape sequences, and converts these sequences to ordinary
Unicode codepoints.
See Soft Echo Options for examples of this conversion.
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.
Also included are additional test programs in various states of completion.
These applications demonstrate specific approaches to design of applications
based on the AnsiCmd library.
See CsvView Demo App, and AcEdit Demo App for more information.
The AnsiCmd library and the associated test programs make extensive use
of the author’s gString class. The gString class encapsulated most
of the smelly (but efficient) C-language string manipulation functions such
as sprintf, scanf and so on.
Please see gString Text Tool for more information.
Access to the system clipboard is enabled through the WaylandCB class.
This class in under a conditional-compile directive.
Please see Build Options for additional information on integration of
clipboard access into the AnsiCmd library.
For a discussion of how system clipboard access is implemented in the library,
please see AnsiCmd Clipboard Access.
Management of temporary files for the AnsiCmd library and the demo
applications included with the package are handled through the TFMan
(Temporary File Management) class.
Please see TFMan Class and the TFMTest Demo App for an introduction
to the use of temporary files in a Linux application.
ANSI - American National Standards Institute
(ECMA-48, ISO/IEC-6429, FIPS 86, ANSI X3.64, JIS X 0211)
https://en.wikipedia.org/wiki/American_National_Standards_Institute
https://www.ecma-international.org/publications-and-standards/standards/ecma-48/
ASCII - American Standard Code for Information Exchange.
(ISO-IR-006, ANSI_X3.4-1968, ANSI_X3.4-1986, ISO_646.irv:1991, ISO646-US,
IBM367, cp367)
https://en.wikipedia.org/wiki/ASCII
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.
EarthPoints application is primarily a test and
demonstration application, the array of available tests is extensive.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.
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.
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 Q option Quit signal Z option suspend ctrl+Z S option cursor Style
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.
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.
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.
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.
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.
--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.
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:
--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.
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.
--term=P:i # Ignore break signal
epts --term=P:ia # Ignore break signal and sound an alert
epts --term=P:e # Exit the application
epts --term=P:u # User prompt on receipt of break signal
epts --term=P:c # Copy command conversion
epts --term=P:t # Terminal handler (default)
Please see Capturing the Break Signal for additional information.
To set this option directly, call the AnsiCmd method: acCaptureBreakSignal.
The Quit Signal (or Kill signal) is similar to the Panic Button described above, except that in addition to terminating the application, it also generates a core dump.
A core dump is a file which contains a description of the the application state when it was terminated. This can include the register values, the call stack (addresses and parameters), a table of RAM contents and other information. This can be a large file, and it is recommended that it not be generated unless you actually need it.
The Quit Signal is captured by default during configuration of the
AnsiCmd class and its derived classes. When the Quit signal is received,
the application is shut down in an orderly manner. Use the
‘Q option’ to disable this functionality.
epts --term=Q:n
To set/reset this option directly, call the AnsiCmd method: acCaptureQuitSignal.
The “Suspend” signal is generated by the Ctrl+Z key
combination. This signal suspends the currently-active process (places it
into hibernation). The process will not be able to respond to any command
other than a command to resume operation. Refer to documentaiton for the
‘fg’ system utility for information on restoring the hibernating
process.
While the "suspend" functionality is a valuable tool in some contexts,
it is merely confusing to the average user when the running application simply
freezes and cannot be restarted.
For this reason, the "suspend" signal (SIGTSTP) is captured by default
and is converted to an ordinary keycode, wcsCTL_Z.
The Ctrl+Z key combination is often used by applications (LibreOffice,
jEdit, etc.) to “undo” a previous action.
epts --term=Z:n
epts --term=Z:y (default)
Specify the shape and animation (blinking or steady) of the visible cursor.
--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.
Tests for the AnsiCmd library are specified as arguments to the
" command-line option.--test"
epts --test=TEST_OPTION
The specific test within a group of related tests is specified by from one
to four characters as detailed in this chapter. The first character indicates
the test group. For instance, the letter 'C' designates the group
of color-attribute tests. If a test group is invoked without indicating a
specific test, then the menu of available tests in that group will be
displayed and the application will exit.
epts --test=C will display the color test menu:
Color Attribute Testing Options:
-----------------------------------------------
'f' Four-bit Fgnd/Bkgnd color attributes.
'b' Background color attribute options.
't' Table lookup, 8-bit color attributes.
'r' R/G/B color-attribute matrix (6x6x6).
'g' Greyscale color attributes.
'a' Aixterm Fg/Bg extensions (non-standard).
'd' Decode tracking data for attribute mods.
's' Swap acaExpand foreground/background.
Similarly, if a test group and a test are specified, but the test requires
an argument or arguments, then a menu of available arguments for that
test will be displayed and the application will exit.
epts --test=Cr will display the RGB color test arguments:
RGB Test Options:
---------------------------------------------------
'r' Red : Display full range of red colors.
'g' Green: Display full range of green colors.
'b' Blue : Display full range of blue colors.
'y' greY : Display full range of greyscale colors.
'w' Web : Display "web-safe" colors.
A few test require two(2) arguments, for example:
epts --test=Tec Terminal group, Echo test, Cursor keys
If a test and its argument(s) are fully specified, then optionally, the
next character indicates the text color attribute to be used for outputting
the results of the test. The available color attributes are:
'k' blacK 'r' Red
'g' Green 'n' browN
'b' Blue 'm' Magenta
'c' Cyan 'y' greY
If not specified, the terminal default color is used.
Note: The color-attribute tests will ignore this argument.
Examples:
epts --test=Eb — Perform 'E'rasure test
with 'b'lue text.
epts --test=Ac — Perform 'A'SCII code test
with 'c'yan text.
epts --test=Tig — Perform 'T'erminal 'i'nput
test with 'g'reen text.
epts --test=Wddb — Test 'W'indow 'd'ialog,
sub-test 'd' with 'b'lue text.
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 IIdeograph test test T Terminal setup tests test W Window tests test D Dialog 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.
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.
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.
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 :-)
ASCII Control Codes
ASCII control codes (00h - 1Fh) were at one time an important part of
systems which relied on serial communication (e.g. Teletype machines) for
user interaction. On modern systems, most of these codes are unused by the
terminal software and inconvenient for application use.
A few control codes however, are vital to operation. The most common are
null(00h), bell(07h), backspace(08h), horizontal-tab(09h), linefeed i.e.
newline(0Ah), vertical-tab(0Bh), form-feed(0Ch), carriage-return(0Dh),
and of course Escape(1Bh). Others may be used in specialized circumstances.
These keycodes are presented to the application as non-printing byte values,
OR as system signals, which if not properly handled can cause
chaos within an application. A prime example of this would be the CTRL+C
Break signal. For this reason, these byte values and signals are captured
by the AnsiCmd library and converted to unique keycodes for use by the
application. A common example of these would be Copy/Cut/Paste
and similar keycodes.
The keycodes in this group consist of the CONTROL key plus one of:
a-z 4 5 6 7 [ \
Note that when the CONTROL key is pressed, the system ignores the SHIFT key,
so CTRL+A generates the same byte code as CTRL+a.
Function Key Combinations
The function keys F01-F12 and their conditioned varients are often
assigned to system-level tasks, but the terminal emulator may also be configured
to pass these keycodes through to the application level.
All function keys generate escape sequences of between three(3) and seven(7)
bytes. There are 48 (12 * 4) Function key combinations available:
a) F01-12, b) Shift+F01-12, c) Ctrl+F01-12, and
d) Ctrl+Shift+F01-12
Only the first three groups are supported by the AnsiCmd class;
(36 sequential codepoints). When received, members of the fourth group,
Ctrl+Shift+Fnn are silently converted to Ctrl+Fnn equivalents.
The AnsiCmd library captures these sequences and converts them
to ordinary Unicode codepoints (keycodes) in the range: 0x002000 through 0x002023.
Unicode assigns these keycodes to mathematical symbols which will seldom, if
ever be generated directly by the keyboard. Some examples of the captured
and converted sequences are shown in the table.
Please see the AnsiCmdDef.hpp source module for the full list.
ALT Key Combinations
The Left ALT key in combination with another key provides what are commonly
known as the GUI keys. These key combinations are often used as shortcut
keys within applications. For instance, ALT+F, ALT+E and ALT+H are
often used to invoke an application’s “File”, “Edit”,
and “Help” menus, respectively.
Because these keycodes are presented to the application as escape sequences,
it is necessary to capture the escape sequences and convert them to unique
keycodes for use by the the application. For the examples mentioned, these are:
The keycodes in this group consist of the Left ALT key plus one of:
a-z ! " # $ % & ' ( ) * + , - . / : ;
< = > ? @ \ ] ^ _ { | }
Note that to avoid clutter, the alphabetic character are processed as
case insensitive: ALT+A yields the same keycode as ALT+a.
Also, the numeric combinations ALT+0 through ALT+9 are assigned
the same keycodes as their shifted equivalents (assumes U.S. English
keyboard layout).
! @ # $ % ^ & * ( )
1 2 3 4 5 6 7 8 9 0
Other Keycodes
The “Special Keys” group of keycodes are also reported by this test.
Please see the AnsiCmdDef.hpp source file for a full list of the
assigned keycode names. (or run this test)
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.
An “ideogram” is technically a symbol representing a concept or and idea, or what today we would call a “meme”. Street signs without words, mathematical-operator symbols or a photo of a cat hanging onto a branch with one paw could be considered as ideograms.
The ideograms defined by the ECMA-48 (ANSI) standard appear to have
been intended as line-drawing tools or text decorations; however, they
seem to have been abandoned before they were completed. As such,
they are unlikely to be supported by modern terminals; however, this test
issues the associated escape sequences to see what happens i.e. nothing:
aesIDEO_UNDER // ideogram underlined
aesIDEO_UDOUBLE // ideogram double-underlined
aesIDEO_OVER // ideogram overlined
aesIDEO_ODOUBLE // ideogram double-overlined
aesIDEO_STRESS // ideogram stress marking
aesIDEO_OFF // all ideogram attributes off
This test exercises the various terminal configuration options and the internal tracking data related to those options.
--test=T # Display the menu of sub-options
epts --test=Tb # Test blocking vs. non-blocking input
epts --test=Tec # Soft-echo options, cursor-movement keys
Developer's Note: The text-modifier tests are included with the
terminal configuration group because the tests include verification of
the flags that track which modifier(s) are set at any given time.
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 window object which optionally contains an
array of text fields and other user-interface controls (see skForm Class).
See also the next section which describes “dialogs”, which are
functionally sub-windows within the main window.
Visually, an ACWin window is simply a rectangle drawn within the terminal window; however, application-level interaction is carefully range-checked and validated to maintain the integrity of the window. This allows the application designer to focus on the project, rather than being distracted with organizing color change sequences, counting text columns and other low-level details.
The tests in this group exercise all the major functionality of defining and managing the ACWin object.
The dialog tests are a functional subset of the the window tests (see ACWin Class), but because the Dialog is at the highest level of abstraction, a large number of tests are required, so they are grouped separately.
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 --test=S # invoke the Sandbox with no arguments
epts --test=St # invoke the Sandbox with one argument
epts --test=S4c # invoke the Sandbox with two arguments
The specified arguments will be displayed in the top row of the window as
shown, and these parameters may be referenced in the usual way.
(A question mark will be displayed for unspecified argument(s)).
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”.
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.
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."
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.
Examples: --coa='Miami: 25 46.50978 : -80 57.948611'" --cob='Buenos Aires: -34 36.20 : -58 22.90'
Examples: --coa='Miami: 25 46 30.5868 : -80 57 56.91666' --cob='Buenos Aires: -34 36 12 : -58 22 54.0'
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.
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.
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.930578Three GPS database files are included with the AnsiCmd package:
'US_Capitols.txt', 'UK_GPS.txt' and 'testpoints.txt'.
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=haversineepts --coa='36.1:-14.3' --cob='37.7:-12.4'--form=allAdditional formulae may be implemented in a future release.
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_VALUEThis 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.2579RConverted Value: dec:-63.959700 deg:-63.000000 min: 57.000000 sec: 34.918520 rad: 4.257900 fmt: vfRad
Specify the foreground and background color attributes for display of the output. The terminal window’s color attributes are used by default.
If the
--windowoption 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 backgroundepts --color=green:dflt// green text on default backgroundepts --color=dflt:blue// default text color on blue background // blue text, grey bkgnd, cyan border fgnd, black border bkgndepts --color=blue:grey:cyan:black// default text fgnd:bkgnd, magenta border fgnd, blue border bkgndepts --color=dflt:dflt:magenta:blue
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)
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
ANSIformatting. 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.
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 : LongitudeFormatting 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-FileIf 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 (?)
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
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
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
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.
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:
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 (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
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.
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)
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.
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.
TermStream 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 IMPLEMENTEDchar localeName[LOCALE_LEN]For those not familiar with the purpose of the 'locale' specification,
the locale selected controls how characters are encoded, formatting of
numbers, timestamps and currency, interpretation of punctuation, comparisons
of text strings and other text formatting decisions. By default, applications
start in the so-called “C-locale” which is not really a locale, but
a lack of locale which interprets everything in terms of ASCII and English,
rendering the application basically useless. For this reason, it is
strongly recommended that all application set the locale for the
language, character set and text conventions in use by the target system.
Please refer to the acSetLocale method for additional information.
EchoOpt echoOptionCharacters 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:
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'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)bool wideStream 'true' : wide (32-bit) I/O streams, wcin and wcout 'false' : narrow (87-bit) I/O streams, cin and coutbool nonStandardANSI standard
(ANSI X3.64 (ISO/IEC6429)).
'true' : non-standard terminal emulator 'false' : ANSI compliant terminal emulator (default)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 bcTypecchtTerm - Terminal handles CTRL+C break-signal.
cchtExit - The application terminates execution in an orderly way.
cchtUser - Ask user whether to exit or discard the signal.
cchtCopy - Convert the break signal to an ordinary keycode.
cchtIgnore - Ignore (discard) the break signal.
See Capturing the Break Signal below for more information.
bool bcAlert'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 cursorStylecsDflt 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.
By default, the AnsiCmd library captures this signal and converts it to an
ordinary keycode (wcsCTL_Z). Under most circumstances, this is the desired
action; however, if specified, the system can be allowed to retain control
of this signal.
'false' : the system retains control of the suspend signal
'true' : the suspend signal is captured and disabled (default)
Please see acCaptureSuspendSignal for additional information.
'false' : the system retains control of the quit signal 'true' : the quit signal is captured and an orderly shutdown is executed (default)aeSeq foregroundenum aeSeq: aesFG_xxxx (default:aesFG_DFLT)aeSeq backgroundenum aeSeq: aesBG_xxxx (default:aesBG_DFLT)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.
'bcType' member of The TermConfig object which is
passed as the argument to the AnsiCmd constructor.While the first option always invokes the AnsiCmd library’s default handler,
the 'acCaptureBreakSignal' call can specify either the default handler
or an alternate handler provided by the application.
The 'acCaptureBreakSignal' method can also be used to return control to
the terminal’s signal handler.
The mechanics of transferring control of the break signal to the application
are straightforward, but non-trivial. It is accomplished by
“registering” a signal-handler function with the system using the
C-library function:
'signal( int SIGNUM, sighandler_t ACTION )'.
This function is defined in the 'signal.h' header file.
The SIGNUM parameter in this case is the macro 'SIGINT' (the interrupt signal).
The ACTION parameter is the address (name) of the function to which the break
signal will be directed.
The terminal’s signal handler is defined by the macro 'SIG_DFL', while
the application’s handler may be specified by the name of any (non-member)
function in the application which is configured to process the signal.
The non-member function in the AnsiCmd library is cryptically named
'BreakSignal_Handler'. The system call is then:
signal ( SIGINT, BreakSignal_Handler );
Because we want to provide for potential user interaction when the break
signal is received, we perform the slightly dangerous operation of allowing
the non-member function to call an AnsiCmd-class member method:
breaksignalReceived ( int sigNum );
This is where the action takes place.
The type of operation to perform has been specified during handler setup, and
is a member of enum CCH_Type (Control_C_Handler Type).
cchtTerm - Terminal handles CTRL+C break-signal by issuing
the kill signal to the application running within the terminal. Generally,
this can be done without serious consequences; however, it may be necessary
to manually reset the terminal by calling the 'reset' utility to return
the terminal configuration to a known state. For instance, if the application
is terminated using CTRL+C, the current terminal attributes will still be
active when the terminal shell regains control.
cchtExit - The application will perform any specified housekeeping
tasks, and then immediately terminate execution, returning control to the
terminal shell program. For the AnsiCmd class, “housekeeping tasks”
include returning the terminal configuration to its original state, deleting
all allocated objects by calling the destructors for the objects in the
proper order, setting the exit code and executing the C-library exit sequence.
cchtUser - Prompt user for whether to exit the application or to
discard the break signal and continue execution.cchtCopy - Convert the captured break signal to the keycode
wcsCTL_C (Ctrl+C). The application can then process the keycode or
discard it as desired. For instance, the ACWin class recognizes this keycode
as the “Copy” command, and copies the selected text to the clipboard.
cchtIgnore - Ignore (discard) the break signal and continue
execution of the application; optionally, sounding an audible alert so
the user knows that the signal was received, but discarded.
(see bcAlert member of the TermConfig class for enabling the audible alert.)
“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 specifies the character-echo option and whether the input stream uses a blocking or non-blocking read.
The soft-echo option may also be specified as a command-line option.
See the 'echoOption' member in the discussion of the
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.
(Edit keycodes are excluded.)See the next section for more information on the “special” keycodes.
Decoding the “Special” Keys
The “special” keycodes consist of certain keycodes which are presented to a console application in the form of escape sequences. An escape sequence is a sequence of bytes beginning with the the escape character (0Bh). The number of bytes in an escape sequence varies from two bytes to seven bytes (or more on some systems).
Many keyboard keys are encoded in this way: the Function Keys, the Cursor Positioning keys, the Backspace/Delete/Insert keys, and most of the keycodes generated in combination with the so-called conditioning keys: Shift, Control, Alt.
For a (nearly) complete list of keystrokes that generate escape sequences and the sequences they generate, please download the author’s NcDialog API package and study the source files
NCursesKeyDef.hppandNCursesKeyDef_auto.hpp.For the AnsiCmd library, only a subset of these escape sequences are captured and decoded. These include the “special” keys listed in the table below, as well as combination-keys discussed in the following sections:
ASCII Control Codes and GUI Keys.Note: Encoding of Backspace and Delete keys are specified in terminal settings.
Key Function Esc Seq (hex) Key Name Glyph/Keycode Up Arrow 1B 5B 41 wcsUARROW ↑2091hDown Arrow 1B 5B 42 wcsDARROW ↓2093hRight Arrow 1B 5B 43 wcsRARROW →2192hLeft Arrow 1B 5B 44 wcsLARROW ←2190hHome Key 1B 5B 48 wcsHOME ↖2196hEnd Key 1B 5B 46 wcsEND ↘2198hPage Up 1B 5B 35 7E wcsPGUP ↗2197hPage Down 1B 5B 36 7E wcsPGDN ↙2199hTab 09 wcsTAB ↱211BhShift+Tab 1B 5B 5A wcsSTAB ↲21B2hBackspace 7F wcsBKSP ↰21B0hDelete 1B 5B 33 7E wcsDELETE ↳21B3hInsert 1B 5B 32 7E wcsINSERT ↥21A5hAlt+Enter 1B 0A wcsAENTER ↧21A7hShift+Up 1B 5B 31 3B 32 41 wcsSUP ↾21BEhShift+Down 1B 5B 31 3B 32 42 wcsSDOWN ⇂21C2hShift+Right 1B 5B 31 3B 32 43 wcsSRIGHT ⇀21C0hShift+Left 1B 5B 31 3B 32 44 wcsSLEFT ↼21BChShift+Home 1B 5B 31 3B 32 48 wcsSHOME ⇇21C7hShift+End 1B 5B 31 3B 32 46 wcsSEND ⇉21C9hCtrl+Home 1B 5B 31 3B 35 48 wcsCHOME ⇈21C8hCtrl+End 1B 5B 31 3B 35 46 wcsCEND ⇊21CAhCtrl+C 03 wcsCOPY ∽223DhCtrl+X 18 wcsCUT ≒2252hCtrl+V 16 wcsPASTE ≐2250hCtrl+A 01 wcsSELECT ∻223BhCtrl+Z 1A wcsUNDO ≔2254hThe Copy/Cut/Paste keys (
Ctrl+C, Ctrl+X, Ctrl+V) and the otherASCIIcontrol codes are described below:
(see ASCII Control Codes).Taken together, these keycodes comprise all the standard keycodes used to edit text within an individual field or on a form consisting of multiple fields.
Please see skForm Class for a description of how these keycodes are interpreted within a form or a field.Also, please see GUI Keys for keycodes which are commonly used as user-interface commands.
ASCII control codes are generated by pressing and holding either CTRL
key and then pressing one of the alphabetic keys: 'a' through 'z',
'A' through 'Z', or '4', '5', '6', '7'.
Note that the Shift key is ignored when the CTRL key is pressed.
Both the uppercase and lowercase alpha characters produce the same values,
and the Ctrl+[4 | 5 | 6 | 7] produce the same values regardless of whether
the Shift key is pressed. Examples:
Ctrl+a == Ctrl+Shift+A
Ctrl+5 == CTRL+Shift+5 ('%')
The Ctrl+C key should be 0x03 in the sequence, but that code is tied
to the Break Signal. To recapture Ctrl+C it is necessary for
the break handler to capture the signal and push the code back into
the input stream. The Break signal handler type “cchtCopy”
performs this conversion.
Please see Capturing the Break Signal for a discussion of
capturing and re-purposing the break signal.
See acCaptureBreakSignal which implements the signal capture.
The Ctrl+Z key should be 0x1A in the sequence, but that
code is tied to the Suspend Signal. To recapture Ctrl+Z it is necessary for
the suspend handler to capture the signal and push the code back into
the input stream. The suspend signal handler performs this conversion.
See acCaptureSuspendSignal which implements the signal capture.
The Ctrl+4 key should be 0x1C in the sequence, but that
code is tied to the Quit Signal (with core dump). To recapture Ctrl+4
it is necessary for the quit handler to capture the signal and provide
for an orderly termination of the application. (Ctrl+4 is not
associated with an application-level keycode.) Note that the Ctrl+\
key combination is equivalent to Ctrl+4.
See acCaptureQuitSignal which implements the signal capture.
The Ctrl+S and Ctrl+Q keys should be 0x13 and 0x11,
respectively, but these codes are tied to the Pause/Resume output stream
signals. At a terminal configuration level, the flow-control flag, IXON
handles stdout flow control. This flag is automatically reset
when configuring the terminal for unbuffered input. This frees the Ctrl+S
and Ctrl+Q key combinations for application-specific purposes.
Please see acBufferedInput for additional information.
Certain Control-key combinations are reserved for use by the desktop
environment or by the terminal emulator program. For instance, Ctrl+PageUp
and Ctrl+PageDown are used to navigate among terminal tabs. Most of these
so-called shortcut keys may be disabled in the terminal’s preferences/settings
page.
GUI KeysThe GUI keys (Graphical User Interface keys) are keycodes that are commonly
used by applications as command shortcut keys. These keycodes are generated
by pressing one or more of the “conditioning keys” in combination
with another key. The conditioning keys are the SHIFT key, the CONTROL keys
and the left-side ALT key.
With the exception of the ASCII control codes, these keycodes are reported
to the application as escape sequences.
The GUI keycodes fall into these general categories:
a-z and 4-7 UpArrow, DownArrow, RightArrow, LeftArrow a-z and A-Z and punctuation characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? [ \ ] ^ _ { | } UpArrow, DownArrow, RightArrow, LeftArrow, Home, End, PageUp, PageDown a-zAll key combinations which are captured are converted to constant values
defined in AnsiCmdDef.hpp.
Technical Notes:
− To use key combinations, first press and hold the conditioning key(s), then press the other key, and release them all together.
− Note that by default, the right-side ALT key is configured for entering keycodes that are not directly available from the keyboard.
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.
TermIos strOrigI/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 strModsTermStream aStrI/O stream. it is a member of enum TermStream, consisting of
stdIn (stdin), stdOut (stdout) and stdErr (stdErr).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 curStylePlease 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 cchTypePlease see Capturing the Break Signal for a discussion of the break-signal handlers built into the AnsiCmd library.
EchoOpt inpEchPlease see Soft Echo Options and TermConfig Class for a discussion of input-echo options.
bool inpBuf 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 inpBlkThe 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 cchAlertCTRL+C) has been received.
Please see Capturing the Break Signal, and also the acCaptureBreakSignal method for a discussion of the break-signal handlers.
bool quitCapCtrl+4 key or Ctrl+\ key
combination. true == signal has been captured and will be handled locally. false == terminal handles the signalbool suspCapCtrl+Z key combination. true == signal has been captured and will be handled locally. false == terminal handles the signalbool strCap'strOrig' member (see above) has been
initialized. true == member initialized false == member not initialized
bool inpMod'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
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 |
| acSetEchoOption | Echo option (unbuffered input only) |
| acGetEchoOption | Report current echo option |
| acBlockingInput | Input blocking (unbuffered input only) |
| acCaptureSignals | Enable Ctrl+C Ctrl+4 Ctrl+Z signals |
| acReleaseSignals | Disable Ctrl+C Ctrl+4 Ctrl+Z signals |
| acCaptureBreakSignal | Enable/disable capture of Ctrl+C |
| acCaptureQuitSignal | Enable/disable capture of Ctrl+4 |
| acCaptureSuspendSignal | Enable/disable capture of Ctrl+Z |
| acRestoreTermInfo | Set terminal configuration to defaults |
| breaksignalReceived | default break-signal handler |
| suspendsignalReceived | default suspend-signal handler |
| quitsignalReceived | default quit-signal handler |
──── Color Attributes ─── | ───────────────────────────────────────── |
| acSetFg | Set text foreground (3-bit, 4-bit, AIX) |
| acSetBg | Set text background (3-bit, 4-bit, AIX) |
| acSetFgBg | Set text fgnd and bkgnd (3/4-bit, AIX) |
| 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) |
| 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 |
| acPause | Read and discard next keystroke |
| acWait | Pause for timeout or keystroke |
| 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 |
| acFormatParagraph | Automatic text formatting |
| acShellOut | Temporarily return to shell program |
| 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 |
| isSpecialKey | Compare to list of special keycodes |
| isCommandKey | Compare to list of command keycodes |
| acCreateTemppath | Enable support for temporary files |
| acDeleteTemppath | Disable support for temporary files |
| acCreateTempfile | Create a temporary file |
| acDeleteTempfile | Delete a temporary file |
| acClipboardEnable | Establish communications with clipboard |
| acClipboardDisable | Terminate communications with clipboard |
| acClipboardTest | Test communications with clipboard |
| acClipboardGetText | Retrieve data from the clipboard |
| acClipboardSetText | Copy data to the clipboard |
| acClipboardCharCnt | Reports number of chars on clipboard |
| acClipboardByteCnt | Reports number of bytes on clipboard |
── Development Support ── | ───────────────────────────────────────── |
| ansiTest | Manage AnsiCmd library testing |
| getDataMembers | Get a copy of internal data members |
| getConfig | Get a copy of terminal configuration |
| tseReport | Report keycode processing |
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.
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).
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.
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.
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.
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.)
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
Input : none Returns: pointer to locale name
Returns a pointer to the name of the current locale.
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:
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.
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.
'VTIME' and 'VMIN' and how those values are interpreted.
To bake a cake and eat it too, see the soft-echo option.
Input : echoType: member of enum EchoOpt:
noEcho : data from the stdin stream will not be
echoed to the terminal window
termEcho : terminal echoes all stdin data to the window
For the soft-echo options, terminal echo is disabled,
and echo of input characters to the display is
handled locally by the acRead() methods which will
echo all PRINTING characters to the display, and
will decode the "special keys" (cursor keys, etc.)
according to the specific soft-echo sub-option.
softEchoA: all special keys (default soft-echo option)
softEchoB: basic set of special keys
softEchoC: cursor-movement keys only
softEchoD: disable all special keys
softEchoE: edit keys only: Backspace, Delete, Insert,
plus the Tab and Shift+Tab keys
Returns: 'true' if echo option modified
'false' if input buffering currently enabled (or invalid type)
Select the input character echo type. (enum EchoOpt).
Echo of user keyboard input (writing the received keycode to the display can be handled in a number of ways as listed above. The terminal can be allowed to decide what key input is echoed to the display, or the application can take control of key input to provide a smoother user interface.
The “soft-echo” options are available for customizing the
user interface.
Please 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.
Input : none Returns: current echo option: member of enum EchoOpt
Get the current input-echo setting which describes how data from the input
stream is processed.
See TermConfig Class for a discussion of input-stream configuration options.
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.
Input : eopt : (optional, softEchoA by default)
specify one of the soft-echo options (enum EchoOpt)
Returns: 'true' if all settings successful
'false' if one or more settings failed
Disable input buffering and capture all system signals generated by keyboard input.
This method is provided as a housekeeping convenience, performing a common sequence of terminal setup operations:
Break Signal : SIGINT - Ctrl+C becomes wcsCTL_C
Suspend Signal: SIGTSTP - Ctrl+Z becomes wcsCTL_Z
Quit Signal : SIGQUIT - Ctrl+4 performs an orderly application shutdown
Input : none Returns: nothing
Release all captured signals. Return control to the terminal software.
1) Break Signal : SIGINT - Ctrl+C
2) Suspend Signal: SIGTSTP - Ctrl+Z
3) Quit Signal : SIGQUIT - Ctrl+4
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.
The handler type is specified by the ’ccType’ member variable which is initialized here.
Exit? 'y'es or 'n'o: _
Ctrl+C --> Ctrl+V.
Input : enable : if 'true', enable application capture of the quit key
if 'false', disable application capture of the quit key
terminal handles the signal
Returns: current state of capture flag
'true' quit key will be captured by the application
'false' quit key will be handled by the terminal program
Pressing the CTRL+4 key (or the CTRL+\ key) generates the
system Quit signal. If the system receives the Quit signal, it will
immediately terminate the application and generate a “core dump” file.
Core dump files are created in /var/lib/systemd/coredump by default.
The format of the file should be ELF (Executable and Linkable) format, but
could be an older format. An explanation of core dump files is beyond the
scope of this document, but see the 'gdb' (GNU Debugger) utility, which
may be used to decode the contents of core-dump files.
The Quit Signal is captured by default during configuration of the
AnsiCmd class and its derived classes. Then when the Quit signal is received,
(CTRL+4 key) the application is shut down in an orderly manner, and
a core dump is not generated.
The local Quit signal handler deletes the temporary files, releases dynamic
memory allocations and performs general housekeeping chores. Before exiting
the application, the bottom two rows of the terminal window are cleared and
a message is written indicating that the application has been terminated.
After all, we’re not just wild animals pooping in the forest.
(well, most of us anyway :-)
See Q option for specifying this option as a command line parameter.
Technical Note:
This signal is sometimes referred to as the Kill signal, but note that the
Quit signal is technically different from the Kill signal in that the Kill
signal cannot be captured or modified. It is an absolute command, and in
fact, failure to respond to the Kill signal would be considered as a
major system bug.
Input : enable : if 'true', enable application capture of the suspend key
if 'false', disable application capture of the suspend key
terminal handles the suspend signal
Returns: current state of capture flag
'true' suspend key will be captured by the application
'false' suspend key will be handled by the terminal program
Enable or disable application-level capture and processing of the SUSPEND key CTRL+Z. Signal name: SIGTSTP.
If this signal is seen by the terminal program, it will suspend the active
process. That is, it will put the process into the background and disable
direct access to it. A different process may then occupy the foreground,
interacting with the input and output streams.
Use the ’fg’ utility to restore the hibernating process.
Because Ctrl+Z is often used as a command (undo) within an application, this signal is captured by default and converted to an ordinary keycode: wcsCTL_Z.
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:
Input : sigNum: signal number to be handled
Currently, only the SIGINT (interrupt) is handled.
Returns: nothing
When the break signal has been captured, (see Capturing the Break Signal), this method is called by a non-member method specified as the dedicated CTRL+C signal handler. The handler type is specified by the ’ccType’ member variable which is set to one of the following:
─ ─ ─ ─ ─ ─ ─ ─ ─ ─
This is technically a public method; however, it is called ONLY by the non-member method which handles receipt of the break-signal (CTRL+C).
Input : sigNum: signal number to be handled
Currently, only the SIGSTP (suspend) is handled.
Returns: nothing
When the suspend signal has been captured, (see acCaptureSuspendSignal),
this method is called by a non-member method specified as the dedicated
CTRL+Z signal handler.
This method captures the signal and converts it to an ordinary keycode: wcsCTL_Z.
─ ─ ─ ─ ─ ─ ─ ─ ─ ─
This is technically a public method; however, it is called ONLY by the non-member method which handles receipt of the suspend-signal (CTRL+Z).
Input : sigNum: signal number to be handled
Currently, only the SIGQUIT (quit) is handled.
Returns: nothing
When the quit signal has been captured, (see acCaptureQuitSignal),
this method is called by a non-member method specified as the dedicated
CTRL+4 signal handler. The handler will then perform an orderly shutdown
of the application, returning all resources to the system.
─ ─ ─ ─ ─ ─ ─ ─ ─ ─
This is technically a public method; however, it is called ONLY by the non-member method which handles receipt of the quit-signal (CTRL+4 or CTRL+\).
Input : fg : foreground color attribute (member of aeSeq)
Returns: 'true' if valid color attributes specified and set
'false' if invalid parameter(s) specified
(attributes will not be modified)
Set text foreground color attribute (3-bit and 4-bit color).
This includes both the standard 3-bit and 4-bit attributes, as well as the non-standard IBM Corp. AIX extensions.
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.
Input : bg : background color attribute (member of aeSeq)
synth: (optional, 'true' by default)
if 'true', use synthesized background color attributes
if 'false', use standard ANSI background color attributes
Returns: 'true' if valid color attributes specified and set
'false' if invalid parameter(s) specified
(attributes will not be modified)
Set text background color attribute (3-bit and 4-bit color).
This includes both the standard 3-bit and 4-bit attributes, as well as the
non-standard IBM Corp. AIX extensions.
(See note on AIX attributes, above.)
Note on synthesis of intense background color attributes
The default color attributes for intense (bold) backgrounds are inadequate because the
'intense'('bold') bit affects only the foreground color.“Synthesized” bold backgrounds are used by default, which bypasses the ’bold’ flag problem by
using a member from the color lookup table which is outside the basic sixteen color (4-bit) group.
Input : fg : foreground color attribute (member of aeSeq)
bg : background color attribute (member of aeSeq)
Returns: 'true' if valid color attributes specified and set
'false' if invalid parameter(s) specified
(attributes will not be modified)
Set text foreground AND background colors (3-bit and 4-bit color).
This includes both the standard 3-bit and 4-bit attributes, as well as the
non-standard IBM Corp. AIX extensions.
(See note on AIX attributes, above.)
|
Programmer’s Note: The foreground is set AFTER the background so that if
the ‘bold’ flag is used in the foreground escape sequence, it will not be masked
by a subsequent non-bold background. Note also that bold background color escape sequences include the ‘bold’ flag,
but unfortunately, because of the way the terminal interprets this flag, it affects
only the foreground attribute. Exception: "synthesized" bold backgrounds are used by default, which bypasses the ’bold’ flag problem by using a different member from the color lookup table which is outside the basic sixteen (4-bit) color group. |
Input :
fgbg : foreground/background/modifiers
encoded as an acAttr bitfield
Returns: 'true'
Set text foreground/background colors using a value encoded as an
acAttr bitfield value.
Although the acAttr group of color attribute bitfields is defined for use
within the AnsiCmd API; this method allows for color attributes to be
specified using these encoded bitfield attributes regardless of whether
the API code is compiled into the library.
The specified value may be created directly as a logical OR of multiple
members of the “acAttr” enumerated type.
Example: acAttr( acaFG_GREEN | acaBG_BLACK | acaUNDERLINE)
The bitfield value may also be built by a call to one of the acaExpand-class methods. See acaExpand class, for details.
|
Note that this is a simplified version of the API method: ’acSetAttributes’, which is preferred when the API methods are available. This method should be used only if the library has been compiled without the API method group. |
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).
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).
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.
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.
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.
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.
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.
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.
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.
Input : fg : AIX foreground color attribute (member of aeSeq)
Returns: 'true' if valid color attributes specified and set
'false' if invalid parameter(s) specified
(attributes will not be modified)
NOTE: This method is obsolete. See acSetFg.
Input : bg : AIX background color attribute (member of aeSeq)
Returns: 'true' if valid color attributes specified and set
'false' if invalid parameter(s) specified
(attributes will not be modified)
NOTE: This method is obsolete. See acSetBg.
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.
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 acResetMods method below for a list of valid text modifiers.
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
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.
Important Note On Cursor Positioning
Cursor positions within a terminal window are always defined as offsets from some reference position. In general, offsets are relative to the upper-left corner of the terminal window, also known as the “origin”.
The terminal window origin is defined as position1:1(not the logically correct0:0).Unfortunately, the developers of terminal software and the authors of the
ANSIcommands and other utilities are not always on the same page regarding whether cursor offsets should be0-basedor1-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!
Input : curcmd: one of the members of the cursor-positioning group which
are included in enum aeSeq.
Example: acSetCursor ( aesCUR_HOME ) ;
arga : (optional, 1 by default)
for options which require arguments, 'arga' specifies the
first argument.
Example: acSetCursor ( aesCUR_ABSCOL, 30 ) ;
argb : (optional, 1 by default)
for options which require arguments, 'argb' specifies the
second argument.
Example: acSetCursor ( aesCUR_ABSPOS, 12, 60 ) ;
Returns: 'true' if valid cursor command (and valid arguments, if required)
'false' if invalid parameter(s) specified
(position will not be modified)
Set cursor position within terminal window.
Some ANSI cursor commands perform cursor movements relative to the current position, while other commands set the cursor at an absolute position within the terminal window.
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.
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.
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.
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'
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 : gsIn : (by reference) receives captured text (null terminated)
limit : (optional, size of gString object by default)
If specified, 'limit' indicates the maximum number of
characters (wide-stream input) OR the maximum number of
bytes (narrow-stream input) that will be extracted from
the stdin buffer.
Important Note: This argument is referenced only when
unbuffered input is active. This argument is ignored
when input-stream buffering is enabled.
Returns: number of characters captured (NOT the number of bytes)
Capture user input as a sequence of characters terminated by the Enter key,
OR when input buffering is disabled and the number of characters
specified by the 'limit' parameter has been reached.
Internally, this method loops a call to the single-character acRead
(see below). The called method contains most of the intelligence of the
operation.
Please see Soft Echo Options for a discussion of when and how key input is echoed to the display.
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.
Input : nl : (optional, default: false)
if 'true', after user keypress, output a newline character
if 'false', no output will be written to display
Returns: keycode from user
Wait for user to press a key. This is an unbuffered read, with no echo of the keycode to the display. Typically, this method would be used after the application displays a ’press any key’ or similar message.
The optional 'nl' parameter may be used to write a newline character
(NEWLINE (0x000A) to the display after the user presses any key. This
will move the cursor to the leftmost column of the next row. This option
should be used only when the application is writing directly to the
terminal window, and not when formatted (ACWin-class) data are being displayed.
Technical Note: After the keycode is received, the input stream is flushed,
that is, any data remaining in the input buffer is read and discarded.
This is done to protect against stale data being left in the buffer
in case the key pressed by the user generates an escape sequence or
another multi-byte sequence. If the initial keycode received is the Escape
keycode (0x001B), the keycode for the space key wcsSPACE (0x0020) will
be returned instead.
Input :
seconds : specifies the sleep interval in seconds (1 minute max)
0 <= seconds <= 60
Returns: nothing
Pause for a specified amount of time OR until user presses a key.
This can be thought of as a combination of the acPause and
nsleep methods.
The specified delay is broken into segments and after each delay segment,
the input stream is pinged to determine whether user has pressed a key.
The pause continues until either the full pause interval is complete, or
until user presses any key, whichever comes first.
Any keycode received is discarded, and before return, the input stream is flushed to avoid abandoning any stale data in the input stream.
Input : none Returns: nothing
Flush stdin, (the active input stream, wcin or cin).
Any data still in the input stream will be discarded.
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.
Input : starting cursor position in one of the following formats:
wp : a WinPos object (by reference)
OR
row : target row
col : target column
text data to be written in one of the following formats:
gsTxt : (by reference) a gString object
OR
wTxt : a wchar_t string (32-bit characters)
OR
cTxt : a char (byte) string
OR
wchar : a single wchar_t (wide) character
OR
cbyte : a single byte
flush : (optional, default: 'true')
if 'true, flush the output buffer before return
if 'false', do not flush the output buffer
Returns: current cursor position (WinPos object)
Write text data to stdout beginning at the specified cursor position.
The final cursor position is at the end of the output. This is the return value.
This method is not reliable for writing ANSI escape sequences and ASCII control codes. For these special cases, use the
'ttyWrite'method below.
The primary difference between this method and traditional TTY-style output
is that newline ('\n') characters are handled as a special case.
When a newline character is encountered in the output stream, it causes the
cursor to be placed on the next row at the same column as
the first column of the previous row. This automatic formatting allows the
application to write formatted paragraph data without the painful task of
having to count columns. (“You’ll thank me later.” — Adrian Monk)
This method is actually a group of overloaded methods which provide flexibility in the way parameters are passed.
Cursor position may be specified either as a WinPos object or as seperate row and column values.
The source text may be formatted as:
By default, the output buffer is flushed after all data have been written.
This is equivalent to the C++ sequence:
wcout << "text_data" ;
wcout.flush() ;
However, flushing the output buffer is a slow operation (relatively speaking),
so if multiple writes are performed in sequence, it is more efficient to
flush the stream only once, after the last write of the sequence. For example,
the following sequence writes three text strings, each in a different color,
with the 'flush' flag set (default value) for the last write.
WinPos wp( 4, 30 ) ;
acSetFg ( aesFG_RED ) ;
wp = acWrite ( wp, "Red textdata.\n", false ) ;
acSetFg ( aesFG_BLUE ) ;
wp = acWrite ( wp, "Blue text data.\n", false ) ;
acSetFg ( aesFG_GREEN ) ;
wp = acWrite ( wp, "Green text data.\n" ) ;
Note that this method is aware of the terminal window dimensions.
If automatic scrolling or automatic line wrap are 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.
Input : text data to be written in one of the following formats:
gsTxt : (by reference) a gString object
OR
wTxt : a wchar_t string (32-bit characters)
OR
cTxt : a char (byte) string
OR
uTxt : a UTF-8 (byte) string
OR
wchar : a single UTF-32 character
OR
cbyte : a single byte (generally: an ASCII control code)
flush : (optional, 'true' by default)
if 'true, flush the output buffer before return
if 'false', do not flush the output buffer
nl : (optional, default: 'false')
append a newline character to the output
Returns: nothing
Write text data (or ANSI sequence) to stdout beginning at the current
cursor position. This emulates the action of a teletype machine (TTY).
(If you don’t know what a teletype machine is, your grandparents will
explain it to you.)
Any newline characters encountered will cause the cursor to be positioned
on the first (leftmost) column of the line below, and if on the last line
in the window, all data will be scrolled upward.
Text will automatically wrap at the right edge of the window.
This method is actually a group of overloaded methods which provide flexibility in the way parameters are passed. The source text may be formatted as
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.
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.
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.
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.
Input : repeat : (optional, 1 by default) repeat count
Range: 1 - 32,767
delay : (optional, 5 by default i.e. 1/2 second)
delay between successive beeps in tenths of a second
in the range: 2 - 600 (0.2sec through 1.0min)
Note: The system is unable to handle short delays, so
a delay of two-tenths second is the safe minimum.
freq : (optional, -1 by default)
if specified, this is the auditory frequency of the beep
[CURRENTLY IGNORED]
Returns: nothing
Invoke the console’s default auditory alert (beep).
When called without parameters, the acBeep method produces a single
beep (or whatever sound your terminal is set up to produce when the
ASCII Bell control code is received.
Three optional parameters are available: 'repeat', 'delay', and freq'
as shown above.
The repeat parameter is straightforward, specifying the number
of individual beeps to produce from 1 (default) to 32,767, although we
can attest that anything over about 200 will cause everyone in your
household to toss the nearest loose object in your direction.
The delay parameter specifies the (approximate) pause between beeps.
The quality and repeatability of the tone is heavily dependent upon the
delay between beeps. This is because the the actual physical timer used and
the system code which controls it are both shared resources.
The delay interval may be specified as a multiple of 0.10 (1 tenth) second,
with the default being 0.5 (5 tenths) second, and the maximum being one
minute (600 tenths). For a stable repeatable sound, the practical
minimum is two or three tenths (0.2 - 0.3) of a second.
The freq parameter specifies the frequency of the tone that will
be produced. For the current (pre)release, this parameter is ignored, and the
tone is produced by simply issuing the ASCII Bell control code.
For the production release, however, we hope to implement a more robust and
flexible sound control.
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.
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.
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.
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.
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:
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).
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.
The API (Application Programming Interface) methods are designed to
encapsulate some of the more common operations performed as a sequence of
calls to the low-level primitive methods. Using the API methods
reduces code clutter at the application level, which will hopefully
reduce development and debugging time for the application.
Color Attribute Methods
The most significant difference between the ANSI primitives and the
API layer is the way color attributes are encoded. While the terminal
emulator program interprets the ANSI escape sequences to set color
attributes and text modifiers, it is rather inconvenient to work with them
directly. Internally, the AnsiCmd library encodes color attributes as
32-bit bit fields.
List of Attribute Names
Attribute Bitfield Definitions
Display Formatting Methods
Erase the current data displayed in the specified area of the terminal
window, or format text paragraph data to fit within a specified area.
Line Drawing Methods
Draw horizontal and vertical lines or draw rectangles in the terminal window.
Identify "Special" Keycodes
Identify whether a given keycode matches one of the defined “special”
or “command-key” keycodes.
Temporary File Management
Create and manage temporary files for useby the application.
Communicate With System Clipboard
Establish a communications channel with the system clipboard and exchange
text data with the clipboard.
AnsiCmd Clipboard Access
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.
acSetAttributes ( acaFG_BLUE ) ;
acSetAttributes ( acaBG_GREEN ) ;
acSetAttributes ( acAttr(acaFG_BLUE | acaBG_GREEN) ) ;
acSetAttributes ( acAttr(acaBOLD | acaITALIC) ) ;
acSetAttributes ( acAttr(acaCLEAR_MODS | acaBOLD) ) ;
acSetAttributes ( acaCLEAR_MODS ) ;
acSetAttributes ( acAttr(acaBOLD | acaFG_BLUE) ) ; or acSetAttributes ( acaFGb_BLUE ) ;
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.
'resetAll' flag set: acSetAttributes ( acAttr(acaFG_BLUE | acaBG_GREY | acaUNDERLINE), true ) ;
'resetAll' flag: acSetAttributes ( acaATTR_DFLT, true ) ;
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 );
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.
Technical Notes on the acAttr Enumerated Type
The
acAttr(AnsiCmd Attributes) enumerated type provides application-level color-attribute and text-modifier configuration for terminal applications. The enumerated list,enum acAttris defined inAnsiCmdDef.hpp.Members of this type specify color attributes and text modifiers in a consistent format which encapsulates the primitive
ANSIescape sequences defined for terminal-window text formatting. (see enum aeSeq).Within the AnsiCmd class, these values are decoded and mapped to their corresponding
ANSIescape 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
acAttris 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 classbelow 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
APImethod 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
acaExpandclass. The data managed by theacaExpandclass are derived from theacAttrenumerated type and theWebSafeRGBenumerated type. These are both defined inAnsiCmdDef.hpp.The
acaExpandclass is also defined inAnsiCmdDef.hpp, and is implemented in theAnsiCmdAca.cppsource module.All methods and data members of the
acaExpandclass 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. Example:
acaExpand aca( acAttr(acaFG_RED | acaBG_GREY) );
void decode ( acAttr bits ) ;
Decode the specified bitfield value into it component parts and store them in the data members.acaExpand aca; aca.decode( acAttr(acaFG_RED | acaBG_GREY) );
acAttr modify ( acAttr acaValue, bool add ) ;
Add (or remove) one or more elements to (from) the bitfield value.
'acaValue'specifies the item(s) to be modified.
'add'(optional, ’true’ by default)
referenced ONLY for text modifiers, not color attributes
if true, add the ’acaValue’ items to the existing bitfield
if false, remove (reset) the specified items
acaEx.modify( acaBOLD, true ); acaEx.modify( acaBOLD, false ); acaEx.modify( acAttr(acaFGb_RED | acaBG_BLUE) );
void update ( aeSeq aesValue, uint8_t colorIndx = ZERO );
Update attribute tracking data by converting the provided member of
enum aeSeq to the equivalent acAttr bitfield value.
'aesValue'aeSeq item specifying attribute to be updated
'colorIndx'for aeSeq items requiring a color-attribute index value
(Used internally, but not really useful at the application level.)
acAttr compose ( void );
Construct an acAttr attribute bitmap from the data in the data members:
fgIndex, bgIndex and the boolean (flag) members. This is the reverse of the'decode'method, above, and is used to encode 8-bit and RGB attribute indices. (Used internally, but not really useful at the application level.)
Please refer to the API-level method acComposeAttributes which calls the ’compose’ method with consistent formatting.
bool swap ( void );
Swap (exchange) the foreground and background attributes.
Text modifiers are not affected.
acAttr buildRgb ( bool fg, WebSafeRGB fgVal,
bool bg = false, WebSafeRGB bgVal = wsrgbMIN ) const
Construct an acAttr bitfield from web-safe RGB color indices.
Specify RGB values for foreground and/or background color attributes. The values are members of enum WebSafeRGB which encode the RGB'hue'and'shade'used to initialize the Red/Green/Blue register values.
'fg'’true’ if foreground value specified in ’fgVal’
’false’ if ’fgVal’ is to be ignored
'fgVal'member of enum WebSafeRGB
if ’fg’ flag is set, web-safe RGB foreground value
if ’fg’ flag is reset, this value is ignored
'bg'’true’ if background value specified in ’bgVal’
’false’ if ’bgVal’ is to be ignored
'bgVal'member of enum WebSafeRGB
if ’bg’ flag is set, web-safe RGB background value
if ’bg’ flag is reset, this value is ignored
Returns: the constructed acAttr bitfield (If one or more parameters out-of-range, acaATTR_DFLT is returned.Examples:
1) Construct a bitfield with medium red foreground and dark blue background. acaExpand aca ; acAttr newVal = aca.buildRgbVal ( true, WebSafeRGB(wsrgbRED + wsrgbSHADE_MED), true, wsrgbBLUE ); aca.decode( newVal ); 2) Construct a bitfield with bright cyan background, and with a standard 4-bit (non-RGB) blue foreground. acaExpand aca ; acAttr newVal = aca.buildRgbVal ( false, wsrgbMIN, true, WebSafeRGB(wsrgbCYAN + wsrgbSHADES - 1) ); newVal = acAttr(newVal | acaFG_BLUE); aca.decode( newVal ); 3) Construct a bitfield with bright magenta foreground, and a medium blue background shade. acaExpand aca ; acAttr newVal = aca.buildRgb ( true, WebSafeRGB(wsrgbMAGENTA + wsrgbSHADE_MAX), true, WebSafeRGB(wsrgbBLUE + wsrgbSHADE_MED / 2) ); aca.decode( newVal ); 4) Construct a bitfield with bright yellow foreground and a medium blue background. acaExpand aca ; acAttr newVal = acaBld.buildRgb( true, WebSafeRGB(wsrgbBROWN + wsrgbSHADE_MAX), true, WebSafeRGB(wsrgbBLUE + wsrgbSHADE_MAX * 0.65) ); aca.decode( newVal );
acAttr build8Bit ( bool fg, uint8_t fgVal, bool bg, uint8_t bgVal ) const
'fg'’true’ if foreground value specified in ’fgVal’
’false’ if ’fgVal’ is to be ignored
'fgVal'index of foreground attribute, range: min8BIT - max8BIT
if ’fg’ flag is set, calculate foreground bitfield
if ’fg’ flag is reset, this value is ignored
and foreground bits are initialized as reset
'bg'(optional, ’false’ by default)
’true’ if background value specified in ’bgVal’
’false’ if ’bgVal’ is to be ignored
'bgVal'(optional, min8BIT by default)
index of background attribute, range: min8BIT - max8BIT
if ’bg’ flag is set, calculate background bitfield
if ’bg’ flag is reset, this value is ignored
and background bits are initialized as reset
Returns: the constructed acAttr bitfieldacaExpand acaBld ; acAttr pbAttr = acaBld.build8Bit( true, 160, true, 82 ) ; acAttr sbAttr = acaBld.build8Bit( true, 16, true, 219 ) ; acAttr rbAttr = acaBld.build8Bit( false, 0, true, 219 ) ; acAttr sbAttr = acaBld.build8Bit( true, 16 ) ;
aeSeq bits2aeseq ( acAttr acaBits, uint8_t byteIndx, bool isFgnd, bool isRgb );
Convert between acAttr (bitfield) and aeSeq (ANSI escape sequence).
Note: If the aeSeq value is one of the 4-bit "bold" foreground attributes, the ’boldMod’ flag is set. Otherwise the flag is not modified.
'acaBits'acAttr bitfields to be converted
'byteIndx'byte index value (either foreground or background index)
(currently unused)
'isFgnd'true if foreground target, false if background target
'isRgb'(optional, false by default)
true if'acaBits'references one of the
web-safeRGB register indices, minRGB-maxRGB.
’false if ’acaBits’ is a lookup table index:
0-15 : 4-bit color index
16-231 : 8-bit color index
232-255 : greyscale index
Returns: member of enum aeSeqacAttr attrBits = acAttr(acaFG_CYAN | acaBG_BLUE) ; WebSafeRGB attrRgb = wsrgbBLUE + wsrgbSHADE_MED ; acaExpand acax ; // 8-bit background aeSeq attrSeq = acaex.bits2aeseq ( attrBits, 0, false ); // RGB foreground attrSeq = acaex.bits2aeseq ( attrRgb, 0, true, true );
acAttr aeseq2bits ( aeSeq aesCmd, bool& setFlag );
Convert between aeSeq (ANSI escape sequence) and acAttr (bitfield).
For named escape sequences only; specifically:
a) 4-bit foreground
b) 4-bit background
c) text modifier flags
All other aeSeq values return acaPLAINTXT (i.e. zero).
Note: If the aeSeq value is one of the 4-bit "bold" foreground or background attributes, the ’boldMod’ flag is set.
Otherwise the flag is not modified.
'aesCmd'member of enum aeSeq to be converted
'setFlag'(by reference) receives the state of the internal
set/reset flag associated with the attribute
Returns: member of enum acAttraeSeq fgnd = aesFGb_BLUE ; bool flag ; acaExpand acax ; acAttr convAttr = acax.aeseq2bits( fgnd, flag ) ; Returns: convAttr == acaFGb_BLUE and flag == true
bool web2regs ( uint8_t webrgb, bool fgnd );
Convert web-safe RGB index into red/green/blue RGB register values.
'webrgb'value indicating one of the web-safe RGB register groups
in the range: wsrgbMIN <= webrgb <= wsrgbMAX.
'fgnd'true if fgnd attributes, false if bgnd attributes
216 web-safe colors are defined by the standard, which are mapped to the 256 color indices defined for terminal color attributes and are then translated to individual R, G and B register values as shown.DARK >>>> LIGHT CORRESPONDING RGB REGISTER INDICES Black : 0 16;16;16 Red group : 1 36 22;16;16 >>>> 231;16;16 Green group : 37 72 16;22;16 >>>> 16;231;16 Blue group : 73 108 16;16;22 >>>> 16;16;231 Brown group : 109 144 22;22;16 >>>> 231;231;16 Magenta group: 145 180 22;16;22 >>>> 231;16;231 Cyan group : 181 216 16;22;22 >>>> 16;231;231 Grey group : 217 231 22;22;22 >>>> 231;231;231
void reset ( bool modsOnly = false ) ;
Reset (clear) all data members. Optionally, reset text-mod flags only.
'modsOnly'if true, reset only the text-modifier attributes
if false, reset all color and text-modifier attributesacaExpand 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
' ',
acAttr fillattr = acaUSEDFLT );
Input : fillchar: (optional, space character ' ' by default)
specify a (single-column) character to be written to
each character cell of the terminal window
fillattr: (optional, default: terminal default attribute)
color attribute for clearing the terminal window.
Note: If a non-default attribute is specified, that will
be the current fg/bg attribute on return.
Returns: nothing
Clear the entire terminal window using the specified fill character and color attribute.
On return, the visible cursor will be at the HOME position (1,1).
wchar_t fillchar = L' ',
acAttr fillattr = acaUSEDFLT );
wchar_t fillchar = L' ',
acAttr fillattr = acaUSEDFLT );
Input : row : top row of target area
col : left column of target area
OR
wpOrig : top row and left column of target area
height : number of rows in target area
width : number of columns in target area
fillchar: (optional, ' ' by default)
specify a (single-column) character to be written to
each character cell in the target area
fillattr: (optional, default: terminal default attribute)
color attribute for clearing the target area.
Note: If a non-default attribute is specified, that will
be the current fg/bg attribute on return.
Returns: 'true' if successful
'false' if parameter(s) out-of-range
Clear the specified rectangular area using spaces (default), or using the
specified fill character.
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.
Note: On return, the cursor position within the window will be indeterminate, so it is caller’s responsibility to adjust cursor position.
bool trunc = true, bool hypenbrk = false,
short *truncIndex = NULL );
bool trunc = true, bool hypenbrk = false,
short *truncIndex = NULL );
Input : on entry, contains raw message text and
on return, contains formatted message text
gsTxt : (by reference) a gString Object
OR
wTxt : a wchar_t string (32-bit characters)
maxRows : maximum rows for message
maxCols : maximum columns on any message row
trunc : (optional, 'true' by default)
if 'true', truncate the data if necessary to ensure
that the data do not extend beyond the
specified target area
if 'false', format the entire source text array, even
if doing so requires violating the specified
height of the target area (maxRows).
(see also 'truncIndx' parameter)
hyphenbrk: (optional, 'false' by default)
if 'false', automatic line breaks occur after space
characters only.
ASCII space (U+0020)
CJK space (U+3000)
CJK comma (U+3001) (see notes)
CJK full stop (U+3002) (see notes)
if 'true', in addition to the space ' ' characters,
enable line break at:
ASCII hyphen '-' (U+002D)
Unicode — '—' (U+2014)
Unicode – '–' (U+2013)
Unicode − '−' (U+2212)
truncIndx: (optional, null pointer by default)
-- referenced _only_ when the 'trunc' flag is reset
if specified, points to a variable to receive the
index at which the data _would_have_been_ truncted to
fit the specified height of the target area if the
'trunc' flag had been set.
a) A positive value indicates that the data have not
been truncated, AND that the data extend beyond the
the specified target area.
b) A negative value indicates that it was not necessary
to truncate the data i.e. the data fit entirely
within the target area.
Returns: number of text rows in formatted paragraph
Reformat the provided text to fit within the specified dimensions.
1) Remove all newlines.
2) Perform word wrap to limit width of each row of the paragraph.
3) If necessary, truncate the text to limit height of the paragraph.
(but see the ’trunc’ and ’truncIndx’ parameters)
This method is used internally by the ACWin-class objects when writing text in the window and when creating dialogs within the window, but may be used freely when sizing text for display.
Both single-width and CJK double-width (two column) characters are handled by
the this method.
Note: “CJK” indicates the Chinese, Japanese, Korean
(and historically, Vietnamese) character sets.
Notes on automatic word wrap:
Special Case: In every-day use, CJK text seldom contains any spaces at all
within a sentence, or even between sentences. Two-column punctuation is
designed to provide a visual spacing effect. For this reason, we have made the
design decision to process the following CJK ideographs as whitespace:
'、' comma U+3001 and '。' full stop U+3002
Caution: Tab characters ('\t') are not recognized as whitespace
characters because they are effectively variable width characters. Don’t use them!
Optionally, the ASCII hyphen and the Unicode hyphen-like characters
can be treated as if they were whitespace for purposes of calculating where
to break a line. See the 'hyphenbrk' parameter.
'truncIndx' parameter)
'hyphenbrk' parameter).
gString gsTxt(
"Dashing–through–the–snow–in–a–one-horse–open–sleigh." ); short sindx = ZERO ; while ( (sindx = gsTxt.find( nDASH, sindx )) >= ZERO ) gsTxt.erase( sindx, 1 ) ;"Dashing through the snow in a one-horse open sleigh." Input :
cmd : (optional, default: null pointer) command to be executed
-- any valid command, or sequence of commands may be
specified, using the syntax recognized by the shell
program.
-- if a command is not specified, the default shell
program is invoked with a message similar to:
"type 'exit' to return."
clrWin : (optional, default: false)
if 'false', the called application begins output at the
at the current cursor position
if 'true', clear the terminal window before invoking the
command. The command will appear at the top
of the terminal window
txtAttr: (optional, default: acaUSEDFLT)
-- if the default value is seen, the the current color
attribute settings will be used for both the optional
clear of the window and for the text written by the
called terminal application.
-- if a non-default value is specified, it is used for
both clearing the terminal window ('clrWin' parameter)
and as the color attributes used by the called program
for writing text to the window.
Note: Many console utilities override the existing
terminal attributes, so the specified attribute
may be ignored.
Returns: exit code of child process
Ideally, this is the exit code of the last utility run in the
child process, but this cannot be guaranteed.
Temporarily return control to terminal shell program.
This method uses the standard library 'system' function which in
turn uses members of the 'exec' function group to format and
execute the command and its arguments.
Refer to standard library docs for details:
info system
man 3 system
See also the ACWin-class ShellOut method.
wchar_t begChar = L'\0', wchar_t endChar = L'\0' );
Input : pos : offset from upper-left corner of terminal window to
upper-left corner of box (1-based)
length : length of the line: number of number of rows (vertical),
or number of columns (horizontal).
vertical: 'true' : vertical line
'false' : horizontal line
lType : (optional, ltSINGLE by default) line style
member of enum LineType: either ltSINGLE or ltDUAL
begChar : (optional, null character by default)
specify the beginning endpoint character
endChar : (optional, null character by default)
specify the final endpoint character
Returns: cursor position at the end of the line:
For horizontal lines, this is the column following the last character.
For vertical lines, this is the column below the last character.
Draw a horizontal or vertical line in the terminal window.
Horizontal lines are drawn left-to-right.
Vertical lines are drawn top-to-bottom.
Optionally, the endpoint character(s) may be specified for the beginning
and/or end of the line. The valid endpoint characters include any of the
line-drawing glyphs defined in AnsiCmdDef.hpp. Note however, that the
'begChar' and 'endChar' parameter are not range checked, so the
character specified (if any), will be written. (Use single-column characters only.)
If the endpoint(s) are not specified, the line-drawing character is used
as the endpoint character.
Example:
// define the dimensions of the box
short hgt = 9, wid = 25 ;
// define the upper left corner of the box object
WinPos wp( 9, 9 ) ;
// clear target area using optional color attributes, and note that
// on return, the specified colors are still active.
acClearArea ( wp, hgt, wid, L' ', acAttr(acaFGb_CYAN | acaBG_BLUE) ) ;
// draw the box
acDrawBox ( wp, hgt, wid, ltDUAL ) ;
// move downward to start position of first line
wp.row += 4 ;
// draw a line the full width of the box with connections on each end
acDrawLine ( wp, 25, false, ltSINGLE, wcsLTEEdv, wcsRTEEdv ) ;
// move to the top center of the box
wp = { 9, 21 } ;
// draw a line that connects with the box at the top and terminates
// with a line-intersection character
wp = acDrawLine ( wp, 5, true, ltSINGLE, wcsTTEEdh, wcsINSECT ) ;
// draw a line from below the intersect character to the bottom
// of the box, and which terminates with a connector character
acDrawLine ( wp, 4, true, ltSINGLE, NULLCHAR, wcsBTEEdh ) ;
╔═══════════╤═══════════╗
║ │ ║
║ │ ║
║ │ ║
╟───────────┼───────────╢
║ │ ║
║ │ ║
║ │ ║
╚═══════════╧═══════════╝
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.
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.
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.
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." ) ;
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.
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.
Input : wkey : (by reference) keycode to be tested
alert: (optional, 'false' by default) audible alert
'true' execute a terminal beep if keycode under test
IS one of the supported soft-echo keycodes, but
IS NOT not included in the active soft-echo group.
'false' do not execute an audible alert
eopt : (optional, null pointer by default)
If specified, this is a pointer to an alternate soft-echo
option to be used for the test.
(used internally for special-key verification)
Returns: 'true' if key is one of the ACTIVE special keys
'false' if key is not one of the active special keys
If the caller's keycode is a Special key that IS NOT a
member of the active group. the keycode will be set to
the null character (NULLCHAR) on return.
Determine whether the specified keycode is one of the "special" keys, AND whether that keycode is a member of the active soft-echo sub-group.
The test is performed against the soft-echo option specified by the prior terminal setup, (but see the ’eopt’ argument).
The available character-echo options are members of enum EchoOpt.
Please refer to TermConfig Class, and specifically the 'echoOption'
member variable for terminal setup information.
Each of the soft-echo options encompasses a subset of the supported
"special" keycodes.
Please see Soft Echo Options for a description of the soft-echo groups.
NOTE: This method should not be called when the echo option is not one of the soft-echo options, but if it is, it will only result in a harmess waste of CPU cycles.
Input : wkey : (by reference) keycode to be tested
all : (optional, 'false' by default)
if 'true', include the "special" keycodes as command keycodes*
if 'false, "special" keycodes are excluded
Returns: 'true' if keycode is one of the command keycodes, else 'false'
By default, this test excludes the “special” keycodes.
(see isSpecialKey), however, this method may optionally include
the “special” keycodes within the command-key group by setting
the 'all' flag.
Technical Note: These keycodes have been converted from escape sequences or ASCII control codes to graphing characters; however, they should not be echoed to the display. They would just look like garbage from the user’s point of view. If the keycode is not associated with an action within the application, it should be discarded. See the (protected)
normalkeyProcmethod for additional information.
Temporary files are an integral part of any application which needs to
interact with the host system or with other applications. The AnsiCmd
library provides full support for creating and managing temporary files
within the system temporary directory.
Although the AnsiCmd library does not make use of temporary files
internally; most non-trivial applications do. For this reason, management
of temporary files for applications based on the AnsiCmd library is
encapsulated here to provide a clean interface to the compiler’s standard
library functions for creating and deleting temporary files.
These methods, in turn, rely on the author’s TFMan class which is a
stand-alone class included in, but functionally seperate from the
AnsiCmd/ACWin/ACDlg group.
Please see TFMan Class for a full description of this class
and the associated test utility TFMTest Demo App.
Input : prefix : (optional, default: null pointer)
specify a constant token which will prefix the name of the
temporary sub-directory in which temp files will be created.
If a prefix is not specified, then the default "ANSICMD_"
prefix token is used.
Important Note: Use only valid filename characters
(not "special" chars) for the prefix string
Returns: 'true' if path/dirname created successfully
'false' if call to standard library function failed
Enable support for temporary files:
Create a unique sub-directory within the system’s temp-file directory
to contain the application’s temporary files.
Internally, this is implemented by creating an instance of the
'TFMan' class. The Temp File Manager class encapsulates
creation and deletion of temporary files. This prevents one of the most
common programmer errors, namely exiting the application and leaving orphaned
temp files for the system to clean up. This can be especially important if
your temp files contain sensitive information.
The optional 'prefix' parameter is used as the leading substring for
the filename to be constructed. A unique six-character sequence will be
appended to this sequence to form the name of the subdirectory.
This name is guaranteed to be unique within the system’s temporary directory.
If no prefix is specified, then the default prefix ("ANSICMD_") will be used.
Input : none Returns: nothing
Disable support for temporary files.
Delete the sub-directory containing the application’s temporary files and
any files remaining in that subdirectory.
1) May be called directly by the application layer, or else
2) Will be called by the AnsiCmd-class destructor.
Input :
tmpPath: (by reference) receives the path/filename of the new file
Returns:
'true' if file created successfully
'false' if library call failed
Create a unique path/filename for a temporary file, then create the file.
The file will have been closed and will be empty (will contain no data).
Input :
tmpPath : full path/filename specification of source
Returns:
'true' if successfully deleted
'false' if library call failed
Delete the specified temporary file.
This method will delete the specified file ONLY if
the file resides within the temporary subdirectory created by
acCreateTemppath.
Input :
version : (optional, default: null pointer) if specified,
pointer to gString object which receives version
number of the WaylandCB class _and_ if available,
the version number of the wl-clipboard utility.
Returns:
'true' if system clipboard connection established
'false' if unable to connect: wl-clipboard utilities
not installed or inaccessable, or system error
Establish communications with the system clipboard.
It is assumed that the system clipboard is managed by the Wayland protocol,
which is the case for most modern Linux distributions.
Create a temporary file in the system temp directory. This file is used for
communications with the external “wl-clipboard” utilities,
“wl-copy” and “wl-paste”.
Please see AnsiCmd Clipboard Access for a discussion of these utilities.
If the wl-clipboard utilities are installed and accessible, establish
the connection with the system clipboard.
This is done through a simple handshake sequence which writes a short text string to the system clipboard, then reads it back. If the received data equal the transmitted data, the connection is verified.
Technical Note: If the connection was previously established, then the
call to acClipboardEnable will reset and re-initialize the connection.
Note on version number report:
If the optional version number parameter is included in the call,
the two version-number sub-strings are returned in the gString object,
separated by a newline character (’\n’) as shown:
"x.y.zz\na.b.c"
where "x.y.zz" is the WaylandCB version, and "a.b.c" is the
reported wl-copy/wl-paste version. Example:
0.0.06\n2.2.1
If communication with the wl-clipboard utilities cannot be established,
the version number will be of the form: “0.0.06\nunknown”
Input : none Returns: nothing
Terminate the connection to system clipboard.
1) Delete the temp files used for communication.
2) Delete the WaylandCB-class object.
3) Return all resources to the system.
Technical Note: If the application forgets to call acClipboardDisable
on exit, the AnsiCmd destructor will release the system resources.
Input : none Returns: 'true' if connection verified, else 'false'
Test the connection with the Wayland clipboard.
Send a short message to the clipboard, then retrieve the data and compare the results.
Input : gsTxt : (by reference) receives contents of clipboard Returns: number of characters returned
Get a copy of the text data on the clipboard.
Technical Note: If communication with the system (Wayland) clipboard has
been established (see acClipboardEnable), the data are copied from
the system clipboard to the local clipboard buffer, and a copy is then
returned to caller.
If communication with the system clipboard has not been established, the
data currently in the local clipboard buffer are returned.
skForm/skField class.
See AnsiCmd Clipboard Access, below for more information.
Input : gsTxt : (by reference) contains data to be written Returns: number of characters written
Write the specified text data to the clipboard.
Technical Note: The data are first written to the local clipboard buffer; then, if communication with the system (Wayland) clipboard has been previously established, the data are copied to the system clipboard.
skForm/skField class.
See AnsiCmd Clipboard Access, below for more information.
Input : none
Returns: number of (wchar_t) characters (including NULLCHAR)
Note that a value of one(1) indicates an empty string.
Returns the number of UTF-32 characters currently in the local clipboard buffer.
Important Note: It can NEVER be assumed that one character equals one byte.
Input : none
Returns: number of data bytes (including NULLCHAR)
Note that a value of one(1) indicates an empty string.
Returns the number of UTF-8 bytes of data on the clipboard.
AnsiCmd library implements a “local clipboard”
which performs copy-and-paste operations within the application. The local
clipboard is under the INCLUDE_API conditional compile directive.
AnsiCmd library is built specifically to avoid third-party
tools; and therefore direct communication between the library and
the system clipboard is not provided; however, an indirect
communications channel to the system clipboard is available, as follows:
AnsiCmd interface with the system clipboard is is included
in this package and is under the INCLUDE_WAYLANDCB conditional-compilation
directive which enables this author’s (very simple) WaylandCB class.WaylandCB
module in the build.WaylandCB class object communicates with the system clipboard
through the Linux utility package, wl-clipboard. The wl-clipboard
suite was written by Sergey Bugaev and is available on most Linux mirror sites: sudo dnf install 'wl-clipboard' or sudo apt-get install 'wl-clipboard'wl-clipboard utility has been installed on the system and its
component interface modules (wl-copy and wl-paste) are
visible on the path, then the WaylandCB object may be initialized at any time
after the AnsiCmd (or ACWin) object has been instantiated. AnsiCmd* acptr = new AnsiCmd( ... ); acptr->acClipboardEnable();
AnsiCmd local clipboard has been established, then data may be
exchanged between the current application and all other processes which
use the system clipboard.
wl-clipboard is not installed, or if communication cannot
be established, then the application will be limited to the local clipboard.
Technical Note: The standalone WaylandCB module
(see By the Same Author)
may be compiled directly into the application instead. If needed, this
would provide the application more direct control of the clipboard interface.
In that case, to avoid resource conflicts, the AnsiCmd instance of the
class should should not be enabled.
For full details on the WaylandCB class and the associated test app,
please visit the author’s website.
skForm object.AnsiCmd methods (acClipboardSetText, etc.) which send data
to the clipboard and retrieve data from the clipboard are for use outside
any window (ACWin object) or dialog (ACDlg object).
Within an ACWin or ACDlg object, data are exchanged with the
clipboard via protected member methods: ('cbCopy' and 'cbPaste').
Text selection, Copy, Cut are Paste operations are initiated using the
“special” key associated with the operation while a
Textbox (ftTB) control has the input focus.
Please see Decoding the Special Keys for a complete list of defined “special keys”.
Invoking the “Copy” or “Cut” operation will copy the
“selected” text of the Textbox field with input focus to the
clipboard. Note that selected text is
underlined
within the field.
The data is first copied to the local (AnsiCmd) clipboard, and then
if the application has enabled communications with the system clipboard,
(see acClipboardEnable), the data are copied from the local clipboard
to the system clipboard, where it will be available to all processes of the system.
(If no text within the field has been “selected”, then the Copy/Cut command will be ignored.)
Invoking the “Paste” operation will copy the text stored on the
clipboard to the IP (insertion point, i.e. the current cursor position)
within the Textbox field which has the input focus.
If the application has enabled communications with the system clipboard,
data is first copied from the system clipboard to the local (AnsiCmd)
clipboard. Then a copy of the data on the local clipboard is written to
the target Textbox field.
If there is “selected” text within the target field the selected
text will be replaced by the clipboard data. Otherwise the clipboard data
will be inserted into the existing text (if any) of the field.
Technical Note: The Paste operation ignores the current state of the
Insert/Overstrike flag when inserting text.
(If the field with input focus is not a Textbox field, then the Paste command will be ignored.)
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.
Input : lo : receives a pointer to current locale structure
tr : (by reference) receives terminal rows
tc : (by reference) receives terminal columns
fn : (by reference) receives current font number
fr : (by reference) receives the 'full-reset' flag value
ws : (by reference) receives the 'wide-stream' flag value
Returns: nothing
Returns a copy of the protected data members of the class.
Used primarily by the ACWin class to synchronize terminal configuration, but may be used by the curious app designer.
void getConfig ( termConfig& tCfg ) ;
Input : tCfg : (by reference) receives configuration data Returns: nothing
For use during development:
The terminal-configuration data used by the AnsiCmd class are private
members; however, during development, it is often useful to retrieve a
snapshot of the current terminal configuration to verify that the terminal
is configured as intended.
void tseReport ( const skForm& skf, const WinPos& wpRpt, uint8_t secret_code ) ;
Although this method is "technically" a public method, it is called ONLY by the test method, Test_SoftEcho() (and its callback function) to report user input and keycode processing. *
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.
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. In addition, “dialogs” (sub-windows)
(see Dialog sub-Windows) may be created within the primary window either to
display informational messages or to interact with the user via
“control” objects such as Pushbuttons.
This table lists the public methods of the ACWin class.
| Method Name | Description |
|---|---|
─── Window-Oriented Methods ─── | ────────────────────────────────────── |
| 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 |
| Write | Write directly to window interior |
| GetCursorPos | Get cursor position in the window |
| SetCursorPos | Set cursor position in the window |
| SetTitle | Specify window title text |
| SetTextAttr | Specify window interior colors |
| SetBorderAttr | Specify window border colors |
| WinInfo | Report basic window information |
─── Form-Oriented Methods ───── | ────────────────────────────────────── |
| EditForm | User edit of skForm object |
| GetForm | Get a pointer to skForm object |
| GetInputFocus | Get index of field with focus |
| 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 |
| isInsertMode | Report insert/overstrike flag |
| AlertEnable | Enable/disable auditory alert |
| EstablishCallback | Specify a callback function |
| KeycodePush | Push a keycode into input stream |
─── Field-Oriented Methods ──── | ────────────────────────────────────── |
| SetFieldText | Replace text in specified field |
| GetFieldText | Get a copy of text in field |
| SetFieldAttr | Set color attributes for a field |
| SetFieldIP | Set insertion point and cursor |
| GetFieldIP | Get current insertion point |
| GetFieldItem | Report highlighted item |
| SetFieldState | Set binary state of field |
| GetFieldState | Get binary state of field |
| SetFieldFlow | Specify auto word wrap option |
| SetFieldLabel | Attach a label to the field |
| SetFieldOutline | Draw a border around a field |
| SetFieldHotkey | Assign a hotkey to the field |
| SetFieldHidden | Set/reset visibility of field |
| SetReadOnly | Set/reset field to read-only |
| SetFieldData | Set field text, color and IP |
| GetFieldData | Report current field stats |
| RefreshField | Redraw text in a field |
| ClearField | Delete text in specified field |
| ReformatFieldText | Reformat text to fit field |
| ScrollFieldText | Auto scroll for multi-row data |
| ShiftFieldText | Block shift for multi-row data |
| HilightFieldText | Highlight a segment of text data |
─── Dialog-Oriented Methods ─── | ────────────────────────────────────── |
| QuickDialog | Simple Info/Decision dialog |
| Dialog | Full-initialization dialog |
| Dialog_GetText | Get data from dialog textbox |
| Dialog_SetText | Set data of dialog textbox |
| Dialog_SetAttr | Set multi-color attributes |
| Dialog_GetItem | Get dialog menu item |
| Dialog_SetItem | Set dialog menu selection |
| Dialog_GetState | Get state of dialog radiobutton |
| Dialog_GetStateXOR | Get state of radiobutton XOR group |
| Dialog_GetField | Get pointer to dialog field object |
| Dialog_Hilite | Highlight a segment of text data |
| Dialog_SetFocus | Set input focus to target field |
| Dialog_SetReadOnly | Set/Reset field’s read-only flag |
| Dialog_Scroll | Adjust control’s insertion point |
| Dialog_Write | Write text to dialog window |
| Dialog_Refresh | Redraw the dialog window |
─────── Utility Methods ─────── | ────────────────────────────────────── |
| FormatParagraph | Automatic text formatting |
| ParagraphSize | Calculate text dimensions |
| isPrint | Test for “graphing” characters |
| EnableFootnotes | Enable/disable output of footnotes |
| Footnote | Write message in bottom border |
| Sidebar | Write message in left/right border |
| DrawBox | Draw a rectangle in text area |
| DrawLine | Draw a line in the text area |
| LaunchDefaultApp | Invoke an external application |
| ShellOut | Invoke an app in current window |
───── Development Support ───── | ────────────────────────────────────── |
| GetWinAttributes | Report color attributes |
| GetWinConfig | Report height, width and position |
| GetFifo | Report saved static text |
| dumpConfig2Log | Write config data to log |
| dumpField2Log | Write skField stats to log |
| dumpMrp2Log | Write MRParse data to log |
| dumpFifo2Log | Write BlockFifo data to log |
| dumpFifoRecord2Log | Write a single FIFO record to log |
| Screenshot | Take a screenshot of the window |
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.
LineType bdrLine = ltSINGLE, acAttr bdrAttrib = acaATTR_DFLT,
acAttr txtAttrib = acaATTR_DFLT, const char* winTitle = NULL, skForm *formDef = NULL );
Input : posRow : Row - position of window within the terminal window
posCol : Column - position of window within the terminal window
winHeight : Height of window in rows
winWidth : Width of window in columns
bdrLine : (optional, member enum LineType, ltSINGLE by default)
border style i.e. type of line for border
Note: specifying either ltHORIZ OR ltVERT will cause
the border to be drawn with spaces only (no line).
bdrAttrib : (optional, acaATTR_DFLT by default, terminal defaults)
border color attributes OR'd value of acAttr bitfields
txtAttrib : (optional, acaATTR_DFLT by default, terminal defaults)
interior color attributes and text modifiers
OR'd value of acAttr bitfields
winTitle : (optional, null pointer by default)
if specified, text for window title displayed in
top border
formDef : (optional, null pointer by default)
an 'skForm' object which specifies the
position and dimensions of the input fields
Returns: implicitly returns pointer to object
Initialization Constructor:
Four parameters are required: upper-left row, upper-left column, window
height (rows) and window width (columns).
Other parameters, if not specified, are set to default values.
Example Instantiation:
ACWin *winPtr = new ACWin( 1, 1, 24, 80 );
Important Note: 'OpenWindow' should be the first ACWin
method called after instantiation because it completes initialization of
the internal data; however, all standard AnsiCmd-class methods are available
through the window object pointer immediately after instantiation.
For instance: winPtr->acCaptureBreakSignal ( true, cchtIgnore, true );
Notes:
'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).
'winHeight' and 'winWidth' specify the number of rows and columns,
respectively defining the dimensions of the window, including the
border.
'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.
'txtAttrib' defines the color attributes for the window interior,
and accepts all foreground/background color attributes and text modifiers.
'winTitle' specifies an optional title which is centered in the
top border of the window.┌───────┤ Wolfie's Favorite Chew Toys ├───────┐'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.stdin) is configured for
unbuffered input, non-blocking read of input data and uses the softEchoA
option to filter keyboard input and echo input to the display.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
}
Input : initText : (optional, null pointer by default)
initial text to be written to window
initField: (optional, -1 by default) [CURRENTLY IGNORED]
index of target field for storing 'initText' data
Ignored if 'initText' not specified.
Returns: cursor position (offset) i.e. text insertion point
This is the character cell following the text in 'initText',
or if no initial text was specified, the upper-left corner.
Complete the window setup sequence and display the window within the terminal display.
For user input fields of the window’s skForm object which have been initialized with text data, the text will be displayed.
On return, the visible cursor will be positioned at the text insertion point
(IP) of the field which has the input focus.
Important Note: 'OpenWindow' should be the first ACWin
method called because it completes initialization of the internal data.
If any other ACWin method is called before 'OpenWindow', it may cause
a reference to uninitialized data.
All standard AnsiCmd-class methods are available through the window object
pointer immediately after instantiation.
Input : clear : (optional, 'true' by default)
if 'true', clear (erase) the display area
if 'false', do not clear the display area
fillColor: (optional, terminal dflt attr by default)
color attribute used to erase the window.
Returns: nothing
Close the window. Relinquish control of the window object.
By default, the window is erased from the terminal display as part of the closing sequence; but the visual display may optionally be retained, even though control over the space has been returned to the system. This includes returning control of input stream buffering to the system.
Note that the window object still exists in memory. To release the window’s
resources, invoke the destructor i.e. delete the ACWin object.
Example: ACWin *winPtr new ACWin ; ... delete winPtr ;
or if the window was created as an automatic variable, the object will
be deleted when it goes out-of-scope. (see ACWin destructor)
Input : none Returns: nothing
Redraw the window to display any changes that have been made, or to recover
when other data have obscured the the window.
For instance, call RefreshWin after a previoius call to HideWin.
The border will be redrawn, the interior of the window will be cleared, and the static text (if any) will be written, and the fields of the skForm object will be redrawn.
Input : fillAttr : (optional, default: terminal default attributes)
color attribute used to erase data from window.
Returns: nothing
Temporarily erase the window from the terminal display.
All window data are retained but are not visible to the user.
To make the window visible again, call RefreshWin.
Input : newPos : (by reference) new row/column position for window origin
(upper-left corner of window)
newText : (optional, null pointer by default)
text to be written to interior of window, beginning at
the upper left corner of the window interior.
Returns: 'true' if success
'false' window position not updated if specified position
would place any part of the window beyond the edges
of the terminal window.
Move the window to another position within the terminal display.
This is simply erasing the window, updating the base position and redrawing
the window at the new position.
The author has found this to be a useful way to draw the user’s attention to some needed action, and of course a moving window could be the basis for a customized screen-saver application.
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.
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.
Input : txtPos : WinPos-class object indicates the zero-based
offset from upper-left corner of window interior
txt : text to write in one of the following formats:
-- gString object by reference
-- wchar_t pointer
-- char pointer
-- a single wchar_t character
txtAttr: (optional, existing text attributes by default)
text attributes and text modifiers
clear : (optional, 'false' by default)
if 'false', existing displayed text unmodified
if 'true', erase window interior before write
Returns: current cursor position (window offset)
Write text to the interior of the window.
This group of methods writes directly into the window’s text area, bypassing
and obscuring any defined text fields.
These methods will automatically reformat the text if necessary to ensure
that the text does not extend into or beyond the window border.
Please see acFormatParagraph for more information on automatic text
formatting.
To write text into one of the input fields within the window, see SetFieldText.
Input : none Returns: current cursor position (window offset)
Get the current cursor offset within the window’s text area.
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.
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.
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).
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.
Input : wInfo: (by reference) a winInfo-class object to receive the data Returns: nothing
Returns a copy of the window’s current size, position, attributes and other basic information.
This information is used primarly for development and debugging;
however, it often may be useful to get a snapshot of the window configuration,
especially the 'skf' and 'tcfg' structures.
class winInfo
{
public:
WinPos winBase ; //* Terminal window offset (1-based)
short height ; //* Height of window object (rows)
short width ; //* Width of window object (columns)
short txtRows ; //* Number of text (interior) rows
short txtCols ; //* Number of text (interior) columns
acAttr bdrAttr ; //* Color attributes for window border
acAttr txtAttr ; //* Color attributes for window interior
LineType bdrStyle ; //* Line type for border
const skForm *skf ; //* Definition of text fields within the window
bool wcbConnect ; //* Set if connected with Wayland clipboard
termConfig tcfg ; //* Terminal configuration data
} ;
Note that the current window dimensions and position are not guaranteed to be those specified during instantiation. This is because the constructor range checks and automatically adjusts these values as necessary to fit within the terminal window.
Input : focusFld : (by reference) receives the index of the field with
input focus on return to caller.
(initial value ignored)
exitField: (optional, default: -1) If specified, this is the index
of the ftPB (Pushbutton) control that, when pressed,
will cause the loop to terminate, and a return to caller.
exitChar : (optional, default: '\0') If specified, when this
character is received, the loop will terminate and
return to caller.
Note: If a callback method has been established which
will determine when to return to caller, then 'exitChar'
should contain the default value.
Returns: keycode of last key pressed
Interactively edit the fields defined within the skForm object.
The skForm class defines an array of user-interface fields within the window which can be used to create an interactive user interface within a console application.
Keyboard input is captured, formatted and written into the fields. Certain
“special keys” are defined for navigating within and among the
fields. These keycodes are discussed in the chapter on terminal configuration.
Please 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.
There are three ways to exit the user-interface loop:
EditForm loop, a
“callback”
method may be established at the application level.
The user interface loop will then invoke the callback method for each
keystroke entered by the user.Input : nothing Returns: pointer to the window's skForm object.
Get a pointer to the window’s skForm object.
Note: This is a ’const’ pointer. Contents may not be modified.
This method is useful when the call to EditForm has returned, because
it reports the final contents and states of the skForm control array.
It is also useful during the development process.
A technical description of the skForm class and the associated skField class as well as a discussion of user interaction with these objects can be found at: skForm Class and skField Class.
InputFocus ( void );
Input : none Returns: index of field with focus
Returns the index of the field within the skForm object which currently
has the input focus.
This value may also be obtained directly if a previous call to GetForm has
initialized a pointer to the internal skForm-class data.
See GetForm, for more information.
InputFocus ( 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.
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.
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.
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).
Input : none Returns: current state of the Insert/Overstrike flag
Reports the current state of the skForm object’s Insert/Overstrike flag.
If set, Insert Mode:
A character written to the target field will be inserted at the current cursor
position, which will push trailing text to the right.
If reset, Overstrike Mode:
A character written to the target field will replace (overwrite) the text
at the current cursor position.
See also the InsertKey method, above.
Input : enable : if 'true', enable alert
if 'false', disable alert
Returns: current state of the alert flag
Enable/disable auditory alert when user presses an invalid key.
The auditory alert is specified during instantiation of the ACWin/skForm
object; however, the alert may be enabled or disabled using this method.
Please see skForm Class for more information.
Input : valid pointer to caller's method of the correct type
OR NULL pointer to disable existing callback
Returns: nothing
Establish (or disable) a callback method which gives the application layer
access to user input so that text fields and other controls in the parent
window may be dynamically updated.
The specified method will be called from within the user-input loop of the
EditForm method.
The external method handles situations that the parent window cannot.
For example:
- secondary validation of text data.
- respond in real time to user keyboard input
- manual update of read-only or hidden controls
- signal that the window is to be closed
The following example of specifying a callback function is taken
from the Test_Menu method in AnsiCmdTest.cpp.
// static non-member pointer providing the non-member
// callback function with access to the ACWin object.
static ACWin* tmwPtr = NULL ;
ACWin *win = new ACWin
( winROW, winCOL, // position (upper-left corner)
winHEIGHT, winWIDTH, // dimensions (height, width)
ltSINGLE, // border style
acaBorder, // border attributes
acaInterior, // interior attributes
" ACWin MenuBar and Context Menu ", // window title
skfPtr // skForm data template
) ;
win->OpenWindow () ; // make the window visible
tmwPtr = win ; // give callback method access to ACWin object
// Specify the callback function to be
// invoked from within the user-input loop.
win->EstablishCallback ( &tmw_Callback ) ;
win->EditForm ( f, NULLCHAR ) ; // interact with the user
win->CloseWindow ( false ) ; // close the window
tmwPtr = NULL ; // reset the external pointer (be safe)
delete ( win ) ; // release the allocated resourses
The callback function is based on the the following template:
typedef wchar_t (*CUPTR)( short ctrlIndex,
wchar_t wkey, bool firstTime );
The 'ctrlIndex' parameter reports the index of the field which
currently has the input focus.
The 'wkey' parameter reports the keycode from the user interface.
The 'firstTime' flag is set ONLY during the initial call
which allow the callback function to initialize its internal data.
The callback function monitors keyboard input and responds to user requests
which cannot be handled automatically by EditForm.
For example, if the user “presses” a Pushbutton or sets/resets
a Radiobutton, the associated action is performed.
The most obvious of the callback actions is responding to the Pushbutton control
which closes the window and returns control to the terminal window shell
program. In this example, the Exit pushbutton is selected by the
user, either by:
1) moving the input focus to that pushbutton and pressing
the 'Enter' (or 'Space') key, or
2) Pressing the "hotkey" associated with the control, which
which in this case is ALT+X.
Note that EditForm automatically interprets the “hotkeys”
associated with individual controls and moves the input focus to that
control. Then the Enter key is passed to the callback indicating that
that control has been “selected”.
As shown in the example, if the control with focus is the Exit pushbutton
and if the keycode indicates that the control has been “selected”,
then the special 'exit' keycode is returned, signalling that EditForm
should terminate the loop and return control to the application level.
const short fldPB_MBAR = ZERO ; // index of pushbutton activating menu bar
const short fldPB_EXIT = ZERO ; // index of 'Exit' pushbutton
if ( firstTime ) // first call
{
// initialize static data (if any)
}
if ( (wkey == wcsENTER) || (wkey == wcsSPACE) )
{
if ( ctrlIndex == fldPB_MBAR )
{
. . .
wkey = L'\0' ; // signal that keycode was handled
}
else if ( ctrlIndex == fldPB_EXIT )
wkey = wcsCTL_4 ; // signal loop termination
}
return wkey ;
The received keycode ('wkey') can be returned as received, or
can be modified as a signal to the EditForm loop.
If the operation has been fully handled, the callback will return the
null character (L'\0').
If the callback method returns wcsCTL_4, it is the signal that
EditForm should terminate the loop and return to caller. Note that
wcsCTL_4 is the ASCII code for the SIGQUIT signal, and will never be
transmitted to the callback method as the 'wkey' parameter.
C++17 support, so we have delayed implementation until
the community has made the transition.
Input :
wKey : keycode to be placed into the queue
Returns:
'true' if keycode successfully pushed into the input queue
'false' if input queue is full
Push a keycode into the input stream.
All valid wchar_t (wide) keycodes are accepted. The maximum number of
keycodes which can be pushed into the input stream FIFO queue without an
intervening read is defined as KEYPUSH_MAX (currently 16).
Keycode FIFO Queue Development
Three additional methods are defined for management of the input stream FIFO queue. These are under a conditional compile directive and are used only during development.
Clear (reset) the KecodePush FIFO queue.
All keycodes in the queue will be discarded. Note that this does not affect data in the system key input stream.
▪ void KeycodePush_Clear ( void );Return the number of keycodes currently in the keycode pushback FIFO queue, and optionally, return a copy of the current contents of the queue.
▪ short KeycodePush_Report ( wchar_t* kfifo = NULL );
wchar_t fifoCopy[KEYCODE_MAX] ;
short kpCount = win->KeycodePush_Report ( fifoCopy ) ;
Extract a keycode from the keycode pushback FIFO queue.
(If the queue is empty, wait for key input from the keyboard.
▪ wchar_t KeycodePush_Pull ( void );Please study the keyPushback class for an example of how a FIFO queue works. Because this is a very small FIFO, it is implemented the easy way, with data shifted each time an item is removed. In a more sophisticated implementation, a dual-indexed wrap-around sequence would be used to enhance performance.
Indx, const gString& srcTxt,
bool refresh = true );
Indx, const wchar_t* srcTxt,
bool refresh = true );
Indx, const char* srcTxt,
bool refresh = true );
Input : fIndx : index of target field within the skForm object
srcTxt: text to be written to target field
Text data may be in the form:
1) gString object (by reference)
2) pointer to wide (wchar_t) text data
3) pointer to UTF-8 (byte-oriented) text data
refresh : (optional, default: true)
if 'true', refresh the field display
if 'false', do not refresh the display
Returns: 'true' if successful
'false' if invalid field index specified, or if operation
is not supported for target field type
Replace the current contents of the field with new data.
The ’ip’ (text insertion point) of the field is set to zero, and the
cursor is set to the field origin.
Field types for which text data may be modified:
1) ftTB (Textbox), 2) ftSB Scrollbox, 3) ftPB (Pushbutton)
Text for other field types is set during instantiation and remains static.
Indx, gString& txtBuf ) const;
Indx, wchar_t* txtBuf, int maxChars ) const;
Indx, char* txtBuf, int maxBytes ) const;
Input : fIndx : index of target field within the skForm object
txtBuf : (by reference) receives a copy of field text
OR pointer to wchar_t buffer
OR pointer to char (UTF-8) buffer
maxChars: for wchar_t target buffer, maximum number of wchar_t
characters to write
OR
maxBytes: for char target buffer, maximum number of UTF-8
bytes to write
Returns: number of characters written to target buffer including null
terminator (if target is UTF-8 buffer, byte count is returned)
-- If invalid field index specified, or if operation is not
supported for target field type, the target buffer is set
to an empty string, and a zero value is returned.
-- If the text is larger than the target buffer, then text
will be truncated to fit the target.
Get a copy of the current contents of the target Textbox (ftTB) field.
IMPORTANT NOTE: Target buffer must be large enough to hold
AT LEAST two(2) wchar_t characters OR five(5) UTF-8 bytes.
Otherwise, you may as well be working for Microsoft.
Indx, acAttr txtAttr );
Input : fIndx : index of target field within the skForm object
txtAttr : (acAttr bitfield) a logical OR of forground and
background color attributes and attribute modifiers
(note: use of 'underline' modifier not recommended)
Returns: 'true' if attribute set successfully
'false' if invalid field index specified
Set the color attributes and modifiers for the specified text field. Refresh the field display using the modified attributes.
On return, the cursor is positioned in the field with input focus.
Indx, const acAttr* rowAttr, short rowCnt );
Input :
fIndx : index of target field (ftMB or ftSB only)
rowAttr: pointer to an array of acAttr color attributes, one
attribute for each text row of the control.
rowCnt : number of attribute values in the 'rowAttr' array (>zero).
(The minimum _practical_ value is two(2).
Returns: 'true' if attribute set successfully
'false' if invalid field index specified, or
if field type does not support per-row
attributes, or if 'rowCnt' out-of-range
Set the color attributes and modifiers for the specified field.
The array of attributes will be applied one per text row within the field.
Multi-color attributes apply only to Menus (ftMB) and Scrollbox (ftSB) controls. These control types contain data which is not edited, and therefore the color specified for each row will remain unchanged until the window is closed.
It is recommended that this method be called AFTER instantiation of the
ACWin object, but BEFORE the call to OpenWindow. If called after the
window has been opened, then on return from the call, the application should
refresh the display explicitly. This will ensure that the changes are visible.
To specify per-row color attributes for controls within an ACDlg
sub-window, please see colorConfig.
IP ( short fIndx, short newIp,
bool centered = false, bool refresh = true );
Input :
fIndx : index of target field
newIp : character offset into the text of the field
ZERO <= newIp <= text characters
where ZERO == field origin and any value at or beyond
the number of characters in the array signals that IP
should be set to end-of-text.
centered: (optional, default:false) vertically center
the row containing the IP within the field.
refresh : (optional, default:true) refresh display
if 'true' make changes visible
if 'false' do not update display
Returns: 'true' if successful
'false' if invalid field index specified
Set the insertion point (IP) for the field. This will set the cursor
position over the character at the specified offset.
Field types supported by this method are:
1) ftTB (Textbox) 2) ftSB (Scrollbox).
Insertion point for other field types is managed programatically.
Scrolling to ensure that new IP position is within visible space:
'centered' parameter will further adjust the
position of the row containing the target IP so that it will be vertically
centered within the field.If 'fIndx' references the field which has input focus, the visible cursor
will also be updated by default, but see the 'refresh' parameter.
Special case: If 'newIp' is greater that the number of characters in the
field, IP will be set to end-of-text (referencing the null terminator).
Example
For example, if user wants to find a tune in the playlist, she will type in a keyword or phrase and the application will locate the token and bring that song title into the visible space.
(Simplified) Code
enum fieldNames : short
{
fnLIST = ZERO,
fnFIND,
fnPLAY,
fnCANCEL,
fnFIELDS
}
int trgetIp ;
gString gsList, gsFind ;
// Get text of "List" field
win->GetFieldText ( fnLIST, gsList ) ;
// Get text of "Find" field
win->GetFieldText ( fnFIND, gsFind ) ;
// Set focus to list field
win->SetInputFocus ( fnLIST ) ;
// Search for token in the list
if ( (targetIp = gsList.find( gsFind.gstr() )) >= ZERO )
{
// Set Insertion Point to first character of token
win->SetFieldIP ( fnLIST, targetIP, true, true ) ;
// Clear the search text
win->SetFieldText ( fnFIND, "", true ) ;
}
// Display error message
else
win->SetFieldText( fnFIND, "Title Not Found", true ) ;
For a more complex example, see 'gotoLine' method of the
AcEdit Demo App.
Indx );
Input : fIndx : index of target field
Returns: current character offset into the text of the field
(if invalid field index specified, zero will be returned)
Get the current insertion point (IP) for the specified field.
Note that although this method returns the IP value for all control types,
this value will be meaningful only for Textbox (ftTB) fields,
and possibly Scrollbox (ftSB) fields.
For other types of controls IP and cursor position are not meaningful.
For controls with “selectable items” i.e. menus (ftMB) and
Scrollbox (ftSB) controls, refer to the GetFieldItem below, or to the
skField-class getItem method.
Input :
fIndx : index of target control
itemIndex : (by reference) receives (0-based) index of item which
is referenced by the IP
itemHotkey: (by reference) receives the "hotkey" character (if any)
for that item.
If no hotkey indicator found, '?' is returned.
itemText : (optional, default: null pointer)
If specified, this is a pointer to a gString object
which will receive the text of the target item.
Returns:
'true' if successful
'false' if invalid field index or target is of unsupported
control type
'itemIndex' will be set to -1 and
'itemHotkey' will be set to '?', and
'itemText' if specified, will be set to an empty string.
For Menus (ftMB) and Scrollbox controls (ftSB), retrieve the index
of the "item" (row) containing the insertion point ('ip').
Generally, this is the currently hightlighted item or the item
which was highlighted when the control lost focus. The “hotkey”
character for the item (if any) is also extracted from the item text.
This method will typically be called from the application’s callback function after the item-selection signal (Enter key) is received; however, a prior item selection is not necessary. It is also useful after return from the EditForm method.
This method calls the low level (but still public) skField-class
getItem method. This low-level method is intended primarily for
use by dialog-oriented callback functions, and is somewhat more
difficult to use. The GetFieldItem method makes the operation
somewhat less painful.
Please see skField Public Methods for more information.
Input : fIndx : index of target field within the skForm object
state : if 'true', set field state
if 'false', reset field state
refresh : (optional, 'false' by default)
if 'true', refresh the field display
if 'false', do not refresh the field
Returns: current state of the field
Set the "state" of a binary field.
Currently, this applies only to Radiobuttons (type==ftRB).
When the binary state is 'set', the indicator character is displayed
between the delimiters:
[♦] Allow your internet provider to sell your personal info.
When the state is 'reset', the indicator character is replaced by
a space character.
[ ] Allow your internet provider to sell your personal info.
Input :
fIndx : index of target field within the skForm object
xorMember: (optional, default: null pointer) for XOR groups only
if specifed, the referenced variable receives the index
of the control whose 'set' flag is 'true.
Returns:
current state of 'state' flag for field referenced by 'fIndx'
Get the current "state" of a binary field.
Currently, this applies only to Radiobuttons (type==ftRB).
XOR Groups:
For radiobutton XOR groups, the binary state for only one member of the group
can be “set” i.e. ‘true’. If 'fIndx' references
a member of an XOR group, and if the 'xorMember' pointer is
non-null, then the variable referenced by 'xorMember' receives the
index of the group member whose flag is “set”.
'xorMember' will receive the 'fIndx' value.
Indx, FloType fType, bool refresh = false );
Input : fIndx : index of target text field
fType : member of enum FloType
refresh : (optional, 'false' by default)
if 'true', immediately reformat field text
and update the display
if 'false', text is reformatted, as needed but
display is not updated
Returns: 'true' if flow option set successfully
'false' if invalid field index specified or if target field
is a single-row field or invalid 'fType'
Set the text-flow type and optionally reformat the existing text.
Note that this option applies only to multi-row text fields. Text of
single-row fields is always truncated at the edge of the field
(see flowShift option).
The available text-flow options are specified by enum FloType and are:
floToken – Automatic text wrap by token. A “token”
is a sequence of characters delimited by whitespace or in certain cases,
also by punctuation.'txt' member
as desired; however, if necessary, the text will be automatically reformatted
to fit within the field. ASCII Space (U+0020) CJKSPACE (U+3000) CJKCOMMA (U+3001) CJKSTOP (U+3002)floHyphen – Same as 'floToken' above, with the addition of
the following hyphen-like characters being recognized as whitespace. ASCII Minus (U+002D) uMINUS (U+2212) HTML − nDASH (U+2013) HTML – mDASH (U+2014) HTML — sDASH (U+00AD) HTML ­floChar – Automatic text wrap by character.floShift – This option disables word wrap. Instead, each
text row that is too wide to fit in the field will be truncated for display
to avoid violating the field boundaries. Note that the source text itself is
not altered; only the displayed data are affected.'floToken' formatting described above
in that 'floToken' data are only scrolled vertically.
floDflt – This option is used as a placeholder for optional
call parameters, and is interpreted to mean that the existing word-wrap option
is not to be modified.
For more information on auto-formatting please refer to acFormatParagraph or the gString-class method, formatParagraph.
Input :
fIndx : index of target field
labText : display text, optionally including a "hotkey" character.
A hotkey is specified using the CARET character ('^')
followed by the ASCII character which indicates the
keycode to be used as a hotkey. (see examples)
labAttr : (optional, default: text attributes of parent window)
color attributes for label text.
center : (optional, 'false' by default) horizontal offset
if set, center the label horizontally in the row above
the field
if reset, label is positioned one row above and in
the same column as the left edge of the field
Returns: 'true' if label successfully written, else 'false'
Assign a label, with or without embedded hotkey, to the specified field.
1 <= length <= labelLEN. This is the storage
capacity expressed as the maximum number of characters (currently 64)
for a label. Text will be truncated if necessary to fit the storage array.
wcsALT_A <= hotkey <= wcsALT_RB.
This corresponds to ASCII A-Z, a-z, and most punctuation characters. "Gra^pefruit"'p', indicating that the hotkey is the
ALT+p key combination which is assigned to the wcsALT_P keycode
constant.
The following is a screenshot of a window demonstrating both field labels
and field outlines. This test window may be found in the Test_Form
method in AnsiCmdTest.cpp.
Input : fIndx : index of target field
if 'fIndx' == number of fields defined, then draw an
outline around each field.
lType : (optional, ltSINGLE by default) line style
member of enum LineType: ltSINGLE or ltDUAL
lnAttr : (optional, acaUSEDFLT by default)
If specified, color attributes to be used.
If not specified, stored text attributes used.
Returns: 'true' if successful
'false' if invalid field index or insufficient space
around the target field
Draw an outline around the outside of the specified field within the window border. The contents of the field will be refreshed after the border is drawn.
The target field must have at least one space open on all sides. That is, it must not be positioned against the window border, and must not be adjacent to any other field.
This method calculates the position and dimensions for the outline and then calls the DrawBox method described elsewhere in this document.
Note: Potential incursion into the border is range checked; however, potential incursion into other fields is not tested. Beware!
For Textbox (ftTB) and Scrollbox (ftSB) controls, a label may optionally
be assigned to the field. This label will be positioned in the upper border
of the field outline.
Please see SetFieldLabel for additional information.
Input : fIndx : index of target field within the skForm object
hotKey : hotkey character
Returns: 'true' if hotkey set successfully
'false' if invalid control index, unsupported control type,
specified keycode is not one of the valid hotkey
characters, target control's hotkey was previously set
Set the "hotkey" for the specified control. A hotkey is a character used to
move the input focus to the associated control.
wcsALT_A <= hotkey <= wcsALT_RB.'ALT' key plus ASCII A-Z, a-z, and most
punctuation characters.
CONTROL+ A-Z characters are also available as hotkeys.
Technical Note: A conditional compile directive controls whether these
keycodes when received, will be automatically converted to the equivalent
ALT+n keycode. See the private isHotkey method for details.
When this conversion is enabled, if user presses one of the CTL+n keys, it
will be automatically converted to the equivalent ALT+n keycode, and the
converted keycode will be used to perform the action specified for that
hotkey.
For example: If the hotkey ALT+B is assigned to a Pushbutton control via
the text of the control:
“ ^BACKUP ”,
then the control would be displayed with the 'B' underlined.
BACKUP
The user may then select the control using either ALT+B (wcsALT_B) or
CTL+B (wcsCTL_B) which will have been converted to wcsALT_B.
When this conversion is disabled, then CTL+B and ALT+B are seen as
different hotkeys.
Certain Control+n keycodes are reserved as specific command keys. For example,
the 'wcsCTL_C', 'wcsCTL_X', 'wcsCTL_V' are reserved for “Copy”,
“Cut” and “Paste” respectively.
Please see ASCII Control Codes for a further information.
wcsF01 <= hotkey <= wcsCF12
Please see test A which describes these keycodes in further detail.
Refer also to the source code for the private methods isHotkey and
isFunky which define the full range of available hotkeys.
Note that the standard method for hotkey specification is to embed the
hotkey character in the control label so that the user has a visual cue,
(see SetFieldLabel).
Menubox controls (ftMB) do not have labels. For this reason, if a hotkey
is desired for a menu control, it must be set during skField instantiation
(see skForm Class), OR via this method after ACWin instantiation.
This method may also be used to set the hotkey for some other types of controls (ftTB, ftSB), but this is not recommended because there would be no visible cue to assist the user.
Note that for Pushbutton and Radiobutton controls, the label (and therefore the hotkey, if any) are embedded in the control itself; and therefore this method may not be used to set the hotkey for those control types. Note also that if a hotkey has been previously specified for the target control, it will not be overwritten by this method.
Input :
fIndx : index of target field within the skForm object
hidden ; if 'true', field will become invisible when the window
is refreshed
if 'false', field will become visible when refreshed
readOnly : if 'true', field cannot receive input focus
if 'false', field can receive input focus
refresh : if 'true', if 'hidden' is set, refresh the entire
window interior
if 'hidden' is reset, refresh only the
target field
if 'false', display is not updated
Returns: 'true' if operation successful
'false' if operation fails (invalid field index)
Set the visible/hidden state of the target control and optionally refresh the display.
Except for menu controls, all controls are set as visible by default; however,
for complex user interface configurations, it is common for some inactive
controls to be obscured by other controls. Those obscured controls become
visible and active when needed and then return to the background. In this
way, a creative use of the 'hidden' and 'read-only' flags can
make efficient use of the limited space within the terminal window.
As an example, the AcEdit application included in this package defines
at least fourteen controls which share the application window: a menu group,
a line-number field, a gutter field, a context menu and five overlapping
controls for editing text: upper/lower, left/right and full-window textbox
controls. See AcEdit Demo App for details.
Making the changes visible:
Indx, bool set );
Input : fIndx : index of target field within the skForm object
set : if 'true', set field as read-only
if 'false', set field as user-accessible
Returns: current state of the read-only flag
Enable or disable read-only state for the specified field.
If a field is set as read-only, then it cannot receive the input focus; and therefore cannot be accessed by the user. A field which has been set as read-only may or may not be visible (see SetFieldHidden above).
Indx, const gString& srcTxt,
acAttr txtAttr = acaUSEDFLT,
short newIp = ZERO, bool refresh = true );
Indx, const wchar_t* srcTxt,
acAttr txtAttr = acaUSEDFLT,
short newIp = ZERO, bool refresh = true );
Indx, const char* srcTxt,
acAttr txtAttr = acaUSEDFLT,
short newIp = ZERO, bool refresh = true );
Input :
fIndx : index of target field within the skForm object
srcTxt : (by reference) new text data for field
txtAttr : (optional, default: acaUSEDFLT, indicating that
current attributes should not be modified)
acAttr bitfield which is a logical OR of forground and
background color attributes and text modifiers
newIp : (optional, zero(0) by default)
character offset into the text of the field
ZERO <= newIp <= text characters
where ZERO == field origin and any value at or beyond
the number of characters in the array signals that IP
should be set to end-of-text.
refresh : (optional, default:true) refresh display
if 'true' make changes visible
if 'false' do not update display
Returns: 'true' if successful
'false' if invalid field index specified
Set or modify the setup data for the specified field.
The effect is the same as seperately calling three individual methods:
SetFieldText, SetFieldAttr and SetFieldIP (see above),
except that this method is more efficient if modifying multiple parameters.
Not all parameters apply equally to all field types. Some combinations of field-type and configuration settings are fixed on instantiation, and some configuration settings are managed internally by the library methods.
Input : fIndx : index of target field within the skForm object
skfld : (by reference) receives a copy of data members
Returns: 'true' if successful
'false' if invalid field index specified
Get a copy of the current settings for the specified field.
This method is intended primarily for reporting data during development;
however, this method may also be useful at the application level for
analysis of the field data after the EditForm method has returned
control to the application.
NOTE: All data members including protected members are reported.
Please see skForm Class for details on the structure and usage of the
skField-class data members.
Indx );
Input :
fIndx: index of target field
If fIndx < ZERO || fIndx >= total of fields defined (fCnt),
then all fields will be refreshed.
Returns: nothing
Refresh (erase and redraw) the contents of the specified field, or optionally, refresh all fields defined by the skForm object.
Input focus remains on the currently active field, and cursor is returned to insertion point within that field.
Technical Note:
There are two ways to refresh the field labels or field outlines in
addition to the field itself. The first is to set 'fIndx' to 'fCnt'
when calling this method, so that all fields will be refreshed. The other
is to call RefreshWin instead. Either option will redraw the data for
all fields, while RefreshWin will also redraw any static text
in the window.
Input : none Returns: nothing
Refresh (erase and redraw) the contents of the field which currently has input focus.
Indx, bool delText = false,
acAttr txtAttr = acaUSEDFLT );
Input :
fIndx : index of target field
delText : (optional, 'false' by default)
if 'true', delete the stored text of the field
if 'false', stored text is not modified
txtAttr : (optional, acaUSEDFLT by default)
color attributes for the operation
(logical OR of forground and background color)
(attributes and text modifiers )
-- If not specified, then current field attributes
will be used.
if 'delText' is set: field attributes will be updated
if 'delText' is reset: specified attributes will be used
for the clear operation, but won't be saved
Returns: 'true' if target field cleared
'false' if fIndx out-of-range or if field type of target
is not supported by this operation (data not modified)
Erase text from the specified text-field display. Optionally, the stored text is also deleted.
This operation applies ONLY to fields with editable text, specifically, Textbox fields (field type: ftTB).
Input :
fIndx : index of target field
floType: (optional, 'floDflt' by default) member of enum FloType
specify the type of text formatting to be used
If 'floDflt', use the existing formatting option;
otherwise, set the formatting type to the specified
value before reformatting the data.
Returns: 'true' if operation is successful
'false' if a) invalid field index specified
b) target field is not a multi-row textbox
field (ftTB)
Reformat text of the target field using the specified formatting type.
All existing newline characters are removed and the data are reformatted
according to the specified formatting option.
1) Set new formatting option if specified.
2) Remove existing formatting (newline characters).
3) Reformat the data.
4) Set IP and logical cursor to field origin (upper-left corner).
5) Refresh the display.
This operation applies ONLY to multi-row textbox fields (ftTB).
Note also that target field should not have the input focus when data
are reformatted because it could easily confuse the poor user.
See also: SetFieldFlow which sets the formatting option, and reformats the data only if necessary to keep the text within the field boundaries.
Input : fIndx : index of target field
steps : number of rows to scroll
Returns: 'true' if successful scroll
'false' if already at limit in specified direction
Scroll upward or downward through multi-row text fields under program control.
This method applies only to multi-row fields Textbox (ftTB) and Scrollbox (ftSB), and is ignored for single-row fields and other field types.
Examples:
(note how the sign of the shift determines direction of scroll)
steps == 1 scroll up by one row (bring rows below into view)
steps == -1 scroll down by one row(bring rows above into view)
steps == hgt scroll upward by one page
steps == -hgt scroll downward by one page
steps == 0 scroll to the first row of text
steps == 999 scroll to the last row of text. Note that any value
at or beyond the last text row will signal a move
to end-of-text.
Input :
fIndx : index of target field
steps : direction of shift
positive value: shift text upward by one row
(toward bottom of text)
negative value: shift text downward by one row
(toward top of text)
Returns:
'true' if successful shift and/or cursor movement
'false' if already at limit in specified direction
or target control does not support text shift
or parameterout-of-range
Perform a vertical block shift of Textbox data, either upward or downward.
This method applies only to multi-row Textbox (ftTB) controls.
This is similar to the ScrollFieldText method which steps the
cursor through the rows of text data, EXCEPT that for ShiftFieldText,
the cursor position remains constant (continues to reference the same character)
unless the shift would place it outside of the visible space.
Technical Note: The ‘steps’ parameter is currently limited
to a single-row shift: -1 <= steps <= 1. It would be possible to implement
a multi-row shift; however, the usefulness of that enhancement is not
currently apparent.
Input :
fIndx : index of target field
set : if 'true', highlight the text segment
if 'false', clear the highlight
begin : index of first (leftmost) character to highlight
(referenced only when 'set' != 'false')
len : number of characters in highlighted segment
Note: If segment spans rows, be sure to include
the newlines in the count.
(referenced only when 'set' != 'false')
txtmod: (optional, default:acaUSEDFLT)
text modifier attribute for highlighted text segment
- If specified, text modifier attribute for highlighted
text segment. One of the following:
acaBOLD bold-text modifier
acaITALIC italic-text modifier
acaUNDERLINE underline-text modifier
acaOVERLINE overline-text modifier
acaXOUT x-out (strikethrough) text modifier
acaBLINK blinking-text modifier
acaCONCEAL concealed (invisible) text
acaREVERSE reversed fgnd/bkgnd (default attribute)
Note: OR'd combinations of these modifiers are not allowed.
- If not specified, then use previously-specified modifier
(if any), else acaREVERSE (fg/bg attributes reversed)
center: (optional, default: true)
if set, assure that highlight is within visible
space by adjusting the IP if necessary.
if reset, do not adjust IP (highlighted text
may or may not be visible).
Returns:
'true' if highlight set/cleared
'false' a) 'fIndx' references an upsupported control type
b) parameter out-of-range
For Textbox controls only (ftTB), highlight a segment of text using one of the text-modifier attributes. If the target field is currently visible, the field will be refreshed before return.
Note that while any combination of the acAttr color attributes
may be freely OR’d under most circumstances, for this method, exactly
one text-modifier attribute may be specified as the highlight attribute.
For a functional example, please execute the highlighting test:
./epts --test=Wh
Technical Notes:
Calling this method will release any “selected” segment in
the target field. If the user selects text using any of the selection keys:
(Shift + Left/Right/Up/Down or ALT + A), it will release any
highlight within the field.
Please see AnsiCmd Clipboard Access for a discussion of text selection
and moving text to and from the clipboard.
'center=true'),
the text will be scrolled to bring the highlighted segment into view
and will be (approximately) centered within the visible space. acAttr(acaFG_BLUE | acaBG_CYAN | acaITALIC) acaITALIC should not be used as the highlight attribute.
Input :
fIndx : index of target field
txtmod: text modifier attribute for highlighting text segments
Returns:
'true' if highlight attribute initialized
'false' a) 'fIndx' references an upsupported control type
b) parameter out-of-range (default parameter set)
For Textbox controls only (ftTB), set the text-modifier attribute to be used for highlighting text segments within the field.
Note that no text is actually highlighted by this method; only the attribute
is initialized.
Please see the HilightFieldText method, above for additional
information.
See also the skField setHiliteMod method.
A dialog is a small window within the parent window which provides information to the user, and optionally asks for a decision or gathers other information from the user. Please see Dialog sub-Windows for a more detailed discussion of Dialog window functionality.
short height = 0, short width = 0, short vOff = 0, short hOff = -1, short timeout = 0, bool dbg = false );
Input :
gsMsg : (by reference) contains the message(s) to be displayed.
The text may be a formatted paragraph with each text
row terminated by a newline character (\n), OR may be
unformatted text which will be automatically formatted
to fit within the dimensions as specified below.
query : 'true' indicates a decision dialog, and user is
prompted for a yes/no response
'false' indicates an information dialog, and user is
prompted to press Enter to exit
title : (optional, default: null pointer)
If specified, this is the dialog title text which will
be centered in the top border of the dialog.
height: (optional, zero (0) by default) height of dialog window
in rows. A zero value indicates that the dialog is
automatically sized to accomodate the dimensions of the
message text in the 'gsMsg' parameter
width : (optional, zero (0) by default) width of the dialog
window in columns. A zero value indicates that the dialog
is automatically sized to accomodate the message text
in the 'gsMsg' parameter
vOff : (optional, default: 0) vertical offset into the parent
window's text area (0-based)
A negative value indicates that the dialog is to be
centered vertically in the parent window.
hOff : (optional, default -1) horizontal offset into parent
window's text area (0-based).
A negative value indicates that the dialog is to be
centered horizontally in the parent window.
timeout: (optional, zero by default) automatic timeout of
dialog display in seconds
-- By default, the dialog is closed when one of the
pushbutton controls is activated.
-- If a positive value (in seconds) is specified, the
dialog will close automatically after the specified
number of seconds has elapsed OR when any keycode is
received, whichever comes first.
dbg : (optional, default: false) for debugging only:
if reset, refresh the parent window on return
if set, dialog remains visible on return
Returns: if 'query' flag is set, then the user response is returned:
'true' if control at index zero(0) selected
'false' if control at index one(1) selected
if 'query' flag is reset, i.e. dialog has only one control,
then return value is always 'true'.
Generate a “quick” dialog window within the application’s ACWin-class window.
QuickDialog invocations are the simpler of the two dialog types, requiring fewer
configuration parameters.
QuickDialogs are generated in either of two modes
(see 'query' parameter).
Working examples of the quick dialog may be found in the AnsiCmd test suite.
Invoke the EarthPoints test application with:
./epts --test=Dq
for a list of quick-dialog tests.
For a fully-configurable dialog, see the Dialog method below, which accepts customized values for all configuration parameters.
const char* sTxt = NULL, const char* tTxt = NULL, short vOff = -1, short hOff = -1, LineType ltype = ltSINGLE, acAttr bdrAttr = acaUSEDFLT, acAttr txtAttr = acaUSEDFLT, short tvOff = 0, short thOff = 1, bool dbg = false );
Input :
dlgHgt: dialog height (rows)
A value of zero (0) indicates that the height of the dialog
is based on the height (rows) of the PREFORMATTED text it
contains, plus necessary padding (typically an additional
three(3) rows).
The height of the dialog may be calculated as the rows
needed by the controls plus the height of the static text
data, plus top and bottom borders. Some additional space is
recommended to present a pleasing and easily-readable
display.
dlgWid: dialog width (columns)
A value of zero (0) indicates that the width of the dialog
is based on the width (columns) of the PREFORMATTED text it
contains, plus necessary padding (typically an additional
four(4) columns).
The width of the dialog may be calculated as the columns
needed by the widest row of controls, or the width of the
static text, whichever is greatest, plus the right and left
borders. Some additional space is recommended to present
a pleasing and easily-readable display.
formDef:pointer to user-interface control definitions (skForm object)
-- At least one of the defined controls MUST BE a Pushbutton
control; otherwise it is an unrecoverable error.
-- Certain member values are overridden by the values in
the skForm object of the parent window.
-- Invalid or out-of-range members will be silently
corrected to maintain dialog integrity.
-- See note below regarding data modified before return
to caller.
sTxt : static text written to be written to dialog interior
(a null pointer or an empty string indicates that there is
no static message)
tTxt : dialog title, if specified, will be written centered in the top
border of the dialog.
(a null pointer or an empty string indicates that
the dialog will have no title)
vOff : vertical offset (0-based) in rows from top of parent window
(optional, default: -1) A value of -1 specifies that
dialog is centered vertically in the parent window.
hOff : horizontal offset (0-based) in columns, from left edge of
parent window.
(optional, default: -1) A value of -1 specifies that
dialog is centered horizontally in the parent window.
ltype : border style (optional, default: ltSINGLE)
Member of enum LineType (ltSINGLE or ltDUAL)
battr : border color attributes
(optional, default: color attributes are taken from those
of the parent window.
tattr : text (dialog interior) color attributes
(optional, default: color attributes are taken from those
of the parent window.
tvOff : static text position, vertical offset
(optional, default: 0, top row of dialog interior)
thOff : static text position. horizontal offset
(optional, default: 1, inset one column from left edge of dialog)
callbk: (optional, default: null pointer) pointer to a non-member callback
function. (See typedef CUPTR for details.)
If specified, this function will be called by the EditDialog method
each time the user presses a key.
dbg : (optional, false by default) for debugging only:
if reset, refresh the parent window on return
if set, dialog remains visible for analysis
Returns:
index of control with focus when dialog is closed
(this is the same value contained in formDef->fi)
The structure referenced by 'formDef' may have been updated
to contain additional information:
a) Text controls (ftTB): The text of the field may have been
modified by user. The data may be retrieved directly from
the skField object.
b) Radiobutton controls (ftRB): The 'set' flag which indicates
the binary state of the control (set or reset) may have changed.
This flag may be read directly from the skField object.
c) Context Menu controls (ftMB): If a menu item has been selected,
a call to the skField-class getItem() method will return the item.
d) Scrollbox controls (ftSB): If a scrollbox item has been selected,
a call to the skField-class getItem() method will return the item.
If the formDef object as received has been malformed, certain
parameters will have been corrected if possible; or if corrections
are not possible:
a) formDef will be ignored,
b) a warning will be displayed, and
c) a minus one (-1) will be returned.
Generate a dialog window within the application ACWin window. The dimensions, position and color attributes are specified directly, while the dialog’s controls are defined by passing a pointer to a fully-initialized skForm-class object. The referenced skForm object is updated in response to user interaction, so that when the dialog is closed, caller may interpret any changes the user has made to the controls’ status. (see notes below)
Note that verification of all parameters is performed by this method, and adjustments will be made to the position and dimensions of the dialog if necessary to make the dialog fit within the parent window. In addition, the display text, and the position of the controls will be adjusted if necessary to fit within the dialog. Keep in mind however, that it is impractical to test for all varieties of foolishness, such as overlapping controls, so construct dialogs with care.
Working examples of the full-initialization dialog may be found in the
AnsiCmd test suite.
Invoke the EarthPoints test application with:
./epts --test=Dd
for a list of dialog tests.
Please see Dialog sub-Windows for a more detailed discussion of Dialog window functionality.
The following group of methods is intended specifically for use by callback functions, and are active only when a dialog window is currently open. The methods of this group are used to access the dialog’s internal data structures in response to user input. Please see Dialog Callback for additional information.
Input :
ctrlIndx : index of target control within the dialog
txtData : (by reference) receives a copy of the Textbox text
Returns:
'true' if a dialog is currently under edit, AND
if 'ctrlIndx' refrences a control of the correct type
for the operation
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For Textbox controls (ftTB) within a dialog, retrieve a copy of current text data.
acAttr color = acaUSEDFLT, bool refresh = true );
Input :
ctrlIndx : index of target control within the dialog
txtData : (by reference) text which will replace the current text
color : (optional, default: acaUSEDFLT)
if specified this is the new color attribute for the
control, else control attribute is unchanged
refresh : (optional, default: true)
if 'true', refresh the display after update
if 'false', display is not refreshed
Returns:
'true' if a dialog is currently under edit, AND
if 'ctrlIndx' refrences a control of the correct type
for the operation
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For Textbox (ftTB) and Scrollbox (ftSB) controls only, replace existing
display text for the control.
Optionally, set new base color attribute for the control.
The display is updated by default, but update can be delayed by resetting
the 'refresh' parameter.
short acaCnt, bool refresh = true );
Input :
ctrlIndx : index of target control within the dialog
acaArray : pointer to an array of acAttr color attributes, one
attribute for each text row of the control.
acaCnt : number of attribute values in the 'rowAttr' array (>zero)
The minimum _practical_ value is two(2).
refresh : (optional, default: true)
if 'true', refresh the display after update
if 'false', display is not refreshed
Returns:
'true' if a dialog is currently under edit, AND
if 'ctrlIndx' refrences a control of the correct type
for the operation
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
Specify an array of color attributes, one for each item (row) displayed
in the control. Only certain control types accept multi-color attributes:
Scrollbox controls (ftSB)
Multi-row Menus (ftMB)
Please see colorConfig and skField config example for details
on constructing an array of color attributes for use within the target control.
The display is updated by default, but update can be delayed by resetting
the 'refresh' parameter.
short& itemNum, bool select = true );
Input :
ctrlIndx : index of target control within the dialog
itemText : (by reference) receives text of the highlighted line item
itemNum : (by reference) receives the (0-based) item number (index)
of the highlighted item
select : (optional, default: true)
if 'true' return the user 'selected' item (if any)
else, return highlighted item
if 'false' return the highlighted item
clear : (optional, default: false)
if 'true' clear (reset) any current "selection" and
refresh the control to erase the selection
indicator.
if 'false' selection is not modified
Returns:
'true' if a dialog is currently under edit, AND
if 'ctrlIndx' refrences a control of the correct type
for the operation
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For Menus and Scrollbox controls within a dialog, return the data for the highlighted “item”.
"item" is the data for a display row within the control.
Generally, this is the highlighted item i.e. the text under the cursor.Enter or Space keys, then the “selected” item, rather
than the highlighted item will be returned.
"item number" is the index of the of the row containing
the item.
'select' parameter specifies whether the
“selected” item (if any) should be returned or if the highlighted
item should always be the returned item."item text" is the text displayed on that row.Example: "│Clear Bookmarks │\n" becomes "Clear Bookmarks"'^'),
then the menu text will include the caret: "Clear ^Bookmarks".
Example: " The cow in the meadow goes moo. \n" becomes "The cow in the meadow goes moo."
Clear Parameter
If the 'clear' parameter is set, then before return, the current item
selection (if any) will be cleared and the associated selection indicator,
if visible will be removed.
This is useful if the item selection has already been handled or if item
selection is unneeded.
Note that there is a potential timing issue for clearing the ’sitem’
selection member. If this method is called from within a callback in
response to selection keystroke (Enter/Space), then the actual selection
has not yet occurred. In this case, the callback would need to signal that
the selection keycode has been handled. To do this, the callback would
return an alternate keycode instead of the Enter/Space. Suggestions:
return NULLCHAR to indicate that the keycode has been handled, or return
wcsTAB to move the input focus to the next field.
Please see Dialog Callback for more information on callback functions.
Please refer to the getItem method in the chapter on skField
Public Methods for a technical description of 'items' and item selection.
Input :
ctrlIndx : index of target control within the dialog
itemNum : index (0-based) of the item to be set as selected
Note: If valueos out-of-range, then nearest _valid_
item will be selected.
refresh : (optional, default: true)
if 'true' refresh the display
if 'false' display is not updated
Returns:
'true' if: a) a dialog is currently under edit,
b) 'ctrlIndx' refrences a control of the correct type
for the operation
c) the target control _does not_ have input focus
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For Menus and Scrollbox controls within a dialog: set the "selected item"
explicitly. This will draw user’s attention to the item and indicate the
current selection. Note that items are zero-based; that is, the first item
is item zero(0).
The target control must not have input focus when this method is called.
Within Scrollbox controls, the “selected” item is indicated by an arrow at the left edge of the text; while for Menus, the “selected” item is displayed in bold/italic font.
If successful, control is refreshed to visually indicate the selected item.
Input :
ctrlIndx : index of target control within the dialog
rbState : (by reference) receives the current state of the control
Returns:
'true' if a dialog is currently under edit, AND
if 'ctrlIndx' refrences a control of the correct type
for the operation
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For binary-state controls within a dialog, return the current ’state’
flag value: 'set' or 'reset'.
Currently, the binary state flag applies only to Radiobutton controls.
Input :
ctrlIndx : index of target control within the dialog
rbIndx : (by reference) receives index of XOR group member
whose state flag is currently set
Returns:
'true' if a dialog is currently under edit, AND
if 'ctrlIndx' refrences a control of the correct type
for the operation, AND
if the target control is a member of an XOR group
then 'rbIndx' receives the target index
else 'false' ('rbIndx' receives 'fCnt')
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For binary-state controls within a dialog which are configured as XOR group
members, return the index of the control within the group whose binary state
is ’set’.
If the target is not a member of an XOR group, then the
Dialog_GetState method should be called instead.
Currently, the binary state flag applies only to Radiobutton controls.
Input :
ctrlIndx : index of target control within the dialog
skfPtr : (by reference) receives a pointer to _constant_ skField
object. Access to all public data members is available.
Access to 'const' methods (if any) is also available.
Returns:
'true' if a dialog is currently under edit, AND
if 'ctrlIndx' refrences a control of the correct type
for the operation
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For controls within a dialog, return a pointer to the specified control object. This is a const pointer, meaning that the public data may be analyzed, but no data within the object may be modified.
The example below retrieves the dimensions of the control and formats a paragraph of text according to the dimensions. The new text is then written to the target control.
gString gs( "Four score and seven years ago"
"...shall not perish from the earth." ) ;
const skField* skfPtr = NULL ;
if ( (this->win->Dialog_GetField ( fldTXTBOX, skfPtr )) )
{
short fldHeight = skfPtr->hgt ;
fldWidth = skfPtr->wid ;
this->win->FormatParagraph ( gs, fldHeight, fldWidth,
false, false ) ;
this->Dialog_SetText ( fldTXTBOX, gs,
acAttr(acaFG_BLUE | acaBGb_RED) ) ;
}
Input :
ctrlIndx : index of target field
set : if 'true', highlight the text segment
if 'false', clear the highlight
begin : index of first (leftmost) character to highlight
(referenced only when 'set' != 'false')
len : number of characters in highlighted segment
Note: If segment spans rows, be sure to include
the newlines in the count.
(referenced only when 'set' != 'false')
txtmod: (optional, default:acaUSEDFLT)
text modifier attribute for highlighted text segment
- If specified, text modifier attribute for highlighted
text segment. One of the following:
acaBOLD bold-text modifier
acaITALIC italic-text modifier
acaUNDERLINE underline-text modifier
acaOVERLINE overline-text modifier
acaXOUT x-out (strikethrough) text modifier
acaBLINK blinking-text modifier
acaCONCEAL concealed (invisible) text
acaREVERSE reversed fgnd/bkgnd (default)
Note: OR'd combinations of these modifiers are not allowed.
- If not specified, then use previously-specified modifier
(if any), else acaREVERSE (fg/bg attributes reversed)
center: (optional, default: true)
if set, assure that highlight is within visible
space by adjusting the IP if necessary.
if reset, do not adjust IP
(highlighted text may or may not be visible).
Returns:
'true' if highlight set/cleared
'false' a) 'fIndx' references an upsupported control type
b) parameter out-of-range
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For Textbox controls only (ftTB), highlight a segment of text using one of the text-modifier attributes. If the target field is currently visible, the field will be refreshed before return.
Note that while any combination of the acAttr color attributes
may be freely OR’d under most circumstances, for this method, exactly
one text-modifier attribute may be specified as the highlight attribute.
Please see HilightFieldText for a techninal description of this functionality.
Input :
ctrlIndx : index of target control within the dialog
Returns:
'true' if a dialog is currently under edit, AND if 'ctrlIndx'
refrences a control of the correct type for the operation
AND if the target control is not set as read-only
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For controls within a dialog, set the input focus to the specified control.
Input :
ctrlIndx : index of target control within the dialog
read_only: if 'true', set field as read-only
(cannot receive input focus)
if 'false', reset the read-only flag
(can receive input focus)
Returns:
'true' if a dialog is currently under edit, AND if 'ctrlIndx'
refrences a control of the correct type for the operation
AND if the target control does not currently have input focus
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For controls within a dialog, set or reset the read-only flag.
If the read-only flag is set, then control cannot receive the input focus.
Input :
ctrlIndx : index of target control within the dialog
steps : (by reference) number of steps to scroll
This value is ignored if 'head' or 'tail' flag is set.
scroll == 0, no scrolling will occur, but on return,
value will be _current_ item/IP.
scroll > 0, scroll forward toward tail of data
scroll < 0, scroll backward toward head of data
head : (optional, default: false) if specified, move to head
of data (overrides value in 'steps')
tail : (optional, default: false) if specified, move to tail
of data (overrides value in 'steps')
Returns:
'true' if a dialog is currently under edit, AND if 'ctrlIndx'
refrences a control of the correct type for the operation
-- On return, 'steps' will contain the currently referenced
item number, or for Textbox controls, the IP.
else 'false' ('steps' is not modified)
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
For controls with a visible cursor position: Textbox (ftTB), Scrollbox (ftSB) or Context Menus (ftMB) only.
Scrolling is managed by the control’s 'ip' (Insertion Point) member.
Position of the highlight (Menus or Scrollbox controls) or visible cursor
(Textbox controls) is calculated based on the value of 'ip'.
The 'steps' value is range checked to prevent the insertion point
from overruning the data.
The 'head' and 'tail' flags override the value in 'steps',
and the 'head' flag overrides the 'tail' flag.
Special case: If both 'head' and 'tail' are reset and if 'steps'
is set to zero, then the current position is reported, but not modified.
bool clear = false, acAttr color = acaUSEDFLT );
bool clear = false, acAttr color = acaUSEDFLT );
Input :
txt : text to be written to dialog interior.
Either: wchar_t* or char*
yOff : position: offset in rows from top of dialog interior
with zero(0) being the top row.
xOff : position: offset in columns from left edge of dialog
Note that all dialog text is automatically indented by
one column from both the left and right borders, so an
xOff value of zero will display text starting in column 1.
clear : (optional, default: false) clear the target row before
writing the data.
color : (optional, default: acaUSEDFLT)
if specified this is the color attribute used to write
the text. Otherwise, text will be written using the
dialog's interior attribute.
Returns: 'true' if a dialog is currently under edit
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
Write one line of text to the interior of the dialog.
If you are uncertain about positioning of static text data within the dialog, it is recommended that a read-only Textbox control be defined for display of transitory messages.
Input : full : (optional, default: false)
if 'false' redraw the interior of the dialog only
this includes the static text data and
all controls
if 'true', redraw the dialog border, then redraw
the dialog interior
Returns: 'true' if a dialog is currently under edit
else 'false'
Note: This method is active only when a dialog (ACDlg object) is open;
and only if a callback method was specified when dialog was created.
Refresh (redraw) the dialog. This method may be called from within the application-level callback to restore the display in case the dialog has been obscured by another operation.
If the parent window has also been obscured by the operation, refresh the parent window first, then refresh the dialog window.
bool trunc = true, bool hypenbrk = false,
short *truncIndex = NULL );
This is a pass-through to the acFormatParagraph method.
Input :
gs : (by reference) text to be analyzed
msgHeight : (by reference) receives number of text rows
msgWidth : (by reference) receives number of text columns
Returns: nothing
Calculate the dimensions (height and width) of the specified block of text.
This method can be used to measure the height in rows and width in columns
for a paragraph of text data. This is useful for determining how the text
will fit within the window, or the dimensions required for a field in
which to display the text.
Note that the number of text rows is determined by the number of newline
characters ('\n') found (excluding trailing newline, if any).
Dimensions are calculated as shown in the following example.
ACWin *win( . . . ) ;
short txtRows, txtCols ;
gString gsText =
"There once was a man from Kirkuk, \n"
"Who was known far and wide for his luck, \n"
"Till while jogging one day, \n"
"he looked the wrong way, \n"
"Whereupon he was hit by a truck." ;
win->ParagraphSize ( gsText, txtRows, txtCols ) ;
gString bsOut( "\n\"Text Dimensions are %hd rows by %hd columns.\"\n",
&txtRows, &txtCols ) ;
win->ttyWrite ( bsOut ) ;
Yields:
"Text Dimensions are 5 rows by 41 columns."
Input : keycode to be tested Returns: true if a "graphing" character, else 'false'
A locale-aware version of the 'std::isprint' function.
The locale-aware version of ’isprint’ takes into account all graphing characters of all languages supported by the Unicode standard. This means that whatever input language is being used for the application, all codepoints of that language will be handled as expected.
Whitespace Keycodes:
Canon says that the Space ' ', Enter '\n', Tab '\t' and similar
codepoints are classed as whitespace rather than graphing characters; however,
canon is wrong on this issue.
This method recognizes these as graphing characters simply because when
written, they cause updates to the display.
Keycodes reserved by the AnsiCmd library:
A small range of Unicode codepoints is reserved by the library for assignment
to decoded ANSI escape sequence, control codes, “conditioned” keys
and ALT-key combinations.
These reserved keycodes consist primarily of arrows, geometric shapes,
and typographic symbols. These keycodes are not integral to any written
language, and should seldom, if ever be needed in daily user interactions.
The range of keycodes in this group are technically graphing characters
but have been reassigned by the AnsiCmd library, and will not be reported
as graphing characters by this method. Most of these are assigned to:
1) wcsALT_A - wcsALT_RB
2) wcsCTL_A - wcsCTL_7
3) wcsF01 - wcsCF12
4) various "conditioned" keys, cursor-movement keys, etc.
The exclusion range is defined by the constants RESKEY_MIN and RESKEY_MAX
which correspond to keycode assignments wcsF01 and wcsALT_RB, respectively.
Note that not all keycodes within this range are currently assigned.
Some are reserved for future development.
Line-drawing characters, bullet characters and similar keycodes defined by the AnsiCmd library fall outside the reserved range, and therefore ARE reported as graphing characters.
If any codepoints within the reserved range needs to be displayed within a specific project, this should not be a problem so long as the AnsiCmd user-interface methods do not see them and try to “interpret” them.
It may be educational to study the full Unicode character table which
can be found at: https://www.utf8-chartable.de/
Input : enable: set : enable output from the Footnote method.
reset : disable output from Footnote method.
Returns: current state of the footnote flag
Enable or disable output to the window written through the ’Footnote’ group of methods described below.
Input :
msg : text of message to be written.
-- Message will be truncated if necessary to the
width of the window minus 4.
-- If 'msg' is an empty string, then erase any
existing message and restore the border.
pause : time in tenths-of-a-second to wait before erasing message
a value of zero(0) indicates that message is to
remain visible on return.
color : (optional, existing border attributes by default)
foreground/background color attributes for message display
center: (optional, 'false' by default)
if 'true', center the message horizontally
if 'false', message is positioned at left edge of the space
Returns: nothing
Write a message in the lower border of the window. This could be a message
to the user, or could be a temporary diagnostic message used during development.
Optionally, wait, a moment, then erase the message, (see 'pause' argument).
For best visual presentation, the first and last characters of the message should be spaces, but this is not enforced.
Pleasse refer to the Test_SoftEcho method or refer to the example
output in the diagram below.
Input :
msg : text of message to be written.
-- Message will be truncated if necessary to the
height of the window minus 4.
-- If 'msg' is an empty string, then erase any
existing message and restore the border.
left : if 'true', message is displayed in left edge border
if 'false', message is displayed in right edge border
color : (optional, existing border attributes by default)
foreground/background color attributes for message display
offset: (optional, zero by default) Specify the offset
(number of rows) from vertically centered position.
if 0, message is vertically centered
if <0, message is offset upward from centered by
specified number of rows.
if >0, message is offset downward from centered by
specified number of rows.
clear : (optional, 'false' by default)
if 'true', clear any existing message from the border
before writing the new message
if 'false', existing messages are unaffected
(unless the new message overwrites an old one)
Returns: nothing
Display a message in the left or right border of the window.
The Sidebar may have no practical value, but it’s fun. :-)
┌────────┤ Title ├──────────┐
┴ │
H │
i ┴
┬ M
│ o
│ m
│ !
│ ┬
│ │
│ │
└─────┤ Smelly Footnote ├─────┘
ACWin *win = new ACWin ( ... ) ;
win->SetTitle ( " Title " ) ;
win->Sidebar ( "Hi", true, acaATTR_DFLT, -2) ;
win->Footnote ( " Smelly Footnote ", 0, acaATTR_DFLT, false ) ;
win->Sidebar ( "Mom!", false, acAttr(acaFG_GREEN | acaBG_BLUE), 0) ;
NOTE: A live test is under conditional compile in the Test_Dialog method.
Input : pos : offset from upper-left corner of text area to
upper-left corner of box (0-based)
height: number of rows for box
width : number of columns for box
lType : (optional, ltSINGLE by default) line style
member of enum LineType: (ltSINGLE or ltDUAL)
bxAttr: (optional, acaUSEDFLT by default)
If specified, these are the color attributes used.
If not specified, stored text attributes are used.
clear : (optional, 'false' by default)
if 'false', interior of box is cleared using 'bxAttr'
if 'true', interior of box is cleared using the interior
color attributes of the parent window
Returns: 'true' if box fits within the window text area
'false' if invalid offset or dimensions specified
Draw a rectangle within the window’s text area.
The position, dimensions, line style and color attributes may be specified. See the example below.
Note that the minimum dimensions for the rectangle are two rows by two columns (2x2). At the minimum dimension, of course there is no space for text within the box.
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.
Input :
targFile : filespec of file to be processed by the external application
redirect : (optional, 'true' by default)
if 'true', redirect stdout and stderr to temp files
if 'false', allow stdout and stderr to write to the
terminal window
Returns:
the child process ID (an integer value)
returns minus one (-1) if child process was not created
Launch the system default application for handling the specified type of file.
Technical Description:
Launching an external application is done by creating a child process to
perform the actual launch, while the parent process continues execution of
the application code. This operation is done via a call to the standard
library’s 'vfork' function.
'targFile' parameter:URL is specified, then that page will be
opened in the browser. /home/sam/Documents/XmasList.html ./XmasList.html "../../Music/Kansas/Dust In the Wind"
'redirect' parameter:LaunchDefaultApp.
(See HideWin).
'xdg-open' system utility: win->LaunchDefaultApp ( ../Texinfo/ansicmd.html );stdin/stderr streams:'dup2' function. This is somewhat more complex than redirection
using 'pipes'. See the 'dup2' documentation for details.
Input :
shellCmd : (by reference) invoke the specified shell builtin
command, shell program or console utility program
- If an empty string, then invoke a copy of
the 'bash' shell.
NOTE: If the default shell IS NOT 'bash', then
'shellCmd' should be used to specify the target
shell program.
textColor: (optional, default: acaUSE_DFLT)
specify an alternate foreground/background
color for text data written to stdout.
[This parameter is currently ignored.]
Returns: exit code of child process
Ideally, this is the exit code of the last utility run
in the child process, but this cannot be guaranteed.
Go to command shell in the current terminal window.
'bash' (or current shell program).'exit' to return to application.
Important Note: This method should be called ONLY from the main application window. AND there should be no sub-dialogs open. If invoked from a sub-dialog, then the primary window’s display data will not be properly saved.
A beginning developer may ask: “Why are the debugging routines so fancy?”
Answer: Writing the debugging routines is a concrete expression of the thought process which informs the overall project development. Highly recommended for all developers. (It’s almost as important as coffee :)
Input :
txtExp : (by reference) acaExpand object to receive text attributes
bdrExp : (by reference) acaExpand object to receive border attributes
Returns: nothing
Debugging method: Get a copy of the window attributes.
Input :
txtExp : (by reference) receives window height (rows)
bdrExp : (by reference) receives window width (columns)
Returns: window position (offset into terminal window)
Debugging method: Get a copy of the window dimensions and position.
Input : none
Returns: const pointer to the private @b{BlockFifo} object.
Debugging method: Get a pointer to the FIFO queue which contains the
static text of the window. For an example, please refer to the Test_Fifo
method in AnsiCmdTest.cpp. Run this test using: epts --test=Ws.
Debugging methods: Write various diagnostic data to the debugging log file.
During development a log file is created when the application is launched.
This file is cryptically named: "dbg.log". Startup and shutdown data are
written to this file, and depending on which conditional-compilation
declarations are enabled, a large amout of additional data are recorded
in the log. See Build Options for more information.
Please refer to the individual methods listed for an explanation of the data written in each case.
Input :
html : (optional, default == false) output format
true : HTML markup
false : plain text
desc : (optional, default == null pointer) discriptive text
Returns: nothing
Capture a screenshot of the specified ACWin object to the log file.
The capture is performed in a sectioned format as shown, and the developer
is then responsible for integrating the sections to produce the finished
screenshot.
This procedure is significantly different from the author’s NcDialog library
(based on ncurses) which performs window capture in a fully-integrated way,
including color attributes. The AnsiCmd/ACWin/ACDlg library, however,
is a much simpler creature.
Plain-text Screenshots
For monochrome plain-text screenshots (Texinfo '.info' documents),
it is likely more efficient to simply copy-and-paste from the terminal
window, but if the 'html' parameter is reset, a plain-text capture will
be performed. See the Linux documentation for Ctrl+Shift+c and
Ctrl+Shift+v copy-and-paste commands.
HTML Screenshots
For HTML documentation, copy-and-paste is inefficient and error prone, so
it is likely more efficient to use this capture method. This is especially
true for a developer who is not fluent in HTML/CSS markup because
placeholder HTML/CSS3 style instructions are embedded in the screen-capture.
The HTML output is placed inside a <div class="tscap">...</div>
pair of tags which defines the dimensions, font family, basic color scheme
and so on.
Each row of the window border is bracketed by a placeholder sequence:
<span class="xxxx">...</span> which provides a method for
specification of color attributes for the left and right borders. Example:
<span class="bl_r">┌─────┐</span>
<span class="bl_r">│</span> Hi! <span class="bl_r">│</span>
<span class="bl_r">└─────┘</span>
which specifies blue text with foreground and background attributes reversed.
┌─────┐ │ Hi! │ └─────┘
Please refer to the CSS class definitions in infodoc-styles.css for
a description of the color-attribute classes.
Each object within the window is also enclosed within a similar sequence.
For greater control over the color palette, instead of calling out the
pre-defined color attribute classes, the <span class="xxxx;">
tag may be replaced with something similar to:
<span style="color:#0033FF; background-color:#99FF99;">
This tag specifies “web-safe” foreground and background color
attributes. Please run the color tests (test C) included in this package, and
visit the author’s website for a document “HTML/CSS Color Chart”
describing web-safe colors.
Hotkey designators are displayed using the ’underline’ text-modifier attribute.
For these characters, a callout for the the CSS "ulin" class is embedded in the
HTML output. For example the text of a Pushbutton may be written as:
"Buy Some ^Jiǎozǐ Today"
The caret character ('^') indicates that the next character is the hotkey
character, ’J’ in this example. Thus the HTML would be:
<span class="xxxx">Buy Some <span class="ulin">J</span>iǎozǐ Today</span>
This will cause the ’J’ to be underlined in the output.
The primary test window for this functionality is Test_Cookie, which is
a simple window used in the Texinfo documentation.
(See skForm Class.)
Note that the Screenshot method is huge compared to its actual
usefulness, so be sure its conditional-compilation is disabled:
#define DEBUG_PHOTO (0)
when the method is not in use. See Building from Source for details.
Editor’s Note: Your humble author designed, tested and wrote the documentation for this routine in two days, all on battery-backup, while the power was out and snow and ice covered everything. Some exciting Spring Festival (春节假期) for 2025, Year of the Snake!
Communication between the application and the user is the most complex (and most error prone) task for the application developer. Most of us would prefer to avoid user interactions as much as possible; however, without users (filthy beasts as they may be) there wouldn’t be much need for applications.
When designing an application, it must be assumed that the user interface
section will not only require more code and more development time than
any other section; it will require the developer to compensate for users’
(often illogical) assumptions about the program, and their blithe
refusal to read the documentation.
The skForm and skField interface classes are your humble
author’s attempt to make this process as painless as possible.
Some developers will want to write directly into the terminal window, and
read the user’s responses directly from the window. The AnsiCmd
primitives acRead, acWrite, ttyWrite, etc. are designed
for this type of interaction.
Others will want to design an array of text-input fields and other
types of controls for user interactions.
These controls are defined by Some-Kind-of-Form i.e. the 'skForm' class.
Both the ACWin class (window) and the ACDlg class (dialog)
support skForm-class objects. Within the skForm object, an array of
'skField' objects defines the individual controls for user interaction.
If the ACWin constructor is called without specifying an skForm object, a default skForm object is created based on the size of the window. The default skForm object will be created with one(1) text-box (ftTB) skField object which takes the dimensions of the window interior.
To achieve direct control over the way the skForm object is configured, a
pointer to an initialized skForm object is passed to the ACWin
or ACDlg constructor.
// Define and initialize an skForm/skField object.
skForm* skfp = new skForm
{
FLD_COUNT,
new skField[FLD_COUNT]
{
. . .
},
// Initialize remaining skForm parameters to default values.
. . .
} ;
// Create a window.
ACWin *win = new ACWin
( winROW, winCOL, // position (upper-left corner)
winHEIGHT, winWIDTH, // dimensions (height, width)
ltSINGLE, // border style
bdrAttr, // border attributes
intAttr, // interior attributes
" Secrets of the Universe ", // window title
skfp // pointer to skForm object
) ;
// Create a dialog within a parent window
this->win->Dialog
( dlgHgt, dlgWid, // dialog dimensions
skfp, // pointer to skForm object
staticText, // text written directly to dialog interior
dlgTitle, // dialog title
ZERO, -1, // dialog offset within parent window
ltDUAL, // border style
acaUSEDFLT, // border color attribute
this->dlgAttr, // interior color attribute
0, 1, // interior text offset
nonmember_dlgCallback // address of callback function
) ;
The position and dimensions of each field must fall entirely within the text area of the window, and the fields should not overlap (unless the obscured field(s) are set as “hidden”).
Although range checking and automatic positioning and size adjustments of the controls is performed, an over-caffinated developer could still cause chaos, so it is important to carefully verify the parameters which define the individual controls.
There are several ACWin objects and ACDlg invocations created in the test code included in this package. Some tests write text directly into the window, while others write into the defined fields (or some combination of the two). Please refer to those examples, as well as the discussion of skForm and skField classes below.
The skForm-class object is a mostly passive construct, that is, the object
doesn’t perform many tasks directly. Its primary function is to store and
display information in an orderly and predictable way. The ACWin or ACDlg
object updates this information in response to user activity.
Please see EditForm which acts as the gateway to the skForm data.
Input : fieldCount : number of skField objects
Range: 1 through 99
Returns: implicitly returns a pointer to the object
Simple constructor. Allocate resources for the skForm object and an array of skField objects. All data members receive default values.
It is assumed that the application will populate all necessary data members after instantiation. Please see the initialization constructor below for more detailed information on the initialization of the individual data members.
Technical Note: The default constructor (the constructor with no arguments) is set as private in order to protect the application layer from creating an unusable object.
short fldIndex = ZERO, acAttr fldAttr = acaUSEDFLT, bool noisy = true, bool ioFlag = true, bool ioToggle = true, bool ioCursor = false, CurStyle insCursor = csBblock, CurStyle ovrCursor = csBuline );
Input : fldCount: number of objects in 'fldArray' (1-99)
fldArray: pointer to an array of skField objects defining
the form
//** Optional Arguments **
fldIndex: (optional, default: zero)
index of field which receives initial input focus
fldAttr : (optional, default: acaUSEDFLT)
For fields which change color when they receive
input focus, this is the focus color attribute.
-- acaUSEDFLT: If default attributes specified, then
when field receives input focus, the field's
embedded foreground and background attributes are
swapped.
-- If focus-color attributes are specified, then
when field receives input focus, this attribute
overrides the field's embedded attributes for as
long as the field holds focus, at which time the
embedded attributes are restored.
noisy : (optional, default: true)
if 'true', beep on unhandled keycode received
if 'false', silently discard the unhandled keycode
ioFlag : (optional, default: set)
initial state of Insert/Overstrike flag
set : Insert mode
reset: Overstrike mode
ioToggle: (optional, default: true)
if 'true', user may toggle between Insert mode and
Overstrike mode
if 'false', mode is fixed, and cannot be modified
by user
ioCursor: (optional, default: false)
if 'true', shape of cursor changes to indicate
current state of Insert/Overstrike flag
if 'false', cursor shape is not modified for
Insert/Overstrike mode
insCursor: (optional, default: csBblock)
member of enum CurStyle indicating the cursor shape
to be used when in Insert mode.
(If 'ioCursor' flag is reset, then )
(only this cursor style is used. )
ovrCursor: (optional, default: csBuline)
member of enum CurStyle indicating the cursor shape
to be used when in Overstrike mode.
Returns: constructors _implicitly_ return a pointer to the object
Initialization constructor.
This constructor fully initializes the skForm data members AND transfers the data
from caller’s skField array to the internal skField array.
Important Note: The number of elements in 'fldArray' must match the
value in 'fldCount'. If the array is larger than ‘fldCount’, then
some field definitions may be discarded. If the array is smaller than
‘fldCount’, then a segmentation fault will be the likely result.
Be Aware!
Note that range checking and error correction are not performed by this constructor. Any needed corrections are made during instantiation of the parent window so that the values may be compared to the window definition.
Input : (by reference) the skForm object containing source data Returns: nothing
Assignment Operator: make a copy of the specified skForm object.
The copy will include both the public and protected data members.
If the assignment operator is used correctly, then source and target arrays should have the same number of elements; however, if the dynamic allocations do not match, the target allocations will be released and re-allocated to accomodate the data to be copied.
Input : none Returns: none
Destructor: Release the dynamic allocation and delete the skForm object.
For an “automatic” constructor allocation:
skForm skf( 6,
new skField[6] = { ... },
... );
The destructor will be invoked when the object goes out of scope.
For a constructor created in dynamic memory:
sdForm* skf_ptr = new skForm
( 6,
new skField[6] = { ... },
... );
The destructor is invoked directly:
delete skf_ptr;
Teacher Rant: Note that forgetting to delete a dynamically-allocated object when the task is complete would be considered as a "memory leak", a failure to return system resources once they are no longer needed. The author once spent five weeks chasing memory leaks in a multi-node Solaris system. It was not pretty. Please use extra care when working with dynamic memory allocations.
Input :
p_base : (by reference) receives offset for upper left
corner of parent window
p_pKey : (by reference) receives most recent 'special'
keycode processed
p_seli : (by reference) receives index of field containing
'selected' text (if any)
p_foot : (by reference) receives the 'footer' flag
'true' if Footer messages are enabled
'false' if Footer messages are disabled
p_dlg : (by reference) receives the 'dialog' flag
'true' if skForm container is an ACDlg object
'false' if skForm container is an ACWin object
Returns: 'true' if AnsiCmd library debugging code is enabled:
(caller's parameters have been initialized)
'false' if AnsiCmd library debugging code is disabled:
(caller's parameters returned uninitialized)
For Debugging Only.
This method reports the “protected” data members of the skForm class.
These values are not directly available at the application level, but may be
useful during development.
'fld' array of skField objects.
While this value is technically a public data member, it is set only once,
during instantiation of the skForm object, and may not be modified after
that.
skField objects which is dynamically
allocated by the skForm constructor. Templates for these fields may be
individually initialized by the application, then passed to the ACWin or ACDlg
constructor, which performs range checking and adjustmens as necessary, and
then copies the application’s values to the internal skForm object.
'true')'true')Insert key unless
the 'togg' flag is reset. (see below)'true')
'false'.)'icur'
and 'ocur' members described below.
'insc' is set, this is the cursor style used when in Insert Mode.'csBblock'. (ignored when 'insc' is reset)
'insc' is set, this is the cursor style used when in Overstrike Mode.'csBuline'. (ignored when 'insc' is reset)
Protected Data Members
ACDlg class is a derived class based on the
ACWin class.) short fldOffsetY, short fldOffsetX, //* Optional Arguments * const char* fldText = NULL, acAttr fldAttr = acaATTR_DFLT, FloType fldFlow = floChar, bool readOnly = false, bool fldBorder = false, bool fldHidden = false, bool fldLocked = true, bool binState = false, wchar_t hotKey = NULLCHAR, wchar_t groupId = noGROUP );
Input :
fldType : field type, member of enum FldType
fldHeight : field height in rows
fldWidth : field width in columns
fldOffsetY : vertical offset from parent window origin
fldOffsetX : horizontal offset from parent window origin
fldText : (optional, default: an empty string "\0")
Initial text data. Data configuration is dependent
on the field type. See documentation for details.
fldAttr : (optional, default: acaATTR_DFLT)
color attribute for field
Note that for field types which change color when they
receive input focus, this is the non-focus color.
fldFlow : (optional, default: floDflt) text flow
Automatic text formatting option for the field.
Formatting option is dependent on field type, and is
fully configurable only for Textbox controls (ftTB).
readOnly : (optional, default: false)
if set, field is view only, cannot receive focus
fldBorder : (optional, default: false)
if false, field has no border.
Exception: Menubox controls always have a border.
if true, draw an outline around the field
Note: Default line type and color attribute will be
used to draw the outline. For a non-default
line type or attribute, see SetFieldOutline().
fldHidden : (optional, default: false)
if set, field is not displayed and cannot receive focus
fldLocked : (optional, default: true)
if set, field is always visible (unless obscured by
another field.)
if reset, field becomes invisible when it loses focus.
(This is primarily for menus.)
binState : (optional, default: false)
For binary-state controls only (Radiobuttons),
specifies the initial state: "set" or "reset".
hotKey : (optional, default: null L'\0')
if specified, this is the hotkey character for setting
focus to field. Please see documentation about
specification and use of hotkeys.
groupId : (optional, default: noGROUP)
For fields whih can be grouped(Menubox and Radiobutton)
this is the character used to identify the members
of the group.
Returns: constructors _implicitly_ return a pointer to the object
Initialization constructor.
The first five(5) arguments are required. The remaining arguments are
optional and if not specified, will receive default values.
The ACWin class test methods provide several examples of skField
initialization.
A representative sample initialization (skForm Initialization) is
shown below.
See test W, sub-test 'f' for additional information.
Input : none Returns: constructors _implicitly_ return a pointer to the object
The default constructor creates an skField object and initializes all
members to their default values. This constructor has little practical value,
but it remains a public method for those who wish to experiment.
See the initialization constructor above for a more robust implementation.
Input : none Returns: nothing
Destructor.
The destructor is like the cleaning crew that comes into your Cabo hotel
room after Spring Break. All resources allocated from the system are
returned to the system, the mini-fridge is restocked and the iguana you
forgot was in the shower is returned to the wild.
(Lo siento mucho, Abue; tenía 19 años y estaba un poco fuera de control.)
Input : (by reference) the skField object containing source data Returns: nothing
Assignment Operator: make a copy of the specified skField object.
The copy will include both the public and protected data members.
See also the skForm operator=() above.
Input :
lType : line type for border, member of enum LineType
ltSINGLE (default), ltDUAL, ltHORIZ (invisible border)
lAttr : (optional, default: acaUSEDFLT) border color attribute
if not specified, takes attribute of window interior
-- Note that this parameter does not apply to menu
controls which take their outline color from the
menu data.
Returns: 'true' if successful
'false' if field type does not allow borders
Set the line type and attribute for the field outline.
The data members which contain these values are ’protected’, that is, they are not available at the application level. This skField public method is provided so these values can be initialized before the window or dialog is instantiated. The configured fields will be displayed when the window(dialog) is opened.
Please see skField config example below for an example of using
outlineConfig.
Input :
labText : display text, optionally including a "hotkey" character.
A hotkey is specified using the CARET character ('^')
followed by the ASCII character which indicates the@item
keycode to be used as a hotkey. (see example above)
labAttr : (optional, default: acaUSEDFLT) color attribute for label
If not specified label color is set to color of parent
window interior
center : (optional, default:'false') horizontal offset
if set, center the label horizontally above the field
if reset, label offset is in the same column as the
left edge of the field
Returns: 'true' if successful
'false' if field type does not allow external label
Specify label text, color and position.
The data members which contain these values are ’protected’, that is, they are not available at the application level. This skField public method is provided so these values can be initialized before the window or dialog is instantiated. The configured fields will be displayed when the window (or dialog) is opened.
Note that this method should be called ONLY before the window (or dialog) constructor is called. To initialize the border after the window is created, call the ACWin-class SetFieldLabel method instead.
Please see skField config example below for an example of using
labelConfig.
Input :
labAttr : color attributes for Radiobutton label
If acaUSEDFLT specified, then label color is set to color
of parent window interior
lableft : (optional, default:'false') horizontal offset
if set, label is displayed to the left of the control
if reset, label is displayed to the right of the control
Returns: 'true' if successful
'false' if incorrect field type
Specify label color attributes and position.
This overload is designed for Radiobutton controls (ftRB) only.
To initialize labels for other types of controls, see above.
By default Radiobutton labels inherit the color attributes of the parent
window/dialog and the label is positioned to the right of the field.
This method allows direct specification of the label attributes and
optionally allows the label to be positioned to the left of the control.
The data members which contain these values are ’protected’, that is, they are not available at the application level. This skField public method is provided so these values can be initialized before the window or dialog is instantiated. The configured fields will be displayed when the window(dialog) is opened.
Note that this method should be called ONLY before the window (or dialog) constructor is called.
skForm* skfp( ... ) ;
// Field definition and formatting for a Radiobutton control:
// The caret character, if present, indicates the hotkey
// character for setting input focus to target field.
// Define the text and position of the control
short row_offset = 2, col_offset 14 ;
const char* rbDef = "[♦] Comp^uter Science" ;
// By default the field and label would be displayed as:
[♦] Computer Science
▔
// If label configuration with field/label swap, the overall
// position within the window will be unchanged, but field
// and label will swap positions as shown.:
skfp->fld[n].labelConfig ( acAttr(acaFG_BLUE|acaUSEDFLT), true );
Computer Science [♦]
▔
Note that a space after the closing brace will automatically be removed,
and a space will be appended to the label text:
"[♦] Computer Science" becomes
"Computer Science [♦]"
See AcEdit Demo App, 'Compare Files' dialog for a working example
of this option.
Input :
rowAttr: pointer to an array of acAttr color attributes, one
attribute for each text row of the control.
rowCnt : number of attribute values in the 'rowAttr' array
Value must be greater than zero, and the minimum
_practical_ value is two(2)
Returns:
'true' if successful
'false' if field type does not support per-row attributes
or if 'rowCnt' less than minimum
Specify an array of color attributes, one for each item (row of text data) within the control.
Customization of text color attributes is often useful to enhance readability of multi-row controls which contain fixed display text. For multi-row Menu controls (ftMB) and Scrollbox controls (ftSB) only, color attributes for each individual display row may be specified.
The data member which contains these color values is ’protected’, that is,
it is not available at the application level. This skField public method is
provided so that custom color attributes may be specified, one attribute
per text row, after the skField object has been instantiated,
but before the window (or dialog) constructor is called.
The reonfigured field will be displayed when the window(dialog) is opened.
The following control types support custom color attributes:
These control types are designed to contain read-only data; (the data may
may not be edited under user control); therefore, it is possible to embed
color attributes within the displayed text.
Any valid acAttr color attribute bitfield may be specified.
The acUSEDFLT value indicates that the target item will use the attribute
specified in the skField’s ’aca’ member. This is the attribute for the
control as a whole.
Please refer to the example below.
IMPORTANT NOTE:
This method includes some defensive programming; however, it is not possible to anticipate all potential foolishness, so be careful! Applying per-item color attributes must rely on text data formatting which has not yet been programatically validated.
This method should only be called for controls within a dialog (ACDlg) object, and only if you are certain that the text to be displayed within the control has been properly dimensioned, ensuring that the attribute count will equal item count.
For controls within a window (ACWin) object, please use the SetFieldAttr
method instead. Using SetFieldAttr will be safer because it will be called
after the control dimensions and text formatting have been verified.
skField config example
// Create and initialize an skForm object with an array of three(3)
// skField objects: a Textbox, a Context Menu and a Pushbutton.
sdForm* skf_ptr = new skForm
( 3,
new skField[3] =
{
{ ftTB, ... }, // Textbox (index 0)
{ ftMB, ... }, // Context Menu (index 1)
{ ftPB, ... }, // Pushbutton (index 2)
},
... );
// Specify that an outline is to be drawn around
// the Textbox control.
skf_ptr->fld[0].outlineConfig ( ltDUAL,
acAttr(acaFG_BLUE | acaBG_CYAN) );
// Specify a label for the Textbox control
skf_ptr->fld[0].labelConfig ( "Date Of Birth " );
// Specify a label for the Menu control,
// (centered, with contrasting color).
skf_ptr->fld[0].labelConfig ( " Education Level ",
acaFG_BLACK | acaBG_GREY), true );
// Specify an array of per-item color attributes for the Menu.
// In this example, progressive web-safe RGB colors are built.
// The divider item inherits the color of the menu control.
// (Note the extra element appended for safety.)
acaExpand acex ;
el00 = acex.buildRgb( true, wsrgbBLACK,
true, WebSafeRGB(wsrgbBROWN + wsrgbSHADE_MED));
...
el10 = acex.buildRgb( true, WebSafeRGB(wsrgbRED + 9),
true, WebSafeRGB(wsrgbGREY + wsrgbSHADE_MED));
short COLOR_ELEMENTS = 11;
acAttr acArray[COLOR_ELEMENTS + 1] =
{ el00, el01, el02, el03, el04, el05, el06,
acaUSEDFLT, el08, el09, el10, acaUSEDFLT };
skf_ptr->fld[1].colorConfig ( acArray, COLOR_ELEMENTS );
Input :
iTxt : (by reference) receives item text data
iNum : (by reference) receives the index of the "item" referenced
by the 'ip' member (item referenced by the cursor)
(This is the 0-based item index.)
selnum: (optional, default: false) for multi-row controls only
if set AND if a previously "selected" item (sitem >= zero),
return index of "selected" item.
if reset, return index of item containing the IP.
Returns: 'true' if supported target control type (ftMB || ftSB), AND
if item identified
else 'false'
For Menus (ftMB) and Scrollbox controls (ftSB), retrieve the index
of the "item" (row) containing the insertion point ('ip').
Generally, this is the currently hightlighted item or the item
which was highlighted when the control lost focus.
The 'getItem' method returns both the item index and the
actual text of the item.
The optional 'selnum' parameter may be used to report either the
target control’s highlighted item or the item (if any)
“selected” by the user via the Enter or Space key.
The text of a menu item may contain an embedded hotkey indicator which
is identified as the character following the caret ('^').
Example "Sa^ve file" where the 'v' is the hotkey character.
This is described more fully in the chapter skField Data Members.
This method will typically be called from an application callback function
or immediately after a dialog window has closed.
See EstablishCallback or the Dialog method’s 'callbk'
parameter for more information on establishing and using callbacks.
Also, see GetFieldItem which is a form-oriented method which provides
information similar to getItem.
Understanding “Items”
For purposes of this discussion, an “item” is a row of text
displayed within the control.
For example, the following diagram shows the different types of menus:
a) context menu, b) menu group sub-menu, and c) the
‘Menubar’ (single-row menu).
Context Menu Group Submenu
┌────────────────┐
│Open a file │ │Open a file │ <-- iNum == zero
│Save file │ │Save file │
│Close file │ │Close file │
│Exit Application│ │Exit Application│ <-- iNum == 3
└────────────────┘ └────────────────┘
Example menubar:
----------------
| File Edit View Help |
↥ ↥ ↥ ↥
item: 0 1 2 3
Scrollbox controls (ftSB) typically contain plain, paragraph-oriented
text data, not itemized data records; however, if desired, the application
may define each display row of the Scrollbox control as a data item.
This implements what is essentially a scrolling menu for situations
where there are a large number of items to be displayed.
The following example is taken from the AcEdit Demo App which displays
a list of files in the current directory, and asks the user to
select a file to be edited. This type of control can accomodate any
reasonable number of items.
The '▶' indicator character, identifies the current item, and when the
user presses the Enter or Space key, that item is “selected”.
In the example, the indicator is on AcEdit.cpp and its item index
is four(4).
When the Scrollbox loses focus, the selection indicator will be replaced by
the '▷' character.
╔══════╣ Open a File For Editing ╠════════╗ ║ .. parent directory ║ ║ > 1_TestData ║ ║ · ace ║ ║ · ace.cfg ║ ║▶ · AcEdit.cpp ║ <-- iNum == 4 ║ · AcEdit.hpp ║ ║ · AcEdit.o ║ ║ · AcEditCfg.cpp ║ ║ · AcEditCfg.o ║ ║ · dbg.log ║ ║ · gString.hpp ║ ║ ───────────────────────────────────────── ║ ║ OPEN CANCEL ║ ╚═══════════════════════════════════════════╝
Input :
txtmod:
text modifier attribute for highlighting text segments.
One of the following text modifier attributes:
acaBOLD bold-text modifier
acaITALIC italic-text modifier
acaUNDERLINE underline-text modifier (not recommended)
acaOVERLINE overline-text modifier
acaXOUT x-out (strikethrough) text modifier
acaBLINK blinking-text modifier
acaCONCEAL concealed (invisible) text
acaREVERSE reversed fgnd/bkgnd (default)
The specified modifier flag _should not_ also be set
as an element of control's base color attribute.
Note: OR'd combinations of these modifiers are not allowed.
Returns:
'true' if highlight attribute set successfully
'false' if a) invalid modifier specified and discarded.
(default modifier, acaREVERSE, will be used)
b) field type does not support text highlighting
For Textbox (ftTB) controls, set the text-modifier attribute to be used for highlighted substrings.
The data member which contains this value is ’protected’, that is, it is not available at the application level. This method can be called for any Textbox field in an initialized skForm object, before the window/dialog has been defined.
//* Define an skForm object with two controls. *
skForm* skfp = new skForm
(
fldCOUNT,
new skField[fldCOUNT]
{
//* Field index 0: ftTB (Textbox: fldTB_SEGMENT) *
{
ftTB, // field type
. . .
},
//* Field index 1: ftPB (Pushbutton: fldPB_FWRD) *
{
ftPB, // field type
. . .
},
} ;
. . .
);
//* Set the modifier for text highlight *
skfp->fld[0].setHiliteMod ( acaITALIC );
//* Define an ACWin object *
ACWin *win = new ACWin
( winROW, winCOL, // position (upper-left corner)
winHEIGHT, winWIDTH, // dimensions (height, width)
ltDUAL, // border style
acaBorder, // border attributes
acaInterior, // interior attributes
" Highlight Field Text ", // window title
skfPtr
) ;
To set the hilight modifier after the window has been created,
please see SetHilightMod or HilightFieldText.
Notes:
Input :
begin : (by reference) receives index of first (leftmost)
character of highlighted text segment
len : (by reference) receives the number of characters in
the highlighted segment
gsTxt : (by reference) receives a copy of the highlighted text
hmod : (optional, default:null pointer) if specified, target
receives current text-modifier attribute used to highlight
the text segment
Returns:
'true' if highlighted text data successfullly captured.
'false' a) target field contains no highlighted/selected text data
b) field type does not support text highlighting
If 'false', then 'begin' and 'len' are set to zero,
'hmod' is set to acaPLAINTEXT and 'gsTxt' is cleared
(set to empty string).
Returns a copy of highlighted text segment within a Textbox (ftTB) field.
This method was developed primarily for use during development; however,
it may have other uses.
Conceptually similar to copying a “selected” text substring to the clipboard, except that the data are returned directly to caller without accessing the clipboard.
Technical Note: This method does not distinguish between
“highlighted” text and “selected” text.
The text delimited by the 'sela' and 'selb' members is returned
regardless.
Example:
This method is used in the callback function for the Test_Hilite
method of the AnsiCmd test suite.
Refer to thtCallback() in AnsiCmdTest.cpp for details.
Please see HilightFieldText for more information on text highlighting.
The data members of the skField class support multiple types of
user interface controls (see UI Control Types).
Most of the members are public, that is, the application can initialize
them and monitor modification arising from user interactions. Other
members are “protected”, meaning that they are not directly
available to the application. These members must be protected to
maintain data integrity; however, most can be read and modified indirectly
using public methods of the ACWin class, the skForm class, the
skField class, or some combination of these.
Some public members must be initialized explicitly, while others can be used with default values. These defaults are listed here.
Public Data Members
and Scrollbox controls. minimum for most types.'base' coordinates,
which in turn is the 1-based offset from the upper-left corner
of the terminal window.'skForm.base' is the same as
the 'txtBase' member of the ACWin object.'hgt'. Width of (container-2) minus 'wid'.The text of each field is managed within a gString object.
Please see gString Text Tool for more information.
The amount of storage space allocated is calculated dynamically
up to a limit if gsALLOCMAX (1.0 Megabyte).
To modify field text, please see SetFieldText.
logical OR of enum acAttr values.
If the default value is used, then field colors will inherited from
the window interior attributes.'true') to indicate that a border is to be
drawn around the field.'bdr' flag is public and may therefore be specified
during instantiation; however the 'btype' (border line type) and
'battr' (border line color) are protected members, so if a
non-default border is needed, it should be set after opening the window.'lock' flag is primarily used to control visibility and
accessibility of menu controls when they receive and lose the input focus.'lock' flag is set, it indicates that the control is always
visible in the window regardless of whether it has focus (unless is obscured
by another control). When 'lock' is reset, the menu field will be set as
invisible and inactive when it loses focus (see ’hide’ flag).'hide'
flag to de-activate other types of fields which are not currently in use.
This prevents wasted time refreshing fields which are fully obscured
by other fields.'true' or 'false').GUI keys (wcsALT_A, etc.) and function keys
(wcsF01, etc.).'hkey' value is ignored.
While direct specification of hotkeys is valid for all other
control types, this is recommended only for Menu controls
because Menu controls have no label.
For all other control types it is recommended that if a hotkey is
desired, it should be embedded in the field label.
See SetFieldLabel and SetFieldHotkey methods for details.
VIEW BUT NOT MODIFY the
text-parsing data. Please study the MRParse class for a description of
these data.Protected Data Members
MRParse object contains analytical data on the field contents
including the number of text rows and the relative display position of
the data within the control. Also included is both the logical and
physical cursor position within the field.'parseFieldText'.'orig' coordinates which defines the position of
the visible cursor. This value is dynamically calculated from the
'ip' (insertion point) member.
enum LineType, either ltSINGLE or
ltDUAL.skField-class
method for details."[♦] ^Authorize daily cookie delivery"
./epts --test=Tea
Field Types
The types of user-interface controls "fields" are defined by the
FldType enumerated type.
The data for each control type is initialized as an instance of the
skField class.
See skField Data Members for a discussion of each data member.
"Your focus determines your reality."
-- Qui-Gon Jinn
To understand input fields, it is important to understand the concept of “input focus”. Input focus, or just “focus” can be defined as the point where keyboard input is received and processed.
Just at the terminal’s 'stdin' stream receives key input
from the user, the control which is currently monitoring the stdin
stream (the control with focus) receives the key input and decides
whether to process it directly (retain focus), or pass it on to another
control (transfer focus).
In general focus is transferred in response to one of the cursor keys:
Tab, Shift+Tab, Up/Down/Right/Left Arrow, PageUp, PageDown, Home, End;
or by receipt of the “hotkey” assigned to a control.
Under some circumstances, the Enter or Space keys can also trigger a
shift in focus.
"Pushbutton".'Enter' and 'Space'.
Thus to “push” a Pushbutton means to press the Enter or
Space key while the control has focus. The application will then
determine what action is taken in response. ▒▒▒OK▒▒▒ ▒▒CANCEL▒▒
'Enter' and 'Space' keys.Radiobuttons are so called because their function resembles that of the buttons on archaic car radios. They have two states: either “ON” or “OFF”.
A Radiobutton can be a stand-alone control, or can be configured as
a member of an XOR Radiobutton group. The term“XOR” is
nerd-speak for “Exclusive OR”, meaning that exacty one
button of the group may be ON at any given moment. All other buttons
of the group are reset (OFF) when any member of the group is set (ON).
[ ] Small
[◆] Medium
[ ] Large
[ ] Extra Large
[ ] XX Large
[ ] XXX Large
If an application-level callback function is active, it can immediately respond to the control’s change in state, or action can be deferred until the window or dialog is closed, or until some other criteria are met.
One special characteristic of Textbox controls is that they can
receive data directly from the clipboard or send data to the clipboard.
See Communicate With System Clipboard for more information.
When configured to display ordinary text, the user may scroll upward and downward through the data. Horizontal scrolling is not supported.
When configured as a list of individual item (one per line), then the user can scroll through the data and “select” any item, just as an item is selected from a Menu control (see below).
GUI application.File Edit View History Bookmarks Tools Help▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔A context menu is generally defined as invisible until it is needed; and becomes invisible again after a selection is made. It is possible, however, to lock a context menu in the visible state.
The context menu shown is from the author’s FileMangler application
See By the Same Author for a description.
Numerous functional examples of these controls are available throughout
the test applications included in the AnsiCmd library.
Please see Development and Testing for a general description of
the tests available. Specifically, the tests listed under test W
and test D, which contain subtests for Windows, skForm/skField
and Dialogs invoked with:
./epts --test=W
./epts --test=D
The AcEdit application includes a functional set of controls
in an (almost) real-world context.
cd AcEdit
./ace
To create an skForm template, allocate a new object specifying the number of fields, the global parameters and the definition for each field.
Define the skForm template:
This example creates an skForm object with three(3) fields: a Textbox (ftTB),
a Radiobutton control (ftRB) and a Pushbutton control (ftPB).
Note that many parameters of these constructors have default values, but for clarity, they are explicity initialized here. See skForm and skField initialization constructors, above for details.
The working code for this example can be found in the 'Test_Cookie' method
in AnsiCmdTest.cpp.
The initialized skForm template is then passed as a parameter for the ACWin constructor. See ACWin constructor.
Note that the example above does not specify a callback function. The
'EditForm' method returns when user the selects the Pushbutton control.
In the more sophisticated examples, the callback function determines
when the edit loop should be terminated.
Please see EstablishCallback for more information.
User Interaction - the skForm class and skField class
Initialization of an skForm object as a parameter for creating an
ACWin window is shown above.
Accessing the form provides a user interface, via the fields defined by
the skForm object.
After the ACWin object has been created, and the window has been opened, the EditForm method is called to give the user access to the field(s).
Example of calling the EditForm method. This is a copy of the code used in the Test_Cookie test method. See screenshot above.
//* Define an ACWin object *
ACWin *winPtr = new ACWin
( winROW, winCOL,
winHEIGHT, winWIDTH,
ltSINGLE,
acAttr(acaFGb_BROWN | acaBG_BLUE),
acAttr(acaFG_RED | acaBG_GREY),
" Window Formatted With \"skForm\" ",
skfPtr // partially-initialized skForm object
) ;
//* Open the window (make it visible) *
winPtr->OpenWindow () ;
//* Get User Input : Returns when enter key is pressed.*
short fieldIndex ; // on return contains index of exit field
winPtr->EditForm ( fldIndex, wcsENTER ) ;
//* Get a pointer to final field configuration, *
//* and retrive final text and button state. *
const skForm* skfp = winPtr->GetForm () ;
gString finalText = skfp->fld[0].txt ; // contexts of textbox
bool finalRadio = skfp->fld[1].state ; // state of radiobutton flag
//* Close the window and delete the object.*
winPtr->CloseWindow () ;
delete winPtr ;
--- --- --- --- ---
The skForm object is fully integrated into the ACWin-class window;
however, it is possible to make it visually appear that the fields
defined within the skForm object are independent from the enclosing
window.
If desired, the skForm object can be displayed in an
“invisible” (borderless) window. In fact, many of the
skForm tests included with the AnsiCmd library use a borderless window.
See the Test_SoftEcho tests for examples of this usage.
A “window”, (ACWin Class) is a sub-window within the
terminal window. In turn, a “dialog”, as defined within
this project, is a sub-window created within the ACWin parent window.
Dialog sub-windows are based on the ACDlg class. The ACDlg
class is constructed as a simplified version of the ACWin class and
shares many characteristics with ACWin.
The greatest difference is that all methods and data of the ACDlg
class are “protected”. This means that it’s methods and data
are not directly available at the application level. All access is
through specialized methods of the ACWin parent class.
A dialog may be invoked to alert the user to some issue or to gather information from the user which it would be inconvenient for the parent window to request directly.
Dialogs are self-contained objects—that is, there are no
post-launch methods for modification of the displayed data, and for
the “quick” dialog, there is no callback method for monitoring user
activity within the dialog.
This is in contrast to the ACWin-class window which may be updated at any
time under application control.
Two types of dialogs are defined:
1) the “quick” dialog, and
2) the “full initialization” dialog.
A common type of information dialog is to alert the user that she has made an invalid request.
A common type of decision dialog is to ask the user a yes-or-no question.
It is of course possible to configure the dialog to ask more complex questions, such as:
Please refer to the chapter describing Dialog testing see test D for functional dialog examples.
The user interface for a dialog is an skForm structure, the same
type of structure used by the parent window; however, for Quick dialogs,
the skForm structure is automatically generated. For the full-initialization
dialog, the application designer may specify all user-interface
configuration parameters.
Please see skForm Class for a discussion of configuring the user interface.
Three factors determine the dimensions of the dialog:
Validating the Parameters: A significant amount of defensive programming is needed to ensure that the dialog does not extend into or beyond the borders of the parent window. Even so, the application programer could trash the display if determined to do so. (Your mother would be so proud...)
Dialog height, width, vertical offset and horizontal offset may be specified directly as invocation parameters, or may be dynamically calculated based upon the dimensions of the static text to be displayed.
If neither positioning nor dimensioning adjustments will keep the dialog within the available space, then the static text will be truncated and if necessary, the controls will be discarded. This guarantees that the dialog will open successfully, although its appearance may come as a surprise.
1 <= offset <= 10
-1 >= offset >= -10
Example: For a dialog with a width of 31 columns, the range would be: -14 <= offset <= 14 11111987654321012345678911111 43210 - 01234 For a dialog of 30 columns, the range would be: -14 <= offset <= 13 1111198765432101234567891111 43210 - 0123
bool QuickDialog ( const gString& gsMsg, bool query, const char* title = NULL,
short height = 0, short width = 0, short vOff = 0, short hOff = -1,
short timeout = 0, bool dbg = false );
Description of Parameters
The optional 'height' and 'width' may be used to override
the formatting of the message text 'gsMsg'.
"__OK__ _CANCEL_"'vOff' parameter is the vertical offset from the top of the
parent window.'vOff' is set to zero, which means that the dialog is
positioned at the top row of the parent window.The 'hOff' parameter is the horizontal offset from the left
edge of the parent window.
By default, 'hOff' is set to -1 indicating that the dialog is to be
horizontally centered in the parent window.
If the combined offset and dialog dimension would obscure the parent window’s border, the dialog offset and/or dialog dimensions will be adjusted so that the dialog will be displayed entirely within the parent window.
The language for the text of the pushbutton controls is matched to the
active "locale" (at least for the languages we know): English, Spanish,
Chinese (simplified) and Vietnamese. The language defaults to English
if the locale is not one of the recognized locales.
Our ancient Greek and Sanskrit would probably be worthless
here, as they are under most circumstances. :-)
संस्कृतं भव्यं लिखितभाषा अस्ति
const short LANGS = 4 ;
const wchar_t *ymsg[LANGS] = // default pushbutton messages
{
L" ^OK ", // English
L" ^.好的 ", // Zhongwen (Hǎo de)
L" De ^Acuerdo ", // Español
L" ^Tốt " // Tieng Viet
} ;
const wchar_t *nmsg[LANGS] =
{
L" ^CANCEL ", // English
L" ^,取消 ", // Zhongwen (Qǔxiāo)
L" ^Cancelar ", // Español
L" ^Hủy Bỏ " // Tieng Viet
} ;
Support for additional languages may be added easily by extending these arrays; testing for the associated system locale, and setting the language index accordingly.
A special case of the information dialog is the “automatic-timeout” dialog which has no user-interface controls. It is displayed for a specified amount of time, then closes automatically.
bool Dialog ( short dlgHgt, short dlgWid, skForm* formDef,
const char* sTxt = NULL, const char* tTxt = NULL,
short vOff = -1, short hOff = -1, LineType ltype = ltSINGLE,
acAttr bdrAttr = acaUSEDFLT, acAttr txtAttr = acaUSEDFLT,
short tvOff = 0, short thOff = 1,
CUPTR callbk = NULL, bool dbg = false );
Description of Parameters
Three(3) parameters are required: dlgHgt, dlgWid and formDef.
All other parameters are optional, and if not specified, receive default
values as described above.
skForm class and its skField-class
array, please see skForm Class.
All control types defined by enum FldType are supported within a dialog window, with the following limitations:
1 <= count <= MAX_DLG_CTRLS
'context' menus (multi-item stand-alone menus) only; AND
unlike context menus defined in the parent window, the menu will
automatically be set as always visible.bool outlineConfig ( LineType lType, acAttr lAttr ); bool labelConfig ( const char* labText, acAttr labAttr, bool center );
Please see skField Public Methods for details.
Within a dialog, the data member which defines per-item color attributes
is ‘protected’, that is, it may not be directly modified at the
application level. A specialized method of the skField class is
available to configure this option:
bool colorConfig ( const acAttr* rowAttr, short rowCnt );
Please see skField Public Methods for details.
The static text and the controls may occupy the same space without
error. For instance the text may be above, below and on either side
of a control. Just be sure that the text is not obscured by the control.
To do this, the static text should contain only spaces (or newlines '\n')
under the area occupied by the control and the control label (if any).
For example, the following static text data will be rendered in a dialog with two Pushbutton controls as shown.
For optimal display, it is recommended that the first and last characters
of the title text be spaces, although this is not enforced.
Example: " Nerd Alert! ".
The text will be truncated if necessary to fit within the width of the dialog.
The title text will be bracketed by delimiter characters corresponding to the border style and color specified for the dialog as shown in the example above.
enum LineType. By default, the border is drawn with a single-width
line (ltSINGLE), but a dual-width line (ltDUAL) may be specified.
'tvOff' is set to zero, indicating that the
static text is to be drawn starting on the top row of the
dialog interior.'thOff' is set to one(1), indicating that the
static text is to be drawn starting at one column from the
left edge of the dialog interior. A positive value indicates
an additional horizontal offset.
The callback functionality for a dialog is identical in most respects to a callback function for the the parent window.
CUPTR template
(macro), but instead of calling the EstablishCallback method,
the CUPTR is passed as a parameter to the Dialog method. typedef wchar_t (*CUPTR)( short ctrlIndex,
wchar_t wkey, bool firstTime );ACWin class are not applicable to dialogs.
ACWin class defines several dialog-specific
methods for use by dialog callback functions:
Please see Dialog-Oriented Methods for details.
Example Dialog Callback
The working code for this example is located in the AcEditMenu.cpp
module, sfaCallback method. This callback monitors user
specification of a filename for the save-file-as operation.
The user may traverse the the filesystem tree to select the target
directory and specify a filename for the data to be written to that
directory.
//***** Static, non-member function directing *****
//***** callback to member method. *****
static wchar_t nonmember_dlgCallback ( short ctrlIndex, wchar_t wkey,
bool firstTime )
{
return ( (aceditPtr->sfaCallback ( ctrlIndex, wkey, firstTime )) ) ;
} //* End nonmember_dlgCallback() *
//***** AcEdit member method invoked as the *****
//***** Callback method for saveFileAs() *****
wchar_t AcEdit::sfaCallback ( short ctrlIndex, wchar_t wkey,
bool firstTime )
{
static const char* Warn_Dupe[uilENV] =
{ // Warn field width is 28 columns.
"Error, file already exists.", // English
"错误,文件已存在。", // Zhongwen
} ;
static const char* Warn_Name[uilENV] =
{
"Invalid filename characters.", // English
"错误,文件名中包含无效字符。", // Zhongwen
} ;
static const char* Warn_Access[uilENV] =
{
"Unable to access target dir!", // English
"无法访问目标目录!", // Zhongwen
} ;
static const char* noName[uilENV] =
{
" Filename not specified.", // English
" 未指定文件名。", // Zhongwen
} ;
static const char* Cancel_Msg[uilENV] =
{
" Operation Cancelled.", // English
" 重命名操作已取消。", // Zhongwen
} ;
// dialog row where filter message is displayed
const short filterMsgRow = 10 ;
// set if warning message is visible
static bool warnMsg = false ;
gString gs, gsCwd, gsName, gsList ;
const skField* skfPtr = NULL ;// pointer to a control within the dialog
acAttr* acArray = NULL ; // pointer to array of Scrollbox attributes
short itemCnt ; // number of items in Scrollbox control
short item ; // Scrollbox item selected
bool vfat ; // state of text filter Radiobutton
// (set==VFAT compatible)
//*------------*
//* First call *
//*------------*
if ( firstTime )
{ /* Nothing to do at this time. */ }
//* If a warning message is currently displayed, erase it. *
if ( warnMsg )
{
gs.clear() ;
this->win->Dialog_SetText( sfaWARN, gs ) ;
warnMsg = false ;
}
//* Note that the hotkey for a field has been automagically *
//* converted to wcsENTER. *
if ( (wkey == wcsENTER) || (wkey == wcsSPACE) )
{
switch ( ctrlIndex )
{
case sfaSAVE:
// retrieve filename data
this->win->Dialog_GetText ( sfaTEXT, gsName ) ;
if ( (gsName.gschars()) > 1 )
{
//* Validate the filename characters. *
//* Radiobutton state determines which filter to use.*
this->win->Dialog_GetState ( sfaVFAT, vfat ) ;
if ( !(this->isFilename ( gsName, false, vfat )) )
{
//* Warn of invalid filename character(s) *
gs = Warn_Name[this->lang] ;
this->win->Dialog_SetText( sfaWARN, gs ) ;
warnMsg = true ; // remember that warning was posted
wkey = NULLCHAR ; // keycode handled
}
else
{
// Get Scrollbox text. Compare user-provided filename
// with each filename in the array of filenames in CWD.
this->win->Dialog_GetField ( sfaCWD, skfPtr ) ;
gsCwd = skfPtr->txt ;
// pointer to source data
const wchar_t* wsrc = gsCwd.gstr() ;
wchar_t wtrg[MAX_FNAME] ; // filename target buffer
int wchars = gsCwd.gschars(),// source characters
si = ZERO,
ti = ZERO ; // target index
bool match = false ; // set if duplicate name
//* Step over the "parent-dir" item at top of list.*
while ( (si < wchars) && (wsrc[si] != NEWLINE) )
++si ;
++si ;
//* Extract each filename *
for( ; si < wchars ; ++si )
{
while ( (wsrc[si] != NEWLINE) &&
(wsrc[si] != NULLCHAR) )
wtrg[ti++] = wsrc[si++] ;
wtrg[ti] = NULLCHAR ; // terminate the string
ti = ZERO ; // reset target index
gs = wtrg ; // load raw data item
gs.shiftChars( -3 ) ; // discard item prefix
gs.strip() ; // strip leading/trailing whitespace
//* Compare with user's filename *
if ( (gsName.compare( gs )) == ZERO )
{ match = true ; break ; }
}
//* If user's data matches an existing *
//* filename in CWD, warn of duplication. *
if ( match )
{
gs = Warn_Dupe[this->lang] ;
this->win->Dialog_SetText( sfaWARN, gs ) ;
warnMsg = true ; // remember that warning was posted
wkey = NULLCHAR ; // keycode handled
}
//* Else, a valid, non-duplicate filename *
//* specified. Signal that dialog s/b closed.*
//* Filename is in Textbox control. *
else
wkey = wcsCTL_4 ;
}
}
else // empty filename string
{
gs = noName[this->lang] ;
this->win->Dialog_SetText( sfaWARN, gs ) ;
this->win->nsleep ( 20 ) ;
wkey = wcsCTL_4 ;
}
break ;
case sfaCANCEL: // Cancel pushbutton
gs = Cancel_Msg[this->lang] ;
this->win->Dialog_SetText( sfaWARN, gs ) ;
this->win->nsleep ( 16 ) ;
wkey = wcsCTL_4 ;
break ;
case sfaCWD: // Scrollbox display of CWD files
//* Get a copy of "selected" item *
if ( (this->win->Dialog_GetItem ( sfaCWD, gs, item )) )
{
// isolate indicator character
wchar_t indyChar = *gs.gstr() ;
gsName = &gs.gstr()[2] ; // item text without prefix
//* Move to parent directory or subdirectory *
if ( (indyChar == PCHAR) || (indyChar == DCHAR) )
{
//* Get filespec of CWD *
if ( !(this->getCWD ( gsCwd )) ) { gsCwd = L"." ; }
if ( indyChar == PCHAR ) // moving to parent directory
{
gs = gsCwd ;
this->ExtractPathname ( gsCwd, gs ) ;
}
else // moving to subdirectory
gsCwd.append( "/%S", gsName.gstr() ) ;
if ( (this->setCWD ( gsCwd )) )
{
//* Scan new CWD and format the entries. *
// Create an array of color attributes to *
//* match the records *
this->win->Dialog_GetField ( sfaCWD, skfPtr ) ;
itemCnt = this->readCwd ( gsList, acArray,
skfPtr->wid ) ;
// Update text data, and array of color attributes.
// Programmer's Note: Refresh is not performed after
// text update, but is performed only after attribute
// update.
this->win->Dialog_SetText ( ctrlIndex, gsList,
acaUSEDFLT, false ) ;
this->win->Dialog_SetAttr ( ctrlIndex, acArray,
itemCnt ) ;
// release the dynamic allocation
if ( acArray != NULL )
{ delete[] acArray ; acArray = NULL ; }
//* Signal caller that operation is compete.*
wkey = NULLCHAR ;
}
else
{ //* Malformed filespec OR user lacks read access *
gs = Warn_Access[this->lang] ;
this->win->Dialog_SetText( sfaWARN, gs ) ;
warnMsg = true ; // remember that warning was posted
wkey = NULLCHAR ; // keycode handled
}
}
else // non-directory filename
this->win->Dialog_SetText ( sfaTEXT, gsName ) ;
}
// else(call is unlikely to fail)
break ;
case sfaVFAT:
//* State of Radiobutton is being toggled. *
//* Match the filter message with Radiobutton state *
//* NOTE: The state flag has not yet been updated *
//* at this point, so the sense is reversed. *
this->win->Dialog_GetState ( sfaVFAT, vfat ) ;
gs = sfaFilterMsg[this->lang][(vfat ? 0 : 1)] ;
this->win->Dialog_Write ( gs.gstr(), filterMsgRow, 0, true ) ;
break ;
} ;
}
return wkey ;
} //* End sfaCallback() *
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.
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.
I 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() *
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.
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’.
Conditional compilation directives control the build options, both for the
AnsiCmd class library and the EarthPoints application.
Four major conditional-compilation directives control most, if not all
the sub-directives. The first is the INCLUDE_API directive which
enables or disables inclusion of the high-level constructs related to
the creation of window objects and user-interface controls.
The second is the DEBUG_ANSICMD_TEST directive which enables the
test suite located in AnsiCmdTest.cpp.
The other two directives manage the debugging code embedded within the
AnsiCmd library methods. These embedded tests are used to verify
algorithm design and functionality for the library as a whole.
These are the DEBUG_ANSICMD and DEBUG_LOG directives. All
other debugging code is designed to be subordinate to these. If these two
are enabled, debugging code (other than the test suite) is potentially
enabled. If these two directives are disabled, then all debugging code
is disabled.
Because the AnsiCmd class as well as the EarthPoints application
are primarily experimental in design, a large number of
conditional-compilation directives are defined to assist in development
and debugging of the code. The following is a list of the directives
which persist beyond the immediate needs of the programming day.
Please see Development and Testing for more information.
AnsiCmd.hpp, and is the master
directive for all debugging code within the AnsiCmd class. #define DEBUG_ANSICMD (1) debugging code is compiled. #define DEBUG_ANSICMD (0) debugging code is excluded.
All other debugging directives in the AnsiCmd source code are nested
within this directive. Setting the definition to zero SHOULD
disable all debugging code within the AnsiCmd class, including
all the testing methods (grouped under DEBUG_ANSICMD_TEST).
AnsiCmd.hpp, and controls whether the
test suite is included in the library build. This directive should be enabled
when linking with the EarthPoints application, so that all tests and
diagnostic code will be available. The test suite is optional when linking the
library with the other demo apps. If present, it will not affect the functionality
of those apps; however, disabling the test suite will reduce the size of the
compiled library by approximately 500Kb.
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
INCLUDE_API directive, as well as the
DEBUG_ANSICMD, DEBUG_LOG and DEBUG_ANSICMD_TEST directives enabled,
which in turn enables the tests of library functionality in the EarthPoints
application.'grep'
utility to display the debugging directives: grep -n '#define DEBUG_' *.[hc]pp | grep '[(]1[)]' (This is why OCD is not really a “disorder” at all. :-)
As a convenience, a small Perl utility, 'report.pl' is included in
the distribution archive. This utility will report the current state of the
conditional-compile directives described above.
This utility is also invoked by the Makefile when performing a clean build:
gmake all
acGetCursor method, in the
AnsiCmd.cpp module.
The test code uses the debugging log file (see above) to report the
transmission of the ANSI escape sequence commands and the capture
of the response.
The ANSI escape sequence for get-cursor-position is the most
complex of the escape sequences defined by the standard. This is because
after issuing the command, the response is returned to the application
as an escape sequence via 'stdin'. This opens the possibility of
trashing the display.
For this reason, special attention is given to the algorithm used to capture the incomming data. — It works, but keep an eye on it.
specialkeyDecode method,
in the AnsiCmd.cpp module.
The test code uses the debugging log file (see above) to report the captured byte sequences, convert them to standard keycodes and determine whether the keycode belongs to the group of “special” i.e. cursor-control keys.
acFlushIn method in AnsiCmd.cpp to verify
terminal configuration flags for flusing the input stream.
breaksignalReceived method in AnsiCmd.cpp,
this enables monitoring of the break signal (Ctrl+C key) capture and
processing.
suspendsignalReceived method in AnsiCmd.cpp,
this enables monitoring of the suspend signal (Ctrl+Z key) capture and
processing.
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.
shiftFieldText method, in the
AnsiCmdWin.cpp module. This method implements block-shift of text
within the target field.
wpos2tpos method which converts
window-relative coordinates to terminal-relative coordinates. (currently unused)
acSetAttributes method and validates
decoding of color-attribute bitfields and transmitting the corresponding ANSI
escape sequences to set the attributes.
ansicmdSetup method which parses
command-line arguments related to terminal configuration.
eotOffset and ipOffset methods,
respectively, and report the interim results when calculating the cursor
position within a field under edit.
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.
Test_Window method, in the
AnsiCmdTest.cpp module. (currently unused)
ddzCallback method, in the
AnsiCmdTest.cpp module. This is the callback method which monitors
real-time user interaction within an ACDlg class window—specifically
for testing scrolling of text data within a field.
Test_Form method, in the
AnsiCmdTest.cpp module. Optionally test field outline for
Radiobutton controls.(currently unused)
AnsiCmdApi.cpp module.
Report the intermediate results of interaction with the system clipboard.
AnsiCmd library.
The API methods are used by the EarthPoints application for
optional output of the coordinate reports to an ACWin-class object; however,
EarthPoints will build successfully even when this directive is disabled
(set to zero). But in this case, the windowed output option will not be available.
The API methods are required by the AcEdit application which
integrates both ACWin-class and ACDlg-class objects into the
application design.
The API methods are not used in the CsvView application which is
implemented using only the low-level AnsiCmd methods.
Therefore, when building the AnsiCmd library, keep in mind the application
to which the library will be linked, and set or reset this directive as needed.
INCLUDE_API directive
and is defined in AnsiCmd.hpp.INCLUDE_API directive enables the local clipboard which
is available only within the application itself.INCLUDE_WAYLANDCB is enabled, access to the Wayland (system)
clipboard becomes available through the WaylandCB class, assuming the
connection with the system can be established.'wl-clipboard'. sudo dnf install 'wl-clipboard' sudo apt-get install 'wl-clipboard'WaylandCB package.ACWin-class and ACDlg-class Directives
Within the
APIgroup of methods, some additional directives are defined. All debugging directives in this group are contained within the globalDEBUG_ANSICMDdirective, so disabling this global debugging directive will also disable allAPIdebugging code.
- DEBUG_WDUMP — enable write of config data to log
- DEBUG_FDUMP — enable write of field data members to log
- DEBUG_MDUMP — enable write of field MRParse data to log
- DEBUG_FIFO — enable write of BlockFifo data to log
- DEBUG_PHOTO — enable screenshot (for documentation)
These directives are defined within theAnsiCmdWin.hppmodule and control output of various groups ofACWinconfiguration information to the debugging log file.- DEBUG_PHOTO2 — located in the
Screenshotmethod. Supports screenshot capture.
- DEBUG_KPUSH — enable support methods of KeycodePush group
- DEBUG_GFD — request copy of skField data structure
- DEBUG_PFT — parsing algorithm for field text
- DEBUG_SKP — special-key processing for ’flowing’ text
- DEBUG_skpST — special-key processing for ’shifted’ text
- DEBUG_skpInterRow — calculate inter-row offset
- DEBUG_DELCHAR — algorithm for deleting a character
- DEBUG_NKP — filter and process ’normal’ keycodes
These directives are defined within theAnsiCmdWin.cppmodule and are related to identification and processing of “special” keycodes received from the user.
- DEBUG_CBGET_FLOW — paste to control with ’flowing’ text
- DEBUG_CBGET_SHFT — paste to control with ’shifting’ text
- DEBUG_CBGET_OVER — overflow of field during paste
These directives are defined within theAnsiCmdSkf.cppmodule and are used to validate the functionality of the local clipboard “paste” operation for Textbox fields.
- DEBUG_skForm — range-check top-level skForm members
- DEBUG_IMF — verify array of skField objects
- DEBUG_IMM — validate data for Menubox controls
- DEBUG_ISB — validate data for Scrollbox controls
These directives are defined within theAnsiCmdSkf.cppmodule and validate initialization of theskFormandskFieldobjects.
- DEBUG_CCFG —
- DEBUG_SB —
- DEBUG_MB — These directives are defined within the
AnsiCmdSkf.cppmodule and validate per-row color attribute configuration for Menu and Scrollbox controls.
- DEBUG_SA — color attribute bitfield initialization
- DEBUG_TERMSETUP — display terminal setup options
- DEBUG_TS_PAUSE — after report, pause for user response
These directives are defined within theAnsiCmdApi.cppmodule and validate terminal window color-attribute initialization and parsing of command-line parameters for terminal configuration, respectively.
- DEBUG_QDialog
This directive is defined within theAnsiCmdDlg.cppmodule and validates configuration of the QuickDialog invocation.
- DEBUG_Dialog
- DEBUG_ADJ
These directives are defined within theAnsiCmdDlg.cppmodule and validate configuration of the full-initialization dialog. Dialog invocation.
- DEBUG_ED_CLIP
This directive is defined within theAnsiCmdDlg.cppmodule and monitors user interaction within theeditDialogmethod.
EarthPoints.hpp module.EarthPoints.hpp module.EarthPoints.hpp module.EarthPoints.hpp module.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.
To test the build, invoke with a request for the EarthPoints version number. You should get something similar to the following:
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.
'ansicmd.info'
documentation.
/usr/local/share/info/dir
For global system users, this is typically:
/usr/share/info/dir
cd /usr/local/share/info
ls -l ansicmd.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).
If you want to remove the menu entry, use the command:
’gString’ is a small, fast and flexible way to seamlessly convert, format and analyze both UTF-8 and wchar_t (’wide’) text.
Modern applications must be designed for a worldwide audience, and for this reason, the application designer must plan for multi-language support.
Fortunately, the Universal Character Set standard ISO/IEC 10646 and UTF-8, the most popular and flexible method of character-encoding smoothly provide all the character sets, alphabets and special characters which are currently in general use.
Unfortunately, the C and C++ languages offer only minimal support for
internationalization. std::string and std::wstring are nothing more than a
cruel joke to a serious application designer. The GTK+ toolkit’s Glib::ustring
class is an excellent internationalization tool, but it requires installation
of the GTK+ toolkit’s ’glib’ and ’glibmm’ libraries.
For more information on Glib::ustring, see: https://developer.gnome.org/
’gString’ falls halfway between the full feature set of Glib::ustring and the meaningless garbage that is std::string. ’gString’ consists of one C++ header file and one C++ source code module. ’gString’ is integrated into the NcDialog API library, but may also be compiled independently as a small (16Kb) link library or the source may be embedded directly into your application.
Here are the basic ideas you will need to understand in order for your application to smoothly support multiple languages.
See also a discussion of multiple-language support in the NcDialog API.
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 | |
| formatParagraph | |
| compare | see Comparisons |
| compcoll | |
| operator== | |
| operator!= | |
| find | |
| findlast | |
| after | |
| findr | |
| findx | |
| scan | |
| gscanf | see Extract Formatted Data |
| gschars | see Statistical Info |
| gscols | |
| utfbytes | |
| isASCII | |
| clear | see gString Miscellaneous |
| wAlloc | |
| uAlloc | |
| freeSpace | |
| reAlloc | |
| Get_gString_Version | |
| dumpGstring | |
| dbMsg |
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.
Input :
none
Returns:
nothing
Constructor: Initialize members to default values (NULL string).
Input :
charAlloc : storage capacity
interpreted as the maximum number of wchar_t (32-bit) characters
for the storage buffer.
Range: gsALLOCMIN <= charAlloc <= gsALLOCMAX
-- The minimum allocation of gsALLOCDMIN will result in the
same storage capacity at the default constructor.
-- The maximum allocation of gsALLOCMAX is 1000 times the
minimum allocation.
The specified value is normalized by rounding upward to the
nearest multiple of gsALLOCMIN.
Returns: nothing
Constructor: Initialize members to default values with empty string.
This constructor is used to specify the initial storage capacity for the
gString object. This may be useful if it is known that the data the
object will hold will be larger than the default storage capacity.
For more information, see Dynamic Memory Allocation.
Input :
usrc : pointer to a UTF-8-encoded, null-terminated string
charLimit: (optional, -1 by default) maximum number of source
characters to be stored (not including nullchar).
This is the number of characters (NOT the number of
UTF-8 bytes).
If not specified, then all source data will be stored
up to the maximum storage limit.
Returns: nothing
Constructor: Convert specified UTF-8-encoded source to gString.
Input :
wsrc : pointer to a wchar_t-encoded, null-terminated string
charLimit : (optional, -1 by default)
maximum number of characters from source array to
convert
Returns: nothing
Constructor: Convert specified wchar_t (’wide’) source to gString.
bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool sign = false, bool kibi = false, fiUnits units = fiK ) ; 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.
__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.
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.
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
This is in contrast to the “stack” memory which is assigned to the application on startup.
Storage capacity is automatically expanded as necessary to accomodate the size of the data assigned to the object.
gString gs( gsALLOCMED ); gString gs( 2500 ); (gsALLOCDFLT == gsALLOCMIN) 1K UTF-32 characters + 4K UTF-8 bytes + 1K 16-bit integers, or 4Kb + 4Kb + 2Kb == 10Kb (approximately).
4K UTF-32 characters + 16K UTF-8 bytes + 4Kb 16-bit integers, or 16Kb + 16Kb + 8Kb == 40Kb (approximately).
1000K UTF-32 characters + 4000K UTF-8 bytes + 1000K 16-bit integers, or 1Mb + 1Mb + 500Kb == 2.5Mb (approximately).The ‘gsmeter’ test application reports all these methods to be fully functional; however, be aware that the allocation/reallocation algorithm is still young, relatively speaking, (about eight months as of May 2025); so if a problem arises, please drop the author a note.
Please see gsmeter Test App for additional information; specifically
the R[a|b] (reallocate) tests which exercise all methods that perform
modifications to the size of the storage buffers.
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.
Input :
usrc : pointer to an array of UTF-8-encoded characters
Returns:
nothing
Assignment operator: converts UTF-8-encoded source to gString.
Input :
wsrc : pointer to an array of wchar_t 'wide' characters
Returns:
nothing
Assignment operator: converts wchar_t (’wide’) source to gString.
Input :
gssrc : gString object to be copied (by reference)
Returns:
nothing
Assignment operator. Copies one gString object to another.
char utf8Data[] = { "Youth is wasted on the young." } ;
gString gs1, gs2 ;
gs1 = utf8Data ;
gs2 = gs1 ;
wcout << gs2 << endl ;
- - -> Youth is wasted on the young.
__attribute__ ((format (gnu_wprintf, 2, 0))) ; __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.
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: gString Instantiation.
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 );
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.
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.
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.
bool lJust = false, bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool lJust = false, bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool lJust = false, bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool lJust = false, bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool lJust = false, bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool lJust = false, bool sign = false, bool kibi = false, fiUnits units = fiK ) ; bool lJust = false, bool sign = false, bool kibi = false, fiUnits units = fiK ) ; 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'
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’.
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.)
formatInt group'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 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 overflowAs 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.
The NcDialogAPI library automatically sets the application locale
according to the console window environment. Please see the NcDialog documentation, chapter: Multi-language Support
for details.
In brief, the “locale” specifies the upper-/lower-case text rules, numeric formatting, language-specific punctuation, currency symbols and so on.
The application locale should be taken from the terminal environment if
possible, This is done by creating an instance of the "std::locale"
structure referencing the empty string ("").
locale* locptr = new locale("");
The captured locale is then made “global”, that is it replaces the
so-called "classic" (C/C++ language) locale with the specified
locale definition.
locptr->global( *locptr );
Please see the C++ documentation for "std::locale" for details.
Input :
none
Returns:
const pointer to array of wchar_t characters
Return a const pointer to the wchar_t (wide) character array.
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).
Input :
none
Returns:
const pointer to array of UTF-8 characters
Return a const pointer to the char (UTF-8) character array.
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).
int32_t charCount, byteCount ; gString gs( "Wherever you go, there you are!" ) ; const wchar_t* wPtr = gs.gstr() ; const wchar_t* wPtr = gs.gstr( charCount ) ; const char* utf8Ptr = gs.ustr() ; const char* utf8Ptr = gs.ustr( charCount, byteCount ) ;
Input :
uTarget : pointer to target array to receive UTF-8-encoded text
maxBytes : maximum number of bytes to copy (incl. NULL terminator)
maxCols : (optional, default: -1, count bytes only)
maximum number of display-columns to copy
Returns:
number of bytes copied (incl. NULL terminator)
Copy gString text to specified target buffer.
|
Important Note: It is the caller’s responsibility to
specify a target buffer large enough to hold the data.
Be safe: |
Technical Note: If source data bytes greater than specified 'maxBytes',
then copy data up to the complete UTF-8 character <= byte limit.
This avoids writing an invalid character into the target array.
Input :
wTarget : pointer to target array to receive wchar_t 'wide' text
maxChars : maximum number of characters to copy (incl. NULL)
maxCols : (optional, default: -1, count characters only)
maximum number of display-columns to copy
Returns:
number of characters copied (incl. NULL terminator)
Copy gString text to specified target buffer.
|
Important Note: It is the caller’s responsibility to
specify a target buffer large enough to hold the data.
Be safe: |
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.
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.
Input :
targ : (by reference, initial contents ignored)
receives null-terminated contents of specified
character range
-- If target buffer is a char*, then data returned is
a UTF-8 text string.
-- If target buffer is a wchar_t*, then data returned is
a wchar_t (wide) text string.
-- If target buffer is a gString object, then both
UTF-8 and wchar_t data are returned
offset : character index at which substring begins
(this IS NOT a byte index)
charCnt : number of characters to copy (not incl. NULL terminator)
Returns:
if target is a wchar_t* or gString object, then returns number of
characters written to target (not including the NULL terminator)
if target is a char*, then returns number of bytes written to
target (not including the NULL terminator)
Note: returns ZERO if either 'offset' or 'charCnt' out of range
Note: If 'charCnt' extends beyond the end of the source data,
then returns the available data.
Copy the specified character range to target buffer.
These methods copy the indicated substring (null terminated) to
the target buffer, leaving the original data unchanged.
If you have a fixed-format field, then the offset and character count will be known in advance. Otherwise you can use the ’find()’ method to locate the substring to be copied.
|
Important Note: It is the caller’s responsibility to
specify a target buffer large enough to hold the data.
If size of substring is unknown, be safe:
|
Please Note: The number of bytes can NEVER be assumed to be the same as the number of characters.
Please refer to the ’Multi-language Support’ chapter of the'NcDialog API'documentation.
gString gs( "That's not flying, that's falling -- with style!\n"
"Buzz Lightyear" ) ;
char utf8Data[gs.gs.utfbytes()] ;
wchar_t wideData[gs.gschars()] ;
gs.copy( utf8Data, gs.utfbytes() ) ;
gs.copy( wideData, gs.gschars() ) ;
gString gstream( "You're a child's TOY! -- Woody" ) ;
wcout << gstream << endl ;
// get a copy of the first word starting with 'c'
gString AusAnimal( "Aardvark Kangaroo Cockatoo Dingo Wombat " ) ;
gString gsc ;
int b = AusAnimal.find( " c" ) ;
if ( b >= 0 )
{
int e = AusAnimal.find( L' ', b + 1 ) ;
if ( e > b )
{
AusAnimal.substr( gsc, (b + 1), (e - b - 1) ) ;
wcout << gsc << endl ;
}
}
- - -> Cockatoo
Input :
wPtr : pointer to array of wchar_t 'wide' text to be appended
OR
uPtr : pointer to array of char UTF-8 text to be appended
OR
wChar : a single, 'wide' character
Returns:
number of characters in resulting string (incl. NULL terminator)
Note: if value returned equals gsALLOCMAX, then
some data MAY HAVE BEEN discarded.
Append text to existing gString text data up to a combined length of gsALLOCMAX. Characters in excess of the maximum will not be appended.
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.
Input :
fmt : a format specification string in the style of sprintf(),
swprintf() and related formatting C/C++ functions.
arg1 : pointer to first value to be converted by 'fmt'
... : optional arguments (between ZERO and gsfMAXARGS - 1)
Each optional argument is a POINTER (address of) the value
to be formatted.
Returns:
number of characters in resulting string (incl. NULL terminator)
Note: if return equals gsALLOCMAX, then
some data MAY HAVE BEEN discarded.
Append formatted text data to existing gString text data up to a combined length of gsALLOCMAX. Characters in excess of the maxmum will not be appended.
Please refer to the ’compose’ method (see Formatted Assignments) for more information on converting data using a format specification string.
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.
Input :
wPtr : pointer to array of wchar_t 'wide' text to be inserted
OR
uPtr : pointer to array of char UTF-8 text to be inserted
OR
wChar : a single wchar_t 'wide' character
offset: (optional, ZERO by default)
character offset at which to insert specified text into
existing text.
Note: if specified 'offset' > number of characters in
existing text, then acts like 'append' method.
Returns:
number of characters in resulting string (incl. NULL terminator)
Note: if value returned equals gsALLOCMAX, then
some data MAY HAVE BEEN discarded.
Insert text into existing gString text data up to a combined length of gsALLOCMAX. Characters in excess of the maximum will be truncated.
gString gs( L"Remember to hurt people!" ) ; gs.insert( L"NOT ", 9 ) ; wcout << gs << endl ; - - -> Remember NOT to hurt people!
Input :
offset: character offset at which to insert specified text into
existing text.
Note: if specified 'offset' > number of characters in
existing text, then data will be appended to existing text.
fmt : a format specification string in the style of sprintf(),
swprintf() and related formatting C/C++ functions.
Format spec may be either char data or wchar_t data.
arg1 : pointer to first value to be converted by 'fmt'
... : optional arguments (between ZERO and gsfMAXARGS - 1)
Each optional argument is a POINTER (address of) the value
to be formatted.
Returns:
number of characters in resulting string (incl. NULL terminator)
Note: if value returned equals gsALLOCMAX, then
some data MAY HAVE BEEN discarded.
Insert formatted text data into existing text data at the specified offset.
Please refer to compose() method for more information on converting data using a format-specification string.
const char* Month = "April" ; short Date = 28 ; gString gs( L"We have a date on to see the Yankees." ) ; int off = gs.find( "to see" ) ; // index insertion point gs.insert( off, "%s %hd ", Month, &Date ) ; wcout << gs << endl ; - - -> We have a date on April 28 to see the Yankees. gString gs( "drive above 90 kph!" ) ; gs.insert( ZERO, "%S", L"Don't " ) ; // insert at head of text int off = gs.gschars() ; // index end-of-text int Speed = 55 ; gs.insert( off, L" Stay under %02d kph in the city.", &Speed ) ; - - -> Don't drive above 90 kph! Stay under 55 kph in the city.
Input :
charCount : maximum number of characters allowed in formatted data
(not including NULL) Range: 1 to storage limit.
Returns:
number of characters in the adjusted data (including NULL)
Truncate the data to no more than charCount display characters.
Insert a null terminator after the specified number of characters.
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.
Input :
colCount : maximum number of display columns allowed in formatted data
Range: 1 to storage capacity.
Returns:
number of columns needed to display the adjusted data
Note: If specified column count occurs in mid-character, then the
partial character will be removed from the string.
Truncate the data to no more than colCount display columns. Insert a null terminator after the number of characters required to fill the specified number of display columns.
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.
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.
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' ').
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.
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.
Input :
fieldWidth: number of columns for the adjusted data array
padChar : (optional, ASCII space 0x20 by default)
character with which to pad the data
Note: Specify a one-column character ONLY.
Multi-column characters will be ignored.
centered : (optional, 'false' by default)
if 'false', all padding will be appended at the end
of the existing data
if 'true', padding will be equally divided between
the beginning and end of the existing data
Returns:
number of display columns in the adjusted array
Append padding to the existing string data to achieve the specified number of display columns.
If the 'centered' flag is set, the padding will be divided equally
between the beginning and end of the data to achieve the specified field
width. Note that if an odd number of columns is to be added, then the odd
column will be placed at the end of the data.
The ‘padCols’ method calculates the number of padding characters needed to fill out the specified field width.
The default padding character is the ASCII space character (20 hex).
Any single-column character may be specified as an alternate padding
character.
Padding will be added until either the specified number of columns is reached, OR until the array contains the maximum number of characters (storage limit).
If the fieldWidth specified is <= the current width of the data, then the data will not be modified.
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."
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’.
Input :
src : source data to be matched, one of the following:
-- pointer to a UTF-8 string
-- pointer to a wchar_t string
-- a gString object containing the source (by reference)
-- a single, wchar_t character
offset : (optional, ZERO by default)
character index at which to begin search
NOTE: This is a character index, NOT a byte offset.
casesen: (optional, 'false' by default)
if 'false', then scan IS NOT case sensitive
if 'true, then scan IS case sensitive
all : (optional, 'false' by default)
if 'false', then only the first instance of the substring
will be deleted
if 'true', then all instances of the specified substring
from 'offset' forward will be deleted
Returns:
index of first character following the deleted sequence
Note: This is the wchar_t character index, NOT a byte index
Returns (-1) if:
a) no matching substring found
b) 'offset' out-of-range
c) 'src' is an empty string or a NULL character
Scan the data for a matching substring, and if found, erase (delete) the
first occurance of the substring, or optionally all instances of the substring
from 'offset' onward.
Actual comparison is always performed against the ’wide’ character array using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included in the comparison.
Input :
offset : (optional, ZERO by default)
index of first character of sequence to be erased
NOTE: This is a character index, NOT a byte offset.
length : (optional, gsALLOCMAX by default)
if not specified, then erase all characters from
'offset' to end of data
if specified, then erase the specified number of
characters beginning at 'offset'
Returns:
index of first character following the deleted sequence
Note: This is the wchar_t character index, NOT a byte index
Returns (-1) if:
a) offset < ZERO
b) offset >= number of characters in data
c) length <= ZERO
(data will not be modified)
Erase (delete) the data sequence specified by ’offset’ and ’length’.
’offset’ is the index of the first character to be deleted, and ’length’ specifies the number of characters to delete.
'limitChars'
method (i.e. truncates the string at 'offset').
'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).
'erase'For the gString object containing the following verbal
exchange, erase all occurances of the word 'crapweasel'.
gString gs( "Ross : Are you familiar with the word crapweasel?\n"
"Paolo: No, I don't know crapweasel.\n"
"Ross : You're a huge crapweasel!" );
int index = ZERO ;
while ( (index = gs.erase( " crapweasel", index )) >= ZERO ) ;
Yields:
"Ross : Are you familiar with the word?\n"
"Paolo: No, I don't know.\n"
"Ross : You're a huge!"
Find the substring, "the the" and erase the extra "the".
gString gs1( L"There are seven candidates in the the Primary Election." );
gString gs2( L"the " );
int index = gs1.find( "the the" );
gs1.erase( index, (gs2.gschars() - 1) );
Yields:
"There are seven candidates in the Primary Election."
Input :
src : source data to be matched
-- pointer to a UTF-8 string
-- pointer to a wchar_t string
-- a single, wchar_t character
newtxt : data to overwrite existing text
-- pointer to a UTF-8 string
-- pointer to a wchar_t string
-- a single, wchar_t character
offset : (optional, ZERO by default)
character index at which to begin search
NOTE: This is a character index, NOT a byte offset.
casesen: (optional, 'false' by default)
if 'false', then scan IS NOT case sensitive
if 'true, then scan IS case sensitive
all : (optional, 'false' by default)
if 'false', then replace only the first occurance found
if 'true', then replace all occurances of the specified
substring
Returns:
'true' if successful
returns 'false' if error (existing data not modified):
a) no matching source substring found
b) 'src' is a empty string or a null character
c) offset < ZERO or offset is beyond existing data
d) modifying the data would cause buffer overflow
Replace the specified source substring, or optionally all matching substrings with the provided substring.
Actual comparison is always performed against the ’wide’ character array using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included in the comparison.
'replace'Correct the spelling errors in the following data: gString gs( "The land near hare is full of Heres, hoping her and ther." ) ; bool okiday = gs.replace( L"hare", L"here" ) ; Yields: "The land near here is full of Heres, hoping her and ther." okiday = gs.replace( "Here", "Hare", ZERO, true ) ; Yields: "The land near here is full of Hares, hoping her and ther." okiday = gs.replace( L'p', L"pp" ) ; Yields: "The land near here is full of Hares, hopping her and ther." int index = gs.find( "her " ) ; okiday = gs.replace( "her", L"here", index, true, true ) ; Yields: "The land near here is full of Hares, hopping here and there." Then, replace all spaces ' ' with underscores '_'. okiday = gs.replace( L' ', L'_', ZERO, false, true ) ; Yields: "The_land_near_here_is_full_of_Hares,_hopping_here_and_there."
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 target storage capacity.
The count should not include the NULL terminator
append : (optional, 'false' by default)
if 'false', replace existing text with specified text
if 'true', append new text to existing text
Returns:
number of characters in modified string (incl. NULL terminator)
'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,"
Reverse the order of characters in the text string.
If RTL text data displayed by your application is not formatted as desired, then this method may be used to reverse the character order before writing to the display. This is useful for manipulating both RTL (Right-To-Left) language text and mixed RTL/LTR text.
The ’para’ parameter is useful for outputting columns of numeric data or when the column labels are in an RTL language (see example below).
Although modern web browsers (Firefox, Opera, Chromium, etc.) usually handle RTL text correctly, other applications often do not. This is especially true of terminal emulator software.
See also a discussion of multiple-language support in the NcDialog API.
Input :
punct : (optional, 'false' by default)
if 'false', invert entire string
if 'true' AND if a punctuation mark is seen at either end
of the string, invert everything except the punctuation
mark(s). typically one of the following:
'.' ',' '?' '!' ';' ':' but see note below.
para : (optional, 'false' by default)
if 'false', invert data as a single character stream
if 'true', invert data separately for each logical line
(line data are separated by newlines ('\n')
rjust : (optional, 'false' by default)
if 'false', do not insert right-justification padding
if 'true', insert padding for each logical line to
right-justify the data
(used to right-justify LTR output)
Note that right-justification is performed
ONLY if the 'para' parameter is true.
Otherwise, 'rjust' will be ignored.
Returns:
number of wchar_t characters in gString object
(if return value >= storage limit, data may have been truncated)
'textReverse'Note that the const Hebrew strings are written canonically in the source, but are displayed incorrectly in the terminal window by the info reader and by the HTML browser (sorry about that).
// Hebrew: "Are you ready for lunch?"
// Sometimes the terminal will inappropriately move the punctuation
// to the opposite end of the string.
// To prevent this, use the 'punct' option.
const wchar_t* const Lunch = L"?םיירהצ תחוראל ןכומ התא םאה" ;
gString gs( Lunch ) ;
gs.textReverse() ;
wcout << gs.gstr() << endl ;
OUTPUT (correct except punctuation) : האם אתה מוכן לארוחת צהריים?
gs = Lunch ;
gs.textReverse( true ) ;
wcout << gs.gstr() << endl ;
OUTPUT (correct): ?האם אתה מוכן לארוחת צהריים
// When the 'punct' flag is set, both leading and trailing punctuation
// are identified.
// Questions in Spanish use a leading inverted question mark (U+00BF),
// and a trailing ASCII question mark (U+003F).
// Reverse the internal text but do not reverse the terminal punctuation.
gs = "¿ozreumla le arap atsil sátsE?" ;
gs.textReverse( true ) ;
wcout << gs.gstr() << endl ;
OUTPUT : ¿Estás lista para el almuerzo?
= = = = =
// Reverse multi-line text (paragraph formatting).
// Ordinary ASCII text is used for this example
// to demonstrate the reversal.
// The example outputs to an NcDialog window referenced by NcDialog *dp
const char* Vaccine = "Have you received your covid-19 vaccination yet?\n
"Protect yourself and others,\n"
"get your vaccination today!" ;
gs = Vaccine ;
// Write unmodified text as LTR data:
dp->WriteParagraph ( 1, 1, gs, nc.grR, true, false ) ;
OUTPUT: Have you received your covid-19 vaccination yet?
Protect yourself and others,
get your vaccination today!
// Reverse the data, without punctuation processing or
// right-justification. (Note: all parameters are optional,
// but are shown here for clarity.)
gs.textReverse( false, true, false ) ;
// Write reversed text as LTR data:
dp->WriteParagraph ( 1, 1, gs, nc.grR, true, false ) ;
OUTPUT: ?tey noitaniccav 91-divoc ruoy deviecer uoy evaH
,srehto dna flesruoy tcetorP
!yadot noitaniccav ruoy teg
// Write the same data as RTL (note the X origin of 48):
dp->WriteParagraph ( 1, 48, gs, nc.grR, true, true ) ;
OUTPUT: ?tey noitaniccav 91-divoc ruoy deviecer uoy evaH
,srehto dna flesruoy tcetorP
!yadot noitaniccav ruoy teg
// Reload the source data and reverse it without punctuation processing,
// but WITH right-justification padding.
gs = Vaccine ;
gs.textReverse( false, true, true ) ;
// Write reversed text as LTR data.
// Note that the padding character is ASCII space ' ',
// however the '-' character is used here to show the padding position.
dp->WriteParagraph ( 1, 1, gs, nc.grR, true, false ) ;
OUTPUT: ?tey noitaniccav 91-divoc ruoy deviecer uoy evaH
--------------------,srehto dna flesruoy tcetorP
---------------------!yadot noitaniccav ruoy teg
// Write the same data as RTL (note the X origin of 48):
dp->WriteParagraph ( 1, 48, gs, nc.grR, true, true ) ;
OUTPUT: ?tey noitaniccav 91-divoc ruoy deviecer uoy evaH
--------------------,srehto dna flesruoy tcetorP
---------------------!yadot noitaniccav ruoy teg
// Combine RTL text with numeric (LTR) data.
// Create an ASCII numeric time string.
// Reverse the numeric string.
// Insert a Hebrew label: "The current time is: "
const wchar_t *timeLabel = L"השעה הנוכחית היא: " ; //(displayed incorrectly)
short hours = 12, minutes = 32, seconds = 45 ;
gs.compose( "%02hd:%02hd:%02hd", &hours, &minutes, &seconds ) ;
gs.textReverse( false, true, false ) ;
gs.insert( timeLabel ) ;
// Write the data as RTL (note the X origin of 26):
dp->WriteParagraph ( 1, 26, gs, nc.grR, true, true ) ;
OUTPUT:
12:32:45 :השעה הנוכחית היא
Technical Note On Punctuation
Determining which characters are and are not punctuation is locale specific
(see the 'ispunct()' C-language function).
Rather than rely on the locale used by the application calling this method,
we test against a list of the most common punctuation characters used in
modern languages. If a punctuation character used by your application is
not recognized as punctuation, please send us a note including the Unicode
codepoint and we will add it to the list.
int32_t *truncIndex = NULL );
Input : maxRows : maximum rows for message (>= 1)
maxCols : maximum columns on any message row (>= 4)
trunc : (optional, 'true' by default)
if 'true', truncate the data if necessary to ensure
that the data do not extend beyond the
specified target area
if 'false', format the entire source text array, even
if doing so requires violating the specified
height of the target area (maxRows).
(see also 'truncIndex' parameter)
hyphenbrk: (optional, 'false' by default)
if 'false', automatic line breaks occur at space ' '
characters only (20h)
Special Case: the following CJK ideographs
are also recognized as whitespace for
purposes of line formatting (see below)
'、' comma U+3001 and
'。' full stop U+3002
if 'true', in addition to the space ' ' characters,
enable line break at:
ASCII hyphen '-' (2dh)
Unicode — '—' (2014h)
Unicode – '–' (2013h)
Unicode − '−' (2212h)
Unicode ­ (00ADh) (soft hyphen)
truncIndex: (optional, null pointer by default)
(referenced _only_ when the 'trunc' flag is reset)
If specified, points to a variable to receive the
index at which the data _would_have_been_ truncted to
fit the specified height of the target area if the
'trunc' flag had been set.
a) A positive value indicates that the data have not
been truncated, AND that the data extend beyond
the specified target area.
b) A negative value indicates that it was not necessary
to truncate the data i.e. the data fit entirely
within the target area.
Returns: number of text rows in the formatted output
Reformat the text so that when written to the display, it will fit within the specified rectangular area.
The dimensions of the formatted text is specified as the number of text rows and columns, with a minimum of one(1) row by four(4) columns.
Technical Description of the Line Break Algorithm
Formatting is done in three steps:
'trunc' and 'truncIndex' parameters)
Token: A ‘token’ as used here is a series of printing characters delimited by whitespace characters. If line breaks on hyphen-like characters is enabled, those characters are also interpreted as token delimiters.
Special Case: CJK text seldom contains any spaces at all within a sentence,
or even between sentences. Two-column punctuation is designed to provide a
visual spacing effect. For this reason, we have made the design decision to
process the following CJK ideographs as whitespace:
'、' comma U+3001 and '。' full stop U+3002
Caution: Tab characters (’\t’) _are not_ recognized as whitespace
characters because they are effectively variable width
characters. Don’t use them!
For safety, if Tab characters are present in the text, they are silently removed.
Optionally, the ASCII hyphen and the Unicode hyphen-like characters
can be treated as if they were whitespace characters for purposes of the
algorithm. (see the 'hyphenbrk' parameter.) The characters included within
this group are:
'trunc' and 'truncIndex' parameters)
Filespecs and URLs should be parsed using specialized formatting methods.
Long words can be a challenge during parsing of the data. Our solution is
to define “long” tokens as those which are more than half the
specified area width ('maxCols').
This method can optionally break after hyphens, but this may sometimes cause
unintended breaks or confusing output. Use the 'hyphenbrk' option wisely.
Input :
uStr : (UTF-8 string) to be compared
OR
wStr : (wchar_t string) to be compared
OR
gs : (by reference) gString object containing
data to be compared
casesen : (optional, 'true' by default)
if 'true' perform case-sensitive comparison
if 'false' perform case-insensitive comparison
length : (optional, -1 by default. i.e. compare to end)
maximum number of characters to compare
offset : (optional, ZERO by default)
If specified, equals the character offset into the
gString character array at which to begin comparison.
Returns:
return value uses the rules of the 'wcsncmp' (or 'wcsncasecmp')
library function (see string.h):
ZERO, text data are identical
> ZERO, first differing char of gString object is numerically larger.
< ZERO, first differing char of gString object is numerically smaller.
Compares the text content of the gString object with the specified text.
The comparison is performed against the gString objects’ wchar_t character
arrays. The character comparisons are numerical, not locale-based.
This includes the relationship between upper-case and lower-case characters.
For locale-specific comparisons, please see compcoll method below.
Input :
gs : (by reference) object whose text is to be compared
casesen : (optional, 'true' by default)
if 'true' perform case-sensitive comparison
if 'false' perform case-insensitive comparison
Returns:
return value uses the rules of the 'wcsncmp' (or 'wcsncasecmp')
library function (see string.h):
ZERO, text data are identical
> ZERO, first differing char of gString object is numerically larger.
< ZERO, first differing char of gString object is numerically smaller.
Compares the text content of two gString objects.
The comparison is performed against the gString objects’ wchar_t character
arrays. The character comparisons are numerical, not
locale-based. This includes the relationship between upper-case and
lower-case characters.
For locale-specific comparisons, please see the compcoll method below.
Input : wStr : (UTF-32 string) to be compared
OR
uStr : (UTF-8 string) to be compared
OR
gs : (gString object by reference) data to be compared
Returns: using the rules of the 'wcscoll' library function (see wchar.h):
ZERO, text data are identical
> ZERO, first differing char of stored data is larger.
< ZERO, first differing char of stored data is smaller.
Compares the text content of the gString object with the specified text.
The comparison is performed according to the active "locale" within the
application. This comparison is known as the “collation order” or
“dictionary order” comparison where lowercase letters are considered as
less than their uppercase equivalents. Characters with diacritical markers
and unitary character sequence (e.g. Spanish 'll') will also be sorted
according to the rules of the active locale.
'compcoll' method is not effective for these languages.
'wcscmp' (numeric comparison)
function because it scans the data multiple times.
'wcscoll' function exclusively to perform the comparison.
Technical Note:
In the ASCII world, the letter
'A'is numerically less than the letter'a'; however, in the world of locale-specific comparison, English lowercase is “less than” uppercase, so'a'is less than'A'.Examples of string comparison using the collation algorithm:
'abc' == 'abc' 'abc' < 'ABC' 'ABC' < 'abc' 'abc' < 'aBc' 'abc' < 'abC' 'abc' < 'abcd' 'abcd' > 'abC' 'abcd' < 'abCd' 'abC' < 'abcd' This would suggest that the collation algoorithm is essentially useless unless your project is to create a dictionary.
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.
Input :
gs2 : (by reference)
gString object containing string to be compared
Returns:
'true' if the strings are different, else 'false'
Comparison operator: Compares the text content of two gString objects.
The comparison is performed against the wchar_t character arrays of the two objects. The comparison is case-sensitive.
Input :
src : source data to be matched, one of the following:
-- pointer to a UTF-8 string
-- pointer to a wchar_t string
-- a gString object containing the source (by reference)
-- a single, wchar_t character
offset : (optional, ZERO by default)
character index at which to begin search
-- if out-of-range, then same as if not specified
casesen: (optional, 'false' by default)
if 'false', then scan IS NOT case sensitive
if 'true, then scan IS case sensitive
maxcmp : (optional, (-1) by default)
-- if not specified, then scan for a match of all
characters in 'src' (not including null terminator)
-- if specified, then scan for a match of only the first
'maxcmp' characters of 'src'
-- if out-of-range, then same as if not specified
Returns:
index of matching substring or (-1) if no match found
Note: This is the wchar_t character index, NOT a byte index
Scan the data for a matching substring and if found, return the index at which the first substring match begins.
Actual comparison is always performed against the ’wide’ character array using wcsncasecmp (or wcsncmp). Null terminator character is not included in the comparison.
Input :
src : source data to be matched, one of the following:
-- pointer to a UTF-8 string
-- pointer to a wchar_t string
-- a gString object containing the source (by reference)
-- a single, wchar_t character
casesen: (optional, 'false' by default)
if 'false', then scan IS NOT case sensitive
if 'true, then scan IS case sensitive
Returns:
index of last matching substring or (-1) if no match found
Note: This is the wchar_t character index, NOT a byte index
Scan the data for the last occurance of the matching substring and if found, return the index at which the substring match occurs.
Actual comparison is always performed against the ’wide’ character array using wcsncasecmp (or wcsncmp). Null terminator character is not included in the comparison.
Input :
src : source data to be matched, one of the following:
-- pointer to a UTF-8 string
-- pointer to a wchar_t string
-- a gString object containing the source (by reference)
offset : (optional, ZERO by default)
character index at which to begin search
-- if out-of-range, then same as if not specified
casesen: (optional, 'false' by default)
if 'false', then scan IS NOT case sensitive
if 'true, then scan IS case sensitive
Returns:
index of the character which follows the matching substring
or (-1) if no match found
Note: This is the wchar_t character index, NOT a byte index
This method is very similar to the ’find()’ method above, but instead of returning the index to the beginning of the substring, returns the index of the character which FOLLOWS the substring.
Input : src : source data to be matched, one of the following:
-- pointer to a UTF-8 string
-- pointer to a wchar_t string
-- a gString object containing the source (by reference)
-- a single, wchar_t character (by reference)
offset : (optional, by default: index of null terminator minus one)
character index at which to begin search
-- if out-of-range, then same as if not specified
casesen: (optional, 'false' by default)
if 'false', then scan IS NOT case sensitive
if 'true, then scan IS case sensitive
Returns: index of the first character (closest to head of data) of the
matching substring or (-1) if no match found
Note: This is the wchar_t character index, NOT a byte index
Scan the data beginning at the specified offset and moving toward the head of the string (toward offset zero). Locate the matching substring and if found, return the index of the first match.
Actual comparison is always performed against the ’wide’ character array using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included in the comparison.
' ', int32_t 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.
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
gString str1( "Toys for Tots" ) ;
gString str2( "The Tin Drum" ) ;
// compare with UTF-8 string
int result = str1.compare( "Toys for Tots" ) ;
// compare with wchar_t string
int result = str2.compare( L"The Tin Drum" ) ;
// compare gString objects
if ( str1 == str2 ) { /* do stuff */ }
if ( str1 != str2 ) { /* do stuff */ }
gString gs( L"Tiny Tim had a titillating tour of Times Square." ) ;
// find first instance of substring "tim" (not case sensitive)
int tIndex = gs.find( "tim" ) ;
wcout << &gs.gstr()[tIndex] << endl ;
- - -> Tim had a titillating tour of Times Square.
// find the next instance of "tim"
gString gsSub( "tim" ) ; // search string in a gString object
tIndex = gs.find( gsSub, tIndex + 1 ) ;
wcout << &gs.gstr()[tIndex] << endl ;
- - -> Times Square.
// find first instance of substring "ti" (case sensitive)
tIndex = gs.find( L"ti", 0, true ) ;
wcout << &gs.gstr()[tIndex] << endl ;
- - -> titillating tour of Times Square.
// match the first three characters of the search string
tIndex = gs.find( L"squirrel", 0, false, 3 ) ;
wcout << &gs.gstr()[tIndex] << endl ;
- - -> Square.
// find first instance of L'R' (not case sensitive)
tIndex = gs.find( L'R' ) ;
wcout << &gs.gstr()[tIndex] << endl ;
- - -> r of Times Square.
// extract the filename from path/filename string
gString gs( "/home/sam/SoftwareDesign/NcDialog/Dialog1/gString.hpp" ) ;
if ( (tIndex = gs.findlast( L'/' )) >= 0 )
wcout << &gs.gstr()[tIndex + 1] << endl ;
- - -> gString.hpp
// insert text after first instance of substring
gString gs( "I think that a parrot would be an ideal pet." ) ;
int pIndex = gs.after( L"would" ) ;
gs.insert( " NOT", pIndex ) ;
- - -> I think that a parrot would NOT be an ideal pet.
For more examples of using gString-class methods, please refer to
Test #6 of the ’Dialogw’ test application.
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 :-)
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.
int sval1, sval2, sval3, sval4 ;
int ival ;
long long int llval ;
double dval ;
char str1[64], str2[16], str3[16], ch1 ;
gString gs( "17 % 18 21 22 48A2B 720451 24.325 A country song "
"is three chords and the truth. - Willie Nelson" ) ;
int32_t cnt =
gs.gscanf( L"%d %% %d %d %d %X %lld %lf %63[^-] %c %16s %16s",
&sval1, &sval2, &sval3, &sval4, &ival, &llval,
&dval, str1, &ch1, str2, str3 ) ;
gString gsOut( "items : %d\n"
"numeric : %d %d %d %d 0x%04X %lld %4.6lf\n"
"text data: \"%s\" %c %s %s\n",
&cnt, &sval1, &sval2, &sval3, &sval4, &ival, &llval, &dval,
str1, &ch1, str2, str3 ) ;
dp->WriteParagraph ( 1, 1, gsOut, dColor ) ;
This yields:
items : 11
numeric : 17 18 21 22 0x48A2B 720451 24.325000
text data: "A country song is three chords and the truth. " - Willie Nelson
A working example may be found in the NcDialog API package,
(Dialogw test application, Test #6).
- - - - -
To begin the scan from a particular offset into the text, the unneeded
initial data may either be scanned into a throw-away buffer or the
scan offset may be specified directly. For example, to discard the
first sixteen(16) characters:
wchar_t junk[gsALLOCMIN] ;
gs = "Useless garbage: 17 21 34" ;
gs.gscanf( L"%16C %d %d %d", junk, &sval1, &sval2, &sval3 ) ;
_or_
gs.gscanf ( 16, L"%d %d %d", &sval1, &sval2, &sval3 ) ;
THIS: %64s %128lls %256S %32[a-z]
NOT THIS: %s %lls %S %[a-z]
Input :
none
Returns:
number of characters in the string
Returns the number of characters in the string including the null terminator.
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.
Input :
none
Returns:
number of columns needed to display the data
Returns the number of columns required to display the string.
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).
This example is from the FileMangler utility. It trims the head of
the provided path/filename string to fit within a dialog window.
void FmConfig::ecoPathFit ( gString& gsPath, short colsAvail )
{
if ( (gsPath.gscols()) > colsAvail )
{
gString gst = gsPath ;
int32_t width = gst.gscols(),
offset = ZERO,
charCount ;
const short* colArray = gst.gscols( charCount ) ;
while ( width > (colsAvail - 3) )
width -= colArray[offset++] ;
gsPath.compose( L"...%S", &gst.gstr()[offset] ) ;
}
} //* End ecoPathFit() *
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.
Input : none Returns: nothing
Reset contents to an empty string i.e. "". The data will consist of
a single, NULLCHAR character (L'\0').
The character and byte counts are set to 1 (one), and the column count is zero.
Input : none
Returns: size of dynamic storage allocation in wchar_t words
OR
size of dynamic storage allocation in uint8_t (char) bytes
Report data storage allocation for the gString object:
Note that this the maximum UTF-32 (wchar_t) characters,
(or UTF-8 byte) capacity, NOT the current number of
characters or bytes stored.
wAlloc : returns the storage allocation for
UTF-32 (wchar_t) characters
uAlloc : returns the storage allocation for UTF-8 bytes
Input : none
Returns: available buffer space
Note: If zero(0) is returned, data may have been
truncated to fit.
Reports the amount of free buffer space available, expressed as a count of UTF-32 (wchar_t) characters.
Input :
steps : number of steps to increase or decrease in buffer size.
Range: +/-999
If value out of range, will be set to upper/lower limit.
clear : (optional, 'false' by default)
if 'false', if possible, retain the existing contents
of the buffer. (Note that if buffer size is
reduced, some data may be truncated.)
if 'true', erase any existing text in the buffer
(same as 'clear' method, above)
Returns: new buffer capacity expressed as the number of wchar_t characters
Increase or decrease the size of storage buffer by the specified number of gsALLOCMIN increments.
The buffer is sized in multiples of gsALLOCMIN in the range:
gsALLOCMIN <= size <= gsALLOCMAX
1024 chars 1,024,000 chars
Input :
none
Returns:
pointer to version string
Return a pointer to gString class version number string.
Input :
gsmsg : (caller's object, by reference)
receives most recent debug message
Returns:
nothing
FOR DEBUGGING ONLY! Application can retrieve most recent debug message.
Note: This method is visible only if the DEBUG_GSTRING flag is set
in gString.hpp.
void dumpGstring ( const wchar_t*& gstr, const char*& ustr, const short*& cwid, int32_t& gsw, int32_t& gsu, int32_t& bsch, int32_t& bsco, int32_t& utfb, bool& isas ) const;
Input :
gstr : array of wchar_t characters
ustr : array of UTF-8 bytes
cwid : array of column widths
gsw : size of gstr array
gsu : size of ustr array
bsco : number of display columns required for stored data
bsch : number of wchar_t characters stored (incl. nullchar)
utfb : number of UTF-8 bytes stored (incl.nullchar)
isas : set if stored data are pure ASCII data
Returns: nothing
FOR DEBUGGING ONLY! Get a snapshot of the private gString data members.
Note: This method is visible only if the DEBUG_GSTRING flag is set
in gString.hpp.
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.
const char* some_UTF-8_data = "I want to buy an hamburger." ; wchar_t some_wide_data[gsALLOCDFLT] ; gString gs( some_UTF-8_data ) ; gs.copy( some_wide_data, gsALLOCDFLT ) ;
const wchar_t* some_wide_data = L"I want to buy an hamburger." ; char some_UTF-8_data[gsALLOCDFLT] ; gString gs( some_wide_data ) ; gs.copy( some_UTF-8_data, gsALLOCDFLT ) ;
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?
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.
This is a formatting method taken from the ’Dialogx’ test application. It breaks a text stream into lines which fit within the dianostic window. It’s not speedy (or particularly smart), but it demonstrates the use of ’gString’ to calculate the space needed to display text data and then formatting the data to fit the space.
//* FormatOutput *
//* Input : gsOut : semi-formatted source data
//* wpos : start position for display
//* lineCount : maximum display lines before truncation
//* Returns: nothing
void dXClip::FormatOutput ( const gString& gsOut,
winPos& wpos, int32_t lineCount )
{
int tWidth = (ddCOLS - 2), // inside width of target window
maxWidth = tWidth * lineCount,// max columns for message
tLines = ZERO ; // loop counter
gString gsw( gsOut.gstr() ), gso ;
if ( gsw.gscols() > maxWidth )
{ // truncate the string if necessary
gsw.limitCols ( maxWidth - 3 ) ;
gsw.append( L"..." ) ;
}
do
{ // break the source into convenient widths
gso = gsw ;
gso.limitCols( tWidth ) ;
gso.append( L'\n' ) ;
gsw.shiftCols( -tWidth ) ;
this->dpd->ClearLine ( wpos.ypos ) ; // clear target display line
wpos = this->dpd->WriteParagraph ( wpos, gso,
dxPtr->dColor, true ) ;
}
while ( ++tLines <= lineCount && gsw.gschars() > 1 ) ;
} //* End FormatOutput() *
The example above is just a simple demonstration of using column widths.
To see it in action, please refer to the ’Dialogw’ NcDialog API Test
Application, test seven (7).
For a more sophisticated text-parsing algorithm, see formatParagraph which parses text data by token rather than simply counting columns.
GSMETER gsmeter Introduction gsmeter Options Building gsmeter
The original design of the gString class was based upon a fixed buffer size
of PATH_MAX, which is the maximum length of a file specification under
the POSIX standard. This is is defined as s GNU compiler constant, (4096 bytes),
which is greater-than-or-equal-to the number of bytes (or characters),
depending on the character set used for filespecs.
This buffer size was chosen specifically to balance storage capacity with
performance. The original gString design has performed far beyond expectations
for over fifteen years, and it is expected to meet or exceed most daily needs
of applications into the future.
In October of 2024, a beta-test branch of the gString class, bString
was created. The design critera for this class were to retain the original
functionality of the gString class with as few modifications as possible,
while converting the static character buffers to dynamically-resized character
and byte buffers.
This compares favorably with std::string and std::wstring which are cute in their own way and semi-functional; but seriously overweight. While it is not our intention to be fat-shaming the C++ language, std::string support for text data is functionally inconvenient, entirely too English-centric and practically-speaking, is often mis-used (or ignored completely) by developers due to its opaque implementation, which is based on a solid idea, but clearly, was designed by committee.
Because this new design touches every aspect of the original gString
functionality, the 'gsmeter' test utility was created to perform
exhaustive regression testing, with a special focus on the algorithms
for allocation and re-allocation of dynamic memory.
The beta branch has now been re-integrated into the mainline gString class, so the test application is now being included as part of the gString distribution. Have fun!
While this application lacks professional polish, it does provide a simple
menu structure and the usual --help and --version options.
gsmeter: version:0.0.05 gString v:0.0.37 - (c) 2024-2025 The Software Samurai
------------------------------------------------------------------------------
Test Suite for gString Class Usage: gsmeter TEST [SUBTEST]
C[a|b] --------- Constructors : S ------- Statistics
I[a|b] --------- Initializers : O ------- Output group
M[a|b|c|d]------ Modifiers : B[a|b] -- Buffer size
A[a|b|c|d|e|f]-- Analyzers : R[a|b] -- Reallocation
--help --version : P ------- Playground
Example Invocations:
gsmeter # No arguments, invokes the options menu
gsmeter Ca # Constructor Group, section 'a'
gsmeter Ac # Analyzer Group, section 'c'
gsmeter --version # Report version numbers, current locale
# and copyright info
The tests are grouped according to functionality, and are sub-divided into smaller groups so that each test run will fit within one terminal window of 39 rows x 150 columns.
There are seven(7) test groups with eighteen(18) tests, plus a “Sandbox” for creating ad-hoc tests.
Reporting of test results is split between the terminal window and a
file (gsmdbg.txt) created in the current working directory.
Note on Application Locale
gsmeter automatically enables the “locale” specified in
the terminal environment. While the gString class is written to be
locale-independent, some of the gsmeter tests rely upon the locale to
function properly.
Specifically, the gString compcoll (compare-collated) method invokes
the locale-aware C-language function,'wcscoll'. This function uses a
dictonary-style comparison which is dependent on the language and locale
involved. Please see compcoll method for details.
gsmeter is a very simple application, so building it is also simple.
There are four(4) ways to invoke the Makefile:
Important Note: Some tests include a snapshot of the gString object’s internal configuration. This report requires that a conditional-compile declaration be enabled: #define DEBUG_GSTRING (1) This declaration is located near the top of gString.hpp. This declaration should be enabled only for use by
gsmeter, and should be disabled for all other applications. #define DEBUG_GSTRING (0)
'CsvView' (csvv) reads any Comma-Seperated-Values file and formats the
data for viewing in the terminal window.
Comma-Seperated-Values files are plain-text files commonly used for transferring tabular data between applications or accross the web. The format is very simple and supported by many applications such as LibreOffice, Excel(tm), as well as various email platforms and database applications.
While there is no formal specification for CSV data, several groups have worked
toward a normalized format, most notably the World Wide Web Consortium (W3C).
https://www.w3.org/TR/tabular-data-primer/
https://www.w3.org/2013/csvw/wiki/Main_Page.html/
Additional information (and the opinions of various parties) are available:
Internet Engineering Administration, Research Task Force (IRTF):
https://datatracker.ietf.org/doc/html/rfc4180
FileFormat.com:
https://docs.fileformat.com/spreadsheet/csv/
Wikipedia:
https://en.wikipedia.org/wiki/Comma-separated_values
For examples of CSV files, please see CSV Encoding, and the sample CSV files included with this distribution.
The CsvView application (csvv) reads any CSV-formatted file and reformats it
for viewing, either directly in the terminal window or through the 'less'
utility. CsvView supports source files in any of the four(4) authorized
encodings:
UTF-8
UTF-8 with byte-order mark (BOM)
UTF-16LE (little-endian)
UTF-16BE (big-endian)
It is important to note that the 'less' can display some CSV files
without the need for reformatting; however, 'less' will often complain
that the target file is a "binary" file, and cannot display the data as text,
even though the file does not actually contain binary data.
For this reason, CsvView reformats the source data into pure UTF-8 encoding
before display. This re-encoding also vertically aligns the fields to present
the data in an orderly manner. CsvView can format the output in any of
three(3) ways.
Horizontal Format: one record per line
NAME TITLE PHONE EMAIL Helena Handbasket Queen of the Castro 415-654-3210 Yaz-Queen@TwinPeaks.com
Vertical Format : one field per line
NAME Helena Handbasket TITLE Queen of the Castro PHONE 415-654-3210 EMAIL Yaz-Queen@TwinPeaks.com
Quick Format : horizontal format, truncated to width of window
┌───────────────────────────────────────────────────────┐ │NAME TITLE PHONE EMA│ │Helena Handbasket Queen of the Castro 415-654-3210 Yaz│ └───────────────────────────────────────────────────────┘
Please see csv display option for selection of the display format.
CsvView may also be used to create files in CSV format using
any of the encoding methods described above.
Please see csv create option for details.
This chapter lists the command-line options for invoking the CsvView (csvv).
The 'help' and 'version' options override all other specified options.
The CsvView application is intentionally very simple — built without
support for direct user-configuration of the AnsiCmd library. The only
available terminal configuration option is for selection of the color
attributes used for text output.
Please see Invoking - Terminal Setup for a detailed discussion of the
AnsiCmd terminal setup options used for the EarthPoints and AcEdit
applications,
OPTION DESCRIPTION csv filespec option Specify the source CSV file csv display option Specify the display format csv fgndattr option Foreground color attribute csv bgndattr option Background color attribute to a file csv language option Specify user-interface language csv header option Specify whether source file includes a header record csv saveas option Save formatted display data csv stats option Report source file stats csv dimensions option Report dimensions of terminal window csv help option Display all application options csv helpless option Same as '--help'option except pipe through'less'csv version option Reports CsvView version number and copyright info. ---Development Options---------------------csv create option Create a CSV file csv capture option Capture a range of records csv terminfo option Report the current terminal configuration csv pause option Pause before display of formatted data
Options may be specified in any order.
For each option that requires one or more arguments, the option name and
its argument(s) may be separated by either '=' or ' ' (space).
Note that if the argument contains whitespace, then the entire argument
sequence must be enclosed within single-quotes or double-quotes.
This prevents the terminal’s shell program from “interpreting”
(trashing) your argument formatting.
Multiple instances of an option will result in unpredictable results, so don’t do it.
Examples:
--filespec=Contacts.csv
--filespec Contacts.csv
--create=Sample.txt,utf8bom,crlf
--create "Sample Records.txt, utf16le, crlf"
Note: As a convenience, the options may be uniquely specified
in a truncated form. At least six (6) characters of the option must be
specified. This consists of the two 'dash' characters, plus the first four
characters of the option name. Example: The “--filespec”
option may be uniquely specified as “--file”.
Specify the file to be displayed.
The source file may be specified as a filename in the current directory, as a relative path, or as an absolute path. Special characters such as'.' '..' '~'are recognized, and symbolic links in the path will be followed. The filename must include the".csv"filename extension.The file must be in Comma-Seperated-Values (CSV) format, and encoded as
UTF-8, UTF-8 with byte-order-mark, UTF-16LE or UTF-16BE.
If the file cannot be verified as containing valid CSV data, a warning will be displayed and the application will exit.
Important Note: Because there is no formal standard for the CSV format, it is possible that a non-CSV file will be accepted for processing. If this happens, then as the saying goes: “Garbage in, garbage out.”EXAMPLES: csvv --filespec=Contacts.csv csvv --filespec='Company Employee Info.csv' csvv --filespec "Fred's Extended Family.csv" csvv --file=Contacts.csv Although it is not recommended, CsvView will accept a source filename WITHOUT the "--filespec" option: csvv Contacts.csv --display=v --stats
The
displayoption specifies the type of formatting to be used for display of the CSV records. The options are:
h — Horizontal (default)Display one record per line.The record fields are aligned vertically for ease of viewing.The data are displayed using the'less'utility to fascilitateboth vertical and horizontal scrolling. v — VerticalDisplay one field per line. This is useful if the recordis wider than the width of the terminal window.The data are displayed using the'less'utility to fascilitateboth vertical and horizontal scrolling. q — QuickThe Quick output format is the same as the Horizontal format except:a) The data are written directly into the terminal window,one page at a time.This is similar to viewing data using the'cat'utility.b) The data are truncated at the right edge of the terminal windowto prevent the terminal from inserting automatic line breaks.Please see Output Formats for further information.
EXAMPLE: csvv --display=v
Specify the foregroud (text) attribute used for display of the data.
By default, the text data are displayed using blue text.The available attributes are the eight(8) basic colors and their “intense” (bold) variants, or the terminal-default attribute.
BASIC INTENSE ----- ------- black blacki red redi green greeni brown browni blue bluei magenta magentai cyan cyani grey greyi dflt EXAMPLES: csvv --fgndattr=green csvv --fgndattr red csvv --fgndattr=redi
Specify the backgroud attribute used for display of the data.
By default, the background attribyte is the terminal default (dflt).The available attributes are the same as those listed for the foreground attributes above.
Note: Avoid using the same attribute for both foreground and background.[** THE bgndattr OPTION IS CURRENTLY IGNORED **]
EXAMPLES: csvv --bgndattr=magenta csvv --bgndattr brown csvv --bgndattr=bluei
Specify the language used by the application’s user interface.
Options:
EN —ENglish
ZH —ZHongwen (中文) Simplified Chinese
tenv —Terminal EnVironent (default)By default, the user interface language used is derived from the locale used by the system. If the system locale is one of the Zhōngwén variants, the Chinese interface will be used; otherwise, the English interface will be used.
See Terminal Configuration for a discussion of locale.To override the automatic language selection, use the
'--language'option to select the desired user-interface language.Note that the ’EN’ and ’ZH’ designators are the internationally accepted language designators.
Please refer to Library Of Congress document: https://www.loc.gov/standards/iso639-2/
or to the Wikipedia article which describes theISO 639standard:
https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
EXAMPLES: csvv --language=ZH csvv --lang en csvv --language tenvNote: This application is designed to be as simple as possible, so we have implemented only our two(2) best languages. Other UI languages may be added in a later release.
Override the application’s determination of whether the source file contains a header record.
A header record contains column headings for the remainder of the records.During the initial scan of the source file, the application tries to determine whether the first record of the file is a header record. The criteria for this test are:
1)Is the first line of the file terminated by a newline?
2)Does the record include at least one comma (’,’) delimeter?
3)Do all fields of the record contain text data, (non-empty)?Clearly, the first record of a CSV file may meet all these criteria and still not be a header record—or may be a header record without meeting these criteria. If this happens, the program’s scan results may be overridden using the
'--header'option to specify whether the file does, in fact include a header record.Note that if a CSV file does not contain a header record, then horizontal output formatting will simply have no column headings; however, for vertical output formatting, generic column headings will be used. Example:
Field # 1 : Helena Handbasket
Field # 2 : Queen of the Castro
Field # 3 : 415-654-3210
Field # 4 : Yaz-Queen@TwinPeaks.com
EXAMPLE: csvv --filespec='Contacts.csv' --header=y
────────────────────Note that the MIME-type database for the system may optionally specify whether CSV files on the system include header records; however, this information is not just optional, it is unreliable and is not referenced by this application. In a corporate setting, CSV files that are routinely used to transfer company data may adhere to the specified MIME type; however, a CSV file created by a non-corporate application (e.g. an email application), or a file randomly downloaded from the web are not likely to conform to the system’s MIME-type database.
When specified, the
'--saveas'option saves a copy of the displayed data to a file in the current working directory. Specify the filename only.The saved data will be plain text in the same format used to display the data in the terminal window.
The data format is determined by the
'--display'option described above, either'Horizonal'or'Vertical'.
(For the “Quick” output format, the data are not saved.)
EXAMPLE: csvv --filespec='contacts.csv' --saveas='formatted_data.txt'
Command-line Help. Display a brief summary of command-line usage and options.
(overrides everything on command line except'--version')EXAMPLES: csvv --help csvv -h
Display command-line help. Same as the
'--help'option above except that the help menu will be piped through the'less'utility.EXAMPLES: csvv --helpless csvv -hl
Display the CsvView version number and copyright information.
(overrides everything else on the command line)
The AnsiCmd-class and gString-class version numbers are also reported.
EXAMPLE: csvv --version
Create a Comma-Seperated-Values (CSV) file using a plain-text file as the source data.
During development, this option was used to create various test files to exercise the functionality and general syntax checking of the application.
The test files included in this distribution were all created from the plain-text file,
'csvsource.txt'using the--createoption. Study this file for more information.The
createoption takes two or three arguments:
1) source filename
2) UTF encoding(utf8, utf8bom, utf16le, or utf16be)
3) newline format (optional) lflinefeed only, or
crlfcarriage-return/linefeed pairsThe CSV file created through this option takes the name of the source file, but with the
".csv"filename extension. Example:
csvsource.txt --> csvsource.csv
csvsource --> csvsource.csvAlthough the source file is technically a plain-text file, it could also be described as a pure UTF-8 encoded CSV file.
Exception:
The newline character, (either a linefeed
'\n'or a carriage-return/linefeed pair"\r\n") is a special character which signals the end of a record within a CSV file. However, it is fairly common to use newlines within a long, free-form field to indicate line breaks, so long as the field is enclosed within secondary-delimeter pairs.To test this functionality, a special two-character sequence within the source file: “\n” is recognized by the
'createCsvFile'method as an embedded newline character. This allows for testing embedded newlines within a field.
Please see CSV Encoding for additional information about newlines and commas embedded within a CSV record.
EXAMPLES: csvv --create=source_data.txt,utf16le csvv --create="source data.txt,utf16be,crlf" csvv --create="source data.txt, utf8bom, crlf"
Extract a range of records from the source file, and if the records are UTF-16 encoded, convert them to UTF-8.
Format the data for analysis, and write the formatted data to a file in the current working directory.
The name of the target file is:"captured_records.txt"The
--captureoption takes three(s) parameters:
a)the source filename,
b)the index of the first record to be captured (>=0), and
c)the index of the last record to be captured (>first record)
Note that the header record (index 0) is always captured.During development, certain records in the source files may either be malformed or, gasp the application may have parsed the record incorrectly. This option may be used to isolate the suspected range of records and format them as both text and
ASCIIhex, which may then be used to visually analyze the data. See example output below.
EXAMPLE: csvv --capture="SourceRecords.csv,5,6"
Sample Output
HEADER RECORD - index:00 ------------------------- N A M E , A G E , O C C U P A T I O N \n 4E 41 4D 45 2C 41 47 45 2C 4F 43 43 55 50 41 54 49 4F 4E 0A RECORD INDEX :05 ----------------- 成 吉 思 汗 , 9 6 2 , 马 语 者 , " 蒙 古 , 6210 5409 601D 6C57 2C 39 36 32 2C 9A6C 8BED 8005 2C 22 8499 53E4 2C 肯 特 山 脊 " \n 80AF 7279 5C71 810A 22 0A RECORD INDEX :06 ----------------- " B o n d , J a m e s " , 3 6 , w o m e n \n 22 42 6F 6E 64 2C 20 4A 61 6D 65 73 22 2C 33 36 2C 77 6F 6D 65 6E 0A
Display information about the specified source file.
This information includes basic information about the file itself, as well as information about the CSV data contained in the file.The following example illustrates the type of information reported.
This test file shown here is included as part of the distribution package.Source File Stats ------------------------------------ Filename : utf8bom_cr.csv # Name of the source file File type : REG # File type (must be Regular) File bytes : 388 # Size of the file in bytes Mod time : 2024-02-15T19:09:30 # Timestamp (modification time) Permissions: r:1 w:1 # Read and Write permission flags Encoding : UTF-8bom Cr:yes Hdr:yes # Type of character encoding # Type of newline: Linefeed only, # or Carriage-return/Linefeed pairs # Report whether file includes a # header record Records : 9 Fields : 4 # Number of records (not incl. header) # Number of fields per record EXAMPLE: csvv --stats --filespec='utf8bom_cr.csv'
Report the size of the terminal window expressed as the number of rows and columns.
When deciding how to format the CSV data to fit within the terminal window, the window dimensions must first be calculated. This option simply reports the results of that calculation.
The following example shows how the report is written to the display.
The report preceeds the formatted output of the CSV file data.┌───────────────────────────────────────┐ │ Terminal Size: 39 rows x 154 columns │ └───────────────────────────────────────┘ Press Any Key To Continue... EXAMPLES: csvv --dimensions csvv --dime --filespec=Contacts.csv
Used during development, this option reports the current terminal window configuration data as reported by the
AnsiCmdlink library. Please see acGetTermInfo for further information about terminal configuration.Terminal Configuration Flags --------------------------------------------- istrip : 7-bit input disabled opost : output flags enabled onlcr : convert newlines to cr/lf enabled xtabs : convert tabs to spaces disabled cread : read terminal input enabled csize : character width 8 bits icanon : enable canonical input disabled echo : echo character input disabled echonl : echo newlines disabled echoctl: echo control chars as (^x) enabled iexten : posix extensions enabled EXAMPLE: csvv --terminfo
This option is included primarily for use during development.
When debugging output is enabled, it is written to the display during startup and during analysis of the source file. This option causes the program to wait for a keypress before the debugging information is overwritten by the formatted CSV records.
EXAMPLE: csvv --pause --filespec='Contacts.csv'
This chapter provides a practical, (but not official) description of Comma-Seperated-Values (CSV) formatting and example data for each of the recognized UTF encodings.
"records", one record per line
of the file. Any reasonable number of records is supported."fields" seperated by the
ASCII comma: ',' (2C hex).
"newline" is either a single linefeed character: '\n' or a
carriage-return/linefeed pair: "\r\n".
In UTF-8 encoded data the newline is represented as:
0A or 0D0A hex
\n or \r\n
In UTF-16LE (little-endian) encoded data the newline is represented as:
0A00 or 0D000A00 hex
\n\0 or \r\0\n\0
In UTF-16BE (big-endian) encoded data the newline is represented as:
000A or 000D000A hex
\0\n or \0\r\0\n
'"' (22 hex) may be used in conjunction
with the basic comma delimeter to create pairs of secondary field delimeters.
This is useful (and necessary) if the field contains either commas or newlines
(as defined above). An example of a record using a secondary-delimeter pair
for the second field of the three-field record is given: Hello!,"When, where\nand why",vape?
48656C6C6F212C225768656E2C2077686572652C0A616E6420776879222C766170653F0A H e l l o ! , " W h e n , w h e r e ,\n a n d w h y " , v a p e ?\n └── ┴┴ ┴┴ ──┘ opening embedded embedded closing delimeter comma newline delimeter
The secondary delimeters enclose the data of the field: ,".....",
and have the effect of dereferencing those special characters, which are then
interpreted as plain text within the field.
The CsvView application includes the functionality to create CSV files from a plain-text source file. (see csv create option) The CSV file is created using the desired UTF encoding and newline format.
Commas and newlines within a CSV file are interpreted as field-delimeter and end-of-record, respectively. However, these characters may be interpreted as ordinary text IF they are enclosed within secondary delimeters as described above.
Within the source file used to create CSV output, a comma embedded within secondary delimeters is automatically identified during conversion; however, because the newline character is a “special” character (i.e. a control character) within a plain-text file, it must be handled as a special case.
The design decision was made that within a source file used to generate
CSV files, embedded newlines are
designated using a sequence of two ordinary ASCII characters:
backstroke: '\' plus a lower case n: 'n'
During creation of the CSV file, this sequence is converted to a newline
character as defined above.
Comment lines may be used within the source file and will be ignored by the conversion algorithm. Comments are identified by using the hash character (’#’) as the first character of the line. When the hash character is encountered, the entire source line will be discarded.
Technical Note: Secondary delimeters must not be used in the first record of the source file (header record). This is because when scanning the first record of a CSV file, the type of encoding has not yet been determined.
Technical Note: It is possible that some designers of CSV files will attempt
to be “creative” by using a character other than the double-quote
character to create secondary-delimeter pairs. Some examples would be the
astrisk '*' or the semicolon ';'. CsvView does not support this kind
of “creativity”, but if you often encounter such constructs,
the 'convertDoubleQuotes' and 'dqDelimeterCount' methods could be
generalized to accomodate such constructs.
The CsvView demonstration application and the AnsiCmd library
upon which it is built, are written in C++ and are built with the GNU C++
compiler and linker. No additional link libraries or third-party tools are needed.
GCC (G++) version 7 and above with support for C++17 (gnu++17) or greater.
The make file, 'Makefile' includes several options for building the
application.
The AnsiCmd library has two(2) global directives which affect conditional
compilation of the library.
1) DEBUG_ANSICMD Enable or disable debugging methods and data.
2) INCLUDE_API Include the high-level API methods and data.
Both of these conditional-compile directives should be set to zero (’0’)
when building the AnsiCmd library (gmake buildlib).
While neither directive affects the functionality of the CsvView application,
disabling them will reduce the size of the executable by approximately 600 Kbytes.
Please see Build Options for the AnsiCmd library for more information
about conditional compilation.
DEBUG_CSVV directive is set to zero
(’0’), all of the following directives will also be disabled.
'SrcScan' method and used to
control code for parsing the fields of a record.
'readRecord' method, this directive
controls debugging output for the rather complex task of reading a single
record from a CSV-formatted file.
'isUTF16' method which scans the first record of the source file
to determine whether the file is encoded as UTF-16 data.
'convert2UTF16' method, this directive
reports intermediate information for conversion from UTF-8 to UTF-16 data.
'convertNewlines' method, this
directive reports on the process of converting linefeed characters to
carriage-return/linefeed pairs.
'deflateNewlines' method which
complements the 'convertNewlines' method by converting carriage-return/linefeed
pairs to linefeed characters.
'isUTF8bom' method, this directive
reports the intermediate steps in determining whether the source CSV file
contains a UTF-8 byte-order mark (BOM).
'convertDoubleQuotes' method, this
directive reports the intermediate steps in processing double-quotation-mark
characters which are used as secondary delimeters within a field.'GetCommandLineArgs' method, this
directive enables reporting on parsing of the application’s command line arguments.
'DisplayData' method,
this directive inserts visible characters (’-’) instead of whitespace for
padding fields to their full width.
To test the build, invoke with a request for the CsvView version number. You should get something similar to the following:
If you have forgotten to disable the AnsiCmd library debugging code,
and/or the AnsiCmd API-level code (see above), a warning message will
be appended to the above output.
Documentation for the 'AcEdit' demo application is under construction.
The AcEdit application is designed as a platform for testing the
high-level functionality of the AnsiCmd library, and for demonstrating
various approaches to building applications based on the AnsiCmd library.
For details, see AnsiCmd Link Library at the top of this document.
AcEdit is a console application, meaning that it runs within a terminal
window.
AcEdit is not designed to be a full-featured text editor, although
subsequent releases may approach full functionality.
AcEdit is invoked like any command-line utility, although the data
are not displayed as TTY output. Instead, AcEdit is a windowed
application, visually similar to an application built on the "ncurses"
library, but vastly more simple in design and execution than an ncurses
application.ncurses library.
Please see Invoking AcEdit for a discussion of all command-line options.
AcEdit is performed by reading the ace.cfg
configuration file on startup.Access to the system clipboard is enabled by default, so data may
be seamlessly transferred between AcEdit and other active applications.
See AnsiCmd Clipboard Access for a discussion of the system clipboard interface.
AcEdit is designed as a multi-language application. Two languages
are initially supported: English and Chinese (simplified). All LTR
(left-to-right) character sets are supported.
Support for RTL languages is too complex for this demonstration app; sorry
about that. Please see the author’s NcDialog API which includes full
support for both LTR and RTL languages.
The application is based on the author’s AnsiCmd link library. The library
is fully self-contained and the build requires only the GNU compiler and
its standard dynamic-load libraries.
(The compiler version must support the C++17 functionality which
became available in GCC v:7.
See Build AcEdit from Source for details.
A local clipboard is built into the library; however, access to the system
clipboard requires the wl-clipboard package which is available for
downlad on most distribution sites.
This chapter lists the command-line options for invoking the AcEdit (ace).
The 'help' and 'version' options override all other specified options.
For a detailed discussion of the AnsiCmd terminal setup options used for
applications based on the AnsiCmd link library.
please see Invoking - Terminal Setup.
OPTION DESCRIPTION ace color option application color attributes ace language option user interface language ace dimensions option application height/width ace help option Display all application options ace helpless option Same as '--help'option except pipe through'less'ace version option Reports AcEdit version number and copyright info. ---Development Options---------------------ace test option Sandbox (testing only)
All parameters are optional, and may be specified in any order.
For each option that requires one or more arguments, the option name and
its argument(s) may be separated by either '=' or ' ' (space).
Note that if the argument contains whitespace, then the entire argument
sequence must be enclosed within single-quotes or double-quotes.
This prevents the terminal’s shell program from “interpreting”
your argument formatting.
Parsing of command line options requires at least the first six(6) characters
of the option token.
For instance, the "--language" token is fully identified
by the first six characters: --lang".
Avoid specifying the same option multiple times. Multiple instances of an option may cause unpredictable results.
Specify file(s) to be edited:
ace strip_cr.pl
ace "../../Perl Utilities/strip_cr.pl"
ace "/home/sam/Documents/Perl Utilities/strip_cr.pl"
Example: ace ~/Videos/DVD_List.txt ace '${HOME}/Videos/Blu-ray/Videos With Subtitles.txt' ace ./Subtitles.txt
ace WkExer.lnk~/Documents/Weekly_Exercise.txt.
AcEdit.
For example: Bash scripts, Perl, C, C++, HTML, XML, etc.
- Border attributes must be specified.
- Text-field and cursor-row attributes are optional
- Application’s default value is indicated by zeros for both foreground and background values:
Example: --color=f00:f00,f10:f04Note that selecting a color scheme should normally be done in the configuration file. See AcEdit Configuration.
Command line specification of color attributes mirrors the syntax of the config file; and while this makes for efficient coding, it is certainly not user friendly. The option sequence is as follows:
--color=Border_FG:Border_BG, Text_FG:Text_BG, Hilite_FG:Hilite_BG │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └ cursor row background │ │ │ │ │ └ cursor row foreground │ │ │ │ └ text field background │ │ │ └ text field foreground │ │ └ border background │ └ border foreground └ option nameThe color options correspond to the terminal color registers for 4-bit palette (16 colors), 8-bit palette (256 colors) and 24-bit palette (RGB).
Each specified attribute consists of a single character (case insensitive), followed by an integer value.
Foreground/Background pairs are seperated by a colon':'.
Color pairs are seperated by a comma','(and optional whitespace).Palette: Character: Value Range: -------- ---------- ------------ 4-bit f 00 - 15 8-bit e 16 - 231 24-bit r 00 - 252 EXAMPLES: ace --color="f12:f03" ace --color="f00:e38, e16:e21" ace --color="f12:f03, r108:r216, r108:r252"Please refer to the color chart in the configuration file, or
see AcEdit Configuration for additional information.
Specify the user interface language for the application.
AcEditis designed specifically for multi-language support. The menus, dialogs and most informational messages are provided in each supported language. An example would be the “Help About” dialog.┌────────────────────────────────────────────────────────────────┐ │ AcEdit (ace): Copyright (c) 2023-2026 v:0.0.05 │ │ The Software Samurai │ │ http://www.SoftwareSam.us/ │ │ │ │ This application is based upon the author's AnsiCmd library │ │ which implements the ANSI escape sequences available within a │ │ Linux terminal window. It is not intended as a full-featured │ │ text editor; but rather is a testing platform for the AnsiCmd │ │ library and the ACWin and ACDlg classes within the library. │ │ AnsiCmd v:0.0.07 WaylandCB v:0.0.06 │ │ gString v:0.0.37 wl-clipboard v:2.2.1 │ │ OK │ └────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐ │ AcEdit (ace): Copyright (c) 2023-2026 v:0.0.05 │ │ The Software Samurai (软件武士) │ │ http://www.SoftwareSam.us/ │ │ │ │ 该应用程序基于同一作者的 AnsiCmd 库。该库实现了 │ │ Linux 终端窗口内可用的 ANSI 转义序列。它并非一个 │ │ 全功能的文本编辑器;而是一个 AnsiCmd 功能的测试平台。 │ │ AnsiCmd v:0.0.07 WaylandCB v:0.0.06 │ │ gString v:0.0.37 wl-clipboard v:2.2.1 │ │ .好的 │ └─────────────────────────────────────────────────────────┘The current release supports two languages:
1) English
2) Zhōngwén, 中文(Chinese, simplified)
By default, the application uses the language specified in the terminal environment if that language is supported. If the language specified in the environment is unsupported, English will be the fall-back language.Hooks for additional languages are provided, so additional languages may be added as desired.
EXAMPLES: ace --language=zh // Zhōngwén interface language ace --language=en // English interface language ace --language=te // Use language specified in // terminal environment ace // language automatically taken // from terminal environmentTechnical Note: The command-line code for taking the language from the terminal environment is
"te". This is technically the code for Telugu, a Dravidian language of south-eastern India. If an enterprising programmer from Telangana builds an application that supports Telugu, then we will be happy to assist in making modifications to our code.
తెలుగు ఒక అందమైన లిఖిత భాష.
Report the terminal window dimensions (rows and columns), then exit.
This option can be used when updating the configuration file to specify the application dimensions to be used on startup.
The “Sandbox” is the traditional name for a section of the application code which can be used for testing new functionality without disturbing the functional code.
The AcEdit application accesses code within the Sandbox using the
--test command-line option. To invoke a specific test, provide the
test number: ace --test=[0|1|2|3]. These tests numbers are
reserved for ad-hoc tests.
Depending on build options, the Sandbox may also contain several pre-constructed
test routines for use during regression testing.
For a list of available tests, invoke without specifying a test number:
ace --test
Command-line Help. Display a brief summary of command-line usage and options.
(overrides everything on command line except'--version')EXAMPLES: ace --help ace -h
Display command-line help. Same as the
'--help'option above except that the help menu will be piped through the'less'utility.EXAMPLES: ace --helpless ace -hl
Display the
AcEditversion number and copyright information.
(overrides everything else on the command line)
The AnsiCmd-class and gString-class version numbers are optionally reported by appending the letter'V'(verbose) to the command.EXAMPLE: ace --version AcEdit (ace) v:0.0.05 (c) 2023-2026 The Software Samurai ================================================================================ License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html> This is free software: you are free to modify and/or redistribute it under the terms set out in the license. There is NO WARRANTY, to the extent permitted by law. EXAMPLE: ace --versionv AcEdit (ace) v:0.0.05 (c) 2023-2026 The Software Samurai ================================================================================ AnsiCmd Link Library v:0.0.07 (gString v:0.0.37) -------------------------------------------------------------------------------- License GPLv3+: GNU GPL version 3 <http://gnu.org/licenses/gpl.html> This is free software: you are free to modify and/or redistribute it under the terms set out in the license. There is NO WARRANTY, to the extent permitted by law.
Documentation for the 'AcEdit' demo application is under construction.
Documentation for the 'AcEdit' demo application is under construction.
All applications, even you humble author’s applications, will occasionally experience an uncontrolled shutdown, either through a system error or (gasp!), due to programmer error. This is primarily due to the developer underestimating the absolute stupidity of the user.
When an application crashes for whatever reason, it is possible that it
will leave behind some potentially recoverable data. The AcEdit
application is no exception.
On the next startup following an uncontrolled exit, AcEdit scans
for orphaned temporary files and if found compares them with the
associated source files and asks the user how to handle the recovered data.
The following example demonstrates the dialog window used to obtain the
user’s decision. In this case, an uncontrolled exit was simulated by
manually creating a temporary backup file associated with the
file under edit, namely:
Welcome_To_AcEdit.txt
The backup file is a “hidden” file located in the same directory
as the file under edit, and takes it name from the source file:
.#Welcome_To_AcEdit.txt#
This naming convention is similar to that used by other text editors, and
is useful in recovering data abandoned in an application crash.
The dialog reports the names of the source and recovered files, as well as
the last modification timestamp and file size for each file.
In this example, the recovered file is about three minutes newer than
the source file and is a different size. This indicates that the recovered
file may contain useful data. The available options are shown.
First, select one of the four Radiobuttons and then press the CONTINUE
Pushbutton; or none of the options matches your needs, select the EXIT
Pushbutton to abandon the recovered file without modification.
'diff' utility to format the contents of the files
for side-by-side display. The data are displayed using the 'less'
utility. (Press ’q’ key to close 'less' and return to the dialog.)
"nn" is replaced by a two-digit
serial number: Recovered_01.txt, Recovered_02.txt, etc.
The renamed file can then be moved, renamed or opened for editing if
desired.
Welcome_To_AcEdit.txt --> Welcome_To_AcEdit.txt~ .#Welcome_To_AcEdit.txt# --> Welcome_To_AcEdit.txt'~') is
recognized by Linux system as indicating a “backup” file.
The recovered file will then be opened as if it were the original source file. The old source file remains in the current directory and can be saved or discarded, as desired.
After the desired operation has been performed, a status message will be displayed, and then the dialog will wait for the next keystroke before closing.
You can test this functionality without actually needing to cause a crash
simply by: 1)closing the application, 2)copying any file that was open for
edit using the filename format described above, and then 3)reopening the
application:
./ace MyApp.cpp
Close the application
cp --preserve=all 'MyApp.cpp' '.#MyApp.cpp#'
./ace
On startup, the backup file will be recognized, and the recovery dialog
will be automatically invoked as described above.
While the AcEdit application is designed as a test and demonstration app
for the AnsiCmd library, and specifically for the ACWin and ACDlg
classes, it reaches a few centimeters into the realm of an actually useful
console application.
File management within the application is done through an array of
FileMan records, one for each file under edit.
While a large number of files can simultaneously be open for edit, the number
of files which are currently visible is limited by the number of visible
edit fields.
Full-window mode: The “active” FileMan record references the file
displayed in that field.
Dual-window mode: The “active” FileMan record references the file
in the field that has the input focus, and the “inactive” FileMan
record references the file displayed in the field which is visible, but does
not have the input focus.
Other open (or recently closed) files are reference by other members of the
FileMan array.
Please see AcEdit Menu System for information on navigating among the
files which are open for edit.
'teindx'.'scr' buffer.
'vtop' to cursor line.'wrkSpec') is newer than the source file
('srcSpec'). This indicates that a save to source is pending.
The AcEdit application startup sequence is built around a configuration file,
ace.cfg by default. This file provides definitions for initialization
of application dimensions, position, color attributes, shortcut keycodes,
a list of previously open files and other setup information.
|
The configuration algorithm is not yet fully implemented. For the current release (0.0.05), the configuration file is read on startup, but is not updated on exit. |
Documentation for the 'AcEdit' demo application is under construction.
'TFMTest' (tfmtest) is a simple test and demo application
supporting the TFMan (Temporary File Management) class.
TFMTest (tfmtest) demonstrates the use of the TFMan class, which
encapsulates creation and management of any temporary files required
by an application.
The next chapter, TFMan Class describes the class itself.
TFMTest is a stand-alone utility designed for stress-testing
the methods of the TFMan class.
stdout.
Invoking TFMTest
TFMTest ('tfmtest') requires one option, either --basic or
--full. Other options are optional :-).
--basicTFMan class are functioning and communicating
with the system as expected.
--fullTFMan
class are functional and that the C-standard library functions are
interacting with the system as expected.
--verbose--redirectstdout by default; however, the output
may be rediected (piped) to the 'less' utility so that the data may
be scrolled for easy viewing.
This redirection is not actually necessary because the full, verbose report only requires approximately 25 lines, and should fit comfortably in a typical terminal window. The pipe mechanism is used here to fulfill a student request for a simple example of how pipes work. Enjoy, Sarah!
--help (or -h)--versionTFMan class and
the gString class.
Building TFMTest
Development Tools: ------------------ g++ (GCC) 14.3.1 20251022 (C++17) Fedora Linux v:42 GNOME Terminal v:3.54.5 (GNOME 47)
TFMTest application source is located in a subdirectory of the
AnsiCmd library distribution archive. Download the archive, open a
terminal window and navigate to the directory containing the archive. cd ~/sam/Documents/Software tar -xjvf ansicmd-x.x.xx.tar.bz2
cd AnsiCmd/TFMTest
TFMTest.cpp // Application source code. Makefile // Build the TFMTest application ls -l g++ --version g++ (GCC) 14.3.1 20251022 (Red Hat 14.3.1-4)
'tfmtest' application. gmake all TFMan.hpp gString.cpp gString.hpp
The TFMTest and gString modules will be compiled and then
linked to create the 'tfmtest' executable.
The build should be clean with no errors and no warnings. If there are errors, then the most likely cause would be that the compiler cannot find a necessary header file or library. Check your LIB_PATH and other environment variables.
./tfmtest --version
[TFMan]$ ldd tfmtest linux-vdso.so.1 (0x00007f9ca33f5000) libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f9ca3000000) libm.so.6 => /lib64/libm.so.6 (0x00007f9ca32ef000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f9ca32c0000) libc.so.6 => /lib64/libc.so.6 (0x00007f9ca2e0d000) /lib64/ld-linux-x86-64.so.2 (0x00007f9ca33f7000)
The TFMan (Temporary File Management) class is desigined
to fascilitate creation, deletion and general management of temporary files
used within an application.
Temporary files created by the system are defined as uniquely named files
created within the system’s shared temporary-file directory. Standard
library functions are available for creating these files, but the author’s
experience in the classroom setting has shown that application management
of these files can be haphazard (to put it politely). The TFMan class
was created to inject a bit of organization into this chaos.
System Interface
The system interface functions of the C++ standard library used by the TFMan class require C++17 support. Be sure that your compiler version is 8.0 or greater (or Clang v:5).
These functions are available in C++17 (released Jan. 2018):
const char* fs::temp_directory_path ( void ) ;|{@*
@verb{| const char* fs::temp_directory_path ( std::error_code& ec ) ;
These functions return the filespec of a directory suitable for temporary files. The path is guaranteed to exist and to be a directory. The overload that takes error_code& argument returns an empty path on error.
On POSIX systems, the path may be specified in an environment variable:
TMPDIR, TMP, TEMP, TEMPDIR, and, if none of them are specified,
the path "/tmp" is returned by the system call.
Please visit: <http://en.cppreference.com> for more information on
the library functions.
In the author’s FileMangler application, which was developed well before C++17 was released, we implemented a literal interpretaton of the above description. Now that the development community has had time to upgrade their compilers, (gcc v:8 and above) we are able to use the library function to obtain the temp-directory path.
Note that the TFMan class does not accept the system’s assurances that the target exists and is a directory. That information, including user’s read/write access, is independently verified.
Requesting a unique hack-resistant filename for a temporary file
The library function:
char * mkdtemp (char *TEMPLATE);
is used to create a subdirectory within the system temp-file directory.
This function returns the uniquely-named directory in which all other
application temporary files will be located.
This makes cleanup of temporary file during application exit as simple as
calling the TFMan destructor.
"sakJhr"
"ANSICMD_sakJhr".
'prefix'
parameter. Example prefix: "SAM" would yield the subdirectory name:
"SAMsakJhr".
The library function used to create the individual temp files is:
int mkstemp (char *TEMPLATE);
Note that both mkdtemp and mkstemp are "atomic", that is,
file creation by one process may not be interrupted by another process.
Technical Note: It is assumed that only non-special filename characters will be used on the temp-file-path. "Special characters" are those which may be interpreted by the shell or other system functionality as requiring special handling.
List of Special Characters:
'\' '"' ''' '?' ':' ';' '&' '>' '<' '|' '*' '`' '$',
'#' '+' '=' '%' '!' '~' '{' '}' '@' '(' ')' '[' ']', ' '
These special character should not be used in filenames. The algorithm for
escaping these characters is slow and probably not worth the
complexity in this context.
Please see notes in the author’s FileMangler application. FMgr-class on
using 'rmdir' and 'unlink' on filenames which contain "special"
characters.
Within the application’s temp-file subdirectory, temporary files take the form: "TF_xxxxxx" where "TF_" is the specified prefix and the "xxxxxx" sequence is replaced by the unique system-provided sequence.
TFMan is a very simple class with the following public methods.
Input : none Returns: implicitly returns pointer to object
Default constructor.
Create a uniquely named temp-file subdirectory within the system’s
temp-file directory. (Prefix for temp-file subdirectory name is
set to default value: "TFMAN_".)
Example tree structure: /tmp/TFMAN_sakJhr
Input :
prefix : pointer to a prefix for temp-file subdirectory name.
-- Valid filename characters only
-- Maximum of 16 bytes including null terminator
Returns: implicitly returns pointer to object
Initialization constructor.
Create a uniquely named temp-file subdirectory within the system’s
temp-file directory using the provided prefix string for the subdirectory
name.
Example:
instance: TFMan* tfm = new TFMan( "MYAPP" );
yields: /tmp/MYAPPsakJhr
Input : none Returns: nothing
Destructor.
Delete all temporary files located within the subdirectory created
by the TFMan constructor, then delete the subdirectory itself.
The destructor is invoked in different ways, depending upon whether the
TFMan object was created in 'stack' (automatic) memory or from
'heap' memory.
If the TFMan object is created on the 'stack', then the destructor
is called implicitly when the object goes out-of-scope.
If the TFMan object is created in 'heap' memory (dynamic allocation),
then the object should be deleted explicity when it is no longer needed.
|
Teacher’s Rant: Note that the application’s heap memory is automatically returned to the system when the application exits; HOWEVER, it is sloppy programming, indeed to simply abandon objects on the heap. Objects on the heap should always be deleted explicity before exiting the application. |
Input :
tmpPath : (by reference) gString object to receive filespec
Returns:
'true' if file successfully created:
(file exists, and contains no data)
'false' if system call failed
Create a uniquely-named temporary file.
The filename takes the form: "TF_xxxxxx" where xxxxxx is the
six-character token which uniquely identifies the file created by the system.
The full filespec is then returned to caller in 'tmpPath'.
The application can then open the file in the usual way
and write data to the (empty) file.
Notice that the gString object’s UTF-8 (byte-oriented) text is used
for the system call. Note also that because the file has been created
by the call, the file may be opened either for “append”,
or for “trunc” output.
Please see gString Public Methods for a discussion
of the string data stored in the gString class.
Please see above for a description of how the system creates
uniquely-named temporary files, or refer to the C standard library
documentation for the 'mkstemp' function.
Input :
tmpPath : (by reference) filespec of file to be deleted
Returns:
'true' if target file successfully deleted
'false' if library call failed (invalid filespec)
Delete a previously created temporary file.
deleteTempFile will delete the specified file ONLY if
the file resides within the temporary subdirectory created by the
TFMan constructor.
Input : none
Returns:
'true' if all target files successfully deleted
'false' if unable to delete one or more target files
Delete all files in the application’s temp-file container subdirectory.
Only files created within the subdirectory created by the TFMan-class
constructor are affected. The application-specific subdirectory created
by the TFMan constructor IS NOT deleted by this method.
Input : none Returns: pointer to const buffer containing filespec
Returns a pointer to the filespec of temp-file subdirectory created by the TFMan constructor. This is a read-only pointer!
This method may be used during application development to locate the application’s temp files.
Input : none
Returns:
'true' if temp-file manager initialized and functional
'false' if initialization failed
Report the active/inactive status of the TFMan object.
Although it is unlikely that the constructor will fail to create the
target subdirectory, if the system call fails, the constructor has
no way to report the error. This method may be used to verify that
the TFMan temp-file manager is active and functional.
Example:
gString gsFilespec ;
TFMan* tfm = new TFMan( "MyApp" ) ;
if ( (tfm->isActive()) )
{
tfm->createTempFile ( gsFilespec ) ;
. . .
tfm->deleteTempFile ( gsFilespec ) ;
}
delete tfm ;
Input : none
Returns: pointer to constant string of the form: "M.m.ss"
indicating the major/minor/step versions
Report the TFMan-class version number.
Example: TFMan* tfm = new TFMan( "SAM_" ) ; cout < "TFMan class version: " << (tfm->tfmVersion()) << endl ; . . . delete tfm ; Output: TFMan class version: 0.0.02
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 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.
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.
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).
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.
‘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 is a simple C++ class definition which provides console applications with seemless access to the system clipboard.
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.
‘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.
The GNU General Public License is a free, copyleft license for software and other kinds of works.
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program—to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
For the developers’ and authors’ protection, the GPL clearly explains that there is no warranty for this free software. For both users’ and authors’ sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users’ freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and modification follow.
“This License” refers to version 3 of the GNU General Public License.
“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
A “covered work” means either the unmodified Program or a work based on the Program.
To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work’s System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work’s users, your or third parties’ legal rights to forbid circumvention of technological measures.
You may convey verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation’s users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party’s predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor’s “contributor version”.
A contributor’s “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor’s essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient’s use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
The hypothetical commands ‘show w’ and ‘show c’ should show the appropriate parts of the General Public License. Of course, your program’s commands might be different; for a GUI interface, you would use an “about box”.
You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see https://www.gnu.org/licenses/.
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read https://www.gnu.org/licenses/why-not-lgpl.html.
The purpose of this License is to make a manual, textbook, or other functional and useful document free in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.
This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.
This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.
A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.
A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.
The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.
The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.
A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called “Opaque”.
Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.
The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text.
The “publisher” means any person or entity that distributes copies of the Document to the public.
A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition.
The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may publicly display copies.
If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles.
You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements.”
You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.
A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.
Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.
If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.
You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it.
The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See https://www.gnu.org/licenses/.
Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document.
“Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A “Massive Multiauthor Collaboration” (or “MMC”) contained in the site means any set of copyrightable works thus published on the MMC site.
“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization.
“Incorporate” means to publish or republish a Document, in whole or in part, as part of another Document.
An MMC is “eligible for relicensing” if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing.
To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with…Texts.” line with this:
If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.
If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.
| Jump to: | 0
1
~
A B C D E F G H I K L M N O P Q R S T U V W Z |
|---|
| Jump to: | 0
1
~
A B C D E F G H I K L M N O P Q R S T U V W Z |
|---|