Converts an expression of any data type into a string

     XTOC(<expValue>) --> cValue


     <expValue>  Designates an expression of any desired data type.


     XTOC() returns a character string version of the <expValue> parameter.


     At first glance, the XTOC() function does not appear to accomplish
     anything that cannot be done with the other functions.  However, the
     advantage lies in the fact that you do not have to pay attention to the
     input data types.  For example, you can convert the data in every field
     within a loop into a string.  You could then link these into a longer
     string and use them to index or for comparisons.

     Each data type always returns a string with a particular fixed length:

     Table 13-9: Resulting String
     Data Type    Result Length
     Numeric      8
     Logical      1
     Date         8
     String       Unchanged


     .  The index string cannot be longer than 256 characters.


     .  In the case of logical parameters, XTOC() works like LTOC():

        ? XTOC(.T.)                              // "T"
        ? XTOC(.F.)                              // "F"

     .  Numeric values always return an 8-byte string:

        ? XTOC(0)                                // Length 8
        ? XTOC(9.9)                              // Ditto
        ? XTOC(-9.9)                             // Ditto
        ? XTOC(99)                               // Ditto
        ? XTOC(-99)                              // Ditto

     .  A string returns the same string:

        ? XTOC("123ABCabc")                      // "123ABCabc"

     .  A date returns the ANSI date:

        ? XTOC(CTOD("12/31/99"))                 // "19991231"
        ? XTOC(CTOD("01/01/00")                  // "19000101"

     .  An empty or false date returns an empty string rather than a
        null string:

        ? XTOC(CTOD("  /  /  ")                  // "        "
        ? XTOC(CTOD("77/77/77")                  // "        "

     .  Show a function where all the fields in a database are
        combined into one string.  This way, you can do a complete comparison
        of the two data strings:

           PRIVATE nI, nFieldNo, cField, cStringRec
           cStringRec := ""
           nFieldNo   := FCOUNT()                // Number of fields
           FOR nI = 1 to nFieldNo
             cField          := FIELD(nI)        //  Field name
             cStringRec := cStringRec + XTOC(&cField)
           NEXT nI
           RETURN (cStringRec)

See Also: CTOF()


 Queries the version number of the Clipper Tools in use

     TOOLVER(<lCheckDriver>) --> cVersion


     <lCheckDriver>  When passed as .T., the function checks if the
     Extended Drivers correspond to the library.  If not, the function
     returns "0.00".


     TOOLVER() returns Clipper Tools as a string in the "n.nn" format; or
     "0.00", if the Extended Drivers does not correspond to the library.


     This function determines the current Clipper Tools version.  It also
     allows you to check if the CT.LIB and the Extended Drivers CTUS.OBJ
     agree.  This agreement is essential.  If they do not agree, the function
     returns "0.00".


     .  Query the Clipper Tools version:

        ? TOOLVER()               // e.g. "5.01"

     .  Verify the driver version:

        IF TOOLVER() <> TOOLVER(.T.)
           ? "Wrong driver or driver not linked in..."



 Determines the remaining stack space

     STACKFREE() --> nFreeByte


     STACKFREE() returns the number of bytes available on the stack.


     This function helps avoid system crashes.  If the returned value falls
     below 100, do not permit deeper branching.  Either change the program so
     that a large nesting depth cannot be reached, or increase the stack size
     when linking.


     .  The stack is a low-level system area.  Each DO requires some
        memory bytes, before a RETURN can ensue.


     .  Query the stack size:

        ? STACKFREE()               // < 100 ??

     .  Link the application within increased stack size:

        RTLINK FI Test /ST:8000

See Also: ALLOFREE()*



 A comparison value used to determine the processor speed

     SPEED([<lMode>]) --> nCPUSpeed


     <lMode>  If designated as .T., causes all interrupts, with the
     exception of the clock, to switch off..  The default value is "Leave
     interrupts on" (.F.).


     SPEED() returns a percentage value to compare to a normal 4.77 MHz PC-
     XT, which corresponds to 100%.


     The function determines, in a precise fashion, the speed to compare to a
     4.77 MHz PC.  To make the measurement more precise, switch the
     interrupts off.  The only exceptions are the timer interrupts that
     refresh  working memory.


     Warning!  When you use the optional parameters to shut off all
     interrupts (with the exception of the timer interrupts) you cannot work
     simultaneously with the serial interface.  After you take the
     measurement, you can restore all interrupts.


     .  For a normal AT:

        ? SPEED(.T.)         // 470  4.7 times PC

     .  Switch off interrupts in the same system:

        ? SPEED(.T.)         // 480  4.8 times PC



 Creates tones (melodies) by designating frequency and duration

     SOUND(<nFrequency>,<nDuration>,[<lTimer>]) --> cNull


     SOUND(<cToneSequence>,[<lTimer>]) --> cNull


     <nFrequency>  Designates the tone frequency in hertz.

     <nDuration>  Designates the duration of the tones in 1/100ths
     seconds; or when <lTimer> is set at .T., in intervals of 1/18.2 seconds.

     <lTimer>  Designates whether the tones designated as values are
     created on a basis of 1/100ths seconds (.F.); or 1/18.2 seconds (.T.).
     The default value is 1/100th seconds (.F.).


     <cToneSequence>  Designates a character string that contains an
     entire melody.  Use the Clipper I2BIN() function to produce 2-byte
     values for frequency and duration.  The string format assumes 2 bytes
     for frequency and 2 bytes for duration, which are alternated until the
     melody is defined.

     <lTimer>  Designates if you want the designated tones values created
     on a basis of 1/100ths seconds (.F.) or 1/18.2 seconds (.T.).  The
     default value is 1/100th seconds (.F.).


     SOUND() always returns a null string as a value.


     Use SOUND() to create tones at intervals of 1/100th seconds, in the
     range of 21 to 65535 hertz, for a maximum of 655.36 seconds.

     To make it compatible with parameters for the Clipper TONE() function
     or various other programming language functions, select the 1/18.2-
     seconds interval.  To achieve this, designate the last parameter as .T..

     The table below shows tones and their frequencies for three octaves at
     1/100th second intervals.  To go one octave higher, double the frequency

     Table 13-8: Tones and their Frequencies
     Tone    Freq.     Tone    Freq.     Tone    Freq.
     C 3     131       C 4     262       C 5     523
     C#      139       C#      277       C#      554
     D       147       D       294       D       587
     D#      156       D#      311       D#      622
     E       165       E       330       E       659
     F       175       F       349       F       698
     F#      185       F#      370       F#      740
     G       196       G       392       G       784
     G#      208       G#      415       G#      831
     A       220       A       440       A       880
     A#      233       A#      466       A#      932
     B       247       B       494       B       988

     Frequency values that lie below 21 hertz, are not perceived by the human
     ear.  You can use them as pauses.


     .  You can find additional uses for SOUND() in the sample file


     .  Show the tonal scale:

        SOUND(262, 40)
        SOUND(294, 40)
        SOUND(330, 40)
        SOUND(349, 40)
        SOUND(392, 40)
        SOUND(440, 40)
        SOUND(494, 40)
        SOUND(523, 40)

     .  Call with a string parameter:

        cVar := I2BIN(262) + I2BIN(40) + I2BIN(294) + I2BIN(40)

     .  Pause for one-half second:

        SOUND(0, 50)

See Also: MILLISEC()


 Continuously displays the INSERT and LOCK status

     SHOWKEY([<cKey>, [[<nLine>], [<nColumn>], <cTextON>,
        <cTextOFF>, [<cAttrON|nAttrON>],
        [<cAttrOFF|nAttrOFF>]]]) --> cNull


     <cKey>  Designates which key to monitor in the form of a letter
     ("C", "N", "S", or "I").  If <cKey> is the only parameter in SHOWKEY()
      (C, N, S, or I), the respective key monitoring is uninstalled.

     <Line>  Designates the line where the display occurs.

     <nColumn>  Designates the column where the display occurs.

     <cTextON>  Designates text for the active status.  A maximum length
     of 15 characters is allowed.

     <cTextOFF>  Designates text for the inactive status. There is a
     maximum of 15 characters and it must have the same length as <cTextON>.

     <cAttrON|nAttrON>  Designates the color attribute for the active
     status.  The default value is 7/0.

     <cAttrOFF|nAttrOFF>  Designates the color attribute for the inactive
     status.  The default value is the same as in <cAttrON|nAttrON>.

     ()  If you call SHOWKEY() without parameters, it uninstalls.


     The SHOWKEY() function always returns a null string.


     SHOWKEY() is an extremely versatile system that can be used to monitor
     the NUM-LOCK, SCROLL-LOCK, CAPS-LOCK, and INSERT keys.  After it is
     installed, you can display an indicator for each key, the desired screen
     position, and a color attribute (without concerning the Clipper
     program).  You can establish a display for both the active and inactive
     status with individual color attributes.  However, both these strings
     must have the same length.

     Since the system INSERT status is handled separately from the
     Clipper INSERT status, this monitoring can only be implemented from
     within a READ.  An indicator display, in so far as it has been
     activated, is refreshed in intervals of approximately 200 milliseconds.
     Therefore, when you clear a portion or the complete screen, do not
     concern yourself with restoring this display.


     Warning!  Always uninstall this function before you leave a program
     or use the Extended Drivers provided with this Clipper Tools.  The
     function changes interrupt vectors.  You may cause a system crash, if
     the old status is not restored before you exit the program!  Use the
     enclosed INTSAVE program to avoid this problem.


     .  Display "CAPS" if CAPS-LOCK is on: CAPS-LOCK for off: "    ",
        in line 24, column 50.  The default value for on and off is "7/0"

        SHOWKEY("C", 24, 50, "CAPS", "    ")

     .  Attributes can be numeric and or designated as in Clipper:

        SHOWKEY("N", 24, 60, "NUM ON", "NUMOFF", 112, "W/R")

     .  Inverse the display for on and off:

        SHOWKEY("S", 24, 70, "SCRL", "  ", "0/7")

     .  Uninstall the NUM-LOCK display:


     .  Uninstall the function:


See Also: SHOWTIME()



 Increases number of time ticks to produce a more precise time measurement

     SETTIC([<lAcceleration>]) --> lAccelerated


     <lAcceleration>  When this parameter is .T., the number of timer
     ticks is increased by a factor of 128.  The default is normal timer
     ticks (.F.).

     ()  With no arguments, SETTIC() returns the current status of the timer
     as a .T. when accelerated; .F. if it is not.


     The SETTIC() function returns .T. when the timer is accelerated;
     otherwise, it returns .F..


     If the integrated timer in your computer uses SETTIC(.T.) to accelerate,
     then the number of ticks per second increases from 18.2 to around 2500.
     This makes time measurement more precise and allows you to compare the
     speed of different routines more accurately.

     The computer's clock time, which is also based on the timer tick,
     continues to operate correctly.


     Warning!  You must uninstall SETTIC() before you leave a program;
     otherwise, you will hang the system.  However, if the Extended Drivers
     CTUS.LIB is linked in, then SETTIC() uninstalls automatically when you
     exit the program.

     .  As long as the timer is accelerated, you cannot implement the
        KEYSEC(), SHOWTIME(), and SHOWKEY() functions because they use the
        timer tick.  Therefore, you must uninstall these functions before you
        implement SETTIC(.T.).

     .  Do not place (link) SETTIC() within an overlay, since an
        interrupt service routine can never be within an overlay.  Of course,
        you can call SETTIC() from an overlay.

     .  Since each timer tick must call an interrupt service, your
        program's execution speed decreases.


     Measure an individual UDF in ticks.  The tick rate increases first, and
     then decreases after UDF is executed and the number of resulting ticks
     is queried:

        MY_UDF(I)            // Needs to be measured...
     ? "Required ticks:", GETTIC()

See Also: GETTIC()



 Queries scan code of keyboard input

     SCANKEY([<lMode>]) --> nKeyValue

     Warning!  Augmented from Clipper Tools.  This is new optional


     <lMode>  Designates whether or not to ignore the additional keys on
     the European extended keyboard.


     SCANKEY() returns the scan code for the key pressed.


     SCANKEY() returns an untranslated scan code for a key.  This allows you
     to differentiate between keys or key combinations that return the same
     INKEY() value.  SCANKEY() does not take the character out of the buffer.
     The function waits for a keyboard input and returns the scan code which
     corresponds.  The third example shows how a returned value is converted
     into something you can display, as in CTSCAN.CH by SCANKEY().  Although
     it depends on the keyboard, the scan codes may differ from those listed
     in CTSCAN.CH.


     .  No key traps (including the Clipper internal key traps),
        are acknowledged.


     .  Return with input of Ctrl-W:

        ? INKEY()                // 23
        ? SCANKEY()              // 4375
        ? NUMLOW(SCANKEY())      // 23
        ? NUMHIGH(SCANKEY())     // 17

     .  When inputting Ctrl-End (numeric key pad), return:

        ? INKEY()                // 23
        ? SCANKEY()              // 29952
        ? NUMLOW(SCANKEY())      // 0
        ? NUMHIGH(SCANKEY())     // 117

     .  Reuse codes with other functions:

        nCode  :=  SCANKEY()
        SETKXLAT(CHR(NUMLOW(nCode)) * CHR(NUMHIGH(nCode)), -1)



 Converts the value returned by a function into a null string

     NUL(<expValue>) --> cNull


     <expValue>  Designates an expression or function that has a return
     value you want to suppress.


     NUL() always returns a null string as a value.


     NUL() converts a function that returns a value into a function that
     returns a null string.  This suppresses the returned value for every


     .  The function is not VOID.  It returns a value of a specific
        data type -- a (null) string.  Therefore, you cannot use this
        function to compare with other data types (see Examples).


     .  Wait for a key stroke:

        ? "Please press a key  :" + NUL(INKEY(0))

     .  Show output that uses LIST and waits for a key stroke after 20

        LIST Name, IF(RECNO() %20 = 0, NUL(INKEY(0)), "")

     .  This leads to a TYPE MISMATCH:

        ? 3 = NUL(INKEY(5))         //  Error after 5 seconds
        ? 7 + NUL(INKEY())          //  Leads to error, like saying 7+""




 Time delay in milliseconds

     MILLISEC(<nDelay>) --> cNull


     <nDelay>  Designates the number of milliseconds the function waits.
     You can specify values between 1 and 65535.


     The MILLISEC() function always returns a null string.


     This function allows you to designate a time delay in milliseconds.


     Pause for different time delays:

     MILLISEC(1)                 // 1 millisecond time delay
     MILLISEC(100)               // 0.1 seconds
     MILLISEC(1000)              // 1 second