Chapter 23 - Additional Library Procedures

In addition to the functions and subroutines built in to True BASIC, there are several small libraries that extend the functions subroutines available. These are all stored in the subdirectory TBLIB that is installed in the main True BASIC directory.

To use any of these libraries of procedures, you must include a LIBRARY statement in your program of the form:

LIBRARY “c:\TBV5\TBLIBS\SORTLIB.TRC”
using the appropriate path name and file names for each library containing functions or subroutines you wish to use. Although source code may also be provided for some libraries, your programs will run much faster if you
use the compiled version of any libraries.
As with all functions stored in external procedures, you must also name any library functions in DECLARE DEF statements before you can use them.
This chapter describes library procedures, listed alphabetically within four categories — math, strings, sorting, and graphics:
Mathematical Tools
MATHLIB.TRC hyperbolic and arc functions
HEXLIB.TRC bit, octal, and hexadecimal manipulation routines

String Tools
STRLIB.TRC string creation, conversion, formatting, editing

Sorting and Searching Tools
SORTLIB.TRC sorting, searching, and reversing items on arrays

Graphics Tools
BGLIB.TRC for pie charts, bar charts, and histograms SGLIB.TRC for plotting data and function values SGFUNC.TRC for plotting values of functions that you define
408 True BASIC Language System

Math Libraries
The built-in trigonometric and hyperbolic functions include: SIN, COS, TAN, CSC, SEC, COT, ATN, ASIN, ACOS, SINH, COSH, and TANH. The math libraries contain the following additional functions:
Math Libraries
——————————————————————————————————————
Library Functions
MATHLIB.TRC Additional hyperbolic and arc functions (radian measure):
ACOT, ACSC, ASEC, COTH, CSCH, SECH, ACOSH, ACOTH, ACSCH, ASECH, ASINH and ATANH.
HEXLIB.TRC Several bit, octal, and hexadecimal manipulation routines: AND (bit-by-bit), BIN$, CONVERT, HEX$, HEXW$,
OR (bit-by-bit), and XOR (bit-by-bit)
——————————————————————————————————————

In addition, TBLIBS contains short files that you can copy and paste or “ include” near the beginning of your program. These files contain a LIBRARY statement and a DECLARE DEF statement to specify the names of the functions in the library, and are named MATHDECL.TRU and HEXDECL.TRU.
Each of the math library functions are described below; the functions are listed alphabetically.

ACOSH Function
Library: MATHLIB.TRC
Syntax: ACOSH (numex)
Usage: LET a = ACOSH (n)
Summary: Returns the value of the hyperbolic arccosine of its argument n.
Details: The ACOSH function returns the value of the hyperbolic arccosine of its argument. Since neither the argument to nor the result of a hyperbolic function is an angle (and since the function definition is stored in a library), the results of the ACOSH function are unaffected by the current setting of the OPTION ANGLE statement.
The absolute value of n must be greater than or equal to 1.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Acosh PRINT Acosh(1)
END
produces the following output:
0
Exceptions: 1003 Overflow in numeric function.
-3000 Argument not in range.
See also: COSH, SINH, TANH, COTH, SECH, CSCH, ASINH, ATANH, ACOTH, ASECH, and
ACSCH. The first three are built-in.
Note: The ACOSH function may be defined in terms of other True BASIC constructs as:
DEF Acosh(x)
IF Abs(x) < 1 then
CAUSE ERROR -3000, “Argument not in range.” ELSE
LET Acosh = Log(x + Sqr(x*x-1)) END IF
END DEF
Math Libraries

409

ACOT Function
Library: MATHLIB.TRC
Syntax: ACOT(numex)
Usage: LET y = ACOT(n)
Summary: Returns the value of the arccotangent of its argument n.
Details: The ACOT functions returns the values of the arccotangent in radians of its argument.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Acot
PRINT Acot(1) END
produces the output
.78539816
Exceptions: 1003 Overflow in numeric function.
See also: ATN, ASIN, ACOS, ASEC, and ACSC. The first three are built-in.
Note: The ACOT function may be defined in terms of other True BASIC constructs as:
DEF Acot(x) = PI/2 - Atn(x)

ACOTH Function
Library: MATHLIB.TRC
Syntax: ACOTH (numex)
Usage: LET a = ACOTH (n)
Summary: Returns the value of the hyperbolic arccotangent of its argument n.
Details: The ACOTH function returns the value of the hyperbolic arccotangent of its argument.
The absolute value of n must be greater than or equal to 1.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Acoth PRINT Acoth(1)
END
produces the following output:
0
Exceptions: 1003 Overflow in numeric function.
-3000 Argument not in range.
See also: COSH, SINH, TANH, COTH, SECH, CSCH, ASINH, ATANH, ACOSH, ASECH, and
ACSCH. The first three are built-in.
Note: The ACOTH function may be defined in terms of other True BASIC constructs as:
DEF Acoth(x)
IF Abs(x) <= 1 then
CAUSE ERROR -3000, “Argument not in range.” ELSE
LET Acoth = Log( (x+1)/(x-1) ) / 2
END IF END DEF
410 True BASIC Language System

ACSC Function
Library: MATHLIB.TRC
Syntax: ACSC(numex)
Usage: LET y = ACSC(n)
Summary: Returns the value of the arccosecant of its argument n.
Details: The ACSC functions returns the values of the arccosecant in radians of its argument.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Acsc
PRINT Acsc(1) GET KEY key END
produces the output
1.57079632
Exceptions: 1003 Overflow in numeric function.
-3000 Argument not in range.
See also: ATN, ASIN, ACOS, ASEC, and ACOT. The first three are built-in.
Note: The ACOT function may be defined in terms of other True BASIC constructs as:
DEF Acsc(x)
IF Abs(x) < 1 then CAUSE ERROR -3000
LET Acsc = Asin(1/x) END DEF

ACSCH Function
Library: MATHLIB.TRC
Syntax: ACSCH (numex)
Usage: LET a = ACSCH (n)
Summary: Returns the value of the hyperbolic arccosecant of its argument n.
Details: The ACSCH function returns the value of the hyperbolic arccosecant of its argument.
The absolute value of n must not be 0, or an exception occurs.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Acsch PRINT Acsch(1)
END
produces the following output:
.88137359
Exceptions: 1003 Overflow in numeric function.
–3000 Argument not in range.
See also: COSH, SINH, TANH, COTH, SECH, CSCH, ACOSH, ASINH, ATANH, ACOTH, and
ASECH. The first three are built-in.
Note: The ACSCH function may be defined in terms of other True BASIC constructs as:
DEF Asech(x)
IF x = 0 then
CAUSE ERROR -3000, “Argument not in range.”
ELSE
LET Acsch = Log((1+sgn(x)*Sqr(x*x+1)) / x)
END IF
END DEF
Math Libraries

411

AND Function
Library: HEXLIB.TRC
Syntax: AND (numex, numex)
Usage: LET n = AND (a, b)
Summary: Returns the result of a bit-by-bit logical AND of the values of a and b.
Details: The AND function returns the result of a bit-by-bit logical AND of the values of a and b.
That is, it compares each bit in the value of a with the corresponding bit in the value of b
and sets the corresponding bit in the resulting value to 1 if both bits being compared are set
to 1. Otherwise, that bit in the resulting value is set to 0.
Note that if the values of a and b are not integers, the AND function uses the greatest integer values which are less than their actual values.
Example: The following program:
LIBRARY “HEXLIB.TRC” DECLARE DEF And

PRINT And(0, 0) PRINT And(1, 0) PRINT And(1, 1) PRINT And(5, 6) PRINT And(-5, 6) PRINT And(5.8, 6.9) PRINT And(255, 127)

END
produces the following output:
0
0
1
4
2
4
127
Exceptions: None
See also: OR, XOR

ASEC Function
Library: MATHLIB.TRC
Syntax: ASEC(numex)
Usage: LET y = ASEC(n)
Summary: Returns the value of the arcsecant of its argument n.
Details: The ASEC functions returns the values of the arcsecant in radians of its argument.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Asec
PRINT Asec(1) END
produces the output
0
Exceptions: 1003 Overflow in numeric function.
-3000 Argument not in range.
See also: ATN, ASIN, ACOS, ACSC, and ACOT. The first three are built-in.
412 True BASIC Language System

Note: The ASEC function may be defined in terms of other True BASIC constructs as:
DEF Asec(x)
IF Abs(x) < 1 then CAUSE ERROR -3000
LET Asec = Acos(1/x) END DEF

ASECH Function
Library: MATHLIB.TRC
Syntax: ASECH (numex)
Usage: LET a = ASECH (n)
Summary: Returns the value of the hyperbolic arcsecant of its argument n.
Details: The ASECH function returns the value of the hyperbolic arcsecant of its argument.
The absolute value of n must be less than or equal to 1, or an exception occurs.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Asech PRINT Asech(1)
END
produces the following output:
0
Exceptions: 1003 Overflow in numeric function.
–3000 Argument not in range.
See also: COSH, SINH, TANH, COTH, SECH, CSCH, ACOSH, ASINH, ATANH, ACOTH, and
ACSCH. The first three are built-in.
Note: The ASECH function may be defined in terms of other True BASIC constructs as:
DEF Asech(x)
IF Abs(x) > 1 then
CAUSE ERROR -3000, “Argument not in range.” ELSE
LET Asech = Log((1+Sqr(1-x*x)) / x) END IF
END DEF

ASINH Function
Library: MATHLIB.TRC
Syntax: ASINH (numex)
Usage: LET a = ASINH (n)
Summary: Returns the value of the hyperbolic arcsine of its argument n.
Details: The ASINH function returns the value of the hyperbolic arcsine of its argument.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Asinh PRINT Asinh(1)
END
produces the following output:
.88137359
Exceptions: 1003 Overflow in numeric function.
See also: COSH, SINH, TANH, COTH, SECH, CSCH, ACOSH, ATANH, ACOTH, ASECH, and
ACSCH. The first three are built-in.
Math Libraries

413

Note: The ASINH function may be defined in terms of other True BASIC constructs as:
DEF Asinh(x) = Log(x + Sqr(x*x+1))

ATANH Function
Library: MATHLIB.TRC
Syntax: ATANH (numex)
Usage: LET a = ATANH (n)
Summary: Returns the value of the hyperbolic arctangent of its argument n.
Details: The ATANH function returns the value of the hyperbolic arctangent of its argument.
The absolute value of n must be less than 1, or an exception occurs.
Example: The following program:
LIBRARY “FMATHLIB.TRC” DECLARE DEF Atanh
PRINT Atanh(.5) END
produces the following output:
.54930614
Exceptions: 1003 Overflow in numeric function.
–3000 Argument not in range.
See also: COSH, SINH, TANH, COTH, SECH, CSCH, ACOSH, ASINH, ACOTH, ASECH, and
ACSCH. The first three are built-in.
Note: The ATANH function may be defined in terms of other True BASIC constructs as:
DEF Atanh(x)
IF Abs(x) >= 1 then
CAUSE ERROR -3000, “Argument not in range.”
ELSE
LET Atanh = Log((1+x)/(1-x)) / 2
END IF
END DEF

BIN$ Function
Library: HEXLIB.TRC
Syntax: BIN$ (numex)
Usage: LET binary$ = BIN$ (n)
Summary: Returns a string containing the signed binary representation of the value of its argument n.
Details: The BIN$ function returns a string containing a binary representation of the value of n. The resulting string contains only the number of digits necessary to represent the value of n; leading zeroes are not added.
Note that the resulting binary value inherits the sign of the value of n. That is, the results of the BIN$ function will be the unsigned binary representation of the absolute value of n,
with the sign of n appearing as the first character if n is negative.
Example: The following program:
LIBRARY “HEXLIB.TRC” DECLARE DEF Bin$

PRINT Bin$(0) PRINT Bin$(1) PRINT Bin$(-1) PRINT Bin$(255) PRINT Bin$(1037)

END
414 True BASIC Language System

produces the following output:
0
1
-1
11111111
10000001101
Exceptions: None
See also: HEX$, HEXW$, OCT$, CONVERT

CONVERT Function
Library: HEXLIB.TRC
Syntax: CONVERT (strex)
Usage: LET decimal = CONVERT (number$)
Summary: Converts the hexadecimal, octal, binary, or decimal value represented by number$ into its decimal numeric equivalent.
Details: The CONVERT function converts a hexadecimal, octal, binary, or decimal value represented as a string into the equivalent decimal numeric value.
The value of number$ may be specified in a number of common formats.
If the value of number$ begins or ends with the character H, h, X, x, or $, it is interpreted as representing a hexadecimal value.
If the value of number$ begins or ends with the character O, o, Q, or q, it is interpreted as representing an octal value.
If the value of number$ begins or ends with the character B or b, it is interpreted as representing a binary value.
If the value of number$ begins with an ampersand (&), the second character is considered. If the second character is an H or an h, the value of number$ is interpreted as representing a hexadecimal value. However, if the second character is a digit, the value of number$ is interpreted a representing an octal value.
If the value of number$ begins with a zero, the second character is considered. If the second character is a digit, the value of number$ is interpreted a representing an octal value, unless the value ends with one of the characters mentioned above. If the second character is an X or an x, the value of number$ is interpreted as representing a hexadecimal value.
If none of the codes mentioned above is present in the value of number$, it will be interpreted as representing a decimal value, and the CONVERT function will behave in a manner identical to the VAL function.
If the value is signed, the sign (+ or –) must be the first character. (The sign is stripped prior to the application of the above rules.)
If the value of number$ does not obey these rules or represents a non-numeric value, an exception will occur.
Example: The following program:
LIBRARY “HEXLIB.TRC” DECLARE DEF Convert

PRINT Convert(“2CH”), Convert(“2ch”) PRINT Convert(“17Q”)
PRINT Convert(“00110011B”) PRINT Convert(“$3B”)
PRINT Convert(“&73”) END
Math Libraries

415

produces the following output:
44 44
15
51
59
59
Exceptions: 4001 Val string isn’t a proper number.
See also: VAL, BIN$, HEX$, HEXW$, OCT$

COTH Function
Library: MATHLIB.TRC
Syntax: COTH (numex)
Usage: LET a = COTH (n)
Summary: Returns the value of the hyperbolic cotangent of its argument n.
Details: The COTH function returns the value of the hyperbolic cotangent of its argument.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Coth
PRINT Coth(1) END
produces the following output:
1.3130353
Exceptions: 1003 Overflow in numeric function.
See also: COSH, SINH, TANH, SECH, CSCH, ACOSH, ASINH, ATANH, ACOTH, ASECH, and
ACSCH. The first three are built-in.
Note: The COTH function may be defined in terms of other True BASIC constructs as:
DEF Coth(x) = 1 / ((Exp(x) - Exp(-x))/(Exp(x) + Exp(-x)))

CSCH Function
Library: MATHLIB.TRC
Syntax: CSCH (numex)
Usage: LET a = CSCH (n)
Summary: Returns the value of the hyperbolic cosecant of its argument n.
Details: The CSCH function returns the value of the hyperbolic cosecant of its argument.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Csch
PRINT Csch(1) END
produces the following output:
.85091813
Exceptions: 1003 Overflow in numeric function.
Division by zero.
See also: COSH, SINH, TANH, COTH, SECH, ACOSH, ASINH, ATANH, ACOTH, ASECH, and
ACSCH. The first three are built-in.
Note: The CSCH function may be defined in terms of other True BASIC constructs as:
DEF Sech(x) = 1 / (Exp(x) - Exp(-x))
416 True BASIC Language System

HEX$ Function
Library: HEXLIB.TRC
Syntax: HEX$ (numex)
Usage: LET hexadecimal$ = HEX$ (n)
Summary: Returns a string containing the signed hexadecimal representation of the value of its argument n.
Details: The HEX$ function returns a string containing a hexadecimal representation of the value of n. The resulting string contains only the number of digits necessary to represent the value of n; leading zeroes are not added.
Note that the resulting hexadecimal value inherits the sign of the value of n. That is, the results of the HEX$ function will be the unsigned hexadecimal representation of the absolute value of n, with the sign of n appearing as the first character if n is negative.
Example: The following program: LIBRARY “HEXLIB.TRC” DECLARE DEF Hex$

PRINT Hex$(0) PRINT Hex$(1) PRINT Hex$(-1) PRINT Hex$(255) PRINT Hex$(1037)

END
produces the following output:
0
1
-1
FF
40D
Exceptions: None
See also: HEXW$, BIN$, OCT$, CONVERT

HEXW$ Function
Library: HEXLIB.TRC
Syntax: HEXW$ (numex)
Usage: LET hexadecimal$ = HEXW$ (n)
Summary: Returns a four-character string containing the unsigned hexadecimal representation of the value of its argument n.
Details: The HEXW$ function returns a string containing the unsigned hexadecimal representation of the value of n. The resulting string will always contain exactly four characters; leading zeroes will be added if necessary.
Negative values of n are treated as two’s complement. Thus, the resulting value will be an unsigned value.
Example: The following program:
LIBRARY “HEXLIB.TRC” DECLARE DEF Hexw$

PRINT Hexw$(0) PRINT Hexw$(1) PRINT Hexw$(-1) PRINT Hexw$(255) PRINT Hexw$(1037)

END
Math Libraries

417

produces the following output:
0000
0001
FFFF
00FF
040D
Exceptions: None
See also: HEX$, BIN$, OCT$, CONVERT

OCT$ Function
Library: HEXLIB.TRC
Syntax: OCT$ (numex)
Usage: LET octal$ = OCT$ (n)
Summary: Returns a string containing the signed octal representation of the value of its argument n.
Details: The OCT$ function returns a string containing a signed octal representation of the value of n. The resulting string contains only the number of digits necessary to represent the value of n; leading zeroes are not added.
Note that the resulting octal value inherits the sign of the value of n. That is, the results of the OCT$ function will be the unsigned octal representation of the absolute value of n, with the sign of n appearing as the first character if n is negative.
Example: The following program:
LIBRARY “HEXLIB.TRC” DECLARE DEF Oct$

PRINT Oct$(0) PRINT Oct$(1) PRINT Oct$(-1) PRINT Oct$(255) PRINT Oct$(1037)

END
produces the following output:
0
1
-1
377
2015
Exceptions: None
See also: HEX$, HEXW$, BIN$, CONVERT

OR Function
Library: HEXLIB.TRC
Syntax: OR (numex, numex)
Usage: LET n = OR (a, b)
Summary: Returns the result of a bit-by-bit logical OR of the values of a and b.
Details: The OR function returns the result of a bit-by-bit logical OR of the values of a and b. That
is, it compares each bit in the value of a with the corresponding bit in the value of b and sets
the corresponding bit in the resulting value to 0 if both bits being compared are set to 0.
Otherwise, that bit in the resulting value is set to 1.
418 True BASIC Language System

Example: The following program:
LIBRARY “HEXLIB.TRC” DECLARE DEF Or

PRINT Or(0, 0) PRINT Or(1, 0) PRINT Or(1, 1) PRINT Or(5, 6) PRINT Or(-5, 6) PRINT Or(5.8, 6.9) PRINT Or(255, 127)

END
produces the following output:
0
1
1
7
-1
8.7
255
Exceptions: None
See also: AND, XOR

SECH Function
Library: MATHLIB.TRC
Syntax: SECH (numex)
Usage: LET a = SECH (n)
Summary: Returns the value of the hyperbolic secant of its argument n.
Details: The SECH function returns the value of the hyperbolic secant of its argument.
Example: The following program:
LIBRARY “MATHLIB.TRC” DECLARE DEF Sech
PRINT Sech(1) END
produces the following output:
.64805427
Exceptions: 1003 Overflow in numeric function.
See also: COSH, SINH, TANH, COTH, CSCH, ACOSH, ASINH, ATANH, ACOTH, ASECH, and
ACSCH. The first three are built-in.
Note: The SECH function may be defined in terms of other True BASIC constructs as:
DEF Sech(x) = 1 / (Exp(x) + Exp(-x))

XOR Function
Library: HEXLIB.TRC
Syntax: XOR (numex, numex)
Usage: LET n = XOR (a, b)
Summary: Returns the result of a bit-by-bit logical XOR of the values of a and b.
Details: The XOR function returns the result of a bit-by-bit logical XOR (“exclusive OR”) of the values of a and b. That is, it compares each bit in the value of a with the corresponding bit
Math Libraries

419

in the value of b and sets the corresponding bit in the resulting value to 0 if both bits being compared are equal. Otherwise, that bit in the resulting value is set to 1.
Example: The following program:
LIBRARY “HEXLIB.TRC” DECLARE DEF Xor

PRINT Xor(0, 0) PRINT Xor(1, 0) PRINT Xor(1, 1) PRINT Xor(5, 6) PRINT Xor(-5, 6) PRINT Xor(5.8, 6.9) PRINT Xor(255, 127)

END
produces the following output:
0
1
0
3
-3
4.7
128
Exceptions: None
See also: AND, OR
420 True BASIC Language System

String Handling Libraries
In addition to the strings functions included in True BASIC, additional tools are provided in the library
STRLIB.TRC. All of the string functions and subroutines are described below in alphabetical order.
The operations provided by these functions and subroutines include: Return sets of string constants
ALPHANUM$, CONTROL$, DIGITS$, LETTERS$, LOWER$, PUNCT$, RNDSTR$, UPPER$
Return simple parts of strings
LEFT$, MID$, RIGHT$ Return date and time strings:
NICEDATE$, NICETIME$, NOW$, SHORTDATE$, TODAY, WEEKDAY, WEEKDAY$
Convert between numeric and other representations of numbers:
DOLLARS$, DOLLARVAL, ENGLISHNUM$, EVAL, LVAL, ROMAN$, SUPERVAL
Parse a string BREAKUP, EXPLODE, EXPLODEN, NEXTWORD
Trim extra spaces INTRIM$, LTRIM$, RTRIM$, TRIM$, JUSTIFY$, NOSPACE$
Format text CENTER$, FILLARRAY, FILLFROM, HEADER$, JUSTIFY$, JUSTIFYARRAY, JUSTIFYFROM, LJUST$, RJUST$
Reverse a string REVERSE$
Find shared or non-shared characters in two strings
CHARDIFF$, CHARINT$, CHARS$, CHARUNION$, UNIQ$ Remove or replace characters from strings
DELCHAR$, DELMIX$, DELSTR$, KEEPCHAR$, MAPCHAR$, NPLUGCHAR$, NREPCHAR$, PLUGCHAR$, PLUGMIX$, PLUGSTR$, REPCHAR$, REPMIX$, REPSTR$

ALPHANUM$ Function
Library: STRLIB.TRC
Syntax: ALPHANUM$
Usage: LET set$ = ALPHANUM$
Summary: Returns the set of alphabetic and digit characters.
Details: The ALPHANUM$ function returns a string containing the set of characters representing the letters of the alphabet, both uppercase and lowercase, as well as the digits, arranged in ascending order according to their ASCII codes. (For a table of the ASCII codes and their corresponding characters, see Appendix A.)
That is, it returns the equivalent of the string constant:
“0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”
Example: None.
Exceptions: None
See also: DIGITS$, LETTERS$, UPPER$, LOWER$, PUNCT$, CONTROL$

BREAKUP Subroutine
Library: STRLIB.TRC
Syntax: CALL BREAKUP (strex, strex, strex)
Usage: CALL BREAKUP (phrase$, word$, delims$)
Summary: Returns the next word, as delineated by a delimiter character, from the specified phrase.
String Handling Libraries

421

Details: The BREAKUP subroutine returns the next “word” from the specified “phrase.”
A phrase is defined as any series of characters, and a word is defined as any series of characters except those defined as delimiters.
When invoking the BREAKUP subroutine, you pass the phrase as phrase$ and the characters to be defined as delimiters as delims$. The subroutine then examines the phrase, looking for the first delimiter character, and returns the characters up to but not including this delimiter as the value of word$. It also updates the value of phrase$ to eliminate the returned word and the delimiter.
Note that the BREAKUP subroutine strips any leading and trailing spaces off of the return values of word$ and phrase$.
For example, assume you have passed delim$ with a value of “*#;” and phrase$ with a value of “***abc***def**” to the BREAKUP subroutine. The subroutine would return word$ with a value of the null string and phrase$ with a new value of “**abc***def**” since there is no non-delimiter value between the beginning of the phrase and the first delimiter. The process of breaking a phrase into words is often referred to as parsing a phrase.
If the value of phrase$ does not contain any delimiters, the BREAKUP subroutine will return the value of phrase$ in word$ and return phrase$ equal to the null string.
Note that the BREAKUP subroutine is closely related to, but subtly different from, the NEXTWORD subroutine. The BREAKUP subroutine treats each individual delimiter character as a delimiter in its own right, while the NEXTWORD subroutine treats a series of contiguous delimiter characters as a single delimiter. For some applications you will want to use the BREAKUP subroutine, for others you will want to use the NEXTWORD subroutine.
Example: The following program:
LIBRARY "StrLib.trc"
LET s$ = "Now is the time for all good men" DO
CALL BreakUp (s$, word$, " ") IF word$ = "" then EXIT DO PRINT word$,
LOOP END
produces the following output:
all good men
Now is the time for
Exceptions: None
See also: NEXTWORD, EXPLODE, EXPLODEN

CENTER$ Function
Library: STRLIB.TRC
Syntax: CENTER$ (strex, numex, strex)
Usage: LET a$ = CENTER$ (text$, width, back$)
Summary: Returns a string of the specified length containing the value of text$ center-justified.
Details: The CENTER$ function takes the value of text$ and adds characters alternately to the beginning and end of it as necessary to create a string containing width characters with the value of text$ centered within it. The characters added will be determined by repeating
the sequence of characters specified by the value of back$.
Note that if the value of text$ cannot be perfectly centered within the result, the extra
422 True BASIC Language System

space will appear to the left of the value of text$ within the resulting string.
If the length of text$ is greater than the value specified by width, the CENTER$
function returns the value of text$ truncated to width characters. If the value of width is
less than or equal to 0, the CENTER$ function returns the null string.
The background pattern added to the beginning and end of the value of text$ will be formed in such a way that all strings formed with the same value of back$ will have identical background patterns, regardless of the value of text$. If the value of back$ is the null string or a space, the background pattern will consist solely of blanks, or spaces.
Example: The following program:
LIBRARY "StrLib.trc"
DECLARE DEF Center$
LET s$ = "Hello, out there"
FOR w = 20 to 25
LET t$ = Center$ (s$, w, "*")
PRINT t$
NEXT w
END
produces the following output:
**Hello, out there**
**Hello, out there***
***Hello, out there***
***Hello, out there****
****Hello, out there****
****Hello, out there*****
Exceptions: None
See also: LJUST$, RJUST$, JUSTIFY$, HEADER$. FILLARRAY, FILLFROM,
JUSTIFYARRAY, JUSTIFYFROM

CHARDIFF$ Function
Library: STRLIB.TRC
Syntax: CHARDIFF$ (strex, strex)
Usage: LET difference$ = CHARDIFF$ (a$, b$)
Summary: Returns the set of characters contained within the value of a$ and not within the value of
b$.
Details: The CHARDIFF$ function returns a string containing the difference of the sets of characters represented by the values of its arguments a$ and b$.
That is, the CHARDIFF$ function returns a string which contains one of each character which appears in the value of its argument a$ but not within the value of its argument b$. The characters will be organized within the resulting string in ascending order by their ASCII codes. Thus, uppercase letters will be listed before all lowercase letters.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF CharDiff$
LET a$ = "Hello, out there" LET b$ = "aeiouy"
PRINT "*"; CharDiff$ (a$, b$); "*" END
produces the following output:
* ,Hhlrt*
Exceptions: None
See also: CHARUNION$, CHARINT$, CHARS$, UNIQ$
String Handling Libraries

423

CHARINT$ Function
Library: STRLIB.TRC
Syntax: CHARINT$ (strex, strex)
Usage: LET intersection$ = CHARINT$ (a$, b$)
Summary: Returns the set of characters contained within the values of both a$ and b$.
Details: The CHARINT$ function returns a string containing the intersection of the sets of characters represented by the values of its arguments a$ and b$.
That is, the CHARINT$ function returns a string which contains one of each character which appears in the values of both its arguments. The characters will be organized within the resulting string in ascending order by their ASCII codes. Thus, uppercase letters will be listed before all lowercase letters.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF CharInt$
LET a$ = "Hello, out there" LET b$ = "aeiouy"
PRINT "*"; CharInt$ (a$, b$); "*" END
produces the following output:
*eou*
Exceptions: None
See also: CHARUNION$, CHARDIFF$, CHARS$, UNIQ$

CHARS$ Function
Library: STRLIB.TRC
Syntax: CHARS$ (numex, numex)
Usage: LET set$ = CHARS$ (start, end)
Summary: Returns the set of characters whose ASCII codes range from the value of start to the value of end.
Details: The CHARS$ function returns a string containing the set of characters whose ASCII codes range in value from start to end.
If the value of start is less than or equal to the value of end, then the characters within the resulting string will be arranged in ascending order by ASCII codes. If the value of start is greater than the value of end, the resulting string will be arranged in descending order.
If either start or end has a value less than 0, a value of 0 will be used instead. Likewise, if either has a value greater than 255, a value of 255 will be used instead.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Chars$ PRINT Chars$ (33, 47) END
produces the following output:
!"#$%&'()*+,-./
Exceptions: None
See also: CHARINT$, CHARDIFF$, CHARUNION$, UNIQ$
424 True BASIC Language System

CHARUNION$ Function
Library: STRLIB.TRC
Syntax: CHARUNION$ (strex, strex)
Usage: LET union$ = CHARUNION$ (a$, b$)
Summary: Returns the set of characters contained within the values of either a$ or b$.
Details: The CHARUNION$ function returns a string containing the union of the sets of characters represented by the values of its arguments a$ and b$.
That is, the CHARUNION$ function returns a string which contains one of each character which appears in the value of either of its arguments. The characters will be organized within the resulting string in ascending order by their ASCII codes. Thus, uppercase letters will be listed before all lowercase letters.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF CharUnion$
LET a$ = "Now is the time" LET b$ = "for all good men" PRINT CharUnion$ (a$, b$) END
produces the following output:
Nadefghilmnorstw
(Note: there is a space before the 'N'.)
Exceptions: None
See also: CHARINT$, CHARDIFF$, CHARS$, UNIQ$

CONTROL$ Function
Library: STRLIB.TRC
Syntax: CONTROL$
Usage: LET set$ = CONTROL$
Summary: Returns the set of control characters.
Details: The CONTROL$ function returns a string containing the set of control characters, arranged in ascending order according to their ASCII codes. (For a table of the ASCII codes and their corresponding characters, see Appendix A.)
That is, it returns a string composed of those characters with ASCII codes between 0 and 31, inclusive.
Example: None.
Exceptions: None
See also: DIGITS$, LETTERS$, ALPHANUM$, UPPER$, LOWER$, PUNCT$

DELCHAR$ Function
Library: STRLIB.TRC
Syntax: DELCHAR$ (strex, strex)
Usage: LET a$ = DELCHAR$ (text$, oldchars$)
Summary: Returns the value of text$ with all characters appearing in oldchars$ removed.
Details: The DELCHAR$ function removes from text$ all characters which are members of the character set represented by the value of oldchars$. That is, it returns the value of text$ after having deleted any occurrences of characters appearing in the value of oldchars$.
String Handling Libraries

425

Example: The following program:
LIBRARY “STRLIB.TRC”
DECLARE DEF CharDiff$, Control$, DelChar$

OPEN #1: NAME “InFile”, ORG BYTE
OPEN #2: NAME “OutFile”, ORG BYTE, CREATE NEW
ERASE #2

LET crlf$ = Chr$(13) & Chr$(10)
LET bad$ = CharDiff$(Control$, crlf$)

DO WHILE MORE #1
READ #1, BYTES 10000: block$
WRITE #2: DelChar$(block$, bad$)
LOOP

END
removes all control characters except carriage return and line feed from the file named
INFILE, and stores the results in a file named OUTFILE.
Exceptions: None
See also: KEEPCHAR$, REPCHAR$, NREPCHAR$, MAPCHAR$, PLUGCHAR$,
NPLUGCHAR$

DELMIX$ Function
Library: STRLIB.TRC
Syntax: DELMIX$ (strex, strex)
Usage: LET a$ = DELMIX$ (text$, old$)
Summary: Returns the value of text$ with all occurrences of the value of old$, in any mix of upper- and lowercase, removed.
Details: The DELMIX$ function removes from text$ all occurrences of the value of old$, without regard to case. That is, it returns the value of text$ after having deleted any occurrences of the value of old$ in any mix of uppercase and lowercase letters.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF DelMix$
LET a$ = "Now is the time for all good men" LET b$ = "e"
PRINT DelMix$ (a$, b$) END
produces the following output:
Now is th tim for all good mn
Exceptions: None
See also: DELSTR$, DELCHAR$, REPMIX$, PLUGMIX$

DELSTR$ Function
Library: STRLIB.TRC
Syntax: DELSTR$ (strex, strex)
Usage: LET a$ = DELSTR$ (text$, old$)
Summary: Returns the value of text$ with all occurrences of the value of old$ removed.
Details: The DELSTR$ function removes from text$ all occurrences of the value of old$. That is, it returns the value of text$ after having deleted any occurrences of the value of old$.
426 True BASIC Language System

Example: The following program:
LIBRARY “STRLIB.TRC” DECLARE DEF DelStr$

DO
LINE INPUT PROMPT “Enter a line (Return to quit): “: line$
IF line$ = “” then EXIT DO
PRINT DelStr$(line$, “,”)
LOOP

END
deletes all commas from lines input by the user.
Exceptions: None
See also: DELMIX$, DELCHAR$, REPSTR$, PLUGSTR$

DIGITS$ Function
Library: STRLIB.TRC
Syntax: DIGITS$
Usage: LET set$ = DIGITS$
Summary: Returns the set of digit characters.
Details: The DIGITS$ function returns a string containing the set of characters representing the digits arranged in ascending order according to their ASCII codes. (For a table of the ASCII codes and their corresponding characters, see Appendix A.)
That is, it returns the equivalent of the string constant:
“0123456789” Example: None. Exceptions: None
See also: LETTERS$, UPPER$, LOWER$, ALPHANUM$, PUNCT$, CONTROL$

DOLLARS$ Function
Library: STRLIB.TRC
Syntax: DOLLARS$ (numex)
Usage: LET formatted$ = DOLLARS$ (number)
Summary: Returns the string representation of its numeric argument as a dollar amount.
Details: The DOLLARS$ function returns the string representation of number as a nicely formatted dollar amount.
The resulting string will begin with a dollar sign, have a comma between each set of three digits to the left of the decimal point, and end with two digits to the right of the decimal point. The resulting string will not contain any extraneous spaces or zeros (except those zeros which may be necessary to provide two digits to the right of the decimal point).
The DOLLARS$ function is a convenient method for creating a very specific formatting of numeric values. The USING$ function, however, provides much greater flexibility in how numeric values are formatted.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Dollars$
PRINT Dollars$ (1234.5678) END
String Handling Libraries

427

produces output similar to the following:
$1,234.57
Exceptions: None
See also: USING$ (built-in function)

DOLLARVAL Function
Library: STRLIB.TRC
Syntax: DOLLARVAL (strex)
Usage: LET number = DOLLARVAL (string$)
Summary: Returns the numeric value represented by the contents of its string argument, allowing dollar signs, commas, asterisks, and embedded spaces.
Details: The DOLLARVAL function is a more flexible form of the VAL function. Like the VAL function it returns the numeric value of contents of its string argument string$, but it ignores any dollar signs, commas, asterisks, and spaces that may be embedded within the string.
Once the embedded dollar signs, commas, asterisks, and spaces have been removed, the string value of string$ must represent a valid numeric constant in a form suitable for use with an INPUT or READ statement. Note that this value may represent a valid numeric constant expressed in exponential (or scientific) notation.
If the value of string$ does not represent a valid numeric constant once the embedded dollar signs, commas, asterisks, and spaces have been removed, the DOLLARVAL function will generate an error.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF DollarVal
PRINT DollarVal ("$1,234.57") END
produces the following output:
1234.57
Exceptions: 1004 Overflow in VAL.
4001 VAL string isn’t a proper number.
See also: VAL, LVAL, EVAL, SUPERVAL

ENGLISHNUM$ Function
Library: STRLIB.TRC
Syntax: ENGLISHNUM$ (numex)
Usage: LET english$ = ENGLISHNUM$ (number)
Summary: Returns the string representation of its numeric argument in English.
Details: The ENGLISHNUM$ function returns the string representation of the proper English name of number. For example, if passed a value of 117, the ENGLISHNUM$ function would return the string value:
One Hundred and Seventeen
As you can see, the English name of the numeric value will be represented in mixed upper- and lowercase letters.
The English representation of a negative number will begin with the word “negative,” and all numbers are rounded to five digits after the decimal point. Thus, if passed a value of
–3.1415926, the ENGLISHNUM$ function will return the string value:
negative Three point One Four One Five Nine
The ENGLISHNUM$ function uses the American, rather than British, names for large numbers. Thus, passing a value of 1000000 results in a return value of:
428 True BASIC Language System

One Million
and passing a value of 1000000000 results in a return value of:
One Billion
Note that the results of the ENGLISHNUM$ function can be wrong for very large numbers (usually those greater than 9,000,000,000) because of the inaccuracy introduced by floating point round off errors.
Example: The following program: LIBRARY “STRLIB.TRC” DECLARE DEF EnglishNum$

FOR i = 1 to 10
FOR j = 1 to 10
PRINT EnglishNum$(i); “ times “; EnglishNum$(j); PRINT “ is “; EnglishNum$(i*j)
NEXT j
NEXT i

GET KEY k
END
produces a multiplication table in English (that is, without using digits).
Exceptions: None
See also: ROMAN$

EVAL Function
Library: STRLIB.TRC
Syntax: EVAL (strex)
Usage: LET result = EVAL (expression$)
Summary: Returns the value of the constant-based expression represented by the contents of its string argument.
Details: The EVAL function evaluates the numeric expression represented by the value of
expression$ and returns the resulting value.
The value of expression$ must represent a numeric expression which is valid under the rules of True BASIC. This expression may contain numeric constants, but not variables. (For the evaluation of expressions containing variables, see the SUPERVAL subroutine.)
The value of expression$ may incorporate any of the following operators:
Operators Available to EVAL
+ - * / ^ ( )
In addition, the value of expression$ may incorporate any of the following numeric functions:
Functions Available to EVAL
SIN COS TAN ATN SQR SINH COSH TANH ASIN ACOS SEC CSC COT MAXNUM EPS PI SGN ABS RAD DEG LOG LOG2 LOG10 EXP RND INT ROUND IP FP CEIL
DATE TIME
Note that numeric functions requiring two arguments, including the two-argument form of the ROUND function, are not available for use in the value of expression$.
Also note that the EVAL function is not as fast as the VAL function, but it is a great deal more flexible.
String Handling Libraries

429

Example: The following program:
LIBRARY “STRLIB.TRC” DECLARE DEF Eval
PRINT Eval(“1.23e-3 + 2*(Sin(Pi/2)+Rnd)”) INPUT PROMPT “Enter an expression: “: expr$
PRINT Eval(expr$)

GET KEY k
END
produces output similar to the following:
3.0982454
Enter an expression: 25 + 12 / 16 * Sin(Pi/3)
25.649519
Exceptions: 1 Eval string isn’t a proper expression.
2 Unknown function or variable in Eval.
3002 Negative number to non-integral power.
3003 Zero to negative power.
3004 LOG of number <= 0.
3005 SQR of negative number.
4001 VAL string isn’t a proper number.
See also: SUPERVAL, VAL, LVAL, DOLLARVAL

EXPLODE Subroutine
Library: STRLIB.TRC
Syntax: CALL EXPLODE (strex, strarrarg, strex)
strarrarg:: strarr
strarr bowlegs
Usage: CALL EXPLODE (phrase$, words$(), delims$)
Summary: Parses the contents of the specified phrase into an array of words, as delineated by the specified delimiters.
Details: The EXPLODE subroutine breaks the specified “phrase” into the “words” which comprise it and returns the resulting words in the form of a string array.
A phrase is defined as any series of characters, and a word is defined as any series of characters except those defined as delimiters.
When invoking the EXPLODE subroutine, you pass the phrase as phrase$ and the characters to be defined as delimiters as delims$. The subroutine then examines the phrase, looking for the first set of one or more non-delimiter characters which are set off from the rest of the phrase by delimiters, and assigns this set of non-delimiter characters, less any leading or trailing delimiters, to the next available element of the words$ array. It then repeats the process, beginning the search after the last assigned word and its surrounding delimiters, until all of the words in the phrase have been assigned to the words$ array.
The process of breaking a phrase into its component words is called parsing the phrase.
The EXPLODE subroutine does not alter the value of phrase$. It will, however, adjust the upper bound of the words$ array to ensure that the returned array has exactly one element for each word in the phrase.
To parse a phrase composed of numeric constants into a numeric array, use the
EXPLODEN subroutine instead.
Example: The following program:
LIBRARY “STRLIB.TRC”, “SortLib” DIM words$(1)
430 True BASIC Language System

LET punct$ = “ !””#$%&’()*+,-./:;<=>?@[\]^)_`{|}˜”

INPUT PROMPT “Enter name of file: “: fname$ OPEN #1: NAME fname$, ORG BYTE
ASK #1: FILESIZE fsize
READ #1, BYTES fsize: file$
LET delims$ = punct$ & Chr$(13) & Chr$(10) CALL Explode(file$, words$(), delims$)
CALL SortS(words$()) MAT PRINT words$

GET KEY k
END
prints a list of the words in a specified file arranged alphabetically.
Exceptions: None
See also: EXPLODEN, NEXTWORD, BREAKUP

EXPLODEN Subroutine
Library: STRLIB.TRC
Syntax: CALL EXPLODEN (strex, numarrarg, strex)
numarrarg:: numarr
numarr bowlegs
Usage: CALL EXPLODEN (phrase$, numbers(), delims$)
Summary: Parses the contents of the specified phrase into an array of numbers, as delineated by the specified delimiters.
Details: The EXPLODEN subroutine breaks the specified “phrase” into the numeric “words” which comprise it and returns the resulting words in the form of a numeric array.
A phrase is defined as any series of characters, and a word is defined as any series of characters except those defined as delimiters. However, if a word does not define a valid numeric constant, the EXPLODEN subroutine will generate an error.
When invoking the EXPLODEN subroutine, you pass the phrase as phrase$ and the characters to be defined as delimiters as delims$. The subroutine then examines the phrase, looking for the first set of one or more non-delimiter characters which are set off from the rest of the phrase by delimiters, and assigns the numeric value of this set of non-delimiter characters to the next available element of the numbers array. It then repeats the process,
beginning the search after the last assigned numeric value, until all of the numeric values in the phrase have been assigned to the numbers array.
The process of breaking a phrase into its component parts is called parsing the phrase. The EXPLODEN subroutine does not alter the value of phrase$. It will, however, adjust the upper bound of the numbers array to ensure that the returned array has exactly one
element for each numeric value in the phrase.
To parse a phrase composed of non-numeric or mixed numeric values, use the EXPLODE
subroutine instead.
Example: The following program:
LIBRARY "StrLib.trc" DIM numbers(0)
LET phrase$ = "123,456,789.777"
CALL Exploden (phrase$, numbers(), ",.") MAT PRINT numbers;
END
String Handling Libraries

431

produces the following output:
123 456 789 777
Exceptions: 4001 VAL string isn’t a proper number.
See also: EXPLODE, NEXTWORD, BREAKUP

FILLARRAY Subroutine
Library: STRLIB.TRC
Syntax: CALL FILLARRAY (strarr, strarrarg, numex)
strarrarg:: strarr
strarr bowlegs
Usage: CALL FILLARRAY (from$(), to$(), width)
Summary: “Fills” the contents of the to$ array to the specified width with the contents of the from$
array.
Details: The FILLARRAY subroutine processes the contents of the from$ array to create the “filled” array to$. The width to which the resulting to$ array will be filled is determined by the value of width.
A common operation in text processing, filling is the process of organizing blocks of text so that each line contains as many words as will fit within a specified margin. A blank line or a line which begins with one or more spaces acts a “break,” which means that the following line will not be absorbed into the previous line.
If a single word is encountered which has a length greater than width, it will be placed on a line by itself; no error will be generated.
It is possible to pass the same array as both from$ and to$, eliminating the need for a temporary array.
The FILLARRAY subroutine is useful for wrapping text to fit within a window with a known margin.
Example: The following program:
LIBRARY "StrLib.trc" DIM from$(16), to$(0) MAT READ from$
DATA Now, is, the, time, for, all, good, men
DATA to, come, to, the, aid, of, their, party

CALL FillArray (from$(), to$(), 20) FOR i = 1 to ubound(to$)
PRINT to$(i) NEXT i
END
produces the following output:
Now is the time for all good men to come to the aid of their party
Exceptions: None
See also: FILLFROM, JUSTIFYARRAY, JUSTIFYFROM, LJUST$, RJUST$, CENTER$,
JUSTIFY$. HEADER$
432 True BASIC Language System

FILLFROM Subroutine
Library: STRLIB.TRC
Syntax: CALL FILLFROM (#rnumex, numex, strvar, strvar) Usage: CALL FILLFROM (#1, width, result$, work$) Summary: Returns a single “filled” line from the specified file.
Details: The FILLFROM subroutine retrieves a “filled” line from the text file associated with the specified channel number and returns it as result$. The width to which the resulting to$ array will be filled is determined by the value of width.
A common operation in text processing, filling is the process of organizing blocks of text so that each line contains as many words as will fit within a specified margin. A blank line or a line which begins with one or more spaces acts a “break,” which means that the following line will not be absorbed into the previous line.
The FILLFROM subroutine treats the entire contents of the text file associated with the specified channel number as the pool of text which needs to be filled. To process an entire file, continue invoking the FILLFROM subroutine until the end of the file is reached.
The value of work$ is used internally by the FILLFROM subroutine. The first time you invoke the FILLFROM subroutine for a given file, pass a work$ argument with a null string value. Then continue passing the same work$ argument, without changing its contents, to each invocation of the FILLFROM subroutine which you intend to read from the same file. Failure to do so could result in the loss of data.
If a single word is encountered which has a length greater than width, it will be returned as a line by itself; no error will be generated.
Example: The following program:
LIBRARY “STRLIB.TRC”

OPEN #1: NAME “TextFile” OPEN #2: PRINTER

DO WHILE MORE #1
CALL FillFrom(#1, 65, line$, work$) PRINT #2: line$
LOOP

END
would produce a printed listing of the filled contents of the file TEXTFILE.
Exceptions: None
See also: FILLARRAY, JUSTIFYARRAY, JUSTIFYFROM, LJUST$, RJUST$, CENTER$,
JUSTIFY$. HEADER$

HEADER$ Function
Library: STRLIB.TRC
Syntax: HEADER$ (strex, strex, strex, numex, strex)
Usage: LET a$ = HEADER$ (left$, center$, right$, width, back$)
Summary: Creates a “header” of the specified width which contains the specified text items.
Details: The HEADER$ function takes the values of left$, center$, and right$ and returns a string of width characters which contains the values of these strings. The value of left$ will be left-justified within the resulting string, the value of center$ will be centered within the resulting string, and the value of right$ will be right-justified within the resulting string. The extra characters between them will be comprised of the background pattern specified by the value of back$.
String Handling Libraries

433

The string resulting from an invocation of the HEADER$ function is commonly used as a header or footer for formatted text.
Any or all of the values of left$, center$, and right$ may be the null string to eliminate text in the appropriate position within the header.
If the value of back$ is the null string or a space, the extra characters between the items in the header will be spaces.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Header$
LET left$ = "Contents" LET center$ = "Page 1" LET right$ = date$
PRINT Header$(left$, center$, right$, 50, " ") END
produces the following output:
Contents Page 1 19980403

Exceptions: None
See also: LJUST$, RJUST$, CENTER$, JUSTIFY$. FILLARRAY, FILLFROM,
JUSTIFYARRAY, JUSTIFYFROM

INTRIM$ Function
Library: STRLIB.TRC
Syntax: INTRIM$ (strex)
Usage: LET a$ = INTRIM$ (string$)
Summary: Returns the value of its argument string$ with all series of spaces within it reduced to a single space.
Details: The INTRIM$ function returns the value of its argument with all series of spaces within it mapped to a single space. That is, it processes the value of string$ looking for any occurrence of two or more contiguous spaces. Upon finding such an occurrence, the INTRIM$ function replaces the series of spaces with a single space.
The INTRIM$ function is useful for cleaning up the results of the USING$ function, which can create strings with several extra spaces. The INTRIM$ function may also be used to undo the results of the JUSTIFY$ function.
To completely remove all of the spaces from a string, use the NOSPACE$ function.
Example: The following program:
LIBRARY “STRLIB.TRC” DECLARE DEF InTrim$

INPUT PROMPT “Enter two numbers: “: a, b
PRINT InTrim$(Using$(“#,### plus #,### equals ##,###”, a, b, a+b))

END
produces output similar to the following:
Enter two numbers: 13, 1200
13 plus 1,200 equals 1,213
Exceptions: None
See also: LTRIM$, RTRIM$, TRIM$, JUSTIFY$, NOSPACE$
434 True BASIC Language System

JUSTIFY$ Function
Library: STRLIB.TRC
Syntax: JUSTIFY$ (strex, numex)
Usage: LET a$ = JUSTIFY$ (text$, width)
Summary: Returns a string of the specified length containing the value of text$ justified.
Details: The JUSTIFY$ function takes the value of text$ and adds spaces as necessary to create a string containing width characters with the “words” in the value of text$ evenly spaced within it. The extra spaces will be added to the value of text$ where spaces already exist in order to “fill out” the value of text$ to the specified number of characters.
By filling out a series of lines, you can produce text with even left and right margins.
The JUSTIFY$ function never adds spaces to the beginning of the value of text$, even if it begins with one or more spaces. This allows the JUSTIFY$ function to operate properly when used with lines of indented text.
If the value of width is less than the length of text$, the JUSTIFY$ function generates an error. Likewise, if the value of text$ contains no spaces, it cannot be filled, and the JUSTIFY$ function generates an error. If the value of text$ is the null string, then the JUSTIFY$ function returns the null string.
The JUSTIFY$ function does not work for lines containing more than 100 words. If you pass a value of text$ which contains more than 100 words, the JUSTIFY$ function will generate an error.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Justify$
LET text$ = "Now is the time for all good men" FOR w = 32 to 40 step 2
PRINT Justify$(text$, w) NEXT w
END
produces the following output:
Now is the time for all good men Now is the time for all good men Now is the time for all good men
Now is the time for all good men
Now is the time for all good men
Exceptions: 1 More than 100 words in line.
2 Can’t justify line.
See also: LJUST$, RJUST$, CENTER$, HEADER$. FILLARRAY, FILLFROM,
JUSTIFYARRAY, JUSTIFYFROM

JUSTIFYARRAY Subroutine
Library: STRLIB.TRC
Syntax: CALL JUSTIFYARRAY (strarr, strarrarg, numex)
strarrarg:: strarr
strarr bowlegs
Usage: CALL JUSTIFYARRAY (from$(), to$(), width)
Summary: “Fills” and justifies the contents of the to$ array to the specified width with the contents of the from$ array.
Details: The JUSTIFYARRAY subroutine processes the contents of the from$ array to create the “filled” and justified array to$. The width to which the resulting to$ array will be filled and justified is determined by the value of width.
String Handling Libraries

435

A common operation in text processing, filling is the process of organizing blocks of text so that each line contains as many words as will fit within a specified margin. A blank line or a line which begins with one or more spaces acts a “break,” which means that the following line will not be absorbed into the previous line, and the previous line will not be justified.
Another common operation in text processing, justification is the process of adding spaces within a line so that the last character on the line falls evenly at the right margin. Spaces are always added where spaces already exist within the line.
The JUSTIFYARRAY subroutine never adds spaces to the beginning of a line, even if it begins with one or more spaces. This allows the JUSTIFYARRAY subroutine to operate properly when it encounters indented lines.
If it encounters a line which contains no spaces, the JUSTIFYARRAY subroutine generates an error, since such a line cannot be justified.
The JUSTIFYARRAY subroutine also cannot justify lines containing more than 100 words. If it encounters a line which contains more than 100 words, the JUSTIFYARRAY subroutine will generate an error.
It is possible to pass the same array as both from$ and to$, eliminating the need for a temporary array.
Example: The following program:
LIBRARY "StrLib.trc" DIM from$(4), to$(4) MAT READ from$
DATA Now is the time DATA for all good men DATA to come to the aid DATA of their party.

CALL JustifyArray (from$(), to$(), 25) FOR i = 1 to ubound(to$)
PRINT to$(i) NEXT i
END
produces the following output:
Now is the time for all good men to come to the aid of their party.
Exceptions: 1 More than 100 words in line.
2 Can’t justify line.
See also: JUSTIFYFROM, FILLARRAY, FILLFROM, LJUST$, RJUST$, CENTER$,
JUSTIFY$. HEADER$

JUSTIFYFROM Subroutine
Library: STRLIB.TRC
Syntax: CALL JUSTIFYFROM (#rnumex, numex, strvar, strvar) Usage: CALL JUSTIFYFROM (#1, width, result$, work$) Summary: Returns a single “filled” and justified line from the specified file.
Details: The JUSTIFYFROM subroutine retrieves a “filled” and justified line from the text file associated with the specified channel number and returns it as result$. The contents result$ will be filled and justified according to the value of width.
A common operation in text processing, filling is the process of organizing blocks of text so that each line contains as many words as will fit within a specified margin. A blank line or a line which begins with one or more spaces acts a “break,” which means that the following line will not be absorbed into the previous line.
436 True BASIC Language System

Another common operation in text processing, justification is the process of adding spaces within a line so that the last character on the line falls evenly at the right margin. Spaces are always added where spaces already exist within the line.
The JUSTIFYFROM subroutine never adds spaces to the beginning of a line, even if it begins with one or more spaces. This allows the JUSTIFYFROM subroutine to operate properly when it encounters indented lines.
If it encounters a line which contains no spaces, the JUSTIFYFROM subroutine generates an error, since such a line cannot be justified.
The JUSTIFYFROM subroutine also cannot justify lines containing more than 100 words. If it encounters a line which contains more than 100 words, the JUSTIFYFROM subroutine will generate an error.
The JUSTIFYFROM subroutine treats the entire contents of the text file associated with the specified channel number as the pool of text which needs to be filled and justified. To process an entire file, continue invoking the JUSTIFYFROM subroutine until the end of the file is reached.
The value of work$ is used internally by the JUSTIFYFROM subroutine. The first time you invoke the JUSTIFYFROM subroutine for a given file, pass a work$ argument with a null string value. Then continue passing the same work$ argument, without changing its contents, to each invocation of the JUSTIFYFROM subroutine which you intend to read from the same file. Failure to do so could result in the loss of data.
Example: The following program:
LIBRARY "StrLib.trc"
OPEN #1: name "TextFile"
OPEN #2: Printer
DO while more #1
CALL JustifyFrom (#1, 65, line$, work$)
PRINT #2
LOOP
END
would produce a printed list of the justified contents of the text file TEXTFILE.
Exceptions: 1 More than 100 words in line.
2 Can’t justify line.
See also: JUSTIFYARRAY, FILLARRAY, FILLFROM, LJUST$, RJUST$, CENTER$,
JUSTIFY$. HEADER$

KEEPCHAR$ Function
Library: STRLIB.TRC
Syntax: KEEPCHAR$ (strex, strex)
Usage: LET a$ = KEEPCHAR$ (text$, oldchars$)
Summary: Returns the value of text$ with all characters which do not appear in oldchars$
removed.
Details: The KEEPCHAR$ function removes from text$ all characters which are not members of the character set represented by the value of oldchars$. That is, it returns the value of text$ after having deleted any occurrences of characters which do not appear in the value of oldchars$.
Example: The following program:
LIBRARY “STRLIB.TRC”
DECLARE DEF KeepChar$, Punct$

OPEN #1: NAME “InFile”, ORG BYTE LET pun$ = Punct$
String Handling Libraries

437

DO WHILE MORE #1
READ #1, BYTES 10000: block$
LET sum = sum + Len(KeepChar$(block$, pun$))
LOOP
PRINT sum

END
counts the punctuation in the file named INFILE.
Exceptions: None
See also: DELCHAR$, REPCHAR$, NREPCHAR$, MAPCHAR$, PLUGCHAR$,
NPLUGCHAR$

LEFT$ Function
Library: STRLIB.TRC
Syntax: LEFT$ (strex, numex)
Usage: LET a$ = LEFT$ (string$, chars)
Summary: Returns the leftmost chars characters of string$.
Details: The LEFT$ function returns a specific number of characters from the beginning of
string$. The number of characters to be returned is given by the value of chars.
If the value of chars is less than or equal to 0, the LEFT$ function returns the null string. If the value of chars is greater than the number of characters in string$, the LEFT$ function returns the value of string$.
Note that the LEFT$ function can be useful when converting programs written in other forms of BASIC. However, you will likely find that the substring expressions discussed in Chapter 17 provide greater speed and flexibility.
Example: The following program: LIBRARY "StrLib.trc" DECLARE DEF Left$
LET a$ = "Now is the time"
FOR chars = 5 to 8
PRINT Left$(a$, chars) NEXT chars
END
produces the following output:
Now i Now is Now is Now is t

Exceptions: None
See also: RIGHT$, MID$

LETTERS$ Function
Library: STRLIB.TRC
Syntax: LETTERS$
Usage: LET set$ = LETTERS$
Summary: Returns the set of alphabetic characters.
Details: The LETTERS$ function returns a string containing the set of characters representing the letters of the alphabet, both uppercase and lowercase, arranged in ascending order according to their ASCII codes. (For a table of the ASCII codes and their corresponding characters, see Appendix A.)
438 True BASIC Language System

That is, it returns the equivalent of the string constant:
“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz”
Example: None.
Exceptions: None
See also: DIGITS$, UPPER$, LOWER$, ALPHANUM$, PUNCT$, CONTROL$

LJUST$ Function
Library: STRLIB.TRC
Syntax: LJUST$ (strex, numex, strex)
Usage: LET a$ = LJUST$ (text$, width, back$)
Summary: Returns a string of the specified length containing the value of text$ left-justified.
Details: The LJUST$ function takes the value of text$ and adds characters to the end of it as necessary to create a string containing width characters with the value of text$ left- justified within it. The characters added will be determined by repeating the sequence of characters specified by the value of back$.
If the length of text$ is greater than the value specified by width, the LJUST$ function returns the value of text$ truncated to width characters. If the value of width is less than or equal to 0, the LJUST$ function returns the null string.
The background pattern added to the end of the value of text$ will be formed in such a way that all strings formed with the same value of back$ will have identical background patterns, regardless of the value of text$. If the value of back$ is the null string or a space, the background pattern will consist solely of blanks, or spaces.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF LJust$ LET a$ = "...Hello" FOR chars = 10 to 12
PRINT LJust$(a$, chars, "*") NEXT chars
END
produces the following output:
...Hello**
...Hello***
...Hello****
Exceptions: None
See also: RJUST$, CENTER$, JUSTIFY$, HEADER$. FILLARRAY, FILLFROM,
JUSTIFYARRAY, JUSTIFYFROM

LOWER$ Function
Library: STRLIB.TRC
Syntax: LOWER$
Usage: LET set$ = LOWER$
Summary: Returns the set of lowercase alphabetic characters.
Details: The LOWER$ function returns a string containing the set of characters representing the letters of the alphabet, in lowercase only, arranged in ascending order according to their ASCII codes. (For a table of the ASCII codes and their corresponding characters, see Appendix A.)
That is, it returns the equivalent of the string constant:
“abcdefghijklmnopqrstuvwxyz”
String Handling Libraries

439

Example: None.
Exceptions: None
See also: UPPER$, LETTERS$, DIGITS$, ALPHANUM$, PUNCT$, CONTROL$

LVAL Function
Library: STRLIB.TRC
Syntax: LVAL (strex)
Usage: LET number = LVAL (string$)
Summary: Returns the numeric value represented by the contents of its string argument, ignoring any extraneous characters on the end of the string.
Details: The LVAL function is a “leftmost” form of the VAL function. Like the VAL function it returns the numeric value of contents of its string argument string$, but it ignores any extraneous characters at the end of the string.
The string value of string$ must begin with a valid numeric constant in a form suitable for use with an INPUT or READ statement; however, it may contain any number of invalid characters following this value. The numeric portion of the value may not contain embedded spaces. Nor may this value contain commas, a dollar sign, or more than one decimal point. Note, however, that this value may represent a valid numeric constant expressed in exponential (or scientific) notation.
If the value of string$ does not begin with a valid numeric constant, the LVAL function returns a value of 0.
The LVAL function is useful when converting programs written in other forms of BASIC, which may interpret their VAL functions in this manner.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF LVal
PRINT LVal(" 123.45 dollars") END
produces the following output:
123.45
Exceptions: None
See also: VAL, DOLLARVAL, SUPERVAL, EVAL

MAPCHAR$ Function
Library: STRLIB.TRC
Syntax: MAPCHAR$ (strex, strex, strex)
Usage: LET a$ = MAPCHAR$ (text$, oldchars$, newchars$)
Summary: Returns the value of text$ with all characters in oldchars$ mapped to the associated characters in newchars$.
Details: The MAPCHAR$ function maps one set of characters onto another. It returns the value of text$ after having replaced any occurrences of characters appearing in the value of oldchars$ with their corresponding characters appearing in the value of newchars$.
The correspondence of the two character sets represented by oldchars$ and newchars$ is based solely upon position within the set. That is, any occurrence of the first character in oldchars$ will be replaced by the first character in newchars$, and so on.
For this reason, the values of oldchars$ and newchars$ must contain the same number of characters; otherwise, the MAPCHAR$ function generates an error.
440 True BASIC Language System

Example: The following program:
LIBRARY “STRLIB.TRC”
DECLARE DEF Punct$, MapChar$
OPEN #1: NAME “InFile” LET pun$ = Punct$
LET sp$ = Repeat$(“ “, Len(pun$))

DO WHILE MORE #1
LINE INPUT #1: line$
PRINT MapChar$(line$, pun$, sp$)
LOOP

END
lists the contents of a text file named INFILE, mapping all occurrences of punctuation to spaces.
Exceptions: 1 MapChar$ sets have different lengths.
See also: REPCHAR$, NREPCHAR$, DELCHAR$, KEEPCHAR$, PLUGCHAR$,
NPLUGCHAR$

MID$ Function
Library: STRLIB.TRC
Syntax: MID$ (strex, numex, numex)
Usage: LET a$ = MID$ (string$, start, chars)
Summary: Returns chars characters of string$ beginning at character position start.
Details: The MID$ function returns a specific number of characters from a specified position within string$. The number of characters to be returned is given by the value of chars. And the character position at which this series of characters should begin is given by the value of start.
If the value of start is less than 1, 1 will be used instead. If the value of start is greater than the number of characters in string$ or the value of chars is less than or equal to 0, the MID$ function returns the null string. If their are fewer than chars characters following the position indicated by start, only the existing characters will be returned.
Note that the MID$ function can be useful when converting programs written in other forms of BASIC. However, you will likely find that the substring expressions discussed in Chapter
17 provide greater speed and flexibility.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Mid$
LET a$ = "abcdefghijklmno" FOR start = 5 to 8
PRINT Mid$(a$, start, start) NEXT start
END
produces the following output:
efghi fghijk ghijklm hijklmno
Exceptions: None
See also: RIGHT$, LEFT$
String Handling Libraries

441

NEXTWORD Subroutine
Library: STRLIB.TRC
Syntax: CALL NEXTWORD (strex, strex, strex)
Usage: CALL NEXTWORD (phrase$, word$, delims$)
Summary: Returns the next word, as delineated by any series of delimiter characters, from the specified phrase.
Details: The NEXTWORD subroutine returns the next “word” from the specified “phrase.”
A phrase is defined as any series of characters, and a word is defined as any series of characters except those defined as delimiters.
When invoking the NEXTWORD subroutine, you pass the phrase as phrase$ and the characters to be defined as delimiters as delims$. The subroutine then examines the phrase, looking for the first set of one or more non-delimiter characters which are set off from the rest of the phrase by delimiters, and returns this set of non-delimiter characters after having stripped off any leading or trailing delimiters. It also updates the value of phrase$ to eliminate the returned word and its adjacent delimiters.
For example, assume you have passed delim$ with a value of “*#;” and phrase$ with a value of “***abc***def**” to the NEXTWORD subroutine. The subroutine would return word$ with a value of “abc” and phrase$ with a new value of “def**”. This process is often referred to as parsing a phrase.
If the value of phrase$ is the null string or contains nothing but delimiters, the
NEXTWORD subroutine will return both word$ and phrase$ with values of the null string.
Note that the NEXTWORD subroutine is closely related to, but subtly different from, the BREAKUP subroutine. The NEXTWORD subroutine treats a series of contiguous delimiter characters as a single delimiter, while the BREAKUP subroutine treats each individual delimiter character as a delimiter in its own right. For some applications you will want to use the NEXTWORD subroutine, for others you will want to use the BREAKUP subroutine.
Example: The following program:
LIBRARY "StrLib.trc"
LET s$ = "Now is the time for all good men"
DO
CALL NextWord (s$, word$, " ") IF word$ = "" then EXIT DO PRINT word$,
LOOP END
produces the following output:
Now is the time for all good men
Exceptions: None
See also: BREAKUP, EXPLODE, EXPLODEN

NICEDATE$ Function
Library: STRLIB.TRC
Syntax: NICEDATE$ (strex)
Usage: LET a$ = NICEDATE$ (adate$)
Summary: Returns the date represented by the value of adate$ in string form consisting of the month name, the day of the month, and the year.
Details: The NICEDATE$ function takes as its argument a date in the format produced by the DATE$ function and returns that date in expanded form. This expanded form consists of the full name of the month, the day of the month, and the full year.
442 True BASIC Language System

The value of adate$ must represent a date in the same format produced by the DATE$ function. That is, the value of adate$ must be a string in the form “YYYYMMDD”, where YYYY represents the year, MM the month, and DD the day. If adate$ does not represent such a value, then the NICEDATE$ function generates an error.
To return the current date in the same format, use the TODAY$ function. To return a date in an abbreviated format, use the SHORTDATE$ function.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF NiceDate$
PRINT NiceDate$("19971015") END
produces the following output:
October 15, 1997
Exceptions: 1 Bad date given to NiceDate$: 00000000
See also: DATE$, DATE, SHORTDATE$, WEEKDAY$, WEEKDAY, TODAY$, TIME, TIME$,
NICETIME$, NOW$

NICETIME$ Function
Library: STRLIB.TRC
Syntax: NICETIME$ (strex)
Usage: LET a$ = NICETIME$ (atime$)
Summary: Returns the time represented by the value of atime$ in string form consisting of the hour and minute and an indication of a.m. or p.m.
Details: The NICETIME$ function takes as its argument a time measured by the 24-hour clock and returns that time as measured by the 12-hour clock in string form. The returned time will be in the form “HH:MM”, where HH is the hour and MM is the minute, and the string “ a.m.” or “ p.m.” will be appended as appropriate.
The value of atime$ must represent a time measured by the 24-hour clock in the same format produced by the TIME$ function. That is, the value of atime$ must be a string in the form “HH:MM:SS”, where HH represents the hour, MM the minute, and SS the second. If atime$ does not represent such a value, then the NICETIME$ function generates an error.
To return the current time in the same format, use the NOW$ function.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF NiceTime$
PRINT NiceTime$("16:50:58") END
produces output similar to the following:
4:50 p.m.
Exceptions: 1 Bad time given to NiceTime$: 99:99:99
See also: TIME$, TIME, NOW$, DATE, DATE$, NICEDATE$, SHORTDATE$, WEEKDAY$,
WEEKDAY, TODAY$

NOSPACE$ Function
Library: STRLIB.TRC
Syntax: NOSPACE$ (strex)
Usage: LET a$ = NOSPACE$ (string$)
Summary: Returns the value of its argument string$ with all spaces removed.
Details: The NOSPACE$ function returns the value of its argument with all spaces removed.
String Handling Libraries

443

Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF NoSpace$
LET s$ = "Now is the time" PRINT s$
PRINT NoSpace$(s$) END
produces output similar to the following:
Now is the time
Nowisthetime
Exceptions: None
See also: LTRIM$, RTRIM$, TRIM$, JUSTIFY$, INTRIM$

NOW$ Function
Library: STRLIB.TRC
Syntax: NOW$
Usage: LET a$ = NOW$
Summary: Returns the current time in string form consisting of the hour and minute and an indication of a.m. or p.m.
Details: The NOW$ function returns the current time as measured by the 12-hour clock in string form.
The time will be in the form “HH:MM”, where HH is the hour and MM is the minute, and the
string “ a.m.” or “ p.m.” will be appended as appropriate.
If the current computer hardware is not able to report the time, then the NOW$ function generates an error.
The NOW$ function obtains its results from your operating system, which in turn obtains its results from your computer’s internal clock. If you find that the NOW$ function is returning erroneous results, you most likely have to reset your computer’s internal clock.
To return an arbitrary time in the same format, use the NICETIME$ function.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Now$ PRINT Now$
END
produces output similar to the following:
1:06 p.m.
Exceptions: 1 Bad time given to NiceTime$: 99:99:99
See also: TIME$, TIME, NICETIME$, DATE, DATE$, NICEDATE$, SHORTDATE$,
WEEKDAY$, WEEKDAY, TODAY$

NPLUGCHAR$ Function
Library: STRLIB.TRC
Syntax: NPLUGCHAR$ (strex, strex, strex)
Usage: LET a$ = NPLUGCHAR$ (text$, chars$, template$)
Summary: Returns the value of text$ with all characters which do not appear in chars$ replaced by the specified template.
Details: The NPLUGCHAR$ function replaces all characters in text$ which are not also members of the character set represented by the value of chars$. Each occurrence within text$ of a character that is not part of chars$ is replaced by the value of template$.
444 True BASIC Language System

The NPLUGCHAR$ function differs from the NREPCHAR$ function in that the value of template$ is treated as a template. This means that each occurrence of the character combination “#1” within the value of template will be replaced with the value of the character which will be replaced by the template.
Example: The following program:
LIBRARY "StrLib.trc"
DECLARE DEF AlphaNum$, NPlugChar$ LET text$ = "Now is the time"
PRINT NPlugChar$(text$, AlphaNum$, "|") END
produces the following output:
Now|is|the|time
Exceptions: None
See also: PLUGCHAR$, DELCHAR$, KEEPCHAR$, REPCHAR$, NREPCHAR$, MAPCHAR$

NREPCHAR$ Function
Library: STRLIB.TRC
Syntax: NREPCHAR$ (strex, strex, strex)
Usage: LET a$ = NREPCHAR$ (text$, oldchars$, new$)
Summary: Returns the value of text$ with all characters not appearing in oldchars$ replaced by the value of new$.
Details: The NREPCHAR$ function maps all characters which are not members of a character set to a single string. It returns the value of text$ after having replaced any occurrences of characters not appearing in the value of oldchars$ with the value of new$.
Example: The following program:
LIBRARY “STRLIB.TRC”
DECLARE DEF Digits$, NRepChar$

OPEN #1: NAME “InFile” LET chars$ = Digits$
DO WHILE MORE #1
LINE INPUT #1: line$
PRINT NRepChar$(line$, chars$, “ “)
LOOP

GET KEY k
END
lists the contents of a text file named INFILE, replacing all characters which are not digits with spaces.
Exceptions: None
See also: REPCHAR$, MAPCHAR$, DELCHAR$, KEEPCHAR$, PLUGCHAR$,
NPLUGCHAR$

PLUGCHAR$ Function
Library: STRLIB.TRC
Syntax: PLUGCHAR$ (strex, strex, strex)
Usage: LET a$ = PLUGCHAR$ (text$, chars$, template$)
Summary: Returns the value of text$ with all characters which do appear in chars$ replaced by the specified template.
String Handling Libraries

445

Details: The PLUGCHAR$ function replaces all characters in text$ which are members of the character set represented by the value of chars$. Each occurrence of a character from chars$ within text$ is replaced by the value of template$.
The PLUGCHAR$ function differs from the REPCHAR$ function in that the value of template$ is treated as a template. This means that each occurrence of the character combination “#1” within the value of template$ will be replaced with the value of the character which will be replaced by the template.
Example: The following program:
LIBRARY “STRLIB.TRC”
DECLARE DEF Control$, PlugChar$

OPEN #1: NAME “InFile”
OPEN #2: NAME “OutFile”, CREATE NEW

LET ctl$ = Control$ DO WHILE MORE #1
LINE INPUT #1: line$
PRINT #2: PlugChar$(line$, ctl$, “/#1”
LOOP

END
places a slash (\) before each control character in the file named INFILE and stores the results in the file named OLDFILE.
Exceptions: None
See also: NPLUGCHAR$, DELCHAR$, KEEPCHAR$, REPCHAR$, NREPCHAR$,
MAPCHAR$

PLUGMIX$ Function
Library: STRLIB.TRC
Syntax: PLUGMIX$ (strex, strex, strex)
Usage: LET a$ = PLUGMIX$ (text$, old$, template$)
Summary: Returns the value of text$ with occurrences of the value of old$, in any mix of upper- and lowercase, replaced by the specified template.
Details: The PLUGMIX$ function replaces all occurrences of the value of old$, in any mix of uppercase and lowercase, within text$. Each occurrence of the value of old$ within text$ is replaced by the value of template$.
The PLUGMIX$ function differs from the REPMIX$ function in that the value of template$ is treated as a template. This means that each occurrence of the character combination “#1” within the value of template$ will be replaced with the value of old$ as it was found in text$.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF PlugMix$
LET text$ = "Now is tHe time"
PRINT PlugMix$(text$, "the", "THE")
END
produces the following output:
Now is THE time
Exceptions: None
See also: PLUGSTR$, PLUGCHAR$, REPMIX$, DELMIX$
446 True BASIC Language System

PLUGSTR$ Function
Library: STRLIB.TRC
Syntax: PLUGSTR$ (strex, strex, strex)
Usage: LET a$ = PLUGSTR$ (text$, old$, template$)
Summary: Returns the value of text$ with occurrences of the value of old$ replaced by the specified template.
Details: The PLUGSTR$ function replaces all occurrences of the value of old$ within text$. Each occurrence of the value of old$ within text$ is replaced by the value of template$.
The PLUGSTR$ function differs from the REPSTR$ function in that the value of template$ is treated as a template. This means that each occurrence of the character combination “#1” within the value of template$ will be replaced with the value of old$.
Example: The following program: LIBRARY "StrLib.trc" DECLARE DEF PlugMix$
PRINT PlugMix$("x/x", "x", "(#1+#1)")
END
produces the following output:
(x+x)/(x+x)
Exceptions: None
See also: PLUGMIX$, PLUGCHAR$, REPSTR$, DELSTR$

PUNCT$ Function
Library: STRLIB.TRC
Syntax: PUNCT$
Usage: LET set$ = PUNCT$
Summary: Returns the set of punctuation characters.
Details: The PUNCT$ function returns a string containing the set of characters representing punctuation, arranged in ascending order according to their ASCII codes. (For a table of the ASCII codes and their corresponding characters, see Appendix A.)
That is, it returns the equivalent of the string constant:
“ !””#$%&’()*+,-./:;<=>?@[\]^_`{|}˜”
where the pair of consecutive quotation marks results in the inclusion of a single quotation mark.
Note that this function returns only those punctuation characters represented in the standard ASCII character set. Depending upon the current operating environment there may be additional punctuation characters available which are not represented within the results of the PUNCT$ function.
Example: None.
Exceptions: None
See also: UPPER$, LOWER$, LETTERS$, DIGITS$, ALPHANUM$, CONTROL$

REPCHAR$ Function
Library: STRLIB.TRC
Syntax: REPCHAR$ (strex, strex, strex)
Usage: LET a$ = REPCHAR$ (text$, oldchars$, new$)
Summary: Returns the value of text$ with all characters in oldchars$ replaced by the value of
new$.
Details: The REPCHAR$ function maps the members of a character set to a single string. It returns the value of text$ after having replaced any occurrences of characters appearing in the
String Handling Libraries

447

value of oldchars$ with the value of new$.
Example: The following program:
LIBRARY “STRLIB.TRC”
DECLARE DEF Punct$, RepChar$

OPEN #1: NAME “InFile” LET chars$ = Punct$
DO WHILE MORE #1
LINE INPUT #1: line$
PRINT RepChar$(line$, chars$, “”) LOOP

GET KEY k
END
lists the contents of a text file named INFILE, replacing all occurrences of punctuation with the phrase “”.
Exceptions: None
See also: MAPCHAR$, NREPCHAR$, DELCHAR$, KEEPCHAR$, PLUGCHAR$,
NPLUGCHAR$, REPSTR$, REPMIX$

REPMIX$ Function
Library: STRLIB.TRC
Syntax: REPMIX$ (strex, strex, strex)
Usage: LET a$ = REPMIX$ (text$, old$, new$)
Summary: Returns the value of text$ with all occurrences of the value of old$, in any mix of upper- and lowercase letters, replaced by the value of new$.
Details: The REPMIX$ function replaces occurrences of one substring with another, ignoring case.
It returns the value of text$ after having replaced any occurrences of the value of old$, in
any mix of upper- and lowercase letters, with the value of new$.
If the value of old$ does not appear within the value of text$, the REPMIX$ function returns the value of text$ untouched.
Example: The following program:
LIBRARY “STRLIB.TRC” DECLARE DEF RepMix$

OPEN #1: NAME “InFile”
OPEN #2: NAME “OutFile”, CREATE NEW SET #2: MARGIN MAXNUM

DO WHILE MORE #1
LINE INPUT #1: line$
PRINT #2: RepMix$(line$, “print”, “PRINT”) LOOP

END
copies the contents of the file named INFILE to the newly created file named OUTFILE, changing all occurrences of the word “print,” regardless of case, into uppercase.
Exceptions: None
See also: REPSTR$, REPCHAR$, DELSTR$, PLUGSTR$
448 True BASIC Language System

REPSTR$ Function
Library: STRLIB.TRC
Syntax: REPSTR$ (strex, strex, strex)
Usage: LET a$ = REPSTR$ (text$, old$, new$)
Summary: Returns the value of text$ with all occurrences of the value of old$ replaced by the value of new$.
Details: The REPSTR$ function replaces occurrences of one substring with another. It returns the value of text$ after having replaced any occurrences of the value of old$ with the value of new$.
If the value of old$ does not appear within the value of text$, the REPSTR$ function returns the value of text$ untouched.
Example: The following program:
LIBRARY “STRLIB.TRC” DECLARE DEF RepStr$

OPEN #1: NAME “InFile”, ORG BYTE
OPEN #2: NAME “OutFile”, CREATE NEW, ORG BYTE

LET cr$ = Chr$(13)
LET crlf$ = cr$ & Chr$(10)

DO WHILE MORE #1
READ #1, BYTES 10000: block$
WRITE #2: RepStr$(line$, cr$, crlf$) LOOP

END
copies the contents of the file named INFILE to the newly created file named OUTFILE, changing all occurrences of a carriage return to a carriage return followed by a line feed.
Exceptions: None
See also: REPMIX$, REPCHAR$, DELSTR$, PLUGSTR$

REVERSE$ Function
Library: STRLIB.TRC
Syntax: REVERSE$ (strex)
Usage: LET a$ = REVERSE$ (string$)
Summary: Returns the value of its argument string$ with all of its characters in reverse order.
Details: The REVERSE$ function accepts a string argument, reverses the order of the characters which it contains, and returns the result.
If the value of its argument is the null string, the REVERSE$ function will return the null string.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Reverse$ DIM text$(3)
MAT READ text$
DATA madam, im, adam
FOR i = 1 to 3
IF text$(i) = Reverse$(text$(i)) then
PRINT text$(i); " is a palindrome" ELSE
String Handling Libraries

449

PRINT text$(i); " is not a palindrome" END IF
NEXT i
END
produces the following output:
madam is a palindrome im is not a palindrome adam is not a palindrome
Exceptions: None

RIGHT$ Function
Library: STRLIB.TRC
Syntax: RIGHT$ (strex, numex)
Usage: LET a$ = RIGHT$ (string$, chars)
Summary: Returns the rightmost chars characters of string$.
Details: The RIGHT$ function returns a specific number of characters from the end of string$.
The number of characters to be returned is given by the value of chars.
If the value of chars is less than or equal to 0, the RIGHT$ function returns the null string. If the value of chars is greater than the number of characters in string$, the RIGHT$ function returns the value of string$.
Note that the RIGHT$ function can be useful when converting programs written in other forms of BASIC. However, you will likely find that the substring expressions discussed in Chapter 17 provide greater speed and flexibility.
Example: The following program: LIBRARY "StrLib.trc" DECLARE DEF Right$
LET a$ = "Now is the time" FOR chars = 5 to 8
PRINT Right$(a$, chars) NEXT chars
END
produces output similar to the following:
time
e time
he time
the time
Exceptions: None
See also: LEFT$, MID$

RJUST$ Function
Library: STRLIB.TRC
Syntax: RJUST$ (strex, numex, strex)
Usage: LET a$ = RJUST$ (text$, width, back$)
Summary: Returns a string of the specified length containing the value of text$ right-justified.
Details: The RJUST$ function takes the value of text$ and adds characters to the beginning of it as necessary to create a string containing width characters with the value of text$ right- justified within it. The characters added will be determined by repeating the sequence of characters specified by the value of back$.
If the length of text$ is greater than the value specified by width, the RJUST$ function returns the value of text$ truncated to width characters. If the value of width is less than or equal to 0, the RJUST$ function returns the null string.
450 True BASIC Language System

The background pattern added to the beginning of the value of text$ will be formed in such a way that all strings formed with the same value of back$ will have identical background patterns, regardless of the value of text$. If the value of back$ is the null string or a space, the background pattern will consist solely of blanks, or spaces.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF RJust$ LET a$ = "...Hello" FOR chars = 10 to 12
PRINT RJust$(a$, chars, "*") NEXT chars
END
produces the following output:
**...Hello
***...Hello
****...Hello
Exceptions: None
See also: LJUST$, CENTER$, JUSTIFY$, HEADER$. FILLARRAY, FILLFROM,
JUSTIFYARRAY, JUSTIFYFROM

RNDSTR$ Function
Library: STRLIB.TRC
Syntax: RNDSTR$ (strex, numex)
Usage: LET a$ = RNDSTR$ (chars$, length)
Summary: Returns a string of the specified length composed of characters randomly chosen from the characters comprising the value of chars$.
Details: The RNDSTR$ function returns a randomly generated string. The length of the string will be determined by the value of length, and the characters in the string will be drawn randomly from the characters comprising the value of chars$.
If a single character appears more than once in the value of chars$, the probability of that character appearing in the resulting string will be increased appropriately.
The RNDSTR$ function is useful for creating names for temporary files. It is also useful for creating strings to test string handling algorithms.
Example: The following program:
LIBRARY “STRLIB.TRC” DECLARE DEF RndStr$

LET first$ = “ABCDEFGHIJKLMNOPQRSTUVWXYZ” LET rest$ = first$ & “0123456789”

DO
LET fname$ = RndStr$(first$,1) & RndStr$(rest$,7)
WHEN ERROR IN
OPEN #1: NAME fname$, CREATE NEW
EXIT DO
USE
! Do nothing
END WHEN
LOOP
PRINT “File created: “; fname$

GET KEY k
END
String Handling Libraries

451

uses the RNDSTR$ function to create a temporary file name and then uses that name to create the file. Note that the name begins with a letter and then contains seven characters which may be letters or digits.
Exceptions: None

ROMAN$ Function
Library: STRLIB.TRC
Syntax: ROMAN$ (numex)
Usage: LET romannum$ = ROMAN$ (number)
Summary: Returns the string representation of its numeric argument in Roman numerals.
Details: The ROMAN$ function returns the string representation of the value of number as Roman numerals. For example, if passed a value of 117, the ROMAN$ function would return the string value:
CXVII
As you can see, the Roman numerals will be represented entirely in uppercase letters. The Roman representation of a negative number will begin with a minus sign.
Since Roman numerals may only represent whole numbers, the ROMAN$ function will generate an error if you pass it a non-integer value.
Example: The following program:
LIBRARY “STRLIB.TRC” DECLARE DEF Roman$

LET year$ = Roman$(1900+Int(Date/1000))
PRINT “Copyright (c) “; year$; “ by True BASIC, Inc.” END
produces the following output:
Copyright (c) MCMXCIV by True BASIC, Inc.”
Exceptions: None
See also: ENGLISHNUM$

SHORTDATE$ Function
Library: STRLIB.TRC
Syntax: SHORTDATE$ (strex)
Usage: LET a$ = SHORTDATE$ (adate$)
Summary: Returns the date represented by the value of adate$ in string form consisting of the day of the month, the month name, and the year in abbreviated format.
Details: The SHORTDATE$ function takes as its argument a date in the format produced by the DATE$ function and returns that date in abbreviated, but legible, form. This abbreviated form consists of the day of the month, the three-character abbreviation of the month name, and the last two digits of the year.
The value of adate$ must represent a date in the same format produced by the DATE$ function. That is, the value of adate$ must be a string in the form “YYYYMMDD”, where YYYY represents the year, MM the month, and DD the day. If adate$ does not represent such a value, then the SHORTDATE$ function generates an error.
To return a date in an expanded format, use the NICEDATE$ function.
452 True BASIC Language System

Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF ShortDate$
PRINT ShortDate$("19971015") END
produces the following output:
15 Oct 97
Exceptions: 1 Bad date given to ShortDate$: 00000000
See also: DATE$, DATE, SHORTDATE$, WEEKDAY$, WEEKDAY, TODAY$, TIME, TIME$,
NICETIME$, NOW$

SUPERVAL Subroutine
Library: STRLIB.TRC
Syntax: CALL SUPERVAL (strarrarg, strex, numvar)
strarrarg:: strarr
strarr bowlegs
Usage: CALL SUPERVAL (table$(), expression$, result)
Summary: Evaluates the expression represented by the contents of expression$ and returns the resulting value in result.
Details: The SUPERVAL subroutine evaluates the numeric expression represented by the value of
expression$ and returns the resulting value in result.
The value of expression$ must represent a numeric expression which is valid under the rules of True BASIC. This expression may contain both numeric constants and variables.
You can use expressions like “a = 2” or “length, width, height = 1” to create variables and set their values.
Like the numeric constants, the variables used in expression$ must follow True BASIC’s rules for the formation of variable names. These variables are not connected with the variables used in your program code; they form their own variable pool which is created and used exclusively by the SUPERVAL subroutine.
The SUPERVAL subroutine uses the table$ array to manage this pool of variables. You don’t need to worry about maintaining the table$ array; just pass any one-dimensional array as table$, and the SUPERVAL subroutine will do the rest. However, since the table$ array is used to store the variable pool, you should be sure to pass the same table$ array to each invocation of the SUPERVAL subroutine which you would like to have access to the variables in that pool.
The value of expression$ may incorporate any of the following operators:
Operators Available to SUPERVAL
+ - * / ^ ( )
In addition, the value of expression$ may incorporate any of the following numeric functions:
Functions Available to SUPERVAL
SIN COS TAN ATN SQR SINH COSH TANH ASIN ACOS SEC CSC COT MAXNUM EPS PI SGN ABS RAD DEG LOG LOG2 LOG10 EXP RND INT ROUND IP FP CEIL
DATE TIME
Note that numeric functions requiring two arguments, including the two-argument form of the ROUND function, are not available for use in the value of expression$.
String Handling Libraries

453

Example: The following program: LIBRARY “STRLIB.TRC” DIM vars$(1)

CALL SuperVal(vars$(), “a = 3^2”, result) CALL SuperVal(vars$(), “b = Sqr(a)”, result) PRINT result

DO
LINE INPUT PROMPT “Expression (0 to quit): “: expr$ IF expr$ = “0” then EXIT DO
CALL SuperVal(vars$(), expr$, result) PRINT result
LOOP

END
produces output similar to the following:
3
Expression (0 to quit): a
9
Expression (0 to quit): b
3
Expression (0 to quit): a + b
12
Expression (0 to quit): c = a/(b*2)
1.5
Expression (0 to quit): a * Pi
28.274334
Expression (0 to quit): 0
Exceptions: 1 SuperVal string isn’t a proper expression.
2 Unknown function or variable in SuperVal.
3 Bad variable name in SuperVal: name
3002 Negative number to non-integral power.
3003 Zero to negative power.
3004 LOG of number <= 0.
3005 SQR of negative number.
4001 VAL string isn’t a proper number.
See also: EVAL, VAL, LVAL, DOLLARVAL

TODAY$ Function
Library: STRLIB.TRC
Syntax: TODAY$
Usage: LET a$ = TODAY$
Summary: Returns the current date in string form consisting of the name of the day of the week, the month name, the day of the month, and the year.
Details: The TODAY$ function returns the current date in string form. The format begins with the name of the weekday, followed by the full name of the month, the day of the month, and the full year.
For instance, the TODAY$ function might return:
Tuesday, June 14, 1994
If the current computer hardware is not able to report the date, then the TODAY$ function generates an error.
The TODAY$ function obtains its results from your operating system, which in turn obtains its results from your computer’s internal clock. If you find that the TODAY$ function is returning erroneous results, you most likely have to reset your computer’s internal clock.
454 True BASIC Language System

Example: None.
Exceptions: 1 Bad date given to NiceDate$: 00000000
1 Bad date given to WeekDay: 00000000
1 Bad date given to WeekDay$: 00000000
See also: DATE$, DATE, NICEDATE$, SHORTDATE$, WEEKDAY$, WEEKDAY, TIME,
TIME$, NICETIME$, NOW$

UNIQ$ Function
Library: STRLIB.TRC
Syntax: UNIQ$ (strex)
Usage: LET a$ = UNIQ$ (text$)
Summary: Returns the set of characters contained within the value of text$.
Details: The UNIQ$ function returns a string containing the set of characters contained in the value of its argument.
That is, the UNIQ$ function returns a string which contains one of each character which appears in the value of its argument. The characters will be organized within the resulting string in ascending order by their ASCII codes. Thus, uppercase letters will be listed before all lowercase letters.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Uniq$
LET s$ = "Now is the time for all good men" PRINT s$
PRINT Uniq$(s$) END
produces the following output:
Now is the time for all good men
Nadefghilmnorstw
Exceptions: None
See also: CHARUNION$, CHARINT$, CHARDIFF$, CHARS$

UPPER$ Function
Library: STRLIB.TRC
Syntax: UPPER$
Usage: LET set$ = UPPER$
Summary: Returns the set of uppercase alphabetic characters.
Details: The UPPER$ function returns a string containing the set of characters representing the letters of the alphabet, in uppercase only, arranged in ascending order according to their ASCII codes. (For a table of the ASCII codes and their corresponding characters, see Appendix A.)
That is, it returns the equivalent of the string constant:
“ABCDEFGHIJKLMNOPQRSTUVWXYZ”
Example: None.
Exceptions: None
See also: LOWER$, LETTERS$, DIGITS$, ALPHANUM$, PUNCT$, CONTROL$

WEEKDAY Function
Library: STRLIB.TRC
Syntax: WEEKDAY (strex)
String Handling Libraries

455

Usage: LET a = WEEKDAY (adate$)
Summary: Returns the number of the weekday on which the specified date falls.
Details: The WEEKDAY function takes as its argument a date in the format produced by the DATE$
function and returns the number of the day of the week on which that date falls.
The WEEKDAY function returns a number between 1 and 7, inclusive, where 1 indicates
Sunday and 7 indicates Saturday.
The value of adate$ must represent a date between the years 1901 and 2099, inclusive, in the same format produced by the DATE$ function. That is, the value of adate$ must be a string in the form “YYYYMMDD”, where YYYY represents the year, MM the month, and DD the day. If adate$ does not represent such a value, then the WEEKDAY function generates an error.
To return the full name of the day of the week on which a particular date falls, use the
WEEKDAY$ function.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Weekday
PRINT Weekday("19971015") END
produces the following output:
4
Exceptions: 1 Bad date given to WeekDay: 00000000
See also: DATE$, DATE, NICEDATE$, SHORTDATE$, TODAY$, WEEKDAY$, TIME, TIME$,
NICETIME$, NOW$

WEEKDAY$ Function
Library: STRLIB.TRC
Syntax: WEEKDAY$ (strex)
Usage: LET a$ = WEEKDAY$ (adate$)
Summary: Returns the full name of the weekday on which the specified date falls.
Details: The WEEKDAY$ function takes as its argument a date in the format produced by the DATE$
function and returns the full name of the day of the week on which that date falls.
The value of adate$ must represent a date between the years 1901 and 2099, inclusive, in the same format produced by the DATE$ function. That is, the value of adate$ must be a string in the form “YYYYMMDD”, where YYYY represents the year, MM the month, and DD the day. If adate$ does not represent such a value, then the WEEKDAY$ function generates an error.
To return the number of the day of the week on which a particular date falls, use the
WEEKDAY function.
Example: The following program:
LIBRARY "StrLib.trc" DECLARE DEF Weekday$
PRINT Weekday$("19971015") END
produces the following output:
Wedneadsy
Exceptions: 1 Bad date given to WeekDay$: 00000000
See also: DATE$, DATE, NICEDATE$, SHORTDATE$, TODAY$, WEEKDAY, TIME, TIME$,
NICETIME$, NOW$
456 True BASIC Language System

Sorting and Searching Libraries

The library file SORTLIB.TRC contains several sorting and searching utilities. Each sorting and searching subroutine comes in two forms, one for numbers and one for strings. The name of the subroutine ends with an “N” for numbers, and in “S” for strings.
The two subroutines SORTN and SORTS perform ordinary in-place sorts. The two subroutines PSORTN and
PSORTS perform indexed (or pointer) sorts.
The two subroutines CSORTN and CSORTS perform sorting according to a relation specified by the programmer. The two subroutines CPSORTN and CPSORTS perform indexed (or pointer) sorts according to a relation defined by the programmer.
The four subroutines CSEARCHN, CSEARCHS, SEARCHN, and SEARCHS search lists (numeric or string) for a match. SEARCHN and SEARCHS use the ordinary relational operator “=”. CSEARCHN and CSEARCHS perform searches according to a relation specified by the programmer.
CSORTN, CPSORTN, and CSEARCHN call a subroutine COMPAREN, which is included in SortLib.tru. It is currently coded to produce the usual ascending sort. If you require a different sorting relation, you can proceed in one of two ways. First, you can make the changes in the subroutine COMPAREN in SortLib.tru, and then recompile SortLib.tru. Second, you can include your own version of COMPAREN following the END statement in your main program; this definition takes precedence over the one in the library file.

CSORTS, CPSORTS, and CSEARCHS performing sorts and searches using special ordering relations specified by calling one of several relation-specifying subrouintes before invoking the sort. These special subroutine calls include:
Sort_Off Sort using ASCII sorting order and entire string Sort_ObserveCase Treat upper- and lowercase as different (default) Sort_IgnoreCase Treat upper- and lowercase as equivalent Sort_NiceNumbers_on See the header of SortLib.tru for definitions Sort_NiceNumbers_off Ditto (default)
Sort_NoKeys Sort using the entire string Sort_OneKey Sort on the substring field specified Sort_TwoKeys Sort on the two substring fields specified

CSEARCHN and CSEARCHS require the list to have been previously sorted using the same relations; i.e., use the same COMPAREN for CSEARCHN, and the same options for CSEARCHS as for CSORTS.The two subroutines REVERSEN and REVERSES simply reverse the order of the elements in the numeric or string array. That is, the first element will become the last, and so on.

CPSORTN Subroutine
Library: SORTLIB.TRC
Syntax: CALL CPSORTN (numarrarg, numarrarg)
numarrarg:: numarr
numarr bowlegs
Usage: CALL CPSORTN (values(), indices())
Summary: Performs a pointer sort on the values stored in values and stores the pointers, or indices, to the elements in indices in the order specified by a customized comparison routine.
Details: The CPSORTN subroutine performs a “pointer sort” on the values stored in the numeric array values. Pointer sorts do not actually rearrange the values in the array which they are sorting, rather they create a second array that contains the first array’s indices arranged in the order of the sorted values. The CPSORTN subroutine returns this array of indices as indices.
For a more detailed discussion of pointer sorts, see the PSORTN subroutine later in this chapter.
Sorting and Searching Libraries

457

The PSORTN subroutine compares elements based upon the standard relational operators in order to create a list of indices that represent the values sorted into ascending order. While this is useful for the vast majority of circumstances, you may occasionally need to specify a different comparison.
The CPSORTN subroutine allows you to specify a particular comparison that will be used to determine the way in which the items will be ordered.
Note that the CPSORTN subroutine sorts the entire values array. Thus, if you have only assigned values to the first 100 elements of a 1000-element array, the resulting indices array will contain the indices of 900 zero-valued elements of values merged into the sorted result.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM name$(6), grade(6), indices(6) MAT READ name$, grade
DATA Kollwitz, Hu, Starr, Ransom, White, Sankar
DATA 75, 93, 95, 68, 84, 88

CALL CPSortN(grade, indices) ! Sort by grades
FOR i = 1 to 6
LET j = indices(i)
PRINT name$(j); grade(j)
NEXT i

END

SUB CompareN (a, b, compflag) IF a > b then
LET compflag = -1
ELSEIF a = b then
LET compflag = 0
ELSE
LET compflag = 1
END IF
END SUB
performs a pointer sort on a set of parallel arrays and uses the results to print both arrays sorted into descending order by grade. The result is the same as that of using PSORTN followed by CALL ReverseN (indicies).
Exceptions: None
See also: CPSORTS, PSORTN, SORTN

CPSORTS Subroutine
Library: SORTLIB.TRC
Syntax: CALL CPSORTS (strarrarg, numarrarg)
strarrarg:: strarr strarr bowlegs
numarrarg:: numarr numarr bowlegs
Usage: CALL CPSORTS (values$(), indices())
Summary: Performs a pointer sort on the values stored in values$ and stores the pointers, or indices, to the elements in indices in the order specified by the programmer.
Details: The CPSORTS subroutine performs a “pointer sort” on the values stored in the string array values$. Pointer sorts do not actually rearrange the values in the array which they are sorting, rather they create a second array which contains the first array’s indices arranged in
458 True BASIC Language System

the order of the sorted values. The CPSORTS subroutine returns this array of indices as
indices.
For a more detailed discussion of pointer sorts, see the PSORTS subroutine later in this chapter.
The PSORTS subroutine compares elements based upon the standard relational operators in order to create a list of indices that represent the values sorted into ascending order. While this is useful for the vast majority of circumstances, you may occasionally need to specify a different comparison.
The CPSORTS subroutine allows you to specify the comparison that will be used to determine the way in which the items will be ordered.
Note that the CPSORTS subroutine sorts the entire values$ array. Thus, if you have only assigned values to the first 100 elements of a 1000-element array, the resulting indices array will contain the indices of 900 null-valued elements of values$ merged into the sorted result.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM name$(6), grade(6), indices(6) MAT READ name$, grade
DATA Kollwitz, Hu, Starr, Ransom, White, Sankar
DATA 75, 93, 95, 68, 84, 88

CALL Sort_IgnoreCase
CALL CPSortS(name$, indices) ! Sort by grades
FOR i = 1 to 6
LET j = indices(i)
PRINT name$(j); grade(j)
NEXT i

END
performs a case-blind pointer sort on a set of parallel arrays and uses the results to print both arrays sorted by name.
Exceptions: None
See also: CPSORTN, PSORTS, SORTS

CSEARCHN Subroutine
Library: SORTLIB.TRC
Syntax: CALL CSEARCHN (numarrarg, numex, numvar, numvar)
numarrarg:: numarr
numarr bowlegs
Usage: CALL CSEARCHN (array(), number, index, found)
Summary: Searches array for the value number utilizing a user-defined comparison and returns found as a non-zero value if it is found. Index reports the subscript value of number within array.
Details: The CSEARCHN subroutine searches through the numeric array array for an element with the value number and returns the subscript of its location in index. This search is performed using a customized comparison subroutine defined by the programmer.
The SEARCHN subroutine compares elements based upon the standard relational operators in order to locate the value number within array. While this is useful for the vast majority of circumstances, you may occasionally need to specify a different comparison.
The CSEARCHN subroutine requires that you have sorted the array using CSORTN, and that you continue to use the same CompareN subroutine.
Sorting and Searching Libraries

459

It is your responsibility to ensure that the behavior of the CompareN subroutine is well- defined and bug-free. If your CompareN subroutine is not well-behaved, the search results may not be valid.
You may define CompareN in the main program file.
Since the CSEARCHN subroutine uses a binary search algorithm, the array must be sorted into ascending order (perhaps through an invocation of the CSORTN subroutine) before being passed to the CSEARCHN subroutine. In general, the CSEARCHN subroutine should utilize the same form of the CompareN subroutine used by the CSORTN subroutine which sorted the array.
If the value of number exists in array, the value of found is set to some non-zero value and the value of index is set equal to the subscript of the element which contains it.
If the value of number cannot be located in array, the value of found is set equal to zero and the value of index is set equal to the subscript of the element in which the value of number would have been stored if it had been present. In other words, the value of index is set to one subscript value past the location of the greatest value which is less than number. If number is greater than every element in array, the value of index will be returned equal to array’s upper bound plus 1.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM array(100) RANDOMIZE
FOR i = 1 to 100
LET array(i) = Int(100*Rnd) + 1
NEXT i
CALL CSortN(array)

DO
INPUT PROMPT “Search value (0 to quit): “: number
IF number <= 0 then EXIT DO
CALL CSearchN(array,number,i,found) IF found <> 0 then
PRINT “Found: “; array(i) ELSE
PRINT “Not found.” END IF
LOOP

END

SUB CompareN (a, b, compflag) IF a > b then
LET compflag = -1
ELSEIF a = b then
LET compflag = 0
ELSE
LET compflag = 1
END IF END SUB
sorts a list of 20 random numbers between 1 and 100 into descending order and allows the user to search the results.
Exceptions: None
See also: CSORTN, SEARCHN, CSEARCHS, CSORTS
460 True BASIC Language System

CSEARCHS Subroutine
Library: SORTLIB.TRC
Syntax: CALL CSEARCHS (strarrarg, strex, numvar, numvar)
strarrarg:: strarr
strarr bowlegs
Usage: CALL CSEARCHS (array$(), string$, index, found)
Summary: Searches array$ for the value string$ utilizing a user-specified relation and returns found as a non-zero value if it is found. Index reports the subscript value of string$ within array$.
Details: The CSEARCHS subroutine searches through the string array array$ for an element with the value string$ and returns the subscript of its location in index. This search is performed using the relations specified by the programmer.
The SEARCHS subroutine compares elements based upon the standard relational operators in order to locate the value string$ within array$. While this is useful for the vast majority of circumstances, you may occasionally need to specify a different comparison.
The CSEARCHS subroutine allows you to specify the comparison that will be used to locate the items.
Since the CSEARCHS subroutine uses a binary search algorithm, the array must be sorted into ascending order (perhaps through an invocation of the CSORTS subroutine) before being passed to the CSEARCHS subroutine. In general, the CSEARCHS subroutine should use the same options used by the CSORTS subroutine which sorted the array.
If the value of string$ exists in array$, the value of found is set to some non-zero value and the value of index is set equal to the subscript of the element which contains it.
If the value of string$ cannot be located in array$, the value of found is set equal to zero and the value of index is set equal to the subscript of the element in which the value of string$ would have been stored if it had been present. In other words, the value of index is set to one subscript value past the location of the greatest value which is less than string$. If string$ is greater than every element in array$, the value of index will be returned equal to array$’s upper bound plus 1.
Example: The following program:
! Sort by last 3 letters, then search for same.
!
DIM array$(10)
MAT READ array$
DATA operculum, partlet, pettifog, grisette, douceur
DATA pollex, sannup, duende, keeshond, maccaboy

CALL Sort_OneKey (4, 6) CALL CSortS(array$)
DO
INPUT PROMPT “Search string (aaa to quit): “: string$ IF string$ = “aaa” then EXIT DO
CALL CSearchS(array$,string$,i,found) IF found<>0 then
PRINT “Found: “; array$(i) ELSE
PRINT “Not found.” END IF
LOOP END

sorts a list of string data by characters 4 through 6 in each element and then allows the user to search the list based on these same characters in an element.
Sorting and Searching Libraries

461

Exceptions: None
See also: CSORTS, SEARCHS, CSEARCHN, CSORTN

CSORTN Subroutine
Library: SORTLIB.TRC
Syntax: CALL CSORTN (numarrarg)
numarrarg:: numarr
numarr bowlegs
Usage: CALL CSORTN (array())
Summary: Sorts the specified numeric array using the customized comparison routine named
CompareN.
Details: The CSORTN subroutine sorts the elements of the specified numeric array into the order determined by a customized comparison subroutine.
The SORTN subroutine compares elements based upon the <= relational operator in order to create a list sorted into ascending order. While this is useful for the vast majority of circumstances, you may occasionally need to specify a different comparison.
The CSORTN subroutine allows you to define a particular comparison that will be used to determine the ordering of the items. You do so by defining an external subroutine named CompareN as in the following example:
The CSORTN subroutine performs an “in-place” sort, which means that it uses very little memory over and above that already occupied by the array itself.
Although it is of little consequence, you may also be interested to know that the sorting algorithm used by the CSORTN subroutine is not stable; if you require a stable sort, use the CPSORTN subroutine instead.
The sorting algorithm used is an optimized quick sort, which makes the CSORTN routine a very efficient, general-purpose sorting routine. Note, however, that since the CSORTN subroutine calls the CompareN subroutine for each comparison, it is not as fast as the SORTN subroutine.
Note that the CSORTN subroutine sorts the entire array. Thus, if you have only assigned values to the first 100 elements of a 1000-element array, the array will have 900 zeroes merged into the sorted result.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM array(100) RANDOMIZE
FOR i = 1 to 100
LET array(i) = Int(100*Rnd) + 1
NEXT i
CALL CSortN(array)
MAT PRINT array

END

SUB CompareN (a, b, compflag) IF a > b then
LET compflag = -1
ELSEIF a = b then
LET compflag = 0
ELSE
LET compflag = 1
END IF
END SUB
462 True BASIC Language System

generates an array of 100 random numbers, sorts it into descending order, and prints the sorted result on the screen.
Exceptions: None
See also: CSORTS, CPSORTN, SORTN, REVERSEN

CSORTS Subroutine
Library: SORTLIB.TRC
Syntax: CALL CSORTS (strarrarg)
strarrarg:: strarr
strarr bowlegs
Usage: CALL CSORTS (array())
Summary: Sorts the specified string array using the customized comparison specified by the programmer.
Details: The CSORTS subroutine sorts the elements of the specified string array into the order determined by a customized comparison.
The SORTS subroutine compares elements based upon the <= relational operator in order to create a list sorted into ascending order. While this is useful for the vast majority of circumstances, you may occasionally need to specify a different comparison.
The CSORTS subroutine allows you to specify the comparison that will be used to determine the ordering of the items.
The CSORTS subroutine performs an “in-place” sort, which means that it uses very little memory over and above that already occupied by the array itself.
Although it is of little consequence, you may also be interested to know that the sorting algorithm used by the CSORTS subroutine is not stable; if you require a stable sort, use the CPSORTS subroutine instead.
The sorting algorithm used is an optimized quick sort, which makes the CSORTS routine a very efficient, general-purpose sorting routine. Note, however, that since the CSORTS subroutine calls the CompareS subroutine for each comparison, it is not as fast as the SORTS subroutine.
Note that the CSORTS subroutine sorts the entire array. Thus, if you have only assigned values to the first 100 elements of a 1000-element array, the array will have 900 null strings merged into the sorted result.
Example: The following program:
LIBRARY “SortLib.TRC” LIBRARY “CompNum.TRC”

DIM array$(100) RANDOMIZE
FOR i = 1 to 100
LET array$(i) = “Item “ & Str$(Int(100*Rnd) + 1)
NEXT i
CALL Sort_NiceNumbers_on
CALL CSortS(array$)
MAT PRINT array$

END
generates an array of 100 strings containing numeric values, sorts it using the version of CompareS contained in the COMPNUM library file, and prints the sorted result on the screen.
Exceptions: None
See also: CSORTN, CPSORTS, SORTS, REVERSES
Sorting and Searching Libraries

463

PSORTN Subroutine
Library: SORTLIB.TRC
Syntax: CALL PSORTN (numarrarg, numarrarg)
numarrarg:: numarr
numarr bowlegs
Usage: CALL PSORTN (values(), indices())
Summary: Performs a pointer sort on the values stored in values and stores the pointers, or indices, to the elements in indices in sorted order.
Details: The PSORTN subroutine performs a “pointer sort” on the values stored in the numeric array values. Pointer sorts do not actually rearrange the values in the array which they are sorting, rather they create a second array which contains the first array’s indices arranged in the order of the sorted values. The PSORTN subroutine returns this array of indices as indices.
For example, if values contained the following items:
10 12 23 14 -8 11 6
the resulting indices array would contain the following items:
5 7 1 6 2 4 3
but the items in values will still be in their original order:
10 12 23 14 -8 11 6
Notice that you can therefore print the elements of values in sorted order with code similar to the following:
FOR i = Lbound(indices) to Ubound(indices) PRINT values(indices(i))
NEXT i
Because they do not change the ordering of information in the values array, pointer sorts are particularly useful when working with “parallel arrays.”
Note that the PSORTN subroutine sorts the entire values array. Thus, if you have only assigned values to the first 100 elements of a 1000-element array, the resulting indices array will contain the indices of 900 zero-valued elements of values merged into the sorted result.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM name$(6), grade(6), indices(6) MAT READ name$, grade
DATA Kollwitz, Hu, Starr, Ransom, White, Sankar
DATA 75, 93, 95, 68, 84, 88

CALL PSortN(grade, indices) ! Sort by grades
FOR i = 1 to 6
LET j = indices(i)
PRINT name$(j); grade(j)
NEXT i

END
performs a pointer sort on a set of parallel arrays and uses the results to print both arrays sorted by grades.
Exceptions: None
See also: PSORTN, CPSORTS, SORTS
464 True BASIC Language System

PSORTS Subroutine
Library: SORTLIB.TRC
Syntax: CALL PSORTS (strarrarg, numarrarg)
strarrarg:: strarr
strarr bowlegs
numarrarg:: numarr
numarr bowlegs
Usage: CALL PSORTS (values$(), indices())
Summary: Performs a pointer sort on the values stored in values$ and stores the pointers, or indices, to the elements in indices in sorted order.
Details: The PSORTS subroutine performs a “pointer sort” on the values stored in the string array values$. Pointer sorts do not actually rearrange the values in the array which they are sorting, rather they create a second array which contains the first array’s indices arranged in the order of the sorted values. The PSORTS subroutine returns this array of indices as indices.
For example, if values$ contained the following items:
bat zoo cat ant dog pig
the resulting indices array would contain the following items:
4 1 3 5 6 2
but the items in values$ will still be in their original order:
bat zoo cat ant dog pig
Notice that you can therefore print the elements of values$ in sorted order with code similar to the following:
FOR i = Lbound(indices) to Ubound(indices) PRINT values$(indices(i))
NEXT i
Because they do not change the ordering of information in the values$ array, pointer sorts are particularly useful when working with “parallel arrays.”
Note that the PSORTS subroutine sorts the entire values$ array. Thus, if you have only assigned values to the first 100 elements of a 1000-element array, the resulting indices array will contain the indices of 900 null-valued elements of values$ merged into the sorted result.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM name$(6), grade(6), indices(6) MAT READ name$, grade
DATA Kollwitz, Hu, Starr, Ransom, White, Sankar
DATA 75, 93, 95, 68, 84, 88

CALL PSortS(grade$, indices) ! Sort by grades
FOR i = 1 to 6
LET j = indices(i)
PRINT name$(j); grade(j)
NEXT i

END
performs a pointer sort on a set of parallel arrays and uses the results to print both arrays sorted by name.
Exceptions: None
See also: PSORTN, CPSORTS, SORTS
Sorting and Searching Libraries

465

REVERSEN Subroutine
Library: SORTLIB.TRC
Syntax: CALL REVERSEN (numarrarg)
numarrarg:: numarr
numarr bowlegs
Usage: CALL REVERSEN (array())
Summary: Reverses the order of the elements within array.
Details: The REVERSEN subroutine reverses the order of the elements stored within the specified numeric array. In other words, it swaps the first and last elements, the second and next-to- last, and so forth.
Although it can be used on any numeric array, the REVERSEN subroutine is most often used to reverse the results of the SORTN or CSORTN subroutines to produce a list sorted in descending order. It can also be used to reverse the pointer list produced by PSORTN, CPSORTN, PSORTS or CPSORTS.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM array(20) FOR i = 1 to 20
LET array(i) = Int(100*Rnd) + 1
NEXT i
CALL SortN(array) CALL ReverseN(array) MAT PRINT array

END
generates an array of random values between 1 and 100 and prints it sorted into descending order.
Exceptions: None
See also: SORTN, CSORTN, REVERSES

REVERSES Subroutine
Library: SORTLIB.TRC
Syntax: CALL REVERSES (strarrarg)
strarrarg:: strarr
strarr bowlegs
Usage: CALL REVERSES (array$())
Summary: Reverses the order of the elements within array$.
Details: The REVERSES subroutine reverses the order of the elements stored within the specified string array. In other words, it swaps the first and last elements, the second and next-to-last, and so forth.
Although it can be used on any string array, the REVERSES subroutine is most often used to reverse the results of the SORTS or CSORTS subroutines to produce a list sorted in descending order.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM array$(20) FOR i = 1 to 20
LET array$(i) = Chr$(Int(26*Rnd) + 65) NEXT i
CALL SortS(array$)
466 True BASIC Language System

CALL ReverseS(array$) MAT PRINT array$

END
generates an array of random uppercase letters and prints it sorted into descending order.
Exceptions: None
See also: SORTS, CSORTS, REVERSEN

SEARCHN Subroutine
Library: SORTLIB.TRC
Syntax: CALL SEARCHN (numarrarg, numex, numvar, numvar)
numarrarg:: numarr
numarr bowlegs
Usage: CALL SEARCHN (array(), number, index, found)
Summary: Searches array for the value number and returns found as a non-zero value if it is found.
Index reports the subscript value of number within array.
Details: The SEARCHN subroutine searches through the numeric array array for an element with the value number and returns the subscript of its location in index.
Since the SEARCHN subroutine uses a binary search algorithm, the array must be sorted into ascending order (perhaps through an invocation of the SORTN subroutine) before being passed to the SEARCHN subroutine.
If the value of number exists in array, the value of found is set to some non-zero value and the value of index is set equal to the subscript of the element which contains it.
If the value of number cannot be located in array, the value of found is set equal to zero and the value of index is set equal to the subscript of the element in which the value of number would have been stored if it had been present. In other words, the value of index is set to one subscript value past the location of the greatest value which is less than number. If number is greater than every element in array, the value of index will be returned equal to array’s upper bound plus 1.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM array(20) FOR i = 1 to 20
LET array(i) = Int(100*Rnd) + 1
NEXT i
CALL SortN(array)

DO
INPUT PROMPT “Enter a number 1 to 100 (0 to quit): “: number
IF number <= 0 then EXIT DO
CALL SearchN(array, number, index, found)
IF found <> 0 then
PRINT “Found at”; index
ELSE
PRINT “Not found”
END IF
LOOP

END
generates an array of random values between 1 and 100 and allows the user to search it.
Exceptions: None
See also: SORTN, SEARCHS, CSEARCHN, CSORTN
Sorting and Searching Libraries

467

SEARCHS Subroutine
Library: SORTLIB.TRC
Syntax: CALL SEARCHS (strarrarg, strex, numvar, numvar)
strarrarg:: strarr
strarr bowlegs
Usage: CALL SEARCHS (array$(), string$, index, found)
Summary: Searches array$ for the value string$ and returns found as a non-zero value if it is found.
Index reports the subscript value of string$ within array.
Details: The SEARCHS subroutine searches through the string array array$ for an element with the value string$ and returns the subscript of its location in index.
Since the SEARCHS subroutine uses a binary search algorithm, the array must be sorted into ascending order (perhaps through an invocation of the SORTS subroutine) before being passed to the SEARCHS subroutine.
If the value of string$ exists in array$, the value of found is set to some non-zero value and the value of index is set equal to the subscript of the element which contains it.
If the value of string$ cannot be located in array$, the value of found is set equal to zero and the value of index is set equal to the subscript of the element in which the value of string$ would have been stored if it had been present. In other words, the value of index is set to one subscript value past the location of the greatest value which is less than string$. If string$ is greater than every element in array$, the value of index will be returned equal to array$’s upper bound plus 1.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM array$(20) FOR i = 1 to 20
LET array$(i) = Chr$(Int(26*Rnd) + 65) NEXT i
CALL SortS(array$)

DO
INPUT PROMPT “Enter an uppercase letter (a to quit): “: string$ IF string$ = “a” then EXIT DO
CALL SearchS(array$, string$, index, found) IF found <> 0 then
PRINT “Found at”; index
ELSE
PRINT “Not found” END IF
LOOP

END
generates an array of random uppercase letters and allows the user to search it.
Exceptions: None
See also: SORTS, SEARCHN, CSEARCHS, CSORTS

SORTN Subroutine
Library: SORTLIB.TRC
Syntax: CALL SORTN (numarrarg)
numarrarg:: numarr
numarr bowlegs
468 True BASIC Language System

Usage: CALL SORTN (array())
Summary: Sorts the specified numeric array using a quick sort.
Details: The SORTN subroutine sorts the elements of the specified numeric array into ascending order. Thus, the array element with the lowest value will be found in the first element of array after the sort, and the array element with the highest value will be found in the last element of array.
The SORTN subroutine performs an “in-place” sort, which means that it uses very little memory over and above that already occupied by the array itself.
The sorting algorithm used by the SORTN subroutine is not stable; if you require a stable sort, use the PSORTN subroutine instead.
The sorting algorithm used is an optimized quick sort, which makes the SORTN routine a very efficient, general-purpose sorting routine.
Note that the SORTN subroutine sorts the entire array. Thus, if you have only assigned values to the first 100 elements of a 1000-element array, the array will have 900 zeroes merged into the sorted result.
To sort an array into descending order, use the REVERSEN subroutine to reverse the results of the SORTN subroutine.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM array(1000) RANDOMIZE
FOR i = 1 to 1000
LET array(i) = Rnd
NEXT i
CALL SortN(array) MAT PRINT array END
generates an array of 1000 random numbers, sorts it, and prints the sorted result on the screen.
Exceptions: None
See also: SORTS, CSORTN, PSORTN, CPSORTN, REVERSEN

SORTS Subroutine
Library: SORTLIB.TRC
Syntax: CALL SORTS (strarrarg)
strarrarg:: strarr
strarr bowlegs
Usage: CALL SORTS (array$())
Summary: Sorts the specified string array using a quick sort.
Details: The SORTS subroutine sorts the elements of the specified string array into ascending order.
Thus, the array element with the lowest value will be found in the first element of array after
the sort, and the array element with the highest value will be found in the last element of
array.
The values of the elements will be compared as strings, which means that they are compared character by character on the basis of each character’s numeric code. Thus, the string value “Zebra” will be considered less than the string value “apple”. This is particularly important when sorting strings which represent numeric constants, for the string value “123” will be considered less than the string value “2”, which can lead to unexpected results.
The SORTS subroutine performs an “in-place” sort, which means that it uses very little memory over and above that already occupied by the array itself.
Sorting and Searching Libraries

469

The sorting algorithm used by the SORTS subroutine is not stable; if you require a stable sort, use the PSORTS subroutine instead.
The sorting algorithm used is an optimized quick sort, which makes the SORTS routine a very efficient, general-purpose sorting routine.
Note that the SORTS subroutine sorts the entire array. Thus, if you have only assigned values to the first 100 elements of a 1000-element array, the array will have 900 null strings merged into the sorted result.
To sort an array into descending order, use the REVERSES subroutine to reverse the results of the SORTS subroutine.
Example: The following program:
LIBRARY “SortLib.TRC”

DIM array$(1)
MAT INPUT array$(?) CALL SortS(array$) MAT PRINT array$
END
obtains an array of string values from the user, sorts it, and prints the sorted result on the screen.
Exceptions: None
See also: SORTN, CSORTS, PSORTS, CPSORTS, REVERSES
470 True BASIC Language System

Graphics Libraries

This section describes subroutines for generating complicated graphical displays of data. The subroutines are contained in three library files:
BGLIB.TRC for drawing pie charts, bar charts, and histograms; including the routines BARCHART, HISTOGRAM, IBEAM, MULTIBAR, MULTIHIST, PIECHART, and several ASK... and SET... routines for finding out about or setting attributes of graphs.
SGLIB.TRC for plotting data and function values; including the routines ADDDATAGRAPH, ADDFGRAPH, ADDLSGRAPH, DATAGRAPH, FGRAPH, MANYDATAGRAPH, MANYFGRAPH, SORTSPOINTS, and many ASK... and SET... routines for finding out about or setting attributes of graphs
SGFUNC.TRC for plotting values of functions that you define: ADDFGRAPH, FGRAPH, MANYFGRAPH
The graphics subroutines are described below, in alphabetical order.

ADDDATAGRAPH Subroutine
Library: SGLIB.TRC
Syntax: CALL ADDDATAGRAPH (numarrarg,, numarrarg, numex, numex, strex)
numarrarg:: numarr
numarr bowlegs
Usage: CALL ADDDATAGRAPH (x(), y(), pstyle, lstyle, colors$)
Summary: Draws another line graph of a set of data points over the current graph.
Details: The ADDDATAGRAPH subroutine draws a line graph of the set of data points whose coordinates are represented by the values of the x and y arrays over the current graph; it simply adds the new graph to the existing graph. Therefore, portions of the added data graph may lie off the graph.
The x array contains the points’ x-coordinates, and the y array contains their y-coordinates. The coordinates in the two arrays are matched according to their subscripts; that is, the elements with subscripts of 1 within both arrays are interpreted as the coordinates of a single point, as are the elements with subscripts of 2, and so on. Thus, the x and y arrays must have the same upper and lower bounds, or an error will be generated.
The value of pstyle determines the point style that will be used to draw the data points which comprise the graph. The allowable values for pstyle are summarized in the following table:
Available Point Styles
Value of pstyle Resulting Point
0 No point (display line only)
1 Dot
2 Plus sign
3 Asterisk
4 Circle
5 X
6 Box
7 Up triangle
8 Down triangle
9 Diamond
10 Solid Box
11 Solid up triangle
12 Solid down triangle
13 Solid diamond
Graphics Libraries

471

The value of lstyle determines the line style that will be used to connect the data points which comprise the graph. The allowable values for lstyle are summarized in the following table:
Available Line Styles
Value of lstyle Resulting Line
0 No line (display points only)
1 Solid line
2 Dashed line
3 Dotted line
4 Dash-dotted line

The graph is actually composed of a series of line segments connecting the data points. You can suppress the display of the data points by passing a value of 0 in pstyle, or you can suppress the display of the connecting line segments by passing a value of 0 in lstyle.
Note that the ADDDATAGRAPH subroutine draws and connects the points in the order in which they are stored in the x and y arrays. If your points are not stored in left to right order, you may wish to use the SORTPOINTS subroutine to order the points before passing them to the ADDDATAGRAPH subroutine.
The value of colors$ determines the color that will be used to draw the new graph. It generally consists of a single color name (in any combination of uppercase or lowercase letters). The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
Note: the color “BACKGROUND” refers to the current background color.
The value of colors$ may also contain a color number instead of a color name, allowing you to access any of the colors supported by the current computer system.
Note that the ADDDATAGRAPH subroutine assumes that a graph currently exists which has been created by an invocation of the FGRAPH or DATAGRAPH subroutine. The ADDDATAGRAPH subroutine simply adds the line representing the specified data points to the existing graph; it does not rescale the graph or redraw the labels or title. If you attempt to invoke the ADDDATAGRAPH subroutine when a suitable graph has not already been displayed, an error will be generated.
Example: The following program, SGData2.TRU, can be found in the directory TBDEMOS:
! SGData2 Chris’ & Dave’s cars’ mileage.

! Both drove the same kind of car. Notice that one car’s mileage
! goes up and down depending on the season (winter is low).
! The other is less affected. Also, notice a few erroneous
! data points!

LIBRARY “..\TBLibs\SGLib.trc”

DIM cmiles(0 to 200), cgallons(200), cmpg(200) DIM dmiles(0 to 200), dgallons(200), dmpg(200)

CALL ReadData (cmiles, cgallons, cmpg) CALL ReadData (dmiles, dgallons, dmpg)

CALL SetText (“Gas Mileage”, “Miles Driven (Thousands)”, “MPG”) CALL DataGraph (cmiles, cmpg, 0, 3, “red green yellow”)
CALL AddDataGraph (dmiles, dmpg, 0, 1, “green”)
472 True BASIC Language System

GET KEY key
SUB ReadData (miles(), gallons(), mpg()) READ miles(0)
LET n = 0
DO
LET n = n + 1
READ miles(n), gallons(n) LOOP until miles(n) = 0
LET n = n - 1

FOR i = 1 to n
LET mpg(i) = (miles(i) - miles(i-1)) / gallons(i) NEXT i
MAT redim mpg(n), miles(1:n) MAT miles = (1/1000) * miles

END SUB

! Chris’s car

DATA 677.3 ! first recorded

DATA 1104.9,9.5, 1567.6,9.3, 1869.7,6.7, 2179.5,6.0
DATA 2564.2,8.0, 2812.3,4.7, 3192.0,7.8, 3540.4,7.4
DATA 4044.4,10.2, 4317.5,5.8, 4747.8,8.7, 4946.2,3.7
DATA 5406.7,9.6, 5870.0,10.1, 6344.2,10.0, 6789.3,9.6
DATA 7208.1,9.1, 7624.8,9.6, 7786.6,3.2, 8244.3,9.4
DATA 8614.1,8.6, 9050.0,9.5, 9584,13.2, 9991.6,9.3
DATA 10389,9.4, 10804.4,9.1, 11216.1,10.3,11623.4,10.1
DATA 11970.4,9.54,12215.5,6.6, 12599.8,9.6, 12921.9,8.84
DATA 13238.1,7.7
DATA 13815.0,14.3,14170.0,8.8, 14531.0,8.3, 14880.9,9.0
DATA 15671,8.95, 16065,8.2, 16453,8.47, 16696,5.4
DATA 17144,8.8, 17568,9.1, 17997,8.65, 18450,9.3
DATA 18934,9.9, 19356,8.7, 19787,8.4, 20162,7.4
DATA 20572,8.25, 21025,8.8, 21345,9.0 ! did I read this right? DATA 21713,5.0, 22043,6.6, 22514,9.2, 22968,9.6
DATA 23450,9.1, 23923,9.5, 24302,7.2, 24814,9.9
DATA 25272,9.1, 25738,9.0, 26128,7.7, 26603,8.9
DATA 26975,7.45, 27145,3.772
DATA 27523,7.36, 27834,6.4, 28266,8.4, 28652,8.3
DATA 29091,8.7, 29510,8.8, 29818,6.4, 30223,8.48
DATA 30626,8.9, 31056,8.24 ! ?
DATA 31410,8.16, 31786,8.6, 32161,8.9 ! ? DATA 32550,9.2, 32941,9.045, 33302,9.3
DATA 0,0

! Dave’s car

DATA 0 ! full tank on delivery
DATA 272,6.35, 599,6.56, 924,7.44, 1281,7.56
DATA 1462,4.47, 1705,4.32, 2099,8.02, 2673,12.03
DATA 3090,8.76, 3537,8.6, 3991,9.28, 4419,8.73
DATA 4779,7.86, 5022,5.4, 5407,7.88, 5731,7.3
DATA 6049,7.04, 6388,7.61, 6836,8.56, 7204,7.87
DATA 7633,9.21, 8000,7.93, 8455,9.52, 8765,7.17
DATA 9188,9.2, 9578,9.21, 10111,13.7, 10551,10.13
DATA 10884,6.16, 11261,8.16, 11550,7.01, 11888,8.43
DATA 12255,6.79, 12690,8.11, 13237,10.8, 13563,6.47
DATA 14036,8.89, 14418,8.91, 14758,7.28, 15183,9.16
DATA 15757,11, 16394,12.75, 16752,7.95, 17108,6.83
Graphics Libraries

473

DATA 17543,9.01, 17943,9.48, 18362,8.88, 18781,9.07
DATA 19179,8.83, 19361,4.63, 19600,6.07, 19898,6.57
DATA 0,0

END
produces a graph comparing the fuel economy of two cars.
Exceptions: 100 Graph’s title is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
110 Data arrays have different bounds in DataGraph
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: DATAGRAPH, MANYDATAGRAPH, FGRAPH

ADDFGRAPH Subroutine
Library: SGFUNC.TRC, SGLIB.TRC
Syntax: CALL ADDFGRAPH (numex, strex)
Usage: CALL ADDFGRAPH (style, color$)
Summary: Draws another line graph of an externally defined function over the current graph.
Details: The ADDFGRAPH subroutine draws a line graph of the function F(x) over the current graph.
The ADDFGRAPH subroutine does not change the scale of the current graph; it simply adds
the new graph to the existing graph. Therefore, parts of the new function may be off the graph.
The function F(x) must be defined external to your main program. That is, it must be defined using a DEF statement or a DEF structure which appears after the END statement. The function you define must be defined over the entire domain specified. If it is not, the ADDFGRAPH subroutine may generate an error or draw the graph incorrectly.
Note that both the ADDFGRAPH subroutine and the FGRAPH subroutine utilize an externally defined function named F. Since a program may not contain two defined functions with the same name, it is your responsibility to ensure that the function F(x) is defined to calculate two different functions if you plan to use the ADDFGRAPH subroutine after calling the FGRAPH subroutine. (See the following example for one method of accomplishing this.)
The value of style determines the line style that will be used to connect the data points which comprise the graph. The allowable values for style are summarized in the following table:
Available Line Styles
Value of style Resulting Line
0 No line (display points only)
1 Solid line
2 Dashed line
3 Dotted line
4 Dash-dotted line

The graph is actually composed of a series of short line segments. You can control the number of line segments used to display a graph with the SETGRAIN subroutine. Using more line segments creates a smoother graph, but takes longer to draw.
The value of color$ determines the color that will be used to draw the new graph. It generally consists of a single color name (in any combination of uppercase or lowercase letters). The valid color names are:
474 True BASIC Language System

RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of color$ may also contain a color number instead of a color name, allowing you to access any color supported by the current computer system.
If the value of color$ contains more than one color, only the last color in the list will be used.
Note that the ADDFGRAPH subroutine assumes that a graph currently exists which has been created by an invocation of the FGRAPH or DATAGRAPH subroutine. The ADDFGRAPH subroutine simply adds the line representing the current function F(x) to the existing graph; it does not rescale the graph or redraw the labels or title. If you attempt to invoke the ADDFGRAPH subroutine when a suitable graph has not already been displayed, an error will be generated.
Example: The following program, SGFunc2.TRU, can be found in the directory TBDEMOS:
! SGFunc2 Graph sine and cosine functions.

LIBRARY “..\TBLibs\SGFunc.trc”, “..\TBLibs\SGLib.trc” PUBLIC flag
CALL SetText (“Sine and Cosine Waves”, “X Values”, “Y Values”) CALL Fgraph (-2*pi, 2*pi, 1, “white white magenta”)
LET flag = 1
CALL AddFgraph (2, “cyan”)

GET KEY key

END

DEF F(x)
DECLARE PUBLIC flag
IF flag = 0 then LET F = Sin(x) else LET F = Cos(x) END DEF
produces a graph of the functions Sin(x) and Cos(x). Notice the use of the public variable
flag to change the behavior of the defined function being graphed.
Exceptions: 118 No canvas window yet.
11008 No such color: color.
See also: SETGRAIN, FGRAPH, MANYFGRAPH

ADDLSGRAPH Subroutine
Library: SGLIB.TRC
Syntax: CALL ADDLSGRAPH (numarrarg, numarrarg, numex, strex)
numarrarg:: numarr
numarr bowlegs
Usage: CALL ADDLSGRAPH (x(), y(), style, color$)
Summary: Computes and draws the least-squares linear fit for the specified points.
Details: The ADDLSGRAPH subroutine calculates and draws the least-squares linear fit of a set of data points.
Graphics Libraries

475

The least-squares linear fit of a set of data points is the straight line which best fits the locations of those data points. That is, the least-squares linear fit of a set of data points is the straight line which minimizes the vertical distance between itself and each of the data points. Such a line may be used to help predict where data points might lie in areas for which data is unavailable.
The set of data points is specified as pairs of coordinates passed as the contents of the x and y arrays. The x array contains the points’ x-coordinates, and the y array contains their y- coordinates. The coordinates in the two arrays are matched according to their subscripts; that is, the elements with subscripts of 1 within both arrays are interpreted as the coordinates of a single point, as are the elements with subscripts of 2, and so on. Thus, the x and y arrays must have the same upper and lower bounds, or an error will be generated.
The value of style determines the line style that will be used to draw the linear fit. The allowable values for style are summarized in the following table:
Available Line Styles
Value of lstyle Resulting Line
0 No line (display points only)
1 Solid line
2 Dashed line
3 Dotted line
4 Dash-dotted line
The value of color$ determines the color that will be used to draw the linear fit. It generally consists of a single color name (in any combination of uppercase or lowercase letters). The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
Note: the color “BACKGROUND” refers to the current background color.
The value of color$ may also contain a color number instead of a color name, allowing you to access any of the colors supported by the current computer system.
Note that the ADDLSGRAPH subroutine assumes that a graph currently exists which has been created by an invocation of one of the various graphing subroutines. The ADDLSGRAPH subroutine simply adds the line representing the specified data points to the existing graph; it does not rescale the graph or redraw the labels or title. If you attempt to invoke the ADDLSGRAPH subroutine when a suitable graph has not already been displayed, an error will be generated.
Example: The following program, SGLSquar.TRU, can be found in the directory TBDEMOS:
! SGLSquar Add a least-squares line to data points.

! Data taken from “The Shortwave Propagation Handbook” (2nd ed)
! by George Jacobs and Theodore J. Cohen. Page 111.

LIBRARY “..\TBLibs\SGLib.trc” DIM x(120), y(120)
MAT READ x, y ! Data later

CALL SetYscale (70, 170)

CALL SetText (“Sunspots vs. Solar Flux”, “Daily Sunspot Number”, “Daily Solar Flux”)
CALL DataGraph (x, y, 6, 0, “red green yellow”) CALL AddLSgraph (x, y, 1, “red”)
476 True BASIC Language System

DATA 16, 17, 5, 4, 18, 19, 21, 24, 22, 25
DATA 28, 30, 32, 33, 31, 35, 21, 25, 26, 30
DATA 28, 31, 37, 37, 39, 38, 34, 25, 40, 41
DATA 43, 44, 42, 45, 47, 48, 50, 50, 52, 56
DATA 57, 59, 46, 42, 41, 45, 48, 52, 44, 45
DATA 49, 55, 58, 59, 53, 55, 55, 59, 57, 65
DATA 64, 61, 63, 64, 66, 65, 67, 69, 71, 76
DATA 75, 81, 80, 80, 81, 82, 87, 90, 84, 84
DATA 64, 65, 78, 78, 73, 80, 77, 74, 70, 70
DATA 61, 63, 73, 74, 73, 77, 79, 78, 79, 63
DATA 81, 94, 97, 93, 93, 86, 79, 98, 93, 116
DATA 116, 115, 116, 104, 127, 125, 130, 131, 123, 139

DATA 81, 84, 84, 88, 89, 87, 90, 89, 87, 87
DATA 85, 82, 91, 90, 87, 85, 96, 95, 95, 99
DATA 93, 94, 95, 98, 96, 103, 105, 111, 100, 94
DATA 99, 97, 97, 94, 97, 98, 100, 95, 97, 102
DATA 104, 104, 104, 105, 107, 109, 108, 108, 112, 115
DATA 115, 115, 116, 117, 120, 119, 127, 125, 133, 103
DATA 106, 110, 108, 111, 108, 107, 108, 107, 108, 105
DATA 110, 102, 107, 108, 108, 106, 110, 114, 118, 119
DATA 116, 115, 119, 118, 116, 114, 115, 114, 121, 122
DATA 126, 127, 125, 128, 131, 126, 127, 131, 130, 133
DATA 131, 129, 131, 123, 135, 138, 140, 144, 146, 148
DATA 158, 157, 156, 157, 154, 159, 159, 163, 162, 166

GET KEY key

END
produces a graph with a least-squares linear fit superimposed over it.
Exceptions: None
See also: SETLS, ASKLS, DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH

ASKANGLE Subroutine
Library: SGLIB.TRC
Syntax: CALL ASKANGLE (strex)
Usage: CALL ASKANGLE (measure$)
Summary: Reports the manner in which subsequent polar graphs drawn by the various data and function plotting subroutines will interpret angle measurements.
Details: The ASKANGLE subroutine is used to report the manner in which subsequent data and function polar plots produced by the DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH, FGRAPH, ADDFGRAPH, and MANYFGRAPH subroutines will interpret angle measurements.
If the value of measure$ is returned equal to “DEG” these subroutines will interpret angular coordinates for polar graphs as degrees. If the value of measure$ is returned equal to “RAD” these subroutines will interpret angular coordinates for polar graphs as radians.
Note that the ASKANGLE subroutine only reports the interpretation of angular coordinates by polar graphs. Use the ASKGRAPHTYPE subroutine to report whether or not subsequent graphs will be drawn as polar graphs.
You can use the SETANGLE subroutine to control the manner in which the next data or function polar plot will interpret angular coordinates.
Example: None
Exceptions: None
See also: SETANGLE, SETGRAPHTYPE, DATAGRAPH, ADDDATAGRAPH,
MANYDATAGRAPH, FGRAPH, ADDFGRAPH, MANYFGRAPH
Graphics Libraries

477

ASKBARTYPE Subroutine
Library: BGLIB.TRC
Syntax: CALL ASKBARTYPE (strvar)
Usage: CALL ASKBARTYPE (type$)
Summary: Reports the arrangement of the bars within each group of subsequently drawn multiple bar chart or histogram.
Details: The ASKBARTYPE subroutine is used to report the arrangement of the bars within each group of a bar chart or histogram that will produced by a subsequent invocation of the MULTIBAR or MULTIHIST subroutine.
Both the MULTIBAR and MULTIHIST subroutines draw multiple bar-based graphs in a single frame. In such a graph, bars associated with a particular unit are grouped together.
The ASKBARTYPE subroutine allows you to report how the bars in each group will be arranged by returning one of the following values in type$:
Types of Bar Groupings
Type$ value Description
“SIDE” Bars arranged side by side with space between them
“STACK” Bars stacked one above the other
“OVER” Bars arranged side by side but overlapped slightly
By default, the bar type is set to a value of “SIDE”. You can use the SETBARTYPE
subroutine to change the current bar type setting.
Example: None
Exceptions: None
See also: SETBARTYPE, MULTIBAR, MULTIHIST

ASKGRAIN Subroutine
Library: SGLIB.TRC
Syntax: CALL ASKGRAIN (numvar)
Usage: CALL ASKGRAIN (grain)
Summary: Reports the grain with which subsequent invocations of the various function plotting subroutines will draw the line graph.
Details: The ASKGRAIN subroutine reports the grain with which subsequent invocations of the FGRAPH, ADDFGRAPH, and MANYFGRAPH subroutines will draw the line representing the function.
These subroutines actually graph the curve of the function which they are plotting as a series of line segments. The grain controls the number of line segments used to form each graphed curve. The higher the value of the grain, the more line segments are used and the smoother the resulting curve appears. However, higher grains also mean more work for the computer, and this means that each curve takes longer to draw.
By default, the FGRAPH, ADDFGRAPH, and MANYFGRAPH subroutines use a grain value of 64, which means that each line graph is composed of 64 individual line segments. This value strikes a generally acceptable balance of smoothness and speed, but this value can be changed using the SETGRAIN subroutine.
Example: None
Exceptions: None
See also: SETGRAIN, FGRAPH, ADDFGRAPH, MANYFGRAPH
478 True BASIC Language System

ASKGRAPHTYPE Subroutine
Library: SGLIB.TRC
Syntax: CALL ASKGRAPHTYPE (strvar)
Usage: CALL ASKGRAPHTYPE (type$)
Summary: Reports the type of graph that will be drawn by subsequent data and function plotting subroutines.
Details: The ASKGRAPHTYPE subroutine is used to report the type of graph that will be produced for subsequent data and function plots produced by the DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH, FGRAPH, ADDFGRAPH, and MANYFGRAPH subroutines.
The type of subsequent graphs is reported as the value of type$. The possible values of
type$ are:

Type$ value Description
“XY” Normal graph
Types of Graphs
“LOGX” Semi-logarithmic graph with x-axis logarithmically scaled “LOGY” Semi-logarithmic graph with y-axis logarithmically scaled “LOGXY” Logarithmic graph with both x- and y-axes logarithmically scaled “POLAR” Polar graph
You can use the SETGRAPHTYPE subroutine to control the type of graph that will be used for the next data or function plot.
Example: None
Exceptions: None
See also: SETGRAPHTYPE, DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH,
FGRAPH, ADDFGRAPH, MANYFGRAPH

ASKGRID Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL ASKGRID (strvar)
Usage: CALL ASKGRID (style$)
Summary: Reports the presence, direction, and type of the grid that will be used in subsequently drawn charts and graphs.
Details: The ASKGRID subroutine is used to report on the presence, direction, and type of the grid that will be drawn within the frame of graphs or charts produced by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH subroutines.
The ASKGRID subroutine reports the presence and direction of the grid lines by returning one of the following values in style$:
Available Grid Directions
Style$ value Description
“” No grid lines
“H” Horizontal grid lines only
“V” Vertical grid lines only
“HV” Both horizontal and vertical grid lines
The returned value of style$ may also include instructions that indicate the type of grid lines that will be drawn. These instructions take the form of special characters appended to the letter (or letters) in the returned value of style$. If no such modifiers are present, grid lines will be drawn as solid lines. The following modifiers are possible:
Graphics Libraries

479

Available Grid Type Modifiers
Modifier Description
- Dashed grid lines
. Dotted grid lines
-. Dash-dotted grid lines

For example, a value of “H-.V” would indicate that dash-dotted grid lines will be used in the horizontal direction and solid grid lines will be used in the vertical direction.
By default, the grid lines are turned off. You can use the SETGRID subroutine to change the current grid setting.
Example: None
Exceptions: None
See also: SETGRID, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM,
FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

ASKHLABEL Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL ASKHLABEL (strvar)
Usage: CALL ASKHLABEL (hlabel$)
Summary: Reports the value of the horizontal label which will be displayed for subsequently drawn charts and graphs.
Details: The ASKHLABEL subroutine is used to report the value of the horizontal label that will be used to label the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, and MANYDATAGRAPH subroutines.
The ASKHLABEL subroutine returns the value of the horizontal label as hlabel$.
You may report the current values for the title, the horizontal label, and the vertical label simultaneously using the ASKTEXT subroutine. Use the ASKVLABEL and ASKTITLE subroutines to report the values of the vertical label and the title, respectively.
You may use the SETHLABEL subroutine to set the current value of the horizontal label.
Example: None
Exceptions: None
See also: SETHLABEL, ASKTEXT, ASKVLABEL, ASKTITLE, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, PIECHART, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

ASKLAYOUT Subroutine
Library: BGLIB.TRC
Syntax: CALL ASKLAYOUT (strvar)
Usage: CALL ASKLAYOUT (direction$)
Summary: Reports the direction of the bars within subsequently drawn bar charts and histograms.
Details: The ASKLAYOUT subroutine is used to report the direction of the bars within each bar chart or histogram produced by a subsequent invocation of the MULTIBAR or MULTIHIST subroutine.
The ASKLAYOUT subroutine allows you to report the direction in which the bars will be drawn by returning one of the following values in direction$:
480 True BASIC Language System

Types of Bar Layouts
Type$ value Description “HORIZONTAL” Bars oriented horizontally “VERTICAL” Bars oriented vertically

By default, the bar direction is set to a value of “VERTICAL”. You can use the
SETLAYOUT subroutine to change the current bar layout setting.
Example: None
Exceptions: None
See also: SETLAYOUT, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST

ASKLS Subroutine
Library: SGLIB.TRC
Syntax: CALL ASKLS (numvar)
Usage: CALL ASKLS (flag)
Summary: Reports whether least-squares linear fits will be drawn automatically for subsequent data plots.
Details: The ASKLS subroutine is used to report whether or not least-squares linear fits will be drawn automatically for subsequent data plots produced by the DATAGRAPH, ADDDATAGRAPH, and MANYDATAGRAPH subroutines.
If the ASKLS subroutine returns flag with a value of 1, subsequent calls to the DATAGRAPH, ADDDATAGRAPH, and MANYDATAGRAPH subroutines will automatically display the graph’s least-squares linear fit. If it returns flag with a value of 0, they won’t.
You can use the SETLS subroutine to control whether least-squares linear fitting is currently active or inactive.
Example: None
Exceptions: None
See also: SETLS, ADDLSGRAPH, DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH

ASKTEXT Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL ASKTEXT (strvar, strvar, strvar)
Usage: CALL ASKTEXT (title$, hlabel$, vlabel$)
Summary: Reports the values of the title, horizontal label, and vertical label that will be displayed for subsequently drawn charts and graphs.
Details: The ASKTEXT subroutine is used to report the values of the title, horizontal label, and vertical label that will be used to label the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, and MANYDATAGRAPH subroutines. (These values also apply to the PIECHART subroutine, but only the value of the title is used.)
The ASKTEXT subroutine returns the value of the title as title$, the value of the horizontal label as hlabel$, and the value of the vertical label as vlabel$.
You may report the value of the title, the horizontal label, or the vertical label individually using the ASKTITLE, ASKHLABEL, or ASKVLABEL subroutines, respectively.
You may use the SETTEXT subroutine to set the current values of the title, the horizontal label, and the vertical label.
Example: None
Exceptions: None
Graphics Libraries

481

See also: SETTEXT, ASKTITLE, ASKHLABEL, ASKVLABEL, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, PIECHART, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

ASKTITLE Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL ASKTITLE (strvar)
Usage: CALL ASKTITLE (title$)
Summary: Reports the value of the title which will be displayed for subsequently drawn charts and graphs.
Details: The ASKTITLE subroutine is used to report the value of the title that will be used to label the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH, and PIECHART subroutines.
The ASKTITLE subroutine returns the value of the title as title$.
You may report the current values for the title, the horizontal label, and the vertical label simultaneously using the ASKTEXT subroutine. Use the ASKHLABEL and ASKVLABEL subroutines to report the values of the horizontal label and the vertical label, respectively.
You may use the SETTITLE subroutine to set the current value of the title.
Example: None
Exceptions: None
See also: SETTITLE, ASKTEXT, ASKHLABEL, ASKVLABEL, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, PIECHART, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

ASKVLABEL Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL ASKVLABEL (strvar)
Usage: CALL ASKVLABEL (vlabel$)
Summary: Reports the value of the vertical label which will be displayed for subsequently drawn charts and graphs.
Details: The ASKVLABEL subroutine is used to report the value of the vertical label that will be used to label the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, and MANYDATAGRAPH subroutines.
The ASKVLABEL subroutine returns the value of the vertical label as vlabel$.
You may report the current values for the title, the horizontal label, and the vertical label simultaneously using the ASKTEXT subroutine. Use the ASKHLABEL and ASKTITLE subroutines to report the values of the horizontal label and the title, respectively.
You may use the SETVLABEL subroutine to set the current value of the vertical label.
Example: None
Exceptions: None
See also: SETVLABEL, ASKTEXT, ASKHLABEL, ASKTITLE, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, PIECHART, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH
482 True BASIC Language System

BALANCEBARS Subroutine
Library: BGLIB.TRC
Syntax: CALL BALANCEBARS (numarrarg, numarrarg, strarrarg, strarrarg, strex)
strarrarg:: strarr
strarr bowlegs
numarrarg:: numarr
numarr bowlegs
Usage: CALL BARCHART (d1(,), d2(,), units$(), legends$(), colors$)
Summary: Draws a balanced bar chart, setting off d1(,) values on one side of the axis versus d2(,) values on the other.
Details: The BALANCEBARS subroutine draws a balanced bar chart in the current logical window, setting off d1(,) values on one side of the axis versus d2(,) values on the other. This is not a particularly common kind of bar chart, but is useful for comparing income versus expenses, etc.
Simply put, it draws a multi-bar chart of d1(,) on the top or right side of the axis, and the same style chart of d2(,) on the bottom or left side of the axis. Neither array may contain any negative values.
The data arrays d1 and d2 are as in the MULTIBAR subroutine, and the units$ and legends$
arrays label both sets of data.
The units$ array must contain the same number of items as the data array. Each element of the units$ array will be used as a label for the bar associated with the corresponding element of the data array.
The value of colors$ determines the color scheme that will be used to draw the graph. It generally consists of at least three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels. And the third color will be used for the graph’s data.
If colors$ contains four colors, the third color will be used for drawing bars representing positive values, and the fourth color will be used for drawing bars representing negative values. If colors$ contains more than four colors, the extra colors will not be used. If colors$ contains fewer than four colors, the last color specified will be used to fill out the remaining colors. If the value of colors$ is the null string, then the current foreground color is used for the entire graph.
By default, the BALANCEBARS subroutine draws the graph with the bars oriented vertically. The y-axis is automatically scaled to fit the data, and the bars are evenly spaced along the x-axis. The labels will appear beneath each bar.
You can change the graph’s orientation so that the bars are drawn horizontally by first invoking the SETLAYOUT subroutine with the argument “HORIZONTAL”. In this situation, the x-axis will be automatically scaled to fit the data, and the bars will be evenly spaced along the y-axis. The labels will appear to the left of each bar.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Graphics Libraries

483

Example: The following program, BGBar3.TRU, can be found in the directory TBDEMOS:
! BGBar3 Show a simple balanced bar chart of products,
! with income/expense for last year and this year.

LIBRARY “..\TBLibs\BGLib.trc”
DIM income(4,2), expense(4,2), units$(4), legend$(2) MAT READ income, expense, units$, legend$
DATA 43,34, 54,63, 33,12, 62,92 ! Incomes
DATA 39,24, 49,52, 17,13, 43,57 ! Expenses
DATA Faucets, Swings, Hoses, Flamingos ! Units
DATA Last Year, This Year ! Legend

CALL SetBarType (“over”)
CALL SetText (“Income/Expense: Last 2 Years”, “”, “Thousands”) LET colors$ = “yellow yellow red green”
CALL BalanceBars (income, expense, units$, legend$, colors$)

GET KEY key

END
produces a bar chart representing quarterly profits.
Exceptions: 100 Graph’s title is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
111 Data and unit arrays don’t match for BarChart.
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also SETBARTYPE, SETTEXT

BARCHART Subroutine
Library: BGLIB.TRC
Syntax: CALL BARCHART (numarrarg, strarrarg, strex)
strarrarg:: strarr
strarr bowlegs
numarrarg:: numarr
numarr bowlegs
Usage: CALL BARCHART (data(), units$(), colors$)
Summary: Draws a simple bar chart of the specified data values, labeled with the specified units and drawn in the specified color scheme.
Details: The BARCHART subroutine draws a bar chart in the current logical window.
The bar chart will contain one bar for each element of the data array, and the height of each bar will be determined by the value of its corresponding element in the data array.
The units$ array must contain the same number of items as the data array. Each element of the units$ array will be used as a label for the bar associated with the corresponding element of the data array.
The value of colors$ determines the color scheme that will be used to draw the graph. It
484 True BASIC Language System

generally consists of at least three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels. And the third color will be used for the graph’s data.
If colors$ contains four colors, the third color will be used for drawing bars representing positive values, and the fourth color will be used for drawing bars representing negative values. If colors$ contains more than four colors, the extra colors will not be used. If colors$ contains fewer than four colors, the last color specified will be used to fill out the remaining colors. If the value of colors$ is the null string, then the current foreground color is used for the entire graph.
By default, the BARCHART subroutine draws the graph with the bars oriented vertically. The y-axis is automatically scaled to fit the data, and the bars are evenly spaced along the x- axis. The labels will appear beneath each bar.
You can change the graph’s orientation so that the bars are drawn horizontally by first invoking the SETLAYOUT subroutine with the argument “HORIZONTAL”. In this situation, the x-axis will be automatically scaled to fit the data, and the bars will be evenly spaced along the y-axis. The labels will appear to the left of each bar.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, BGBar1.TRU, can be found in the directory TBDEMOS:
! BGBar1 Draw a simple bar chart. LIBRARY “..\TBLibs\BGLib.trc”
DIM units$(4), data(4)

MAT READ units$, data
DATA Q-1, Q-2, Q-3, Q-4
DATA 498, 322, 395, 430

CALL SetText (“Quarterly Profits”, “Quarter”, “Thousands”) CALL BarChart (data, units$, “white cyan magenta”)

GET KEY key

END
produces a bar chart representing quarterly profits.
Exceptions: 100 Graph’s title is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
111 Data and unit arrays don’t match for BarChart.
117 Can’t handle this graph range: low to high.
Graphics Libraries

485

11008 No such color: color.
See also: SETTEXT, SETLAYOUT, MULTIBAR, HISTOGRAM

DATAGRAPH Subroutine
Library: SGLIB.TRC
Syntax: CALL DATAGRAPH (numarrarg,, numarrarg, numex, numex, strex)
numarrarg:: numarr
numarr bowlegs
Usage: CALL DATAGRAPH (x(), y(), pstyle, lstyle, colors$)
Summary: Draws a simple line graph of a set of data points.
Details: The DATAGRAPH subroutine draws a line graph of the set of data points whose coordinates are represented by the values of the x and y arrays.
The x array contains the points’ x-coordinates, and the y array contains their y-coordinates. The coordinates in the two arrays are matched according to their subscripts; that is, the elements with subscripts of 1 within both arrays are interpreted as the coordinates of a single point, as are the elements with subscripts of 2, and so on. Thus, the x and y arrays must have the same upper and lower bounds, or an error will be generated.
Both the x- and y-axes will be scaled automatically by the DATAGRAPH subroutine.
The value of pstyle determines the point style that will be used to draw the data points which comprise the graph. The allowable values for pstyle are summarized in the following table:
Available Point Styles
Value of pstyle Resulting Point
0 No point (display line only)
1 Dot
2 Plus sign
3 Asterisk
4 Circle
5 X
6 Box
7 Up triangle
8 Down triangle
9 Diamond
10 Solid Box
11 Solid up triangle
12 Solid down triangle
13 Solid diamond

The value of lstyle determines the line style that will be used to connect the data points which comprise the graph. The allowable values for lstyle are summarized in the following table:
Available Line Styles
Value of lstyle Resulting Line
0 No line (display points only)
1 Solid line
2 Dashed line
3 Dotted line
4 Dash-dotted line
The graph is actually composed of a series of line segments connecting the data points. You can suppress the display of the data points by passing a value of 0 in pstyle, or you can suppress
486 True BASIC Language System

the display of the connecting line segments by passing a value of 0 in lstyle.
Note that the DATAGRAPH subroutine draws and connects the points in the order in which they are stored in the x and y arrays. If your points are not stored in left to right order, you may wish to use the SORTPOINTS subroutine to order the points before passing them to the DATAGRAPH subroutine.
The value of colors$ determines the color scheme that will be used to draw the graph. It generally consists of three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels. And the third color will be used for the graph’s data.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, SGData1.TRU, can be found in the directory TBDEMOS:
! SGData1 Average fuel economy for all cars in USA. Source: EPA. LIBRARY “..\TBLibs\SGLib.trc”
DIM year(36), mpg(36) MAT READ year, mpg
DATA 1940, 1945, 1950, 1951, 1952, 1953, 1954, 1955
DATA 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965
DATA 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975
DATA 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983
DATA 15.29,15.03,14.95,14.99,14.67,14.70,14.58,14.53
DATA 14.36,14.40,14.30,14.30,14.28,14.38,14.37,14.26,14.25,14.07
DATA 14.00,13.93,13.79,13.63,13.57,13.57,13.49,13.10,13.43,13.53
DATA 13.72,13.94,14.06,14.29,15.15,15.54,16.25,16.70

CALL SetText (“Fuel Economy - All Cars”, “”, “MPG”) CALL DataGraph (year, mpg, 9, 1, “red green yellow”)

GET KEY key

END

produces a graph of the average fuel economy of all new cars produced in each year from
1940 through 1983.
Exceptions: 100 Graph’s title is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
110 Data arrays have different bounds in DataGraph
Graphics Libraries

487

117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: SETTEXT, ADDDATAGRAPH, MANYDATAGRAPH, FGRAPH

FGRAPH Subroutine
Library: SGFUNC.TRC, SGLIB.TRC
Syntax: CALL FGRAPH (numex, numex, numex, strex)
Usage: CALL FGRAPH (startx, endx, style, colors$)
Summary: Draws a simple line graph of an externally defined function.
Details: The FGRAPH subroutine draws a line graph of the function F(x) over the domain startx
to endx.
The function F(x) must be defined external to your main program. That is, it must be defined using a DEF statement or a DEF structure which appears after the END statement. The function you define must be defined over the entire domain specified. If it is not, the FGRAPH subroutine may generate an error or draw the graph incorrectly.
The y-axis will be scaled automatically by the FGRAPH subroutine.
The value of style determines the line style that will be used to connect the data points which comprise the graph. The allowable values for style are summarized in the following table:
Available Line Styles
Value of style Resulting Line
0 No line (display points only)
1 Solid line
2 Dashed line
3 Dotted line
4 Dash-dotted line

The graph is actually composed of a series of short line segments. You can control the number of line segments used to display a graph with the SETGRAIN subroutine. Using more line segments creates a smoother graph, but takes longer to draw.
The value of colors$ determines the color scheme that will be used to draw the graph. It generally consists of three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels. And the third color will be used for the graph’s data.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, SGFunc1.TRU, can be found in the directory TBDEMOS:
! SGFunc1 Graph the function “Sin(x*x)”.
LIBRARY “..\TBLibs\SGFunc.trc”, “..\TBLibs\SGLib.trc” CALL SetText (“Sin(x*x)”, “X Values”, “Y Values”)
CALL Fgraph (-pi, pi, 2, “white white magenta”)
488 True BASIC Language System

GET KEY key

END

DEF F(x) = Sin(x*x)
produces a graph of the function Sin(x2).
Exceptions: 100 Graph’s title is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: SETTEXT, SETGRAIN, ADDFGRAPH, MANYFGRAPH

HISTOGRAM Subroutine
Library: BGLIB.TRC
Syntax: CALL HISTOGRAM (numarrarg, strex)
numarrarg:: numarr
numarr bowlegs
Usage: CALL HISTOGRAM (data(), colors$)
Summary: Draws a simple histogram of the specified data values in the specified color scheme.
Details: The HISTOGRAM subroutine draws a simple histogram in the current logical window.
The histogram automatically “groups” similar values from the data array and draws one bar per group. The height of each bar reflects the number of members in the associated group.
For instance, if you use the HISTOGRAM subroutine to chart students’ grades, it might group all those students with grades in the range 80 through 84 and draw a single bar to represent this group of students. The bars will be labeled “75>”, “80>”, “85>”, and so forth. This means that the first bar represents the group of students whose grades are greater than or equal to 75 but less than 80. The second bar represents the group with grades greater than or equal to 80 but less than 85, and so forth.
The value of colors$ determines the color scheme that will be used to draw the graph. It generally consists of at least three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels. And the third color will be used for the graph’s data.
If colors$ contains more than three colors, the extra colors will not be used. If colors$ contains fewer than three colors, the last color specified will be used to fill out the remaining colors. If the value of colors$ is the null string, then the current foreground color is used for the entire graph.
Graphics Libraries

489

By default, the HISTOGRAM subroutine draws the graph with the bars oriented vertically. The y-axis is automatically scaled to fit the data, and the bars are evenly spaced along the x- axis. The labels will appear beneath each bar.
You can change the graph’s orientation so that the bars are drawn horizontally by first invoking the SETLAYOUT subroutine with the argument “HORIZONTAL”. In this situation, the x-axis will be automatically scaled to fit the data, and the bars will be evenly spaced along the y-axis. The labels will appear to the left of each bar.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, BGHisto1.TRU, can be found in the directory TBDEMOS:
! BGHisto1 Draw a simple histogram. LIBRARY “..\TBLibs\BGLib.trc”
DIM data(30)

MAT READ data
DATA 65, 70, 93, 85, 83, 68, 77, 92, 83, 85
DATA 89, 72, 75, 81, 80, 84, 73, 79, 78, 84
DATA 80, 79, 72, 91, 85, 82, 79, 76, 74, 79

CALL SetText (“Final Grades”, “”, “# of Students”) CALL Histogram (data, “white cyan magenta”)

GET KEY key

END
produces a histogram of student grades.
Exceptions: 100 Graph’s title is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
111 Data and unit arrays don’t match for Histogram.
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: SETTEXT, SETLAYOUT, BARCHART, MULTIHIST

IBEAM Subroutine
Library: BGLIB.TRC
Syntax: CALL IBEAM (numarrarg, numarrarg, strarrarg, strex)
strarrarg:: strarr
strarr bowlegs
numarrarg:: numarr
numarr bowlegs
Usage: CALL IBEAM (high(), low(), units$(), colors$)
Summary: Draws an “I-beam” chart of the specified data values, labeled with the specified units and drawn in the specified color scheme.
490 True BASIC Language System

Details: The IBEAM subroutine draws an “I-beam” chart in the current logical window.
The I-beam chart displays ranges of values and will contain one I-beam for each element of the high array. The height and position of each I-beam will be determined by the difference between corresponding elements of the high and low arrays. For this reason, the high and low arrays must contain the same number of elements.
The units$ array must contain the same number of items as the high and low arrays. Each element of the units$ array will be used as a label for the I-beam associated with the corresponding elements of the high and low arrays.
The value of colors$ determines the color scheme that will be used to draw the graph. It generally consists of at least three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels. And the third color will be used for the graph’s data.
If colors$ contains more than three colors, the extra colors will not be used. If colors$ contains fewer than three colors, the last color specified will be used to fill out the remaining colors. If the value of colors$ is the null string, then the current foreground color is used for the entire graph.
By default, the IBEAM subroutine draws the graph with the I-beams oriented vertically. The y-axis is automatically scaled to fit the data, and the I-beams are evenly spaced along the x- axis. The labels will appear beneath each I-beam.
You can change the graph’s orientation so that the I-beams are drawn horizontally by first invoking the SETLAYOUT subroutine with the argument “HORIZONTAL”. In this situation, the x-axis will be automatically scaled to fit the data, and the I-beams will be evenly spaced along the y-axis. The labels will appear to the left of each I-beam.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, BGIBeam.TRU, can be found in the directory TBDEMOS:
! BGIBeam Show I-beam chart of stock values. LIBRARY “..\TBLibs\BGLib.trc”
DIM low(5), high(5), units$(5)

MAT READ low, high, units$
DATA 33.1, 33.2, 34.1, 34.1, 33.1
DATA 34.5, 33.9, 36.2, 34.7, 33.9
DATA Mon, Tues, Wed, Thurs, Fri

CALL SetText (“Stock Values”, “Day”, “Price”)
CALL Ibeam (low, high, units$, “magenta white white”)

GET KEY key

END
produces an I-beam chart representing the daily ranges of a stock’s value over a one week period.
Exceptions: 100 Graph’s title is too wide.
Graphics Libraries

491

102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
111 Data and unit arrays don’t match for IBeam.
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: SETTEXT, SETLAYOUT

MANYDATAGRAPH Subroutine
Library: SGLIB.TRC
Syntax: CALL MANYDATAGRAPH (numarrarg,, numarrarg, numex, strarrarg, strex)
strarrarg:: strarr
strarr bowlegs
numarrarg:: numarr
numarr bowlegs
Usage: CALL MANYDATAGRAPH (x(,), y(,), connect, legends$(), colors$)
Summary: Draws multiple line graphs of a set of data points.
Details: The MANYDATAGRAPH subroutine draws several line graphs within a single frame. Each graph is based upon a set of data points whose coordinates are represented by the values of corresponding rows of the x and y arrays. For example, the statement:
DIM x(3,15), y(3,15)
would create the x and y matrices for a graph with three lines, each composed of fifteen data points.
Each row of the x matrix contains the x-coordinates for the points of a single line graph, and the corresponding row of the y matrix contains their y-coordinates. The coordinates in the separate rows of the two matrices are matched according to their second subscripts, or column numbers; that is, the elements with second subscripts of 1 within corresponding rows of both matrices are interpreted as the coordinates of a single point, as are the elements with second subscripts of 2, and so on. Thus, the x and y matrices must have the same upper and lower bounds in both dimensions, or an error will be generated.
Both the x- and y-axes will be scaled automatically by the MANYDATAGRAPH subroutine. Each graph will use a different point style. These point styles will be drawn in order from the
available point styles (with point styles 0 and 1 excepted). When the possible point styles are
exhausted, they will be reused from the beginning of the list. For an ordered list of the
available point styles, see the discussion of the DATAGRAPH subroutine.
If the value of connect is not equal to 0, the data points of each line graph will be connected by a line segment.
Note that the MANYDATAGRAPH subroutine draws and connects the points in the order in which they are stored in the x and y matrices. If your points are not stored in left to right order, you may wish to use the SORTPOINTS2 subroutine to order the points before passing them to the MANYDATAGRAPH subroutine.
The MANYDATAGRAPH subroutine creates a legend just below the graph’s title to assist the user in identifying the various lines. Each label for the legend will be taken from the corresponding element of the legends$ array. Thus, the number of rows in the x and y arrays must be equal to the number of elements in the legends$ array.
492 True BASIC Language System

If you would like to omit the legend entirely, then pass a legends$ array which contains no elements.
The value of colors$ determines the color scheme that will be used to draw the graphs. It generally consists of at least three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels. And the remaining colors will be used for the graphs’ data.
If the number of graphs exceeds the number of colors provided for the graphs’ data, the MANYDATAGRAPH subroutine uses line styles to help distinguish the lines of the graphs. First, it draws solid lines in the colors specified. Then it switches to dashed, dotted, and finally dash-dotted lines. Thus, if you graph five functions with the MANYFGRAPH subroutine using the color scheme “red yellow green blue” you will get (in order): a solid green line, a solid blue line, a dashed green line, a dashed blue line, and a dotted green line.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, SGData3.TRU, can be found in the directory TBDEMOS:
! SGData3 Display multiple sets of data points. LIBRARY “..\TBLibs\SGLib.trc”
DIM x(5,10), y(5,10), legends$(5)

MAT READ legends$ DATA A, B, C, D, E

FOR i = 1 to 5
FOR j = 1 to 10
LET x(i,j) = j
LET y(i,j) = (i*i*j) ^ 2
NEXT j
NEXT i

CALL SetText (“Multiple Sets of Data”, “Signal”, “Reflection”) CALL SetGraphType (“logy”)
LET colors$ = “white white magenta cyan”
CALL ManyDataGraph (x, y, 1, legends$, colors$)

GET KEY key

END
produces a graph several related data sets.
Exceptions: 100 Graph’s title is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
Graphics Libraries

493

109 Horizontal marks aren’t wide enough—use SetHMarkLen.
110 Data arrays have different bounds in DataGraph
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: SETTEXT, ADDDATAGRAPH, MANYDATAGRAPH, FGRAPH

MANYFGRAPH Subroutine
Library: SGFUNC.TRC, SGLIB.TRC
Syntax: CALL MANYFGRAPH (numex, numex, numex, strarr, strex)
Usage: CALL MANYFGRAPH (startx, endx, n, legends$(), colors$)
Summary: Draws multiple line graphs based upon an externally defined function.
Details: The MANYFGRAPH subroutine draws several line graphs within a single frame. All of the functions drawn are based upon the definition of the function F(x) over the domain startx to endx. The number of graphs which are to be drawn is indicated by the value of n.
The function F(x) must be defined external to your main program. That is, it must be defined using a DEF statement or a DEF structure which appears after the END statement. The functions you define must be defined over the entire domain specified. If they are not, the MANYFGRAPH subroutine may generate an error or draw one or more of the graphs incorrectly.
The MANYFGRAPH subroutine uses the public variable fnum to inform your defined function F(x) which value to compute. The MANYFGRAPH subroutine sets the value of fnum to 1 when plotting the first function, 2 when plotting the second function, and so on until the number of functions specified by n have been plotted. Your defined function F(x) should contain a PUBLIC statement listing fnum so that the MANYFGRAPH subroutine can communicate with it properly. (See the following example for an illustration.)
The y-axis will be scaled automatically by the MANYFGRAPH subroutine.
The MANYFGRAPH subroutine creates a legend just below the graph’s title to assist the user in identifying the various lines. Each label for the legend will be taken from the corresponding element of the legends$ array. Thus, the value of n must be equal to the number of elements in the legends$ array.
If you would like to omit the legend entirely, then pass a legends$ array which contains no elements.
The value of colors$ determines the color scheme that will be used to draw the graphs. It generally consists of at least three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels. And the remaining colors will be used for the graphs’ data.
If the number of graphs (represented by the value of n) exceeds the number of colors provided for the graphs’ data, the MANYFGRAPH subroutine uses line styles to help distinguish the lines of the graphs. First, it draws solid lines in the colors specified. Then it switches to dashed, dotted, and finally dash-dotted lines. Thus, if you graph five functions with the MANYFGRAPH subroutine using the color scheme “red yellow green blue” you will get (in order): a solid green line, a solid blue line, a dashed green line, a dashed blue line, and a dotted green line.
494 True BASIC Language System

Each graph is actually composed of a series of short line segments. You can control the number of line segments used to display the graphs with the SETGRAIN subroutine. Using more line segments creates smoother graphs, but they take longer to draw.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, SGFunc3.TRU, can be found in the directory TBDEMOS:
! SGFunc3 Graph many functions.

LIBRARY “..\TBLibs\SGFunc.trc”, “..\TBLibs\SGLib.trc” DIM legend$(3)
MAT READ legend$ DATA #1, #2, #3

CALL SetText (“Various Waves”, “X Values”, “Y Values”) LET colors$ = “white white cyan magenta white”
CALL ManyFgraph (-pi, 2*pi, 3, legend$, colors$)

GET KEY key

END

DEF F(x)
PUBLIC fnum SELECT CASE fnum CASE 1
LET F = Sin(x) CASE 2
LET F = 1.5 * Cos(x*2) CASE 3
LET F = .5 * Cos(x+pi/2) END SELECT
END DEF
produces a single graph of three different functions. Notice the use of the public variable
fnum to define three distinct behaviors for the single function F(x).
Exceptions: 100 Graph’s title is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
112 Data and legend arrays don’t match for ManyFGraph.
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: SETTEXT, SETGRAIN, FGRAPH, ADDFGRAPH
Graphics Libraries

495

MULTIBAR Subroutine
Library: BGLIB.TRC
Syntax: CALL MULTIBAR (numarrarg, strarrarg, strarrarg, strex)
strarrarg:: strarr
strarr bowlegs
numarrarg:: numarr
numarr bowlegs
Usage: CALL MULTIBAR (data(), units$(), legends$(), colors$)
Summary: Draws a multi-bar chart of the specified data values, labeled with the specified units and legend and drawn in the specified color scheme.
Details: The MULTIBAR subroutine draws a multi-bar chart in the current logical window. In a multi-bar chart, each unit is represented by a cluster of bars. To produce simple bar charts with only one bar per unit, use the BARCHART subroutine.
The multi-bar chart will contain one cluster of bars for each row of the data array, and each cluster will contain one bar for each column of the data array. The height of each bar will be determined by the value of the appropriate element in the data array.
For example, if the data array contains five rows and three columns, the multi-bar chart will consist of five clusters, and each cluster will contain three bars.
The units$ array must contain the same number of items as the first dimension of the data array. Each element of the units$ array will be used as a label for the cluster of bars associated with the corresponding row of the data array.
The legends$ array generally must contain the same number of items as the second dimension of the data array. The legends$ array will be used to add a legend to the graph (positioned between the title and the graph itself) which will allow the user to identify the individual bars within the clusters. Each element of the legends$ array provides the label for the corresponding column of the data array. To suppress the appearance of such a legend, pass a legends$ array which contains zero elements.
The value of colors$ determines the color scheme that will be used to draw the graph. It generally consists of at least three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels and the legend text. And the third color will be used for the graph’s data.
If colors$ contains more than three colors, the third and following colors will be used in repeating sequence for drawing the bars in each cluster. If colors$ contains fewer than three colors, the last color specified will be used to fill out the remaining colors. If the value of colors$ is the null string, then the current foreground color is used for the entire graph.
By default, the MULTIBAR subroutine draws the graph with the bars oriented vertically. The y-axis is automatically scaled to fit the data, and the clusters are evenly spaced along the x-axis. The labels stored in the units$ array will appear beneath each cluster.
You can change the graph’s orientation so that the bars are drawn horizontally by first invoking the SETLAYOUT subroutine with the argument “HORIZONTAL”. In this situation, the x-axis will be automatically scaled to fit the data, and the clusters will be evenly spaced along the y-axis. The labels stored in the units$ array will appear to the left of each cluster.
By default, the MULTIBAR subroutine draws the bars in each cluster side-by-side; however,
496 True BASIC Language System

they can also be drawn stacked or overlapped. Invoke the SETBARTYPE subroutine with an appropriate argument prior to invoking the MULTIBAR subroutine in order to determine the arrangement of the bars.
The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, BGBar2.TRU, can be found in the directory TBDEMOS:
! BGBar2 Draw a simple multi-bar graph.

! Last year’s sales in yellow; this year’s in green. LIBRARY “..\TBLibs\BGLib.trc”
DIM data(4,2), units$(4), legend$(2)

MAT READ data, units$, legend$
DATA 103,106, 47,68, 112,115, 87,94
DATA Books, Software, Cards, Candy
DATA Last Year, This Year

CALL SetBarType (“side”) CALL SetLayout (“h”)
CALL SetGrid (“v”)
CALL SetText (“Sales: Last Year and Current”, “Thousands”,”Category”)

CALL MultiBar (data, units$, legend$, “red red yellow green”) GET KEY key
END
produces a horizontal multi-bar chart representing a comparison of annual sales.
Exceptions: 100 Graph’s title is too wide.
101 Graph’s legend is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
111 Data and unit arrays don’t match for MultiBar.
112 Data and legend arrays don’t match for MultiBar.
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: SETTEXT, SETLAYOUT, SETBARTYPE, BARCHART, HISTOGRAM

MULTIHIST Subroutine
Library: BGLIB.TRC
Syntax: CALL MULTIHIST (numarrarg, strarrarg, strex)
strarrarg:: strarr
strarr bowlegs
numarrarg:: numarr
numarr bowlegs
Usage: CALL MULTIHIST (data(), legends$(), colors$)
Graphics Libraries

497

Summary: Draws multiple histograms of the specified data values in a single frame in the specified color scheme.
Details: The MULTIHIST subroutine draws multiple histograms in the current logical window. All histograms drawn by the MULTIHIST subroutine are overlaid in the same frame, with the bars for similar data values forming “clusters.” To produce a simple histogram with only one bar per unit, use the HISTOGRAM subroutine.
Each histogram automatically “groups” similar values from a single row of the data array and draws one bar per group. Thus, each cluster will contain one bar for each row of the data array. The height of each bar reflects the number of members in the associated group.
For instance, if you use the HISTOGRAM subroutine to chart students’ grades for two different classes, it might group all those students in the first class with grades in the range
80 through 84 and draw a single bar to represent this group of students. When the histogram for the second class was compiled, a bar representing the number of students in that class with grades in the range 80 through 84 would be added to the cluster containing the previous bar. The resulting clusters will be labeled “75>”, “80>”, “85>”, and so forth. This means that the first cluster will contain one bar representing the group of students in the first class whose grades are greater than or equal to 75 but less than 80 and another bar representing students from the second class whose grades fall in the same range. The second cluster will contain bars representing the groups with grades greater than or equal to 80 but less than 85, and so forth.
The legends$ array generally must contain the same number of items as the second dimension of the data array. The legends$ array will be used to add a legend to the graph (positioned between the title and the graph itself) which will allow the user to identify the individual bars within the clusters. Each element of the legends$ array provides a label for one of the histograms produced from the data array. To suppress the appearance of such a legend, pass a legends$ array which contains zero elements.
The value of colors$ determines the color scheme that will be used to draw the graph. It generally consists of at least three color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame, including the horizontal and vertical labels and the legend text. And the third color will be used for the graph’s data.
If colors$ contains more than three colors, the third and following colors will be used in repeating sequence for drawing the bars in each cluster. If colors$ contains fewer than three colors, the last color specified will be used to fill out the remaining colors. If the value of colors$ is the null string, then the current foreground color is used for the entire graph.
By default, the MULTIHIST subroutine draws the graph with the bars oriented vertically. The y-axis is automatically scaled to fit the data, and the clusters are evenly spaced along the x-axis. The cluster labels will appear beneath each cluster.
You can change the graph’s orientation so that the bars are drawn horizontally by first invoking the SETLAYOUT subroutine with the argument “HORIZONTAL”. In this situation, the x-axis will be automatically scaled to fit the data, and the clusters will be evenly spaced along the y-axis. The cluster labels will appear to the left of each cluster.
By default, the MULTIHIST subroutine draws the bars in each cluster side-by-side; however, they can also be drawn stacked or overlapped. Invoke the SETBARTYPE subroutine with an appropriate argument prior to invoking the MULTIHIST subroutine in order to determine the arrangement of the bars.
498 True BASIC Language System

The text used for the graph’s title and vertical and horizontal labels will be the values most recently set by the SETTEXT subroutine.
Example: The following program, BGHisto2.TRU, can be found in the directory TBDEMOS:
! BGHisto2 Draw a multiple histogram. LIBRARY “..\TBLibs\BGLib.trc”
DIM data(2,30), legend$(2)

MAT READ data, legend$
DATA 65, 70, 93, 85, 83, 68, 77, 92, 83, 85
DATA 89, 72, 75, 81, 80, 84, 73, 79, 78, 84
DATA 80, 79, 72, 91, 85, 82, 79, 76, 74, 79
DATA 75, 60, 83, 75, 73, 88, 67, 82, 73, 75
DATA 79, 62, 65, 71, 70, 74, 63, 69, 68, 74
DATA 70, 69, 62, 81, 75, 72, 69, 66, 64, 69

DATA Day, Evening

CALL SetBarType (“over”)
CALL SetText (“Final Grades”, “”, “# of Students”)
CALL MultiHist (data, legend$, “white cyan magenta cyan”)

GET KEY key

END
produces a horizontal multi-bar chart representing a comparison of annual sales.
Exceptions: 100 Graph’s title is too wide.
101 Graph’s legend is too wide.
102 Graph’s horizontal label is too wide.
103 Graph’s vertical label is too long.
104 Need more room for graph’s vertical marks.
105 Need more room for graph’s horizontal marks.
106 Need greater width for graph.
107 Need greater height for graph.
108 Vertical marks aren’t wide enough—use SetVMarkLen.
109 Horizontal marks aren’t wide enough—use SetHMarkLen.
111 Data and unit arrays don’t match for MultiHist.
112 Data and legend arrays don’t match for MultiHist.
117 Can’t handle this graph range: low to high.
11008 No such color: color.
See also: SETTEXT, SETLAYOUT, SETBARTYPE, HISTOGRAM, BARCHART

PIECHART Subroutine
Library: BGLIB.TRC
Syntax: CALL PIECHART (numarrarg, strarrarg, strex, numex, numex)
strarrarg:: strarr
strarr bowlegs
numarrarg:: numarr
numarr bowlegs
Usage: CALL PIECHART (data(), units$(), colors$, wedge, percent)
Summary: Draws a pie chart of the specified data values, labeled with the specified units and drawn in the specified color scheme.
Details: The PIECHART subroutine draws a pie chart in the current logical window.
Graphics Libraries

499

A pie chart is displayed as a circle divided into wedges. The pie chart will contain one wedge for each element of the data array, and the proportion of the circle’s area allocated to each wedge will be determined by the proportional relationship of the value of its corresponding element in the data array to the sum of the elements of the data array.
The wedge associated with the first element of the data array is placed at the top of the pie, and the remaining items of the data array are arranged in order clockwise around the remaining portion of the pie.
The units$ array must contain the same number of items as the data array. Each element of the units$ array will be used as a label for the wedge of the pie associated with the corresponding element of the data array. Each label will be connected to its associated wedge by a line. If an element of the units$ array has a value of the null string, the associated wedge will have neither a label nor a connecting line.
The value of colors$ determines the color scheme that will be used to draw the graph. It generally consists of at least four color names (in any combination of uppercase or lowercase letters) separated by spaces. The valid color names are:
RED MAGENTA YELLOW GREEN BLUE CYAN BROWN WHITE BLACK
BACKGROUND
The value of colors$ may also contain color numbers instead of color names, allowing you to access any of the colors supported by the current computer system.
The first color specified by the value of colors$ will be used for the graph’s title. The second color will be used for the graph’s frame. And the remaining colors will be used repeatedly for the wedges of the pie.
If the value of wedge fall between the lower and upper bounds of the data array, inclusive, the wedge of the pie associated with the element of data whose index is represented by the value of wedge will be exploded out of the pie. That is, it will be drawn slightly separated from the rest of the pie in order to draw the user’s attention. If the value of wedge falls outside this range, no wedge will be exploded out of the pie.
If the value of percent is non-zero, each wedge will be labeled not only with the corresponding element of the units$ array, but also with the percentage of the total which it represents. If the value of percent is 0, the wedges will be labeled only with the elements of the units$ array. Note that the percentages are rounded before being displayed. Therefore, it is not guaranteed that they will add up to exactly 100%.
Example: The following program, BGPie.TRU, can be found in the directory TBDEMOS:
! BGPie Draw a simple pie chart.

! Highlight hammers, and show percentages. LIBRARY “..\TBLibs\BGLib.trc”
DIM data(5), units$(5)

MAT READ data, units$ DATA 120, 34, 87, 65, 21
DATA Nails, Hammers, Saws, Pliers, Awls

CALL SetTitle (“Honest Boy (tm) Product Income”)
CALL PieChart (data, units$, “yellow green red”, 2, 1)

GET KEY key

END
produces a pie chart representing income by product, highlighting hammers and displaying percentages with each label.
500 True BASIC Language System

Exceptions: 100 Graph’s title is too wide.
106 Need greater width for graph.
107 Need greater height for graph.
111 Data and unit arrays don’t match for PieChart.
11008 No such color: color.
See also: SETTITLE

SETANGLE Subroutine
Library: SGLIB.TRC
Syntax: CALL SETANGLE (strex)
Usage: CALL SETANGLE (measure$)
Summary: Controls the manner in which subsequent polar graphs drawn by the various data and function plotting subroutines will interpret angle measurements.
Details: The SETANGLE subroutine is used to control the manner in which subsequent data and function polar plots produced by the DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH, FGRAPH, ADDFGRAPH, and MANYFGRAPH subroutines will interpret angle measurements.
When these subroutines interpret angle measurements, they interpret them as radians by default. However, by passing a value of “DEG” as measure$, you can instruct them to interpret angles in degrees. Passing a value of “RAD” to the SETANGLE subroutine will reset the default interpretation.
Note that the SETANGLE subroutine only controls the interpretation of angular coordinates by polar graphs. Use the SETGRAPHTYPE subroutine to cause subsequent graphs to be drawn as polar graphs.
You can use the ASKANGLE subroutine to determine the manner in which the next data or function polar plot will interpret angular coordinates.
Example: None
Exceptions: None
See also: ASKANGLE, SETGRAPHTYPE, DATAGRAPH, ADDDATAGRAPH,
MANYDATAGRAPH, FGRAPH, ADDFGRAPH, MANYFGRAPH

SETBARTYPE Subroutine
Library: BGLIB.TRC
Syntax: CALL SETBARTYPE (strex)
Usage: CALL SETBARTYPE (type$)
Summary: Controls the arrangement of the bars within each group of a multiple bar chart or histogram.
Details: The SETBARTYPE subroutine is used to control the arrangement of the bars within each group of a bar chart or histogram produced by a subsequent invocation of the MULTIBAR or MULTIHIST subroutine.
Both the MULTIBAR and MULTIHIST subroutines draw multiple bar-based graphs in a single frame. In such a graph, bars associated with a particular unit are grouped together.
The SETBARTYPE subroutine allows you to control how the bars in each group will be arranged by passing one of the following values in type$:
Types of Bar Groupings
Type$ value Description
“SIDE” Bars arranged side by side with space between them
“STACK” Bars stacked one above the other
“OVER” Bars arranged side by side but overlapped slightly

The value of type$ may be specified in any combination of uppercase and lowercase letters.
Graphics Libraries

501

If the value of type$ does not represent one of these values, an error will be generated.
By default, the bar type is set to a value of “SIDE”. You can use the ASKBARTYPE
subroutine to report the current bar type setting.
Example: See the example programs in the desciptions of BALANCEBARS (BGBar3.TRU,) MULTIBAR (BGBar2.TRU,) and MULTIHIST (BGHisto2.TRU) for examples of the use of this subroutine.
Exceptions: 130 No such barchart type: xxx
See also: ASKBARTYPE, MULTIBAR, MULTIHIST

SETGRAIN Subroutine
Library: SGLIB.TRC
Syntax: CALL SETGRAIN (numex)
Usage: CALL SETGRAIN (grain)
Summary: Controls the grain with which subsequent invocations of the various function plotting subroutines will draw the line graph.
Details: The SETGRAIN subroutine controls the grain with which subsequent invocations of the FGRAPH, ADDFGRAPH, and MANYFGRAPH subroutines will draw the line representing the function.
These subroutines actually graph the curve of the function which they are plotting as a series of line segments. The grain controls the number of line segments used to form each graphed curve. The higher the value of the grain, the more line segments are used and the smoother the resulting curve appears. However, higher grains also mean more work for the computer, and this means that each curve takes longer to draw.
By default, the FGRAPH, ADDFGRAPH, and MANYFGRAPH subroutines use a grain value of 64, which means that each line graph is composed of 64 individual line segments. This value strikes a generally acceptable balance of smoothness and speed, but you can change this value by passing the new grain value in the grain argument to the SETGRAIN subroutine.
You can use the ASKGRAIN subroutine to report the current grain value.
Example: The following program, SGGrain.TRU, can be found in the directory TBDEMOS:
! SGGrain Demonstrate SetGrain.

LIBRARY “..\TBLibs\SGFunc.trc”, “..\TBLibs\SGLib.trc” OPEN #1: screen 0, .49, 0, 1
CALL SetGrain (10)
CALL SetTitle (“Grain = 10”)
CALL Fgraph (-pi, pi, 1, “white white magenta”)

OPEN #2: screen .5, 1, 0, 1

CALL SetGrain (100)
CALL SetTitle (“Grain = 100”)
CALL Fgraph (-pi, pi, 1, “white white magenta”)

GET KEY key

END

DEF F(x) = Sin(3*x)
demonstrates the use of the SETGRAIN subroutine by displaying two graphs of the same function side by side — one with a grain of 10 and the other with a grain of 100.
Exceptions: None
See also: ASKGRAIN, FGRAPH, ADDFGRAPH, MANYFGRAPH
502 True BASIC Language System

SETGRAPHTYPE Subroutine
Library: SGLIB.TRC
Syntax: CALL SETGRAPHTYPE (strex)
Usage: CALL SETGRAPHTYPE (type$)
Summary: Controls the type of graph that will be drawn by subsequent data and function plotting subroutines.
Details: The SETGRAPHTYPE subroutine is used to control the type of graph that will be produced for subsequent data and function plots produced by the DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH, FGRAPH, ADDFGRAPH, and MANYFGRAPH subroutines.
The type of subsequent graphs is determined by the value passed as type$. The possible values of type$ are:

Type$ value Description
“XY” Normal graph
Types of Graphs
“LOGX” Semi-logarithmic graph with x-axis logarithmically scaled “LOGY” Semi-logarithmic graph with y-axis logarithmically scaled “LOGXY” Logarithmic graph with both x- and y-axes logarithmically scaled “POLAR” Polar graph

Logarithmic and semi-logarithmic graphs look very similar to normal graphs, but one or both of the axes is scaled logarithmically.
Polar graphs, however, look quite different from normal graphs in that they are circular. For this reason, the horizontal and vertical labels are ignored for polar graphs; only the title is shown.
When a graphing routine is used to draw a polar graph, what would normally be the x- and y- coordinates are interpreted as r and theta (or distance and angle) coordinates, respectively. Therefore, as you might expect, the function plotting subroutines expect to find an externally defined function in the form r = F(theta).
Polar graphs interpret angle measures as radians by default, but you can change this interpretation using the SETANGLE subroutine.
You can use the ASKGRAPHTYPE subroutine to determine the type of graph that will be used for the next data or function plot.
Example: See the example program in the description of MANYDATAGRAPH (SGData3.TRU) for an example of the use of this subroutine.
Exceptions: None
See also: ASKGRAPHTYPE, DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH,
FGRAPH, ADDFGRAPH, MANYFGRAPH

SETGRID Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL SETGRID (strex)
Usage: CALL SETGRID (style$)
Summary: Controls the presence, direction, and type of the grid within subsequently drawn charts and graphs.
Details: The SETGRID subroutine is used to control the presence, direction, and type of the grid within the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH subroutines.
The SETGRID subroutine allows you to control the presence and direction of the grid lines by passing one of the following values in style$:
Graphics Libraries

503

Available Grid Directions
Style$ value Description
“” No grid lines
“H” Horizontal grid lines only
“V” Vertical grid lines only
“HV” Both horizontal and vertical grid lines

The value of style$ may be specified in any combination of uppercase and lowercase letters. In addition, the value of style$ may include instructions that indicate the type of grid lines that you would like drawn. By default, grid lines are drawn as solid lines. However, you can append one of the following modifiers to a letter in the value of style$ to specify a different line type for grid lines traveling in that direction:
Available Grid Type Modifiers
Modifier Description
- Dashed grid lines
. Dotted grid lines
-. Dash-dotted grid lines

For example, passing a value of “H-.V” for style$ would result in dash-dotted grid lines in the horizontal direction and solid grid lines in the vertical direction.
If the value of type$ does not represent a valid value, however, an error will be generated. By default, the grid lines are turned off. You can use the ASKGRID subroutine to report the
current grid setting.
Example: See the example program in the description of MULTIBAR (BGBar2.TRU) for an example of the use of this subroutine.
Exceptions: 113 No such SetGrid direction: xxx
See also: ASKGRID, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM,
FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

SETHLABEL Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL SETHLABEL (strex)
Usage: CALL SETHLABEL (hlabel$)
Summary: Sets the value of the horizontal label which will be displayed for subsequently drawn charts and graphs.
Details: The SETHLABEL subroutine is used to set the value of the horizontal label that will be used to label the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, and MANYDATAGRAPH subroutines.
The SETHLABEL subroutine expects the value of the horizontal label to be passed as
hlabel$. Passing a null string effectively eliminates the horizontal label.
If the value you set for the horizontal label exceeds the available room, the graphing subroutine which draws the next graph will generate an error.
There is no default value for the horizontal label. Therefore, if you want it to appear, you will need to specify its values before drawing the graph.
You may specify new values for the title, the horizontal label, and the vertical label simultaneously using the SETTEXT subroutine. Use the SETVLABEL and SETTITLE subroutines to set the values of the vertical label and the title, respectively.
You may use the ASKHLABEL subroutine to report the current value of the horizontal label.
Example: None
504 True BASIC Language System

Exceptions: None
See also: ASKHLABEL, SETTEXT, SETVLABEL, SETTITLE, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, PIECHART, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

SETLAYOUT Subroutine
Library: BGLIB.TRC
Syntax: CALL SETLAYOUT (strex)
Usage: CALL SETLAYOUT (direction$)
Summary: Controls the direction of the bars within subsequently drawn bar charts and histograms.
Details: The SETLAYOUT subroutine is used to control the direction of the bars within each bar chart or histogram produced by a subsequent invocation of the MULTIBAR or MULTIHIST subroutine.
The SETLAYOUT subroutine allows you to control the direction in which the bars will be drawn by passing one of the following values in direction$:
Types of Bar Groupings
Direction$ value Description “HORIZONTAL” Bars oriented horizontally “VERTICAL” Bars oriented vertically

The value of type$ may be specified in any combination of uppercase and lowercase letters. In addition, the value of type$ may be truncated to any number of letters. That is, values of “H” and “V” will suffice. If the value of type$ does not represent a valid value, however, an error will be generated.
By default, the bar direction is set to a value of “VERTICAL”. You can use the ASKLAYOUT
subroutine to report the current bar layout setting.
Example: See the example program in the description of MULTIBAR (BGBar2.TRU) for an example of the use of this subroutine.
Exceptions: 131 No such barchart direction: xxx
See also: ASKLAYOUT, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST

SETLS Subroutine
Library: SGLIB.TRC
Syntax: CALL SETLS (numex)
Usage: CALL SETLS (flag)
Summary: Controls whether least-squares linear fits will be drawn automatically for subsequent data plots.
Details: The SETLS subroutine is used to control whether or not least-squares linear fits will be drawn automatically for subsequent data plots produced by the DATAGRAPH, ADDDATAGRAPH, and MANYDATAGRAPH subroutines.
The least-squares linear fit of a data plot is the straight line which best fits the locations of the data points. That is, the least-squares linear fit of a data plot is the straight line which minimizes the vertical distance between itself and each of the data points which form the plot. Such a line may be used to help predict where data points might lie in areas of the graph for which data is unavailable.
By default, the DATAGRAPH, ADDDATAGRAPH, and MANYDATAGRAPH subroutines draw the data plots without displaying the least-squares linear fit of the data points. However, invoking the SETLS subroutine with the value of flag equal to 1 will instruct subsequent invocations of these routines to add such a linear fit to each graph they draw. You may then turn off this line fitting by invoking the SETLS subroutine again with the value of flag equal to 0.
Graphics Libraries

505

When the DATAGRAPH and ADDDATAGRAPH subroutines draw a linear fit, they draw a solid line in the data color. The MANYDATAGRAPH subroutine draws each graph’s linear fit in the same color and line style as the lines connecting that graph’s data points.
You can use the ASKLS subroutine to determine whether least-squares linear fitting is currently active or inactive.
Example: None
Exceptions: None
See also: ASKLS, ADDLSGRAPH, DATAGRAPH, ADDDATAGRAPH, MANYDATAGRAPH

SETTEXT Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL SETTEXT (strex, strex, strex)
Usage: CALL SETTEXT (title$, hlabel$, vlabel$)
Summary: Sets the values of the title, horizontal label, and vertical label which will be displayed for subsequently drawn charts and graphs.
Details: The SETTEXT subroutine is used to set the values of the title, horizontal label, and vertical label that will be used to label the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, and MANYDATAGRAPH subroutines. (These values also apply to the PIECHART subroutine, but only the value of the title is used.)
The SETTEXT subroutine expects the value of the title to be passed as title$, the value of the horizontal label to be passed as hlabel$, and the value of the vertical label to be passed as vlabel$. Passing a null string for any of these values effectively eliminates that label.
If the values you set for one or more of these labels exceeds the available room, the graphing subroutine which draws the next graph will generate an error.
There are no default values for the title, the horizontal label, or the vertical label. Therefore, if you want any of them to appear, you will need to specify their values before drawing the graph.
You may specify a new value for the title, the horizontal label, or the vertical label individually using the SETTITLE, SETHLABEL, or SETVLABEL subroutines, respectively.
You may use the ASKTEXT subroutine to report the current values of the title, the horizontal label, and the vertical label.
Example: See almost all the example programs described in this section for examples of the use of this subroutine.
Exceptions: None
See also: ASKTEXT, SETTITLE, SETHLABEL, SETVLABEL, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, PIECHART, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

SETTITLE Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL SETTITLE (strex)
Usage: CALL SETTITLE (title$)
Summary: Sets the value of the title which will be displayed for subsequently drawn charts and graphs.
Details: The SETTITLE subroutine is used to set the value of the title that will be used to label the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH, and PIECHART subroutines.
506 True BASIC Language System

The SETTITLE subroutine expects the value of the title to be passed as title$. Passing a null string effectively eliminates the title.
If the value you set for the title exceeds the available room, the graphing subroutine which draws the next graph will generate an error.
There is no default value for the title. Therefore, if you want it to appear, you will need to specify its values before drawing the graph.
You may specify new values for the title, the horizontal label, and the vertical label simultaneously using the SETTEXT subroutine. Use the SETHLABEL and SETVLABEL subroutines to set the values of the horizontal label and the vertical label, respectively.
You may use the ASKTITLE subroutine to report the current value of the title.
Example: See the examples programs in the descriptions of SETGRAIN (SGGrain.TRU) and
SORTPOINTS (SGSortPt.TRU) for examples of the use of this subroutine.
Exceptions: None
See also: ASKTITLE, SETTEXT, SETHLABEL, SETVLABEL, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, PIECHART, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

SETVLABEL Subroutine
Library: BGLIB.TRC or SGLIB.TRC
Syntax: CALL SETVLABEL (strex)
Usage: CALL SETVLABEL (vlabel$)
Summary: Sets the value of the vertical label which will be displayed for subsequently drawn charts and graphs.
Details: The SETVLABEL subroutine is used to set the value of the vertical label that will be used to label the frame of graphs or charts drawn by subsequent invocations of the BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, FGRAPH, MANYFGRAPH, DATAGRAPH, and MANYDATAGRAPH subroutines.
The SETVLABEL subroutine expects the value of the vertical label to be passed as vlabel$. Passing a null string effectively eliminates the vertical label.
If the value you set for the vertical label exceeds the available room, the graphing subroutine which draws the next graph will generate an error.
There is no default value for the vertical label. Therefore, if you want it to appear, you will need to specify its values before drawing the graph.
You may specify new values for the title, the horizontal label, and the vertical label simultaneously using the SETTEXT subroutine. Use the SETHLABEL and SETTITLE subroutines to set the values of the horizontal label and the title, respectively.
You may use the ASKVLABEL subroutine to report the current value of the vertical label.
Example: None
Exceptions: None
See also: ASKVLABEL, SETTEXT, SETHLABEL, SETTITLE, BARCHART, MULTIBAR, HISTOGRAM, MULTIHIST, IBEAM, PIECHART, FGRAPH, MANYFGRAPH, DATAGRAPH, MANYDATAGRAPH

SETXSCALE Subroutine
Library: SGLIB.TRC
Syntax: CALL SETXSCALE (numex, numex)
Usage: CALL SETXSCALE (70, 170)
Summary: Turns off auto-scaling and sets the x-range for subsequent graphs.
Graphics Libraries

507

Details: The SETXSCALE subroutine is used to set the value of the x-scale for subsequent graphs. It turns off auto-scaling. The actual x-range may be slightly different as this subroutine may round to “good-looking” numbers.
Example: None.
Exceptions: None
See also: SETYSCALE

SETYSCALE Subroutine
Library: SGLIB.TRC
Syntax: CALL SETYSCALE (numex, numex)
Usage: CALL SETYSCALE (70, 170)
Summary: Turns off auto-scaling and sets the y-range for subsequent graphs.
Details: The SETYSCALE subroutine is used to set the value of the y-scale for subsequent graphs. It turns off auto-scaling. The actual y-range may be slightly different as this subroutine may round to “good-looking” numbers.
Example: See the example in the description of ADDLSGRAPH (SLSquar.TRU) for an example of the use of this subroutine.
Exceptions: None
See also: ADDLSGRAPH, SETXSCALE

SORTPOINTS Subroutine
Library: SGLIB.TRC
Syntax: CALL SORTPOINTS (numarrarg, numarrarg)
numarrarg:: numarr numarr bowlegs
Usage: CALL SORTPOINTS (x(), y())
Summary: Sorts the one-dimensional parallel arrays x and y into ascending order by the values of stored in the x array.
Details: The SORTPOINTS subroutine sorts the parallel, one-dimensional arrays x and y into ascending order by the values stored in the x array.
Parallel arrays are simply arrays in which elements with identical subscripts are related. For instance, the x and y arrays are considered to be parallel if the first element of the x array is related to the first element of the y array, the second to the second, and so forth for each element in both arrays. When parallel arrays are sorted, the elements in both arrays are rearranged in an identical manner so as to maintain these relationships.
The SORTPOINTS subroutine is useful for sorting the arrays of coordinates passed into the DATAGRAPH and ADDDATAGRAPH subroutines, but it can be used to sort any pair of one-dimensional parallel arrays.
To sort two-dimensional arrays in a similar fashion, use the SORTPOINTS2 subroutine. To sort a single one-dimensional array, use the SORTN subroutine.
Example: The following program, SGSortPt.TRU, can be found in the directory TBDEMOS:
! SGSortPt Display unsorted vs. sorted data points. LIBRARY “..\TBLibs\SGLib.trc”
DIM x(10), y(10)

FOR i = 1 to 10 ! Get some unsorted data points
LET x(i) = rnd
LET y(i) = rnd
508 True BASIC Language System

NEXT i

OPEN #1: screen 0, .49, 0, 1 ! Left: unsorted points
CALL SetTitle (“Unsorted”)
CALL DataGraph (x, y, 10, 3, “”)

OPEN #2: screen .5, 1, 0, 1 ! Right: sorted points
CALL SetTitle (“Sorted”) CALL SortPoints (x, y)
CALL DataGraph (x, y, 10, 3, “”)

GET KEY key

END
demonstrates the usefulness of using the SORTPOINTS subroutine with the
DATAGRAPH subroutine.
Exceptions: None
See also: SORTPOINTS2, DATAGRAPH, ADDDATAGRAPH, SORTN

SORTPOINTS2 Subroutine
Library: SGLIB.TRC
Syntax: CALL SORTPOINTS2 (numarrarg, numarrarg)
numarrarg:: numarr
numarr bowlegs
Usage: CALL SORTPOINTS2 (x(,), y(,))
Summary: Sorts the parallel rows of the two-dimensional arrays x and y into ascending order by the values of stored in rows of the x array.
Details: The SORTPOINTS2 subroutine sorts the elements of the parallel rows of the two- dimensional arrays x and y into ascending order by the values stored in the rows of the x array.
Parallel arrays are simply arrays in which elements with identical subscripts are related. For instance, the x and y arrays are considered to be parallel if the first element of the x array is related to the first element of the y array, the second to the second, and so forth for each element in both arrays. When parallel arrays are sorted, the elements in both arrays are rearranged in an identical manner so as to maintain these relationships.
The SORTPOINTS2 subroutine treats corresponding rows of the x and y arrays as individually parallel one-dimensional arrays. That is, the elements of each pair of corresponding rows are rearranged independently of the other rows.
The SORTPOINTS2 subroutine is useful for sorting the arrays of coordinates passed into the MANYDATAGRAPH subroutine, but it can be used to sort any pair of two-dimensional arrays with parallel rows.
To sort one-dimensional arrays in a similar fashion, use the SORTPOINTS subroutine. To sort a single one-dimensional array, use the SORTN subroutine.
Example: None
Exceptions: None
See also: SORTPOINTS, MANYDATAGRAPH, SORTN
509