String Manipulation (Intro)

Introduction String Manipulation

There are an abundance of powerful string functions described in this
chapter. A high degree of speed is assured because these functions and
all of the CA-Clipper Tools are written exclusively in Assembler.
We have made an effort to find an appropriate example for as many
unusual variations as possible. In view of this, we would like to take
this opportunity to clarify a few ground rules regarding the use of
these functions.

Passing Parameters by Reference

This chapter includes functions that pass parameters by reference. The
following paragraphs contain clarification about these functions.
It has been possible to pass parameters of the character string type by
reference to a UDF since the summer of 1987. This means that a
reference to the original string is passed, thus avoiding the creation
of an internal copy. When a function accepts this type of parameter and
changes it, the original string is actually changed. This behavior does
not normally apply to CA-Clipper functions. However, some CA-Clipper
Tools functions behave differently and take parameters passed by
reference. These functions and their corresponding parameters are
described as reference sensitive in this section and are identified with
[@] in the argument section of each function's description.

Passing parameters by reference has advantages and disadvantages. The
most important advantage is that memory requirements are reduced. This
allows you to avoid runtime errors that could result when there is
insufficient memory available for string manipulation.

Whether or not the insufficient memory is a disadvantage depends on the
function being used. Often you will want to change the original string.
In a call that does not pass parameters by reference, the copy changed
by the function must then be passed back to the "original" string again:
AR := "Hello"
When you work with very long strings, this method takes memory and time!
Here is an example of the reference method:
VAR := "Hello"


With most CA-Clipper Tools functions, it doesn't make any sense to pass
parameters by reference. In some cases, a result is different when a
parameter is passed in this way. However, when you do pass by
reference, the functions change the parameters passed by the string
directly. Memory is saved, and the functions work more quickly because
you no longer need to make an internal copy. Watch for the [@] marker,
indicating that a parameter is reference sensitive.

Functions which change the length of a string cannot, in principle pass
by reference. Here is an overview of the functions that change length,
or depending upon usage, could change if you attempt to pass by


This function additionally allows you to significantly optimize
reference sensitive functions with regard to execution speed and memory
use. Full details can be found in the corresponding function
description later in this chapter.


Introduction Extended Drivers


In addition to supporting the window functions, the CTUS.LIB extended
 driver contains a series of independent functions, all of which are
 described in this chapter.
We are concerned here with functions that relate directly to Clipper
 keyboard input, screen and printer output, or other internal functions.
 To use these internal functions, the driver must be linked in. The use
 of CTUS.LIB does not mean that all the code for all the functions
 contained in CTUS.LIB is linked to your application. An intensive
 modularization effort causes RTLINK to link only those portions that are
 actually needed.

The Use of CTUS.LIB

The extended driver is delivered as an .OBJ file (CTUS.OBJ) to allow
 replacement of the Clipper driver module in CLIPPER.LIB during
 linking. The extended driver must be included in the list of object

Video Modes

Some functions which relate to screen adapters are found in the Video
 Modes chapter rather than in the Video Functions chapter.

Changing Modes

Some settings are reset by a mode change:
Cursor position to: Line 0, Column 0
Screen page 0: SETPAGE()
All font information: SETFONT(), FONTLOAD(), FONTSELECT()
All palette information: EGAPALETTE(), VGAPALETTE()
Border settings: SET COLOR TO

DSETWINDOW()/External Screen Output

This is a very important switch for Clipper Tools that impacts many
 functions and other modules. DSETWINDOW() determines whether or not the
 output of external programs or modules is redirected to a window.
 (Clipper Tools functions are considered "external").
The default setting for this switch (.T.) redirects the output. To make
 this possible, the driver changes the interrupt vector 10H. Under
 certain circumstances external programs will not accept changes in
 particular interrupt vectors, which is why you must call DSETWINDOW(.F.)
 before you call the RUN function.
Certain other functions, like ISANSI() or NUMCOL(), return false or
 differing values in conjunction with DSETWINDOW(). Pay attention to the
 accompanying notes in the function descriptions.

System Settings Are Saved

When you end an application under Clipper's control (normal program
 termination, Alt-C, or ending after a Clipper error message), the
 cursor type, color attribute, and interrupt vectors 0 to 127 are
However, if you exit a program in any other way (usually with an
 external module containing errors) then the extended driver system
 settings cannot be restored. Previously changed interrupt vectors are
 probably still changed, which sooner or later result in a system crash.
 If this occurs, reboot as soon as possible.

The QUIT File

A QUIT file can be added to any of the extended driver functions. The
 QUIT file provides information at the next program start as to whether
 the previous run ended correctly. Additionally, the user's keyboard
 input is also recorded.

The default name for this file is the same name as your Clipper
 program except that it has a .Q extension instead of a .EXE extension.
 However, you can select another name for the file. For more
 information, please see DSETQFILE(), DSETQNAME() and KEYREAD().


  Since this section is about DOS-TEXT mode programming, considered as obsolete and details 

Introduction Serial Communications

There are a number of ways that the serial port can be used. Modems,
 bar code readers, and many other devices deliver data over this port or
 are regulated by it. Although standards do exist, in the final
 analysis, the type of communication is different every time.
The functions in this chapter offer possibilities for data transmission
 and allow you to influence control signals. These functions do not
 support any particular protocol or any specific instrument. For a few
 expanded applications, like the XMODEM protocol, you should find
 sufficient information in the example programs for Clipper Tools.
Port Parameters
All the parameters for the port, like baud rate, parity, file length,
 and stop bits, are fully adjustable. It is possible to change the
 settings for a port without closing it. In this way the transmission
 speed can be changed without losing the contents of the buffer or
 terminating an existing connection (DTR-signal).
Data Transmission
Using Clipper Tools, you can use up to four serial ports
 simultaneously. You can create a sending and a receiving buffer of up
 to 64kB in size. The characters for the background transmission mode
 are placed in the sending buffer, while characters received through the
 port are stored using an interrupt handler. You can determine the
 number of characters in the receive buffer from your Clipper program,
 and as many of the available characters as you like can be read.
 Additional special control functions exist for the sending buffer that
 give the governing program full control. It is also possible to engage
 a software or hardware handshake that is performed completely in the
As previously mentioned, Clipper Tools functions support both a
 hardware and software handshake. As soon as the receiving buffer
 threatens to overflow by at least one page, a special handshake
 character is transmitted that tells the other side that no further data
 should be transmitted. Whether you implement the hardware or software
 handshake depends upon the type of data transmission. Hardware
 handshakes use physical port controls. These port controls are usually
 RTS and CTS, so within the scope of Clipper Tools functions, these
 control ports cannot be used for modem transmission. Modems are
 generally not able to reproduce port controls directly over the
 transmission route (i.e. telephone connection). A software handshake
 must be implemented in such cases.
A software handshake uses characters from the ASCII character set to
 control the data flow. The ASCII character set is a standard which
 defines the XOFF (stop data, transmission off) as CHR(19) and the XON
 (continue transmission, transmission on) as CHR(17). (You will
 recognize the similarity to your keyboard since CHR(19) corresponds to
 Ctrl-S, and CHR(17) corresponds to Ctrl-Q).
If one of the handshake processes is implemented, the software must test
 both sides to see if the receiving buffer has been filled. The software
 then either deactivates the CTS controls or sends an XOFF character. By
 contrast, when sending data you must constantly test to see if the RTS
 input from the remote station has been deactivated or if an XOFF
 character has been received. In both cases transmission must stop
Since you can never be sure if the remote stations stop immediately
 after receiving an XOFF character, the internal handshake becomes active
 when the buffer is 75% full. If the remote stations ignore the
 handshake, the 75% limit is probably insufficient at a set buffer size
 of 100 byte (which equals a 25 byte reserve).
The techniques described here for the handshake are managed completely
 by the Clipper Tools routines. They do not concern themselves with
 the interface cards or the Universal Asynchronous Receiver Transmitters
 (UARTS). It is sufficient to activate the selected method, which allows
 your program to regulate the status of the sending and receiving buffers
 on an ongoing basis.
As previously mentioned, remote data transmission is, as a rule,
 implemented only through a software handshake. A significant
 disadvantage to this method is that the characters used for flow
 control, CHR (19) and CHR(17) can no longer appear in the original data.
 Because these characters appear in binary files, remote data
 transmission is not possible -- transmission protocols must be used.
 You find XMODEM routines written in Clipper in the example programs.
 Using the Clipper Tools port functions and this example as a basis,
 other protocols can be developed fairly simply.
Firm protocols are not provided within Clipper Tools because their
 realization in Clipper code presents no real advantage. It is more
 important that you have the ability to create your own protocols so that
 you are not locked into whatever protocol is within Clipper Tools.
Control Signals
You can set or query all important port connector control signals, like
 CD (carrier detect), DTR (data terminal ready), etc.. To simplify your
 programming, there is a separate function for each signal. For all
 other status and control information, which is seldom required in serial
 communications, you can read or describe the corresponding UARTS
 register of the port directly.
Direct Hardware Access
All Clipper Tools port functions directly address the hardware.
 Working over BIOS or even DOS calls would be impractical or even
 impossible. We therefore presuppose 100% hardware compatibility with
 the established IBM personal computer industry standard.
In order to guarantee that everything is functioning properly, both
 ports must be equipped with either UART 8250 or the compatible 16450.
 When you use the 8250, interrupt controlled transmission is only
 possible up to 2400 baud. Technical details regarding the ports and the
 UART registers can be found in the corresponding technical instructions,
 like the IBM Technical Reference Manuals.
I/O Addresses and Interrupt Requests
Clipper Tools assumes the following basic settings for the four
Table 1: Standard Port Settings
 Port I/O Address IRQ
 COM1: 3F8H 4
 COM2: 2F8H 3
 COM3: 3E8H 4 - Not specifically defined
 COM4: 2E8H 3 - Not specifically defined
In contrast to COM1 and COM2, the I/O addresses and IRQs for other ports
 are often different. If you want to use hardware that is not entirely
 compatible, Clipper Tools has additional functions that you can use:
 COM_SETIO() and COM_SETIRQ(). When you use these functions, the I/O and
 IRQ settings for the port routines can be changed to the selected
 values. However, please notice that incorrect settings can have a wide
 range of consequences when they come in conflict with other hardware.
 These consequences include data loss or damage to hardware.
The correct settings for your hardware can be found at any given time in
 its accompanying documentation.
Possible Hardware Conflicts
Clipper Tools recognizes the four addresses mentioned above for the
 ports COM1 to COM4. The COM_NUM() function uses these addresses to
 determine the number of available ports. For example, if the PC has a
 built-in ArcNet adapter, you can have a conflict between the I/O
 addresses. The Clipper Tools routine addresses 02EAh, which is
 defined totally differently for the ArcNet adapter than for a serial
 interface. In this case an existing network connection would probably
 be disconnected. The COM_SETIO() function can provide assistance by
 designating the second parameter as 0:
The corresponding standard address within the internal address table is
 deleted and access to other hardware is avoided. However, this is only
 possible if the COM_NUM() function has not previously been called within
 the program. (In this case the interface would have already been marked
 "in use.")
Important Notes
As the table of default settings indicates, it is possible for multiple
 ports to use the same IRQ -- a procedure known as interrupt sharing.
While Clipper Tools functions support these procedures, standard port
 hardware usually does not. Specialized multiple port cards are
 available from different manufacturers for this purpose.
Generally we cannot guarantee that interrupt sharing can be
Clipper Tools supports up to four ports, each with sending and
 receiving buffers of up to 64kB and speed of up to 19200 baud. This is
 not to say that all this could be used at the same time to its highest
 limit. Eight buffers at 64kB are not possible. The buffers must be in
 conventional memory because the buffers are handled by interrupt
 routines. The number of ports and the speed with which they can
 function correctly is dependent upon the computer being used.
Differences from BASIC
In contrast to other programming languages (like BASIC),
 COM_OPEN()/COM_INIT() do not influence control signals. If you want to
 address a modem over the serial port using Clipper, you must set DTR
 and any other signals yourself, using the corresponding Clipper Tools

Note :

    This section of CTools  considered as obsolete and details skipped.


Introduction Window Functions

Introduction Window Functions


It is hard to imagine using Clipper without using windows. Windows
 are the best way to show multiple tasks so you can get a genuine
 overview of the system operation. The functions in this chapter offer a
 particularly valuable extension to Clipper in this area.

The Window System

If you are only working with one screen, the Clipper Tools functions
 permit up to 255 windows, depending on available memory. In conjunction
 with the MONISWITCH() function from the Video Function chapter,
 Clipper Tools can even support two screens linked to a single CPU,
 with one monochrome screen and one color screen. In this way two
 entirely independent window systems, each with 255 windows, are
The window functions take into account the fact that Clipper Tools
 supports larger screens than the common 25 rows x 80 columns. A screen,
 and therefore also a window, can be up to 255 rows or 255 columns in
 size. However, the complete contents of a screen can never require more
 than 32 KB of memory. So with 255 rows, no more than 128 columns are
Moving Interactively
As soon as SCROLL LOCK is activated, the active window can be moved with
 different cursor keys. Depending on how you open them, windows can even
 overlap. The gray Plus key in the numeric key pad works like the
 function WCENTER(). You use the Plus key to move a partially visible
 window back into a completely visible area. All window movements done
 after you activate SCROLL LOCK can be undone using the ESC key.

Programming with Window Functions
. Each window is assigned a number between 1 and 255 when it is
 opened. This number is known as the window handle. Handle 0 is the
 original screen, with no open windows. The window handle returned
 will be used to refer to that window during programming. (For
 example, you need the window handle when you select a background
WMODE(.T., .T., .T., .T.) // Overlap permitted
nWindow1 := WOPEN(....)
 nWindow2 := WOPEN(....) // This is the active window
WSELECT(nWindow1) // Activate first window
. The coordinates used for screen output are relative only to
 the selected window, and not the entire screen.
nWindow1 := WOPEN(....) // Selected window
@ 02, 02 SAY "Clipper Tools"
. Since a window behaves exactly as the normal screen would,
 QOUT() style output (?, ??, etc.) will be scrolled up as soon as it
 reaches the bottom row.
. The window in the following example, which extends to row 24,
 will not overwrite the help message on row 25:
@ 24, 00 SAY "........ HELP-ROW........"
 nWindow1 := WOPEN(0, 0, 23, 79) // Protects the last row
 FOR nI = 1 TO 100
 ? "Clipper Tools ...."
. A window displays as a full value, but is a virtual screen,
 which differs from the original physical screen only in size.
 Extended drivers make the MAXROW() and MAXCOL() functions available
 in a version enhanced over and above Clipper to accommodate the
 changed size. Now the coordinates of virtual screens can also be
 determined; these functions return the last row or column concerned
 with the currently selected window:
nWindow1 := WOPEN(10, 10, 20, 60)
? MAXROW() // Row: 10
 ? MAXCOL() // Column: 50
. The underlying screen area is saved automatically when a new
 window is opened. This applies equally to any area of the screen
 that becomes overlapped by the movement of a window. At the same
 time, all settings in the areas that have been overwritten are saved.
 These settings include cursor shape and position, as well as color
 attributes. So you do not have to save anything out of the affected
 screen area; Clipper Tools takes over this task automatically.
. The following example shows you how the window functions save
 both the color and cursor setting:
SET COLOR TO R // Set color RED
 ? "Test-Text 1 ..." // Output in RED
 nWindow1 := WOPEN(10, 10, 20, 55)
 WBOX() // RED window border
 SET COLOR TO BG // Set color CYAN
 ? "Test-Text 2 ..." // Output in CYAN
 INKEY(0) // Wait for keystroke
 WFCLOSE() // Close window again
? "Test-Text 3 ..." // Output again in RED
 // and directly below "Text 1"

Active Windows
After you close a window, the active window with the highest handle is
 the one selected, not the window that was previously active. If, for
 example, the highest window handle is 9 and window 5 was just selected,
 a newly opened window is assigned handle 10. However, after you close
 this window number 10, window 9 is selected. It is therefore important
 to save the window's handle to a variable when you open it, so that you
 can select the required window later.
You can save the active window handle by calling WSELECT() with no
. The external output of programs called with RUN within a
 Clipper program can be tied to windows:
 nWindow1 := WOPEN(10, 10, 22, 70)
 RUN DIR // Display results in window
The only prerequisite is that such output is through DOS or BIOS. The
 DSETWINDOW() function controls whether or not this output is
 subsequently redirected. The Extended Driver chapter has more details.
In addition to the examples shown here there are many more window
 functions available for use that contribute to a comprehensive windows

Note : "Window" concept of Clipper Tools related only text (DOS) mode 
programming. It's superseded by GUI programming concepts and at least 
GT (General Terminal) facilities of Harbour.

RG Summaries

Reference Guides Summaries Overview

Like almost all materials in this blog, almost all materials in this section /category are compiled / copy-pasted from anywhere; neither original nor complete. You can use them only under your own risk.

Clipper 5.x

Clipper 5.3 Guide (Summary)

Clipper 5.x – Drivers Guide

Clipper Tools


NanForum Toolkit


Tools — GET/READ Functions

Introduction GET/READ Functions
COUNTGETS()  Determines the number of posted GET fields
CURRENTGET() Determines the number of the currently active GET field
GETFLDCOL()  Determines the screen column of a GET field
GETFLDROW()  Determines the row of a GET field on the screen
GETFLDVAR()  Determines the name of a GET field
GETINPUT()   Keyboard input function similar to a GET field
GETSECRET()  Keyboard input function for hidden input similar to a GET field
RESTGETS()   Restores GET settings from an array
RESTSETKEY() Restores SET KEY..TO settings from an array
SAVEGETS()   Saves the GET settings of the active environment
SAVESETKEY() Saves SET KEY..TO settings in an array

Tools – PEEK/POKE Functions

Introduction PEEK/POKE Functions
INBYTE()   Reads an 8 byte from a port
INWORD()   Reads in a 16-bit word from a port
OUTBYTE()  Sends a byte to a port
OUTWORD()  Sends a 16-bit word to a port
PEEKBYTE() Reads a byte from memory
PEEKSTR()  Reads a byte sequence from memory
PEEKWORD() Reads a 16-bit word from memory
POKEBYTE() Writes a byte to memory
POKEWORD() Writes a 16-bit word to memory

Tools — Mathematical Functions

Introduction Mathematical Functions
ACOS()    Computes the cosine arc
ASIN()    Computes the sine arc
ATAN()    Computes the tangent arc
ATN2()    Computes the angle size from the sine and cosine
CEILING() Rounds up to the next integer
COS()     Computes the cosine
COT()     Computes the cotangent
DTOR()    Converts from a degree to radian measure
FACT()    Computes the factorial
FLOOR()   Rounds down to the next integer
FV()      Computes future value of capital
GETPREC() Determines the level of precision that is set
LOG10()   Computes the common logarithm
PAYMENT() Computes the periodic payment amount
PERIODS() Computes number of payment periods necessary to repay a loan
PI()      Returns pi with the highest degree of accuracy
PV()      Computes the cash present value after interest charges
RATE()    Computes the interest rate for a loan
RTOD()    Converts from a radian to degree measure
SETPREC() Sets the precision level for trigonometric functions
SIGN()    Determines the mathematical sign of a number
SIN()     Computes the sine of a radian value
TAN()     Computes the tangent of a radian value

Tools – Miscellaneous Functions

Introduction Miscellaneous Functions
ALLOFREE()*  Determines the maximum memory size allocation
BLANK()      Creates a blank value for each data type
COMPLEMENT() Forms the complement value of a data type
DATATYPE()*  Determines the data type of a variable or UDF
GETTIC()     Determines the number of timer ticks
KBDDISABLE() Locks/unlocks the keyboard
KBDEMULATE() Inserts characters into BIOS keyboard buffer to emulate input
KBDSPEED()   Sets keyboard auto repeat speed
KBDSTAT()    Tests for key shift state status, such as Ctrl and Shift
KBDTYPE()    Determines the type of keyboard in use
KEYSEC()     Triggers a key trap after a time delay
KEYTIME()    Triggers a key trap at a specific clock time
MILLISEC()   Time delay in milliseconds
NUL()        Converts the value returned by a function into a null string
SCANKEY()    Queries scan code of keyboard input
SETTIC()     Increases number of time ticks
SHOWKEY()    Continuously displays the INSERT and LOCK status
SOUND()      Creates tones (melodies) by designating frequency and duration
SPEED()      A comparison value used to determine the processor speed
STACKFREE()  Determines the remaining stack space
TOOLVER()    Queries the version number of the Clipper Tools in use
XTOC()       Converts an expression of any data type into a string