Text-Sensitive ACHOICE()

David R. Alison

[Reprinted from Nantucket News, November/December 1988.
Copyright (c) 1988 Nantucket Corporation.  All Rights Reserved.]


ACHOICE() provides Clipper programmers with a simple way to select
items from a menu.  TextSens gives it even more power by allowing you
to perform a text-sensitive search on items in the ACHOICE() array.
You or your users can select an item just by typing part of the name.
This can save time, for example, if 25 of the menu choices begin with
the same letter.

TextSens loads the current directory into an array with ADIR(), then
sorts it using ASORT().  When the menu appears, you can move through
the names with the arrow keys.  When you type a letter, TextSens
moves the cursor to the first item that matches that name.  As you
continue to type letters, this "search string" is displayed in the
small box at the bottom of the ACHOICE() menu.  The cursor continues
to move to the next item that matches that description.  At any time
during the selection process you can press the arrow keys or space
bar to cancel the search string.

In the TextSens example, the items in the current directory listing
serve as the ACHOICE() menu items.  This is done by declaring an
array with the number of elements that match the "*.*" file
specification.  The array is then loaded with all of the files in the
current directory by using ADIR().  Sorting the array is handled by
ASORT().

Next, some public memory variables for an array pointer and search
field are declared and initialized.  They are made public so that the
user-defined function SeekText() can modify them.

The meat of the program is in the DO WHILE loop.  Rather than trying
to perform all of the features from within SeekText(), we simply call
ACHOICE() repetitively, specifying the initial ACHOICE() element
(init), and the relative window position (rel).  ACHOICE() is used
only to display the menu on the screen and check to see whether the
user has made a selection.

SeekText(), called from within ACHOICE(), checks on the last key that
the user pressed.  If the LASTKEY() was the Enter (13), Escape (27),
Space (32) or Backspace (8), SeekText() tells ACHOICE() to select the
current item and terminate ACHOICE(), passing control back into the
program.  If the LASTKEY() has a value under 30 (virtually all of the
arrow keys), SeekText() resets the search string and tells ACHOICE()
to continue with the selection process.

Once ACHOICE() has been terminated, the program continues to process
the last key using DO CASE.  The OTHERWISE evaluator assumes that if
the last keystroke got this far, it must be an alphabetical character
to be added to the search string.  First, the UPPER() case version of
the CHR() of LASTKEY() is appended to the search string.  The new
search string (s_name) is searched for inside the "names" array with
ASCAN().  If the new search string is found, the new initial element
(init) for ACHOICE() is set to the location of the find.  If the
string is not located in "names," a tone sounds and the search string
is reduced by one character.  After the loop terminates, a simple IF
statement evaluates whether or not a choice was made.

I find the best use for TextSens is with ACHOICE() menus that have a
large number of available selections.  This example uses all of the
files in the current directory as the menu.  You can just as easily
make it a list of reports that can be run or a list of databases
available for use in a program.  It would be rather simple to turn
the bulk of the TextSens program into an entire user-defined
function, so that calling a text-sensitive ACHOICE() would simply be
a matter of specifying a single command line.


David Alison, Systems Analyst, is a Clipper Consultant based in
Northridge, California.  He is available through CompuServe at
72727,1132.
