The functions in this chapter provide access to the Netware broadcast message system. With the utility SEND, Netware allows you to send messages between workstations. The NNETSN() functions of CA-Clipper Tools make it possible to send messages from within a CA-Clipper application.
Each Netware user knows the problem of getting a message during a running application: the application is usually interrupted when a message is received. CA-Clipper Tools provide two possibilities to solve this problem: suppressing incoming messages with the NNETBRDCST() function (corresponding to the Novell utility CASTOFF) or using the CA-Clipper Tools broadcast system. The broadcast system allows you to receive messages in the background and read the messages later from the broadcast buffer.
The functions of this chapter allow the start and termination of capture processes from within a CA-Clipper application. Additionally, the most important parameters for a capture process can be set.
The Print Job Definition chapter can be substituted for these functions. When working with print job definitions you do not have to worry about the settings of capture processes. You only have to activate a print job definition that can be created and maintained with the Novell utility PRINTCON.EXE.
This chapter provides functions that return information about the connection between workstations and file servers and allow you to set up or terminate connections. Even the login of a user from within a CA-Clipper application is possible. With the functions in this chapter, you can create a list of file servers within the internal network and all attached file servers, and you can determine the network address of a workstation.
Important! The term "attach" in conjunction with CA-Clipper Tools only describes the setup of a logical connection between a workstation and a file server and does not include a login, as is the case with the Novell utility ATTACH.EXE.
The functions presented in this chapter are a useful extension of database handling. For example, you can determine if there is a memo file (.dbt) associated with a database, the number of decimal places, or the data type of a particular field.
This section contains functions that make many date computations easier to perform. Date-type values have been a feature of the xBASE language standard, and is preserved in CA-Clipper. In spite of this, it is always necessary to develop UDFs to execute certain technical financial computations. CA-Clipper Tools offers an alternative that not only spares you the work of writing a UDF, but also provides implementation in Assembler to guarantee fast execution.
This chapter also contains clock time functions. These include time changes, time span computations, time control of loops, and memory- resident clock display.
Please note that valid date tests are already carried out in CA-Clipper. CA-Clipper internal date tests cannot be canceled, so it is impossible to implement an individual UDF for error handling , if there is an invalid date.
CA-Clipper always replaces an invalid date with a null date. These internal tests are carried out by keyboard input, as well as by CToD() allocation. For this reason, there are no examples with invalid dates in the date function descriptions. Rather, the result of a function with a null date is shown.
Netware provides the ability to manage printer and form information in a database (NET$PRN.DAT). The functions of this chapter allow a read access to the contents of NET$PRN.DAT and make it possible to connect an application's printer management with Netware.
One of the biggest problems in stable application development is how to handle errors. Errors that occur during hard or floppy disk operations are especially frustrating. You may also encounter critical errors, which disable the program or operating system. The result, known to all CA-Clipper programmers, are the DOS error choices: (A)bort, (R)etry, (I)gnore.
Avoiding Errors
Error trap functions allow you to react to this type of error, but a strategy to avoid them completely is better. Therefore, CA-Clipper Tools includes functions to make it easier to handle floppy and hard disk errors.
Backup Systems
Backup systems, another component of the CA-Clipper application, are also discussed in this chapter. The recursive FileSeek() system, which allows you to format disks with DISKFORMAT(), is particularly useful. Complete directories can be scanned recursively, and queries regarding detailed information for every file can be made. The ideal time to carry out this process is during source and target drive back ups, because only the information that has changed is copied.
To avoid the annoying and not particularly fault-tolerant "RUN FORMAT", you can format the file disks directly from the application in all commonly available formats. Since the control UDF for DISKFORMAT() uses a concept similar to dbEdit(), you can display the format procedures on the screen as desired.
You can also determine a good deal of varied information about disk drives, files, and other things. This information far exceeds that of the FileSeek() system.
File Attributes
Following is the coding for each function where a file can be designated:
Table 1:
Value Symb. constants Assigned attribute
0 FA_NORMAL
1 FA_READONLY READ ONLY
2 FA_HIDDEN HIDDEN
4 FA_SYSTEM SYSTEM
8 FA_VOLUME VOLUME
16 FA_DIRECTORY DIR
32 FA_ARCHIVE ARCHIVE
If multiple attributes are implemented for a file, then the table values are added accordingly. For example, if the HIDDEN and SYSTEM attributes are implemented, the function must pass a 6 (2 + 4) as the attribute mask.
All file attributes do not behave the same. To initiate a file into the process, you must explicitly specify the HIDDEN, SYSTEM, VOLUME and DIR attributes. However, if either no attribute, R/O, or ARCHIVE is implemented with a file, it does not matter which value is passed. These rules for attribute handling are grounded in DOS, which compares the specified value with the actual file attributes in this way. Since in some circumstances this may lead to problems, the FileSeek() function allows you to switch on an additional EXACT ATTRIBUTE MATCHING.
Share Modes
For DOS version 3.0 or higher, if a function uses the DOS OPEN FILE call internally, it must pass a share mode. This way, one station determines how all other stations in the network can access the open file. This is valid for as long as the file remains open. The following variations exist:
Table 3: Share Mode
Code Symb. constants Share Modes
0 SHARE_COMPAT Compatibility mode. Here, DOS or the
network software itself, determines the
share mode. In Novell networks, the
SHAREABLE attribute plays an important role
in this relationship.
1 SHARE_EXCLUSIVE Both read and write by other programs are
locked out
2 SHARE_DENYWRITE Write by other programs are locked out
3 SHARE_DENYREAD Read by other programs are locked out
4 SHARE_DENYNONE Not locked. Read and write by other
programs is allowed
With the basic setting, all files are opened in the compatibility mode (relating to older DOS). As a rule, the share mode depends on file attributes or the network software setting.
Also in this chapter is the SETSHARE() function, which determines the share mode that enables all CA-Clipper Tools functions to open a file. CA-Clipper commands or functions are not affected in any way.
Use the CSetSafety() function as a safety switch to protect existing files from unwanted overwriting during file operations with CA-Clipper Tools functions. You will find this function in the chapter on Switches and Status Information, since it concerns all CA-Clipper Tools file operations.
The functions in this chapter let you manipulate the drive mapping of workstations. New mappings can be executed, and existing mappings can be deleted. Furthermore, you can query information about current mappings. The basic function of this group of functions is NNETMAP(). NNETMAP() is used to create or delete an allocation. All extended possibilities, such as search drives and fake roots, are supported. Drive mappings can be defined temporarily. Temporary mappings are deleted automatically at the end of an application.
In conjunction with the ability to log in a user with NNETLOGIN(), the functions of this chapter allow you to set up the complete network environment of a workstation within an application.
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 CA-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.
b>The Use of CTUS.LIB
The extended driver is delivered as an .OBJ file (CTUS.OBJ) to allow replacement of the CA-Clipper driver module in CLIPPER.LIB during linking. The extended driver must be included in the list of object files.
b>Video Modes
Some functions which relate to screen adapters are found in the Video Modes chapter rather than in the Video Functions chapter.
This is a very important switch for CA-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. (CA-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.
b>System Settings Are Saved
When you end an application under CA-Clipper's control (normal program termination, Alt-C, or ending after a CA-Clipper error message), the cursor type, color attribute, and interrupt vectors 0 to 127 are restored.
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.
b>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 CA-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().
This chapter includes network functions for IBM PC LAN/Microsoft MS-NET software.
b>PC LAN/MS-NET
PC LAN/MS-NET is software that has been offered for networks by IBM and Microsoft. Both programs are based upon the NETBIOS protocol; CA-Clipper does not directly affect the NETBIOS protocol. All internal function calls to the network software occur under DOS, which requires version 3.1 or higher. The functions in this group are in the format NETXXX().
An exception is the NetDisk() function. It can also determine whether a drive is local or remote under other network software. This assumes that the network software properly supports DOS in the background.
CA-Clipper enables you to program nested GET/READ masks. The functions in this chapter are retained in CA-Clipper Tools for compatibility reasons and to make them easy to use.
The active GET is saved with the help of a character string and restored through this string later. This allows you to newly query inputs without losing your main input mask. You can save KEYTRAP() definitions the same way and redefine them as you wish.
Important! It is impossible to use the saved information any longer that the runtime of an application. The character string that results cannot be saved to a file and reloaded later.
Other functions in this chapter return information about GET fields, such as screen position, the names of the accompanying variables, or information about whether a field is currently active.
CA-Clipper Tools was designed for use with the CA-Clipper compiler. Therefore it should only be used on IBM PC/XTs, PC/ATs, or completely compatible systems. The screen functions may not work on a system where a modified CA-Clipper driver module has been used. (The string functions, on the other hand, are generally hardware independent.)
CA-Clipper Tools requires PC-DOS or MS-DOS, version 2.10 or higher, but some functions work with system calls which are not supported until PC/MS-DOS version 3.1 or higher. This applies, for example, to network functions: if you work with network functions under a DOS version earlier than 3.1, the functions will not work properly.
We cannot guarantee that CA-Clipper Tools will work under any operating system other than PC-DOS or MS-DOS.
Installation Program
CA-Clipper Tools is supplied with an installation program, located on Disk 1. To install CA-Clipper Tools, perform the following steps:
■ Insert Disk 1 in drive A
■ Type A: and press Return to change the default drive to A
■ Type INSTALL and press Return to start the installation
procedure
The installation procedure is self-explanatory. You will be prompted to insert other disks as the installation program needs them. (Some of the files are compressed; therefore you cannot use the DOS COPY command to copy them to your hard disk. You must use the installation program.)
When the installation is complete, read the READ.ME file (located on disk 1) to learn about any last minute changes or enhancements.
Compatibility
CA-Clipper Tools is generally compatible with previous versions, but there are some deviations. If you require full compatibility for existing applications developed under CA-Clipper S'87, you must link in the #include file ct.ch. Notice, however, that we do not recommend this procedure for development of new applications.
As CA-Clipper develops, some of the functions in previous versions of the CA-Clipper Tools program are no longer meaningful. These functions remain unchanged in CA-Clipper Tools to avoid problems during the compilation of existing applications, but they have been flagged with asterisks (*) at the function name. Again, we do not recommend that you use these functions to develop new applications.
Documentation
All of the CA-Clipper Tools functions are described in detail in this four-volume Reference Guide. To allow you to find the function you need in a particular situation, the Reference Guide is divided into chapters. Each chapter presents a group of functions that serve a particular purpose, such as date functions, database functions, or system functions. Each function is then described in detail on a separate page. Appendixes provide keyboard tables, DOS error codes, and Novell network error codes.
A Quick Reference Guide gives the complete syntax and a short description of every function. In this booklet, the functions are organized in alphabetical order for quick reference. A chapter and page number tells you where to look in this four-volume Reference Guide for a complete description of the function.
The CA-Clipper Tools software contains a text retrieval system that lets you search online for the expression you need. This text retrieval system finds the appropriate function for your purpose in seconds — even if you don't know what that function is — and provides complete documentation on that function online.
CA-Clipper Tools contains over 800 functions which you can use to develop CA-Clipper applications and system-level routines. These functions give CA-Clipper programmers capabilities previously reserved for C or Assembler programmers with detailed system knowledge.
In order to use working memory as economically as possible, virtually all the functions are written in Assembler and are highly optimized. This guarantees high speed with a minimal use of memory. This efficiency is further supported by the modularity of the software within the CA-Clipper Tools library.
Each Netware file server maintains a database of users and resources available on the network. This special-purpose database is called the bindery. The bindery contains objects uniquely specified by an object name and an object type. Possible object types are: users, user groups, print queues, or print servers. Each object has associated with it a number of properties that can be addressed with names and contain information about the object. For example, the property GROUPS_I'M_IN contains a list of user groups of which a user is a member.
The functions of this chapter allow a low level access to the bindery. This provides you with maximum flexibility for programming within Novell. The low level functions allow the creation of your own bindery objects as well as the development of bindery analyzers.
However, even though the bindery concept has a high security level, incorrect use of the low level bindery functions can be very dangerous if you have supervisor or equivalent access rights. The network could be brought to a standstill. You should use these functions only with extensive knowledge of the bindery concept, the Novell API, and bindery management. For example, you must know the terms object, item, and set property.
For frequent, complex purposes that require bindery access, like adding a user to a group, CA-Clipper Tools provides high level functions that can be used without a problem. These functions are based on the low level functions and are available in CA-Clipper source code.
Netware internally uses a high low sequence to store numeric values, which is contrary to the standard format of the 80x86 processor family (low high sequence). For efficiency reasons, the Netware functions of CA-Clipper Tools expect numeric values that are passed to Netware (object types or object IDs) in the high low sequence. However, this will not affect the practical work with the CA-Clipper Tools because symbolic constants are defined in the high-low format in the header file CTNNET.CH for the most important object types.
This chapter offers an array of interesting mathematical functions to implement in CA-Clipper. It includes trigonometric functions, finance- oriented math computations, and functions to determine the factorial, sign, or the next-largest integer of a value.
SetPrec() is important for trigonometric functions. With this function you can specify the precision as a number of places to the right of the decimal. However, if it is less accurate, the speed is greater.
Functions that do not belong in any other module are assembled in this group under the Miscellaneous heading. However, this does not imply they are less useful. For example, use KeyTime() or KeySec() to activate a CA-Clipper procedure at a specific time, after a delay of seconds, implement file saves, or control demo programs.
This module enables you to determine complements, determine data types, and query keyboard scan codes.
b>Passing Parameters by Reference
Finally, this chapter discusses functions that permit you to pass parameters by reference. To find more information on this subject, see Chapter 4, String Manipulations.
This chapter contains some useful functions that do not belong in any other chapter of network functions. The functions HexToStr() and StrToHex() are not network functions, but these functions have been included in CA-Clipper Tools specifically for working with internet addresses that are returned or are required by functions such as NNETADR() or IPXOPEN(). The function NNETVER() is very useful if you are developing applications that access Netware 2.2 and Netware 3.11 servers because the behavior of some CA-Clipper Tools functions depends on the Netware version used (for example, NNETRIGHTS(), NNETPURGE()). Other functions are available for only one Netware version (for example, NNETSNDLOG(), NNETSALLST()).
This module discusses number and bit manipulation. Specifically, the numeric section deals with conversions between two different number systems, and the creation of random numbers.
The bit manipulation section covers such required binary operations as AND, OR, XOR, and NOT, and how to test, set and clear bits. The NumLow() and NumHigh() functions are important for CA-Clipper Tools functions that take two 8-bit values and return them as combined 16-bit numbers. An example is the GETCURSOR() function from the Extended Drivers module.
Many of the functions in this module have a value parameter type. In this case, a number can be in the range of 0 to 65535 (or 4 294 967 295) and/or a hexadecimal string in the range of "0000" to "FFFF" (or "FFFFFFFF").
Despite the many capabilities of CA-Clipper Tools, there are times when direct port or memory access is needed. The functions in this chapter serve this purpose. For example, you can read memory regions by byte, word, or as a string through the PEEK function. POKE functions enable you to write a byte or word to working memory, but not a string.
Warning! POKE functions can be very dangerous. If you write to the wrong area in memory it can cause a lot of problems you may not foresee. Use POKE functions ONLY if you have extensive system knowledge.
This also applies to all the IN/OUT functions in this chapter, which allow you to directly manipulate a port. For example, if you address a disk controller improperly, the result may lead to data loss.
The CA-Clipper Tools contain functions that allow direct communication between workstations in Novell or NetBIOS compatible networks by bypassing the file server. This type of communication is called Point- To-Point communication.
The data exchange between two workstations is interrupt controlled. Incoming data is copied in the background to a receiving buffer and can then be read with CA-Clipper Tools functions. As soon as the receiving buffer is full, incoming data is discarded. Outgoing data is copied to a sending buffer. While the CA-Clipper application continues, data is sent in the background from the sending buffer to the target address. Interrupt controlled sending of data is necessary to avoid a long wait when you send large datasets. When you use IPX/SPX communication or one of two possible NetBIOS communication variants, the data is broken up into packets internally. The packet size depends on the protocol used (IPX: 546 bytes, SPX: 534 bytes, NetBIOS: 512 bytes). The packets are sent sequentially.
Normally, the packet structure of the transmitted data is transparent and does not affect the handling of the data. The receiving buffer of the target workstation receives the data in the same way that the data has been written to the sending buffer. When you use IPX/SPX protocols in addition to the data, a header that is included in each IPX or SPX packet can be transmitted to the receiving buffer. This header makes a number of packet specific functions possible. The tables 31.1 and 31.2 describe the structure of the IPX and SPX header. The header positions start with 1, corresponding to string functions.
The NetBIOS communication variants have no similar mechanism available.
Table 31.1: IPX Packet Header
Position Length Description
1 2 Checksum
3 2 Packet length in bytes
5 1 Transmission control
6 1 Packet type (4=IPX)
7 4 Network number of target station
11 6 Station ID of target station
17 2 Target socket (High, Low format)
19 4 Network number of source station
23 6 Station ID of source station
29 2 Source socket (High, Low format)
Table 31.2: SPX Packet Header
Position Length Description
1 2 Check sum
3 2 Packet length in bytes
5 1 Transmission control
6 1 Packet type (5=SPX)
7 4 Network number of target station
11 6 Station ID of target station
17 2 Target socket (High, Low format)
19 4 Network number of source station
23 6 Stations ID of source station
29 2 Source socket (High, Low format)
31 1 Connection control
32 1 Datastream type
33 2 Connection number on source station (High, Low format)
35 2 Connection number on target station (High, Low format)
37 2 Sequence number (High, Low format)
39 2 Acknowledge number (High, Low format)
41 2 Allocation number (High, Low format)
When you install a communication buffer (a communication buffer can contain a sending and a receiving buffer), you receive a communication handle as a return value. You should store this handle in a variable as it is absolutely necessary for further operations with the communication buffer.
The functions for Point-To-Point communication fall into two groups: protocol specific functions and functions that can be used for any kind of communication buffer. Protocol specific functions are functions for a connection setup: (IPXOPEN(), SPXESTBCON(), SPXLISTCON(), NBDOPEN(), NBSCALL(), and NBSLISTCON()). The name of a protocol specific function always starts with three characters that describe the respective protocol (IPX, SPX, NBD: NetBIOS Datagram, NBS: NetBIOS Session).
Functions that write or read a buffer, or query the buffer status, are not protocol specific and can be used for any kind of communication buffer. The names of these functions start with PPC (Point-To-Point Communication). For example, the function PPCWRITE() is used to write data to a communication buffer. The protocol specific process of the data is regulated internally.
IPX/SPX Communication
Novell Netware (including Netware Lite) allows the direct use of the IPX and SPX communication functions. By loading the Novell NetBIOS emulator (NETBIOS.EXE), you can also use NetBIOS communication functions in Novell networks. However, the use of the emulator compared to IPX/SPX reduces the performance and the available memory. Therefore, you should use the IPX/SPX communication functions for applications running only in Novell networks.
IPX (Internetwork Packet Exchange Protocol) is a rudimentary protocol whose main advantage is that data can be sent to all waiting workstations in an internal network with only one call. However, IPX has no suitable handshake mechanism available that guarantees a successful delivery and a correct process of the sent data on the destination workstation. (Related mechanisms can be implemented with the IPX functions of CA-Clipper Tools. However, these mechanisms are application specific and have no general validity.)
The SPX protocol (Sequenced Packet Exchange Protocol) only allows communication between two workstations within an internal network. SPX has mechanisms available that guarantee the successful delivery of sent data.
Unlike SPX, which can be seen as real Point-To-Point communication protocol, the IPX communication is implemented as a pseudo Point-To- Point communication. When you use IPX, data for a specific workstation can be received by any workstation. However, a destination address is defined for interrupt controlled sending. (This address can specify all workstations within an internal network.) The destination address is not defined by the protocol, so it is not necessary to specify the destination address each time you access the send buffer. When you use the SPX protocol, a connection between two workstations is established.
The IPX/SPX communication between two workstations is based on two sockets on each side of the connection that can be opened and closed, similar to files. Sockets are represented by numeric values between 1 and 65535. Some socket numbers are reserved either by the Netware operating system or by Novell for third party vendors. The sockets between 16384 and 20480 (4000h - 5000h) are the dynamic sockets, meaning there are no reserved sockets in this range. A collision with socket numbers reserved by Netware can be avoided by using sockets out of that range.
NetBIOS Communication
The NetBIOS communication functions can be used in all networks that are based on NetBIOS specifications. In CA-Clipper Tools, two kinds of NetBIOS communication have been implemented: NetBIOS datagram and NetBIOS session communication. The NetBIOS datagram communication can be compared to the IPX communication; a successful delivery of sent data on the destination workstation is not guaranteed by the protocol. Like IPX, the datagram connection can also be implemented as pseudo Point-To- Point communication between two workstations. Additionally, a workstation can communicate with a group of workstations or with all workstations in a network.
Like an SPX connection, a session connection is a fixed connection between two workstations. The dataflow between two workstations is supervised internally by a protocol that guarantees the delivery of sent data on the destination workstation.
For the communication with other workstations in a NetBIOS network, NetBIOS names are used. A NetBIOS name can be up to 15 characters long and is case sensitive. NetBIOS differentiates between two kinds of names: station names that specify a workstation and are unique in a network, and group names that can be assigned to any number of stations. Each workstation contains a local name table with up to 20 NetBIOS names. A workstation can be addressed with each name in the name table. Once you have defined single or group names, messages can be sent easily to a station or a group of stations.
Because of the importance of NetBIOS names for the Point-To-Point communication, CA-Clipper Tools not only includes functions for the sending and receiving of data, but also functions for creating and deleting NetBIOS names.
With the Novell utility PRINTCON.EXE, print job definitions that contain the settings for a capture process can be created. The functions in this chapter allow you to control the print job definitions of the current users and all other users on a file server. You can create new job definitions and query or modify settings in existing definitions. It is possible to read the settings of a job definition and to directly start a capture process (NNETPJCAPF()). This function call is equivalent to a call of the CAPTURE utility with the parameter /J=.
Important! Within the Netware documentation the term "job" is used to describe a print job within a queue and also a set of capture parameters (print job definition). Within this chapter the term "job" or "job definition" only describes the definition of capture parameters.
The functions in this chapter cover the entire area of print queue control under Netware. Print queues can be created or deleted. Users, operators, and print servers for a print queue can be defined or removed. The queue functions allow you to manipulate jobs within a queue. All settings for a print job can be queried or modified if the job is not currently processed (provided that you have sufficient access rights). Jobs can be deleted or moved within a queue.
Important! Within the Netware documentation the term "job" is used to describe a print job within a queue and also to describe a set of capture parameters (print job definition). Within this chapter the term "job" only describes a print job.
Under Netware 3.x, control of network printers is no longer handled by a file server but by a print server. (However, as an NLM, the print server can also run on a file server.) Under Netware 2.2, a print server VAP is available. The functions of this chapter provide the ability to access the most important information and functions of a print server. For example, you can determine the status of a print server printer. In conjunction with the functions for Point To Point communication, a CA-Clipper application is able to emulate a remote printer (see sample program RPRINTER.PRG).
This chapter discusses printer output. Although CA-Clipper handles printer errors with an error trap, it is always better to avoid them completely. As a result, error traps for printer output will not become superfluous, since errors also occur during output. You can also determine a wide variety of information, such as the number of available printers or the printer status.
This chapter also describes functions that support DOS print spoolers. To implement these functions, prior to starting the respective application, you must run the DOS PRINT program to make the print spooler memory resident. Files can then be exclusively passed from a program to the spooler. However, you must first reroute your print output to a file (SET PRINTER TOfile), before you can output it in the background.
A semaphore controls certain states: for example, the states between two applications that run on different workstations. To enable all stations to access existing semaphores, each Netware file server has a table available to manage these semaphores.
Semaphores can be interpreted as variables kept on the file server. Each semaphore is assigned a name when it is created. A semaphore name can be up to 127 characters long and is not case sensitive. An application can access a semaphore by opening the semaphore with its name (NNETSEMOPN()).
A semaphore can be opened by any number of workstations. For each workstation, the semaphore has the same value. The semaphore value cannot be modified; however, by using specific functions it can be incremented (NNETSEMSNG()) or decrements (NNETSEMWAI()) by 1.
Each semaphore is assigned information in addition to the semaphore value. For each semaphore, the file server counts the number of stations currently accessing the semaphore. This information can be determined with the function NNETSEMOPC(). For example, a semaphore named after an application can be used to limit a resource to this application.
Semaphores are often used to implement logical lockings for any kind of resource. A semaphore is assigned to each resource. Before the resource is accessed, the application tries to decrement the semaphore's value by one (NNETSEMWAI()). If the resulting value is negative, the resource is locked by another station. When an application is finished using a semaphore's resource, the function NNETSEMSNG() must be called to increment the semaphore's value.
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 CA-Clipper Tools.
b>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).
b>Data Transmission
Using CA-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 CA-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 background.
b>Handshake
As previously mentioned, CA-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 CA-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 immediately.
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 CA-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.
b>Protocols
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 CA-Clipper in the example programs. Using the CA-Clipper Tools port functions and this example as a basis, other protocols can be developed fairly simply.
Firm protocols are not provided within CA-Clipper Tools because their realization in CA-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 CA-Clipper Tools.
b>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.
b>Direct Hardware Access
All CA-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.
b>I/O Addresses and Interrupt Requests
CA-Clipper Tools assumes the following basic settings for the four ports:
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, CA-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.
b>Possible Hardware Conflicts
CA-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 CA-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:
com_SetIO(port,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.")
b>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 CA-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 implemented.
CA-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.
b>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 CA-Clipper, you must set DTR and any other signals yourself, using the corresponding CA-Clipper Tools functions.
In this chapter, the group of functions determine the switch status and were implemented in the CA-Clipper Tools (CA-Clipper Summer 1987 release). CA-Clipper implemented the Set() function, so that these settings can be determined, set, and saved with this version. Therefore, some functions in this chapter only exist to enable compatibility with existing programs. All the affected functions are flagged with an "*".
If the functions relate to the CA-Clipper switches (SET's), the function name is represented as follows: CSET + the first four characters of the switch name. For example, if the switch is named CONFIRM, then the function that corresponds is CSETCONF(). If the parameter is optional and unspecified, the function returns the current setting for its switch, without a status change. When called with parameters, the function sets the switch to the passed value and returns the prior status as a value. In this way, a function call can both change a switch and save the old status. The logical value .T. corresponds to the ON setting of a switch; .F. corresponds to OFF.
b>Example
In the following example, the CONFIRM switch was set to .F.:
lOldValue:= CSETCONF(.T.)
After execution, the old variable lOldValue has a value of .F.; while the CONFIRM switch is ON (.T.).
In addition to their usefulness with CA-Clipper switches, these functions determine an assortment of other status information. For example, you can determine the current status of the debugger, set LASTKEY, and differentiate key traps. You can also determine the status of CAPS-LOCK, NUM-LOCK, INSERT, and SCROLL-LOCK.
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.
b>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:
VAR := "Hello" VAR := FUNCTION(VAR)
When you work with very long strings, this method takes memory and time!
Here is an example of the reference method:
VAR := "Hello" FUNCTION(@VAR)
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 reference.
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.
The functions in this chapter provide system information about the operating system (MS-DOS), the BIOS, and hardware. It determines a large number of system facts and settings — from the DOS-COUNTRY setting to the mathematical coprocessor. It is even possible to warm or cold boot a computer from within a program. In addition, you can query and set DOS VERIFY and BREAK.
This chapter provides functions for the use of the TTS within a CA-Clipper application. The use of the TTS within a CA-Clipper application requires more than start and termination or cancellation of a transaction with the related CA-Clipper Tools functions. With regard to the architecture, the application must be oriented to the specifics of TTS. The TTS takes into consideration only files managed on a server volume.
Transaction tracking occurs only on the files that have been marked as transactional. The transactional bit is an extended file attribute that can be set with the Novell utility FLAG.EXE or with the related CA-Clipper Tools function NNETEXTATT(). All files related to a .DBF file, (.NTX, .DBT) must also be marked as transactional.
The time between the start and the termination or cancellation of a transaction should be as short as possible. Avoid direct entries into database fields. Use memory variables for data input and then update the database within a transaction.
The reason for minimizing the transaction time is a characteristic of the Netware operating system that cannot be influenced by the application. When data in a file is modified, Netware physically locks the affected file area. In contrast to a logical locking with RLock(), the affected data cannot be read as long as the transaction is incomplete. If the transaction has been terminated successfully, the database record is updated. If the transaction has been interrupted, the record is reset to the previous value. A successful read access by another workstation could lead to fatal logical errors. The physical lock is removed automatically after the transaction has been completed or canceled. If a workstation tries to access a physically locked area, CA-Clipper causes an ACCESS DENIED error message and evaluates the error block. Normally, this results in a branch into the error recovery routine. An error message box is displayed, and the user can cause a repetition of the operation that failed. The error message text can be adapted to the running transaction. However, the problem is that from the beginning the application is not able to determine whether the ACCESS DENIED error results from a running transaction or another error source. Therefore, an application using the TTS should have a mechanism available that allows it to determine if a transaction is active for a specified group of files or not. Using Netware semaphores, for example, allows you to check to see if a transaction is active, either during the error recovery or before a file is accessed.
The functions of the User and Group Management chapter are based exclusively upon low level bindery accesses and could be accomplished completely with the low level bindery functions. However, working with low level bindery functions can be dangerous (see the Introduction to the Low Level Bindery Access chapter). Therefore, CA-Clipper Tools provide a number of high level functions for the most common requirements of user and group management. The functions in this chapter allow you to add or remove users, or groups of users, to or from groups. Various lists can be created: established users or groups, currently logged in users, members of a group, or groups of which a user is a member. You can determine if a user is a member of a specified group. For example, this allows you to combine the availibility of menu options with Netware settings.
A number of functions in this chapter have been developed in CA-Clipper with the use of low level bindery functions. The source code for these functions can be found on the product disks and can be used as an example for the use of the low level bindery functions.
To use the CA-Clipper Tools functions in your programs, specify the CT.LIB library during the LINK procedure. If required, also specify the CTUS.OBJ Extended Driver file. (See the section called "Extended Driver" below.)
All CA-Clipper rules apply when calling functions. For example, a function's return must not be assigned to a variable.
Both types of calls are possible:
FUNCTION(par1, par2) Var=FUNCTION(par1, par2)
Linking
CA-Clipper Tools functions can be linked with MS-LINK (often referred to as the DOS linker) as well as with RTLink.
Here is an example using MS-LINK:
LINKProg1+Prog2+CTUS,,,CT/SE:nnn/NOE
With the exception of small test programs, MS-LINK requires that a value be assigned to the /SE: switch. We cannot recommend an adequate value for nnn.
Here is an example using RTLink in FreeFormat mode:
RTLINK FIProg1,Prog2,CTUS LIB CT
RTLink also contains a positional mode. When using this mode, the link command has to be identical to that in MS-LINK. Further information regarding RTLink can be found in the CA-Clipper Programming and Utilities Guide.
PLL Files
CA-Clipper Tools cannot be implemented in conjunction with the BASE50.PLL file created at CA-Clipper installation. You can, however, create a new corresponding .PLL file with the linker script file CT.LNK included in CA-Clipper Tools. Use the following command:
RTLINK @CT
This will exchange a particular module from the CA-Clipper library as well as several I/O routines out of TERMINAL.LIB for others in CTUS.OBJ or CT.LIB. The new .PLL file is called CT.PLL. If a new .PLL file is not created, then the alternative I/O routines and therefore many of the CA-Clipper Tools functions will not work for all the programs generated via prelinking.
If the CT.PLL file has been created once, the link procedure can be called as follows:
RTLINK FIprogLIB CT PLL CT
The CTUS.OBJ Extended Driver must not be specified, since it is already in the .PLL file.
Further CA-Clipper Tools modules have not been included in this or other .LNK files, since prelinked modules are always loaded at program start and increase memory usage accordingly. Creation of a .PLL file in conjunction with other external libraries becomes an individual procedure. However, all CT.LIB modules can be prelinked. You simply need to include a public for the desired module by inserting the REFER command.
Here is an example. By inserting:
REFER COM_BREAK, ACOS
the _COM and _TRI3 modules (serial interfaces and trigonometric functions) will be prelinked. The names of the module and the publics can be determined with a library manager like MS-LIB.
CA-Clipper Libraries
None of the preceding examples mentions any of the files belonging to CA-Clipper itself. This is because, during compiling, CA-Clipper's default setting enters the names of its four libraries in the resulting .OBJ file. When you influence this procedure, for example by using the /r compiler switch, all the required libraries must be called explicitly at linking.
Static Overlays
Most functions or CA-Clipper Tools modules cannot be stored to a static overlay, as they contain interrupt service routines. They may not reside in an overlay. The functions affected are KeySec(), KeyTime(), ShowTime(), SHOWKEY(), PRINTSCR(), PRINTSCRX(), and SETTIC(), as well as serial interface functions that also work interrupt controlled.
The Extended Driver CTUS.OBJ may never be placed in an overlay, since it is needed by CA-Clipper for every input and output. Linking CTUS.OBJ in an overlay will result in a system crash immediately after the start of your application. Therefore, be aware that the overlay will always have to be loaded in order for the function to be available.
All CA-Clipper Tools functions can be called from an overlay. The program code for some functions, however, cannot be placed within an overlay.
Possible Linking Problems
When implementing CA-Clipper Tools in an existing application for the first time, the linker warning message "Duplicate Definitions" may occur. In this case, probably one of your own procedures or functions or a function from another library has a name that was also used by one of the CA-Clipper Tools functions. If the name of this other function or procedure cannot be changed, it must be specified as a separate .OBJ file. Otherwise CT.LIB must be designated as the last library.
Note, also, that an .OBJ file will always overwrite a library module with the same name, independent of its position in the LINK command line. Therefore, the CA-Clipper Tools Extended Driver is delivered as an .OBJ file.
Extended Driver
In addition to the CT.LIB library, you will find a separate .OBJ module on your disk called CTUS.OBJ. This is the CA-Clipper Tools Extended Driver. If this is linked in, it replaces the CA-Clipper library driver. Above all, the Extended Driver is important for the implementation of window functions, but it also offers other interesting possibilities. For this reason all the functions in the chapter on the Extended Driver in this Reference Guide form a part of this module.
The CTUS.OBJ must only be added to the .OBJ file list to be linked. The sequence is not important. The Extended Driver replaces the CA-Clipper library driver module, so storing out to an overlay is not possible. You will find further information in the Extended Driver chapter.
Debugging
Working with CA-Clipper Tools makes additional debugger features available. These features are also controlled via the CLIPPER environmental variable, by setting a switch DEBUG:n.
How Problems Arise
There are many possible screen modes, fonts, windows, and virtual screens, so various problems can arise. The debugger also uses windows, as you can see on the debugger Windows menu. To avoid a collision with the windows of your application, the debugger has an additional windowing system.
Working with One Screen
When working with one screen, the debugger must be able to switch between the application screen and its own screen. The contents of the application screen must be saved. This can happen in an area of the available memory or in a free screen page.
Using a screen page saves memory and offers better performance, but it takes a screen page of the application. This is, however, taken into account by CA-Clipper Tools. The MAXPAGE() function, for example, returns a reduced value. The default value for the application is screen page, which can be changed with the environmental variable.
Working with Two Screens
Working intensively with CA-Clipper Tools video functions and the debugger on one screen is difficult. For this situation, the debugger supports two screens. This is possible because the PC can operate two cards simultaneously, for example, a Hercules card and a VGA card. The application output always occurs on the screen from which it was started, while the debugger output is displayed on the other screen. This capability is set via the CLIPPER environmental variable, by specifying DEBUG:2.
DEBUG Values
The DEBUG: n switch can be set with a numeric value. Each individual bit has a certain meaning. At this time, only two bits are used:
Bit: When set: Default
1 use PAGE 1
2 two screens 0
Note: Particular switch combinations in the CLIPPER environmental variable can lead to problems. Please construct your environmental variable as follows:
SET CLIPPER=/Fnnn /Ennnn /DEBUG:2 /SWAPPATH:"path"
Reference Sensitive[@]
CA-Clipper can pass parameters of the character string type to a UDF by reference. This means that what is actually passed is a pointer to the original, thus avoiding the creation of an internal copy. When a function takes on this type of parameter and changes it, it is the original that is actually changed. Here is an example:
VAR := "Hello" MYFUNC(@VAR)
Passing of parameters by reference has advantages and disadvantages. An important advantage is that memory usage is reduced. This avoids runtime errors that result from not having enough memory for string manipulation. If, on the other hand, you do not want the original string to be changed, passing of parameters by reference is a disadvantage.
With a normal call (that is, not by reference), it is the copy that is changed by the function. The change must then be passed back to the original:
VAR := "Hello" VAR :+ MYFUNC(VAR)
Particularly in the case of long strings, this method takes up memory and time.
It is not a good idea to pass parameters by reference for most of the CA-Clipper Tools functions. (In some cases there will even be a difference in the result when a parameter is passed this way.) The functions then change the string passed as a parameter directly. This saves memory space and the functions work more quickly, since there are no internal copy procedures taking place. Watch for the [@] identifier meaning reference sensitive.
This function allows you to further optimize memory requirements and speed for different string functions. This assumes that a function is only working with data passed as a parameter and avoids internal copies of returned values as well. When CSetRef() is set, the affected function no longer returns a value.
You will find more information on this function in the chapter on string functions.
This module discusses video functions that are either directly or indirectly concerned with the screen. Included are all functions that deal with such screen adapters as CGA, EGA and Hercules. Different modes on various adapters are supported, such as a 40-column CGA, a 43- line EGA, or a 50-line VGA.
Many of the functions in this chapter depend on setting the DSETWINDOW() switch. This switch determines if the screen output of external programs, as well as DOS, are redirected to a window. CA-Clipper Tools output functions are also valid as external. If the default setting in DSETWINDOW() is .T. or on, this rerouting is carried out. Some functions will then return inaccurate, or at the very least, different results. Examples of this are ISANSI() or NUMCOL()
Attribute
Many of the functions in this module work with color attributes designated as parameters. These arguments are carried out in three different ways:
A numeric value, which corresponds to a combined color attribute (e.g., 7).
A string in the "NN/NN" form, with two specified numeric values (e.g., "7/0").
A string in the "CC/CC" form, with two specified attributes are designated in the form CA-Clipper requires (e.g., "W/N").
With many functions, the attribute returns a combined numeric value. Attributes for the foreground and background are tied together this way.
Color attributes are constructed as follows:
Bit 8 7 6 5 4 3 2 1 Attribute * R G B + R G B
_ _ _ _ _ _ / _ _ _ _ _ _
Background / Foreground
Each attribute consists of four bits, which represent a value in the range of 0 to 15. Therefore, there are a total of 16*16, or 256, different values from 0 to 255. These numeric values can be changed into the "nn/nn" format, that can be used under CA-Clipper with the NTOCOLOR function. However, it is possible to directly influence this combined attribute value. The following examples show this and relate back to the chapter on number and bit manipulation:
NumOr( nattr, 128) // Flashing on NumAnd(nattr, 127) // Flashing off NumXor(nattr, 128) // Change flashing NumOr(nattr, 8) // High intensity on NumAnd(nattr, 247) // High intensity off NumXor(nattr, 8) // Switch high intensity
Special Parameter Type
With many functions, a parameter may be of the mIcCharacter|nCharacter type (e.g., an individual character). This can occur in two different ways:
Numerically, as the ASCII code of the desired character (e.g., 7).
Alphanumeric as the character (e.g., ":").
Because of this, you must not use the Chr() function to change special characters.
CLEARA and CLEARB
Some of the CA-Clipper Tools functions use a standard attribute and character to delete lines or screen areas. This attribute is described as CLEARA; the character as CLEARB. You can query both CLEARA and CLEARB with the corresponding functions. At the same time, certain preset values are in effect for CLEARA and CLEARB. The attribute "W/N" is the standard preset for CLEARA, while Chr(255) is the character used for CLEARB. If you use this character for CLEARB, it fills the background with the corresponding color for every deletion on every screen adapter.
Use the following functions to set standard values for CLEARA and CLEARB:
If you use the SETCLEARx() functions in conjunction with the corresponding parameters (Attribute or Character), the currently existing default value is replaced by a parameter.
Clipper Functions and Commands Which Delete
If you use the CA-Clipper Extended Drivers, Chr(255) is used instead of a space for all CA-Clipper functions and commands that delete the screen in one way or another (see CLEARB). A Chr(255) is helpful on many screen adapters, since in contrast to a space, you can assign it a color. Then, the screen will not appear so fuzzy.
More precisely, the functions and commands concerned always use the delete character set by SetClearB(), which uses Chr(255) as the default setting. If you want to use a space to clear in CA-Clipper or CA-Clipper Tools, insert a SetClearB(32) into the program.
Re-implement a space for clear:
SetClearB(32) CLEAR // The affected Clipper command
Video Modes
Occasionally, there is some confusion about video modes. You will not be able to work in EGA mode just because your computer has an EGA adapter built into it. By the same token, you will not get either EGA or VGA modes, if you do not work with graphics.
EGA43 / VGA50 / VGA28, etc.
In this section, the concern is not to just get a mode "hardwired"' into a card, but for CA-Clipper Tools it is to generate corresponding fonts and other settings. For these reasons, the GETMODE() and GETSCRMODE() functions generate their own values that are greater than 255.
For example, changes to the screen mode concerned with line count can be combined with a 40-column mode:
You cannot implement functions that change the base address for screen memory while windows are open. This includes all mode changes, as well as SETPAGE and SETSCRSTR.
This chapter combines functions that deal with server volumes and files on server volumes. The NNETVOLXXX() functions return information about server volumes. The functions, NNETDIRS() and NNETFILES(), allow you to determine extended directory information (analogous to the Novell utility NDIR). The chapter also includes functions used to query and set rights, extended file attributes, and functions that can perform the tasks of the Novell utilities PURGE and SALVAGE. The operation of the functions NNETPURGE() and NNETSALVAG() depends on the Netware version.
It is hard to imagine using CA-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 CA-Clipper in this area.
b>The Window System
If you are only working with one screen, the CA-Clipper Tools functions permit up to 255 windows, depending on available memory. In conjunction with the MONISWITCH() function from the Video Function chapter, CA-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 available.
The window functions take into account the fact that CA-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 possible.
b>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.
b>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 window.)
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 "CA-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
? "CA-Clipper Tools ...."
NEXT nI
■ 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 CA-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:
■ 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; CA-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"
b>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 parameters.
■ The external output of programs called with RUN within a
CA-Clipper program can be tied to windows:
DSETWINDOW(.T.) 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 system.
cString [@] Designates the character string that is processed.
nValue Designates the value that is added to the ASCII value of the character.
nPosition Designates the position of the character to which the nValue is added. The default value tells CA-Clipper Tools to add to the ASCII value of the last character.
Returns
AddAscii() returns the modified character string.
Description
This function is very useful when you call procedures using macros. When you use AddAscii(), the string representing the macro can be changed without needing to include functions like Left(), Right(), Asc(), or SubStr() (see example).
This function also allows you to subtract a value. However, a conversion is necessary. If a lower case letter is converted into an upper case letter, a value of 32 must be subtracted. This occurs according to the following formula:
Chr((Asc(Character) + 256 - Difference) % 256)
Notes
■ If the nPosition is greater than the length of cString or
less than 0, the string remains unchanged.
■ Zero changes the value of the last character.
■ CSetRef() can be used to suppress the returned value for this
function in order to save space in working memory.
Examples
■ A value of 1 is added to the next to the last position in a
string and to the last position in a string (Chr(Asc("2")+1) yields
"3" etc.):
? AddAscii("macro21", 1, 6) // "macro31"
? AddAscii("macro21", 1) // "macro22"
■ You can also subtract; -- 32 is the difference between lower
case and upper case letters, therefore Chr((Asc("m")+256-32) %256):
? AddAscii("macro21", 224, 1) // "Macro21"
If CA-Clipper Tools functions that change interrupts are not properly uninstalled or if the Extended Driver is not implemented, you could use the INTSAVE.EXE and INTOFF.EXE programs as additional security.
INTSAVE
Drive:INTSAVE[/S|/R[FileName]]RETURN
INTSAVE saves all 256 interrupt vectors to a file called INSAVE.TAB. Alternatively, a different filename can be selected, if multiple applications need to access the same path in a network. A call with the /S switch saves the interrupt vectors,while a call with /R restores them.
If the program is called without parameters, it explains its operation on the screen and, if required, displays a list of interrupt vectors that have been changed.
INTOFF
Drive:INTOFF RETURN
This program represents an "emergency brake". It sets the vectors described below to an IRET in the system ROM, so that there is no danger of a system crash as a result of erroneous interrupt vectors. The mouse interrupt (033h) is also newly initialized and the timer tic rate is reset. Memory resident programs are uncoupled from their interrupt vectors as well and are thereby rendered unusable. The program sets the following interrupt vectors to harmless IRETs:
Operation Vector Use in CA-Clipper Tools
IRET Timer 1C KeySec(), SHOWIME()
Alarm 4A KeyTime()
COM1 0C V24 Functions
COM2 0B V24 Functions
INIT Mouse 33 If foreign routines linked in
Timerspeed SETTIC()
Both programs could be linked into a batch job which starts your CA-Clipper application. This would look as follows:
dDate Designates the date to which the nMonth months is added. The default is the system date.
nMonth Designates the number of months to add to dDate.
Returns
AddMonth() returns the new date after nMonth is added to dDate.
Description
Use this function to calculate payment due dates based on an invoice date and for similar applications. It permits you to add months to a given date. If you use a negative number, months are subtracted.
Notes
■ An empty date parameter will result in an empty date.
Examples
Show today's date, plus 36 months:
? "The payment period ends on: ", AddMonth(36)
cSearchFor Designates the string for which the function searches.
cString Designates the string to search.
nCounter Designates which occurrence of cSearchFor within cString is found. The default value specifies the last occurrence in the search expression.
nIgnore Designates the number of characters that are eliminated from the search. The default value ignores none (0).
Returns
AfterAtNum() returns the remainder of the cString string from the first character after the nth (nCounter) occurrence of cSearchFor. If the last character in the sequence located is also the last character in the string being searched, then a null string is returned.
Description
This function finds the nth (nCounter) occurrence of cSearchFor within cString and returns the remainder of the string from the first position behind the located sequence.
In order to determine the nth (nCounter) occurrence of cSearchFor, AfterAtNum() searches from the left for each instance of this sequence. If CSetAtMupa() is off, then the search is continued after the last character of the sequence most recently found. Otherwise the search is continued after the first character of the sequence most recently found.
Notes
■ Implementing SetAtLike() allows you to use wild card
characters within cSearchFor.
Examples
■ Search a string for the last appearance of "aa" in two
different ways:
CSetAtMupa(.T.)
? AfterAtNum("aa", "aBaaBaaX") // "X"
CSetAtMupa(.F.)
? AfterAtNum("aa", "aBaaBaaX") // "aX"
■ Search a string for the third existing "xx" within the string,
where the first four characters are ignored! Notice the differing
results, depending on the multi-pass mode!
String := " AxxBBBBxxCCCCxxxDxxEExx"
CSetAtMupa(.T.)
? AfterAtNum("xx", String, 3, 4) // "DxxEExx"
CSetAtMupa(.F.)
? AfterAtNum("xx", String, 3, 4) // "EExx"
■ Examples for SetAtLike() can be found under the corresponding
function description.
AlloFree([<lMode>]) → nFreeMemory
* This has been retained in CA-Clipper for compatibility purposes.
Use the CA-Clipper Memory() function to develop future
applications.
Arguments
lMode If passed as .T., the total available memory size is returned. The default value is the largest contiguous block (.F.).
Returns
AlloFree() returns the maximum possible size for a contiguous memory block or the total amount of free memory available.
Description
Use this function to help avoid "memory fault" error messages. You can implement it in conjunction with other functions that use a string area as a buffer (as when you read files).
Notes
■ If there is not enough room on the stack, AlloFree(.T.)
returns a value of -1.
Examples
■ This is what can happen if you try to print a maximum-length
string without enough free memory:
Var := Space(65520)
■ Make a string of the maximum-length possible:
Var := Space(AlloFree()) // Under no circumstances
// call with .T.!
? Len(Var) // How long has it become?
■ Read in a file...
FileStr("Bigfile", AlloFree()) // The largest possible buffer
■ Entire available memory:
? AlloFree(.T.) // Available memory
Finds the sum of the ASCII values of all the characters of a string
Syntax
AsciiSum(<cString>) → nASCIISum
Arguments
cString Designates the character string for which the sum of all the ASCII values is computed.
Returns
AsciiSum() returns a number that corresponds to the sum of the ASCII codes of all the characters in cString.
Description
AsciiSum() allows you to form simple checksums for character strings. For example, this can be implemented during remote data transmission to identify transmission errors.
Notes
■ This function does not take character position into account,
so it cannot determine a character transposition. The Checksum() function should be used to determine character transposition.
cSearchFor Designates the character string for which the function searches, or the character string that provides the reference point for adjustment.
cString Designates the character string within which the adjustment occurs.
nTargetPosition Designates from which position within the character string the search expression is adjusted.
nCounter Designates which occurrence of the Searchexpression is taken into account. The default value is for the last occurrence.
nIgnore Designates the number of characters at the beginning of the search string that are removed. The default value is none.
nCharacter|cCharacter Designates a character, as necessary, to carry out the adjustment. It can be an individual character or an ASCII value between 0 and 255. The default value is a space Chr(32).
Returns
AtAdjust() returns the modified character string.
Description
The function first looks for the cSearchFor parameter within the character string. From this point, the rest of the cString is moved (adjusted) by either inserting or removing blanks until the nTargetPosition is reached. In lieu of blanks, nCharacter| cCharacter can be used as a fill character.
Additionally you can specify that the nth occurrence of cSearchFor be used and whether or not a specific number of characters at the beginning of the search string is eliminated.
Notes
■ Using CSetAtMupa() can influence how the search is performed.
Using SetAtLike() permits the use of wild cards within the search sequence.
Examples
■ Align comments at column 60. The search is for the first
occurrence of "//". Since there is usually at least one space before
each "//", search for " //":
? AtAdjust(" //", Line, 60, 1)
■ Move the extensions for the following list of file names to
position 10 and eliminate the ".":
WINDOW.DBF
PLZ.DBF
BACK.DBF
HELP.DBF
LOG.DBF
CharRem(".", AtAdjust(".", File, 10))
WINDOW DBF
PLZ DBF
BACK DBF
HELP DBF
LOG DBF
■ Use AtAdjust() with CSetAtMupa(). There is always a problem
determining whether "AA" occurs twice or three times in "AAA".
Depending on CSetAtMupa(), the function searches behind the last
character, or starts from the last character of a located sequence:
CSetAtMupa(.F.)
? AtAdjust("AA", "123AAABBB", 7, 2) // Sequence not found
CSetAtMupa(.T.)
? AtAdjust("AA", "123AAABBB", 7, 2) // "123A AABBB"
Atn2() returns the angle sine in radians, where the sine and the cosine of a given point have been specified. The function returns results for all four quadrants and corresponds to a call of Atan(x/y). One advantage of the Atn2() function is that no "divide by zero" error can occur. The returned value is in the range of -pi to +pi.
Notes
■ The SetPrec() function can influence the precision of the
result.
Examples
■ Compute the sine and cosine of 30 degrees. DToR() is then
used to convert these into the radian value:
SET DECIMALS TO 4
X := Sin(DToR(30))
Y := Cos(DToR(30))
■ Use RToD() to compute the result in degrees:
? RToD(Atn2(x, y)) // 30.0000
cSearchFor Designates the expression for which the function searches.
cString Designates the character string to search.
nCounter Designates which occurrence of cSearchFor within cString is determined. The default value is for the last occurrence of the search expression.
nIgnore Designates the number of characters that should be excluded from the search. The default value is none (0).
Returns
The function returns the position where cSearchFor begins. If no corresponding position can be determined, the function returns 0.
Description
AtNum() determines the initial position of the nth (nCounter) occurrence of cSearchFor within the cString. Additionally, the function takes into account the CSetAtMupa() setting, which causes differing results.
AtNum() searches from the left in order to determine the nth (nCounter) occurrence of the cSearchFor. If CSetAtMupa() is off, the search continues after the last character of the sequence most recently located. However, if the CSetAtMupa() is on, the search always continues after the first character in the most recently located sequence.
If the nIgnore parameter is not specified, the function initiates the search with the first character of cString. If the nIgnore parameter is specified, nIgnore characters are ignored from the start of the string and are excluded from the search.
Notes
■ If no value is specified for nCounter, the function
determines the last occurrence of the cSearchFor sequence.
■ When you implement SetAtLike(), wildcard characters can be
used within the search expression.
Examples
■ Search for the last occurrence:
? AtNum("bc", "abcdeabc") // Result: 7
■ Search for the first occurrence:
? AtNum("bc", "abcdeabc", 1) // Result: 2
■ Search for the first occurrence, excluding the first three
characters:
? AtNum("bc", "abcdeabc", 1, 3) // Result: 7
■ Determine the impact of CSetAtMupa() on a search for the last
occurrence of "aa" in "aaa":
CSetAtMupa(.F.) // Off
? AtNum("aa", "aaa") // Result: 1
CSetAtMupa(.T.) // On
? AtNum("aa", "aaa") // Result: 2
cSearchFor Designates the expression for which the function searches.
cString [@] Designates the character string that is searched.
cReplace Designates the character string that is exchanged for the sequence in cString.
nCounter Designates which or how many occurrences of cSearchFor within cString are replaced by cReplace. The default value is for the last occurrence of the search expression.
lMode Designates if only the nth (nCounter) sequence is replaced (.T.), or if all sequences up to the nth (nCounter) are replaced (.F.). The default value (.F.) designates that all sequences are replaced.
Returns
The function returns a character string in which one or many of the cSearchFor sequences have been replaced by cReplace.
Description
AtRepl() allows you to replace one or more sequences within cString. cReplace can be shorter or longer than cSearchFor.
nCounter specifies that the function searches for the nth occurrence of the sequence. If no value is specified, then the last occurrence is used. All occurrences of cSearchFor, up to and including the one sought, are replaced unless nCounter is assigned a value greater than 0 and lMode is designated .T..
The CSetAtMupa() setting is only checked when the length of cReplace is shorter than or equal to that of cSearchFor, yielding different results. Beginning on the left, the character string is searched for each occurrence of the cSearchFor sequence. If CSetAtMupa() is off (.F.), then the search continues after the last character of the replaced sequence. However, if CSetAtMupa() is on, the search always continues from the first character of the replaced sequence.
Notes
■ By implementing SetAtLike() you can use wildcard characters
within the search sequence.
■ cString can be passed by reference. If this is the case,
then both cSearchFor and cReplace must be the same length.
■ If cSearchFor and cReplace are identical, the function
terminates immediately. Such an exchange makes no sense, and if CSetAtMupa() is (.T.), the exchange results in an endless loop.
Examples
■ Exchange all "123" with "ab":
? AtRepl("123", "123_123_123", "ab") // "ab_ab_ab"
■ Replace "789" with a longer string "abcd" (ignore multi-pass):
? AtRepl("789", "789_789", "abcd") // "abcd_abcd"
■ Exchange all "123" with "ab", up to and including the second
occurrence:
? AtRepl("123", "123_123_123", "ab", 2) // "ab_ab_123"
■ Exchange only the second occurrence of "123" with "ab":
? AtRepl("123", "123_123_123", "ab", 2, .T.) // "123_ab_123"
■ Exchange all "aa" for "a" and the change the influence of
CSetAtMupa():
CSetAtMupa(.F.)
? AtRepl("aa", "aaaa", "a") // "aa"
CSetAtMupa(.T.)
? AtRepl("aa", "aaaa", "a") // "a"
■ Exchange "abc" with "ab", with and without multi-pass:
CSetAtMupa(.F.)
? AtRepl("abc", "123abcc456", "ab") // "123abc456"
CSetAtMupa(.T.)
? AtRepl("abc", "123abcc456", "ab") // "123ab456"
cString Designates the character string that is passed.
cDelimiter Designates the delimiter list used to identify the tokens.
nCounter Designates which token's position is determined. The default value is for the last token located.
Returns
AtToken() returns the beginning position of the nth (nCounter) token within the cString.
Description
AtToken() allows you to determine the beginning position of a token in cString. This value can be extremely helpful when you work with other string functions. The function uses the following list of delimiters as a standard:
CHR 32, 0, 9, 10, 13, 26, 32, 138, 141
and the characters ,.;:!?/<<>>()^#&%+-*
This list can also be replaced with your own list of separators, cDelimiter. Here are some examples of useful delimiters:
Table 4-1: Recommended Delimiter Sequences
Description <cDelimiter>
Pages Chr(12)(Form Feed)
Sentences ".!?"
File names ":\."
Numerical strings ",."
Date strings "/."
Time strings ":."
Examples
■ Find the beginning position of the last token:
? AtToken("Good Day") // 6
■ Find the beginning position of the fourth token:
? AtToken("What a beautiful day.", 4) // 18
■ Attempt to determine the beginning position of an unavailable
token:
? AtToken("What a beautiful day.", 6) // 0
cSearchFor Designates the string for which the function searches.
cString Designates the string that is searched.
nCounter Designates which occurrence of the cSearchFor within the cString is determined. The default value is for the last occurrence in the search expression.
nIgnore Designates the nuber of characters that are eliminated from the search. The default value ignores none (0).
Returns
The function returns all the characters in cString in front of the sequence determined. If no corresponding sequence is found, then a null string is returned.
Description
This function determines the beginning position of the nth (nCounter) occurrence of cSearchFor within cString and returns the string segment before this sequence. Additionally, the function takes into account the CSetAtMupa() setting, which can cause differing results.
In order to determine the nth (nCounter) occurrence of the cSearchFor, BeforAtNum() searches from the left for each instance of this sequence. If CSetAtMupa() is off, then the search continues after the last character of the sequence most recently found. If CSetAtMupa() is on, the search continues after the first character of the sequence most recently found.
Notes
■ Implementing SetAtLike() allows you to use wildcard characters
within the search sequence.
Examples
■ Search a string for the last appearance of a sequence:
? BeforAtNum("ab", "abcabdabe") // "abcabd"
■ Search a string for the first occurrence of a sequence:
? BeforAtNum("ab", "abcabdabe", 1) // ""
■ Search a string for the first occurrence of a sequence, where
the first three characters are not considered in the search:
? BeforAtNum("ab", "abcabdabe", 1, 3) // "abc"
■ Search a string for the third occurrence of "xx", where the
first four characters are not considered! Notice the different
results when you use the multi-pass mode:
String := "AxxBBBBxxCCCCxxxDxxEExx"
CSetAtMupa(.T.)
? BeforAtNum("xx", String, 3, 4) // "AxxBBBBxxCCCCx"
CSetAtMupa(.F.)
? BeforAtNum("xx", String, 3, 4) // "AxxBBBBxxCCCCxxxD"
nInteger Designates a number in the range of 0 to 65535, which corresponds to a bit pattern.
cBitpattern Designates a character string with a maximum of 16 characters. Each character corresponds to a bit in nInteger, where the last character corresponds to the lowest-value bit.
lMode When this optional parameter is designated as .T., 0 bits change to blanks. The default is no change.
Returns
The returned string contains the corresponding characters passed by the bit pattern.
Description
The BitToC() function changes the bits of a number into a sequence of corresponding characters. This facilitates work with such bit-coded information as file attributes. Depending on the lMode logical parameter (the l in lMode symbolizes logical), 0 bits either displays no character (.F.) or a blank (.T.).
Notes
■ If lMode is designated as .T., the string length that
results always corresponds to cBitpattern.
Examples
■ Change file attributes:
■ The number 2 corresponds to a binary "00000010":
? BitToC(2, "ADVSHR") // "H" as the next to
// last character
■ The number 5 corresponds to a binary "00000101":
? BitToC(5, "ADVSHR") // "SR"
■ The number 5, with the 0 bit displayed as a blank:
? BitToC(5, "ADVSHR", .T.) // " S R"
As a rule, all industry-standard PC's insert a generated date at a particular memory location in the BIOS. Based on this date, incompatibilities known to exist up to a particular release can be acknowledged. The function returns a date-type value and spares you an elaborate PEEK.
Notes
■ Although unlikely, you may not find a date at this BIOS
position. Therefore, you should test to see if a date is returned.
Examples
Is this an older computer?
IF BIOSDATE() < CToD("01/01/85")
? "Older version ...!"
ENDIF
expValue[@] Designates any valid expression; the type is not important.
lMode Designates whether or not the length of the expValue is to change in the event that expValue is a string. If .T. is designated, the length is retained. The default value is Change Length (.F.).
Returns
Blank() returns a blank value with the same data type as the expValue parameter.
Description
Blank() clears desired data fields with the variables. Blank() returns the following results:
Table 13-1: Data Type Blank Values
Argument Returned Value
Character string Null string or blank string
Numeric Value of 0
Logical .F.
Date A blank date
The default for lMode is .F. and produces a null string when a character string is input. However, if this parameter is designated as .T.., the string length is not changed.
Notes
■ SET DATE has no affect on how Blank() handles a date. The
blank date display is created in the format you select.
■ You can suppress the value this function returns by
manipulating strings through CSetRef() implementation. To save room in the working memory, designate lMode as .T..
dDate Designates a date for which the first day of the month that contains this date, is determined. The default is the system date.
Returns
BoM() returns the first day of the month in which dDate lies.
Description
BoM() allows you to determine the first day of the month that contains dDate. This allows you to determine how many days have past since the beginning of the month.
Notes
■ If no date is passed, then the function automatically uses the
system date. An empty date parameter always returns an empty date.
Examples
Display the elapsed days in the current month:
? Date() - BoM()
Determines the date for the beginning of a quarter
Syntax
BoQ([<dDate>]) → dBeginningOfQuarter
Arguments
dDate Designates a date for which the first day of the quarter in which it lies is determined. The default is the system date.
Returns
BoQ() returns the date at the beginning of the quarter that contains dDate.
Description
For example, use BoQ() to determine when the current quarter that contains dDate began, and then compute the number of days that have elapsed since the quarter began.
Notes
■ If you do not specify a date, the function automatically uses
the system date. An empty date parameter always returns an empty date.
Examples
Display the date of the first day of the current quarter:
? "The first day of the current quarter is:", BoQ()
BOOTCOLD() allows you to restart the system after a critical error (assuming anything is still working), or to allow any program changes you have made in CONFIG.SYS or AUTOEXEC.BAT to take effect. The function calls for a cold start. This means a RAM check and POST (power on self test) are carried out.
Notes
■ Close all files prior to a boot. You can use CLOSE DATABASES.
■ If there is a large system memory, a RAM check takes a long
time. To avoid this lengthy procedure, you might consider using the BOOTWARM() function for a restart after changing CONFIG.SYS.
Examples
An error in an error trap can no longer be changed:
CLOSE DATABASES
BOOTCOLD()
This function allows changes in CONFIG.SYS or AUTOEXEC.BAT to become effective. This function restarts the system just like BOOTCOLD(), but no RAM check or POST (power on self test) are carried out.
Notes
■ Close all files before you boot. You can use CLOSE DATABASES
to do this.
■ BOOTWARM() is the same as pressing the Ctrl-Alt-Del keys.
Examples
A new CONFIG.SYS is created within the program and the system reboots:
COPY TO CONFIG.SYS SDF
CLOSE DATABASES
BOOTWARM()
nComPort Designates the serial interface (1 to 4) where a break is set.
nDuration Designates the time in milliseconds that the break remains active. The default value is 100 milliseconds.
Returns
com_Break() returns .T. when the break has been successfully set.
Description
The output of a break means that the transmission line of an interface is held at a specific level for a fixed period of time. This time can be selected as a numeric parameter between 1 and 65535 milliseconds.
As a rule, a break is usually between 100 and 350 milliseconds long.
Examples
Output a 200 millisecond on interface COM1:
com_Break(1, 200)
Clears the receiving buffer and closes the com port
Syntax
com_Close(<nComPort>) → lClosed
Arguments
nComPort Designates which port is closed, COM1(1) to COM4(4).
Returns
A return of .T. indicates that the port is open and can be closed successfully.
Description
This function closes one of the ports (1 to 4). This means that the buffer is cleared, and all signals in the modem control register (MCR) are deactivated. Characters remaining in the buffer are lost. The DTR and RTS signals become inactive, and any existing modem connection is broken.
Notes
Warning! All characters in the buffer are cleared, and the status register is set to 0. Existing connections are always broken!
Examples
nCharacter := com_Count(1) // How many characters in
// the buffer ?
IF nCharacter > 0
* Read everything from buffer!
cContent := com_Read(1, nCharacter)
ENDIF
com_Close(1)
Counts the number of characters in the input buffer
Syntax
com_Count(<nComPort>) → nTotalCharacters
Arguments
nComPort Designates the port (1 to 4) for which the number of characters in the input buffer is determined.
Returns
com_Count() returns the number of characters in the selected buffer.
Description
This function allows you to determine the number of characters in one of the four possible buffers. This lets you determine how many characters can be read with the com_Read() function.
Notes
■ If an attempt is made to read the number of characters
available in a closed port, the function returns a value of -1.
Examples
nCharacter := com_Count(1) // Number of characters-port 1
IF nCharacter > 0
com_Read(1, 1) // Read 1 character
ENDIF
cString Designates the character string for which a CRC is computed.
nStart Designates a starting value that is added to the CRC. This value is computed in order to form a CRC for multiple character strings. The default value is 0.
nPolynomial Designates another polynomial. The maximum is a 17- bit polynomial. The default polynomial is CRC-16 X.25 (see below).
Returns
com_CRC() returns the 16-bit CRC for cString as a numeric value between 0 and 65535.
Description
CYCLIC REDUNDANCY CHECK Many file transfer protocols use CRC for accurate error recognition. This CRC function offers you decisive help when programming your own protocols, like XMODEM or KERMIT.
The specific CRC value always depends on the polynomial that you use. This information can be passed as an optional parameter in the form of an integer so that the function has almost universal utility. The CRC 16 X.25 polynomial used in X.25 systems,. XMODEM is the default value used in the examples below.
A few examples of polynomials:
Table 3-1: The Different Polynomials
Type Arguments Polynomial
Parity 3 2^1+1
LCR-8 257 2^8+1
CRC-12 5011 2^12+2^11+2^3+2^2 +2^1+1
CRC-16 X.25 69665 2^16+2^12+2^5+1
CRC-16 98309 2^16+2^15+2^2+1
Notes
■ If nStart is not passed, then the loss of the previous
Chr(0) out of cString is not detected by a later CRC review. This can be avoided if nStart is given a starting value that is not equal to 0.
■ A function called XMoBlock() is available for building XMODEM
blocks.
Examples
■ These are simple CRC calculations:
com_CRC("abc") // 40406
com_CRC("cba") // 54260
■ These are calculations for multiple strings:
nCRC1 := com_CRC("123")
nCRC2 := com_CRC("456", nCRC1)
? nCRC2 == com_CRC("123456") // .T., values are equal
■ Form a block for data transmission. The string is appended to
the data:
cData := "ABCDEFGHIJKLMNOP"
nCRC := com_CRC(cData)
cCRCSTR := I2Bin(CRC) // CRC as a string
cCRCSTR := CharSwap(cCRCSTR) // Exchange both bytes
cBlock := cData + cCRCSTR // Transmission block
■ The CRC must be 0 for the entire transmitted block!
? com_CRC(cBlock) = 0 // .T., when correctly
// transmitted
nComPort Designates the port (1 to 4) for which CTS is tested.
Returns
A return of .T. indicates that CTS is active (MSR Bit 5 = 1). A return of .F. indicates that CTS is inactive (MSR Bit 5 = 0).
Description
com_CTS() lets you check the Clear To Send (CTS) signal within a program. Whether CTS is used for a hardware handshake or for other purposes, depends on the external hardware that you use.
Notes
■ If Delta-CTS is required, you must use com_MSR().
Examples
DO WHILE .NOT. com_CTS(1) // Wait for CTS
* ...
ENDDO
com_Send(1, "Good Morning") // Transmit text
nComPort Designates the port (1 to 4) on which DCD is tested.
Returns
A return of .T. indicates that DCD is active (MSR Bit 8 = 1). A return of .F. indicates that DCD is inactive (MSR Bit 8 = 0).
Description
com_DCD() lets you check the Data Carrier Detect signal within a program. When you use a modem, DCD indicates that you have a remote connection.
Notes
■ If Delta-DCD is required, you must use com_MSR().
Examples
A connection is only established when a valid DCD signal has been
recognized:
? "Call recognized..."
DO WHILE .NOT. com_DCD(1) // Wait for carrier (DCD)
* ...
ENDDO
? "Carrier recognized - connection established ..."
cString Designates a string that is output through DOS.
nLine Designates the line number where the string is output. The default position is the cursor position.
nColumn Designates the column number where the string is output. The default position is the cursor position.
Returns
This function always returns a null string.
Description
com_DosCon() allows you to output a string through DOS. This function can be used to provide an interpretation of ANSI control sequences through ANSI.SYS. The installed status of the ANSI driver can be determined using the ISANSI() function.
In this way you can easily create a communications program with ANSI terminal emulation.
Notes
■ Notice that DSETWINDOW() should be switched off when using
this function. Otherwise the output is routed through the CA-Clipper driver module, and operates like a print (?) with a position instruction.
Examples
When ANSI.SYS is linked in, output is through DOS. This makes a simple
terminal emulation possible!
DSETWINDOW(.F.) // Important for ISANSI()
cData := com_Read(1) // Data read in
IF ISANSI() // ANSI driver present?
com_DosCon(cData)
ELSE
* Own ANSI handling
ENDIF
nComPort Designates the port (1 to 4) on which DSR is tested.
Returns
A return of .T. indicates that DSR is active (MSR Bit 6 = 1). A return of .F. indicates that DSR is inactive (MSR Bit 6 = 0).
Description
com_DSR() lets you check the Data Set Ready signal within a program.
Notes
■ If Delta-DSR is required, you must use com_MSR().
Examples
Many modems give an active DSR as soon as a connection is established:
DO WHILE .NOT. com_DSR(1) // Wait for DSR (Call)
* ...
ENDDO
? "Call recognized."
nComPort Designates the port (1 to 4) on which DSR is tested.
lNewDTRStatus Designates the status of DTR. .T. designates that the DTR signal is active, and .F. designates that the signal is inactive. If the parameter is not specified, CA-Clipper Tools does not affect the DTR exit signal.
Returns
The returned value corresponds to the DTR signal status prior to the new setting, or in the absence of lNewDTRStatus, the returned value corresponds to the current DTR. A return of .T. indicates that the DTR is active (MCR bit 1 = 1). A return of .F. indicates that the DTR is inactive (MCR bit 1 = 0).
Description
com_DTR() queries the DTR signal status. If the second parameter is not supplied, the DTR signal status does not change.
Notes
■ The com_Close() function resets DTR (to inactive). By
contrast, COM_OPEN does not automatically make DTR active!
Examples
A com_Open() does not set the DTR signal. You must specifically set the
DTR signal.
nBuff_size := 4000 // 4000 byte buffer
lComOk := com_Open(1, nBuff_size) // Open COM1
IF lComOk
com_DTR(1, .T.) // Activate DTR Port 1
* ...
ENDIF
nComPort Designates the port (1 to 4) where an external line termination character is established.
nErrorCharacter|cErrorCharacter Designates the individual error character, which can be given as a number or a character. When it is not specified, the port functions do not set any error character in the buffer.
Returns
com_ErrChr() returns .T. when the opened port is addressed.
Description
It is always possible that characters received during a file transmission from the port, UART, are recognized inaccurately. In such cases either an error procedure must be called (i.e. com_Key()) or the inaccurate character must be flagged. During remote transmission, a "trash" character is output. Chr(177) is the default "trash" character; however, you can use whatever error character you choose or you can suppress the output of a "trash" character entirely.
Notes
■ The Line Status Register (LSR) setting is used to determine
whether or not characters were inaccurately received.
Examples
■ Use Chr(250) as an error character for port 2:
? com_ErrChr(2, 250) // .T., when accepted
■ Switch off the use of an error character for port 4:
? com_ErrChr(4) // .T., when accepted
Designates which event at the port triggered a key trap
Syntax
com_Event(<nComPort>,<nMode>) → nCode
Arguments
nComPort Designates the port (1 to 4) that is tested for the event.
nMode Designates a numeric value between 1 and 5 (see table 3-2).
Returns
This function returns the code of an incoming character, MSR status, LSR status, or the number of errors that have occurred to date as a function of the nMode parameter value.
Description
As a rule, it is necessary to determine the cause of a trap if a character is placed in the keyboard buffer and the procedure specified with SET KEY TO is called. The numeric parameter determines what information is accessed. The information returned for modes 1 to 5 are defined as follows:
Table 3-2: Query Codes for Event Information
Code Event Information
1 The function will return the ASCII code of the incoming
character. If no character is available, a -1 is returned.
2 The function returns the status of the MS register at the time
of the interrupt.
3 The function returns the status of the LS register at the time
of the interrupt.
4 The value of the internal error counter will be returned. The
error events in the LSR since the last com_Init() will be
counted.
5 Returns the number of characters which had to be rejected
because the buffer was 100% full.
Notes
■ With the exception of the error counter, all status
information is reset when you open the port or when you call com_Key() again.
■ The conditions of MSR and LSR are considered at each interrupt
and are linked to the respective status byte in the internal environment through a logical OR operation. It is therefore possible to place multiple bits in one of the registers.
■ Overrun errors, parity errors, and frame errors (bits 1 to 3)
are counted as errors exclusively.
Important! The input lines on conventional PC interface cards are normally not terminated. This can lead to inexplicable results when you query the MSR.
Examples
Determine the number of errors that have occurred:
nErrorCnt := com_Event(1, 4)
IF nErrorCnt > 25
* more than 25 errors?
? "Too many errors - terminate program!"
lRelease := .T.
ENDIF
nComPort Designates the port (1 to 4) for which the receiving buffer is cleared.
Returns
If the receiving buffer can be cleared successfully, the function returns .T..
Description
This function allows you to flush all the characters in a receiving buffer. This makes it unnecessary to tediously determine how many characters are currently in the buffer in order to remove them with a read procedure.
com_Flush() guarantees a truly empty buffer. However, a new character can be received between the time that you call a com_Count() and a com_Read().
Notes
■ A com_Flush() on an unopened port is ineffective.
Examples
cHayes := "ATZ" // Hayes modem reset command
com_Send(1, cHayes) // Issue Hayes command
Inkey(1) // Wait one second
com_Flush(1) // Reject modem reply messages
nComPort Designates the port (1 to 4) to which the current I/O address is delivered.
Returns
com_GetIO() returns the I/O address of the designated port. With an invalid parameter or an unavailable port, the function returns a value of -1.
Description
com_GetIO() determines with which port I/O address CA-Clipper Tools functions communicate. This function only returns a value known to CA-Clipper Tools software. It cannot determine the I/O address of an interface card!
Examples
■ Determine the COM1 I/O address:
? com_GetIO(1) // 1016
■ Specify that you need the address in hexadecimal form:
? NToC(com_GetIO(1), 16) // "3F8"
■ Specify an invalid port number:
? com_GetIO(5) // -1
nComPort Designates the port (1 to 4) to which the IRQ currently in use is delivered.
Returns
com_GetIRQ() returns the IRQ currently in use for the designated port. When there are incorrect parameters, the function returns a value of -1.
Description
com_GetIRQ() determines which IRQ is served by the CA-Clipper Tools functions for a particular port. This value corresponds to an internal CA-Clipper Tools software setting. You cannot determine which IRQ is using a particular port.
Examples
■ Determine the interrupt request for IRQ to COM2:
? com_GetIRQ(2) // 3
■ Specify an inaccurate port number:
? com_GetIRQ(5) // -1
nComPort Designates the port (1 to 4) for which the hardware handshake is switched on or off.
lNewHandshake Designates whether the handshake is on (.T.) or off (.F.).
lDTR/DSR Designates whether the function uses the DTR/DSR handshake or the RTS/CTS handshake. When passed as .T., the function uses the DTR/DSR handshake instead of the RTS/CTS handshake.
Returns
When called only with nComPort, the com_Hard() returns .T. if the hardware handshake is on and .F. if the hardware handshake is off. When lNewHandshake is passed, the function returns the status prior to the new setting.
Description
The size of a receiving buffer is always limited. To avoid overflow, and thereby a loss of characters, software or hardware handshakes are usually implemented. During a hardware handshake, the port monitors the RTS signal. If you use this function to switch this handshake on, the signal is activated as soon as the buffer is 75% full. As soon as the buffer content is once again reduced to 50% or less, the port (the RTS signal) is once again released. Some printers use the port signals, DTR (output like RTS) and DSR (entry like CTS) instead of RTS/CTS, to avoid buffer overflow. In this case, lDTR/DSR can be passed with .T..
Notes
■ The hardware handshake only supports background transmission
(when com_Open() is implemented with the third parameter nBufferOut).
■ This function works for data input as well as output.
■ If you use a hardware handshake, then the RTS signal should no
Turn on the hardware handshake at a port:
com_Open(2, 1000, 1000) // Open COM2, background send
// buffer
com_Hard(2, .T.) // RTS/CTS Hardware handshake
// for port 2
nComPort Designates the port (1 to 4) that is initialized.
nBaudRate Designates the selected baud rate for the port. Settings of 300, 600, 1200, 2400, 4800, 9600 and 19200 baud are possible. The default value is 300 baud.
cParity Designates parity in the following form: (E)ven, (O)dd, (M)ark, (S)pace, or (N)one. The default value is (N)one.
nDataLength Designates the data length; seven or eight bits are possible. The default value is eight bits.
nStopBits Designates the number of stop bits, one or two. The default value is one stop bit.
Returns
If the com port is initialized successfully, the function returns .T..
Description
In order to use the serial port after you open it, four operating parameters must have been passed to this function. These operating parameters are the transmission speed (baud rate), the data length, the parity, and the number of stop bits. Today most bulletin boards use the configuration "300 - 9600 baud, 8N1". This configuration means eight data bits, no parity, and one stop bit. What is important is that all these parameters can be changed while the port is closed. Neither the data buffer or the modem status register (DTR, etc.) are affected.
Notes
■ The port must have been opened previously. It is impossible
to initialize a port prior to opening it.
■ If any or all of the four operating parameters are not
designated, or are designated incorrectly, the standard arguments of 300 baud, no parity, eight data bits, and one stop bit is used.
Examples
■ Open and initialize a port:
nBuff_size := 4000 // 4000 character buffer
lComOk := com_Open(1, nBuff_size) // Open port
IF lComOk
* The port is open, now it is to be initialized with 1200
* baud, no parity, eight data bits, and one stop bit.
lInitOk := com_Init(1, 1200, "N", 8, 1)
IF .NOT. lInitOk
? "Port cannot be initialized !"
ENDIF
ENDIF
■ You can also omit the last three parameters in the above
example because they correspond to the default settings:
lInitOk := com_Init(1, 1200) // Init. with 1200, N, 8, 1
nComPort Designates the port (1 to 4) where particular activities are monitored.
nKeyValue1 Designates the key code placed in the keyboard buffer in case an interrupt occurs. Values permitted with CA-Clipper's SET KEY TO command are allowed, as a numeric value or a character. If this parameter is not specified, then the port interrupts are not monitored.
nKeyValue2 Designates another key code that is placed in the keyboard buffer when the receiving buffer is 75% or more full. Values permitted with CA-Clipper's SET KEY TO command are allowed, as a numeric value or a character. If this parameter is not specified, the buffer overflow is not monitored.
Returns
com_Key() returns .T. when at least one trap is switched on and returns .F. when all monitoring is switched off.
Description
com_Key() allows you to monitor a port while the program is in a READ. In this way, various events at the port can cause a particular key code, selected by the programmer, to be placed in the keyboard buffer. This happens when:
■ Data arrives at the port.
■ A transmission error or a BREAK is recognized in the LSR.
■ One of the signals in the MSR changes.
■ The receiving buffer becomes 75% or more full.
The MSR and LSR status, the number of errors that have already occurred, and the receipt of individual characters can be monitored through the nKeyValue1 key code. All information is saved in an internal memory area and can be queried from there using the com_Event() function. This procedure is important because the register or the flags that release the interrupt, are automatically reset during read access. Otherwise, the information is lost.
If the nKeyValue2 parameter is specified, then one more procedure can be specified using the SET KEY TO command when the receiving buffer is 75% or more full. If the nKeyValue2 parameter is specified, the nKeyValue1 key code is no longer placed in the keyboard buffer when characters are received. However, you can still monitor the MSR and LSR.
Notes
■ The status of the various interface registers are connected to
the internal memory for as long as the event is "serviced" by a new com_Key() function call. This means that the modifications made during this period cannot be lost.
■ COM_KEY must be newly activated after every executed trap.
This deletes information concerning the internal environment.
■ When com_Key() places a character into the buffer because the
buffer is close to full, it does so independently of the com_Soft() or com_Hard() functions.
Examples
Chr(227) is placed in the keyboard buffer and calls the COMERRORS
procedure if an error is recognized at port 2 or if the modem status
signal changes. As soon as the buffer is 75% full or more, Chr(228) is
placed in the keyboard buffer. When Chr(228) is placed in the keyboard
buffer, the BUFFERFULL procedure is called:
#include ctcom.ch // Symbolic constants
// for interface
com_Open(2, 1000) // Open COM2
CON_INIT(2, 1200, "N", 8, 1) // Initialize COM2
SET KEY 227 TO ComErrors
SET KEY 228 TO BufferFull
com_Key(2, 227, 228) // Monitor COM2
cName := Space(20) // The port can arrange
PROCEDURE COMMERRORS(A, B, C)
nMSR_Status := com_Event(2, 2) // Read accumulated
// MSR data
nLSR_Status := com_Event(2, 2) // Read accumulated
// LSR data
com_Key(2, 227, 228) // Reactivate traps, reset
// internal values of COM_EVENT
IF IsBit(nMSR_Status, MSR_RI) // Ring bit set?
? "Call (ring) acknowledged!"
ELSE
IF ISBIR(nLSR_Status, nLSR_Break) // Break bit set?
? "Break acknowledged!"
ENDIF
ENDIF
RETURN
PROCEDURE BUFFERFULL(A, B, C)
* The input buffer must be read!
com_Key(2, 227, 228) // Traps activated here
cData := COM.READ(2) // Read all data
SELECT MESSDAT
REPLACE ComDat WITH cData // Save data
SKIP
SELECT INPUT
RETURN
nComPort Designates the port (1 to 4) for which the Modem Control Register (MCR) is read or set.
nMCR Designates a specified parameter between 0 and 255. If this parameter is not specified, then MCR is read only.
Returns
com_MCR() returns the contents of the Modem Control Register.
Description
The Modem Control Register can be read only and/or read and set. The second optional parameter determines if a new value is set. The bits have the following meaning:
Table 3-4: MC Register Coding
Bit Symb.Const. Definition
0 MCR_ERROR Parameter error
1 MCR_DTR Data terminal ready (DTR)
2 MCR_RTS Request to send (RTS)
4 MCR_OUT_1 OUT 1
8 MCR_OUT_2 OUT 2
16 MCR_LOOP LOOP
Notes
■ The OUT1, OUT2, and LOOP control bits can only be changed
using this function. Additional functions are available for DTR and RTS.
Examples
nStatus := com_MCR(1) // Port 1 MCR is read only
IF NumAnd(nStatus, 3) = 3
? "DTR and RTS are active!"
ENDIF
nComPort Designates the port (1 to 4) for which the Modem Status Register is read. COM1(1) to COM4(4) are possible.
Returns
com_MSR() returns a value between 0 and 255 that corresponds to the contents of the MSR.
Description
Not all the values for this status register can be determined from separate functions. For example, if you need Delta status information, you can use this function and test the corresponding bit. The individual bits are defined as follows:
Table 3-5: MC-Register Coding
Bit Symb. Const. Definition
0 MSR_ERROR Parameter error
1 MSR_DELTA_CTS DELTA ready to send (DCTS)
2 MSR_DELTA_DSR DELTA data terminal ready (DDSR)
4 MSR_TERI Trailing edge RING (TERI)
8 MSR_DELTA_DCD DELTA data carrier detected (DDCD)
16 MSR_CTS Clear to send (CTS)
32 MSR_DSR Data terminal ready (DSR)
64 MSR_RI RING indicator (RI)
128 MSR_DCD Data carrier detected (DCD)
Notes
■ The simultaneous testing of multiple bits in the MSR is fairly
simple when using a logical AND operation.
■ All delta bits in this register are reset using a read
Gives the number of the highest available serial interface port
Syntax
com_Num() → nMaxCom
Returns
com_Num() returns the number of the highest available serial interface port.
Description
This function returns the number of the serial interface port available. This is not to say that a return value of 3 necessarily means that ports 1 through 3 are available; for example, COM2 could be missing. Whether or not a serial port can actually be used can be tested using the com_Open() or com_Init() functions.
Normally the addresses described in the Introduction to this chapter are scanned for available ports. Scanning can happen over alternate addresses selected through com_SetIO().
Important! Four I/O addresses are assigned to ports COM1 - COM4, internal to the port functions. The com_Num() function goes through these four addresses and tests to see if a port is available there. This can lead to problems if some other hardware is installed in one of the address areas. For example, problems like this have been noted in conjunction with ArcNet network cards, which conflict in the address area with COM4. The critical address areas are listed in the table below.
Table 3-6: I/O Addresses for COM1-COM4
Port I/O Addresses
COM1 03F8h - 03FFh
COM2 02F8h - 02FFh
COM3 03E8h - 03EFh
COM4 02E8h - 02EFh
If any kind of hardware is found within this I/O address area, then the conflicting COM port can be masked. Additionally, using com_SetIO() (nComPort, 0) the accompanying base address within the internal table is deleted. You can only mask the conflicting port when com_Num() has not previously been called in the program. If com_Num() has been called in the program, the interface is marked "in use".
Examples
■ Determine the number of ports at the standard addresses:
? com_Num() // e.g. 4
■ Determine the number of ports at unusual addresses:
com_SetIO(3, "110") // COM3, 110h
com_SetIO(4, "120") // COM4, 120h
? com_Num()
com_Open(<nComPort>,<nBufferIn>,<nBufferOut>,
[<lTrapMode>]) → lStatus
Tip: The new optional parameter is an enhancement over previous
versions!
Arguments
nComPort Designates the number of the port (1 to 4).
nBufferIn Designates the size of the receiving buffer up to 64 kByte. The default value is 100 bytes.
nBufferOut Designates the size of the sending buffer for background transmission up to 64 kByte. The default specification is a no send buffer.
lTrapMode Designates when the port triggers an interrupt. When this parameter is .T., the port only triggers an interrupt while receiving data, and not as a result of transmission failure. The default value causes the port to trap all occurrences.
Returns
com_Open() returns .T. when the port has been successfully opened and you can select the buffer.
Description
This function allows you to open a serial interface port from COM1 to COM4. These ports have particular I/O addresses. For example, CA-Clipper Tools uses 3F8H as a base address for COM1. DOS or BIOS routines are not even involved; I/O addresses are not read from the BIOS data area. The default values described in the Introduction to this chapter are applied, or the values are set using com_SetIO(). The availability of a port is tested for these addresses before the port is opened.
Receiving Data A buffer of up to 64 kByte can be reserved for each com port. All arriving characters are saved here, even when the CA-Clipper program is active elsewhere with another process. The number of characters in the buffer can be checked and partially read.
Sending Data You can also reserve a sending buffer. If you reserve a sending buffer, com_Send() controls the interrupt function for data transmission, which means that the interrupt occurs in the background. Several functions are available to control the send buffer.
Interrupts during Transmission Errors If lTrapMode is specified as .T., the UART port only triggers an interrupt when there is data incoming or interrupt driven data being sent. Events connected with the MSR or the LSR are no longer taken into account. This affects the status signal and particularly affects transmission errors.
This capability was added as the result of research that indicated that some adapter ports seemed to trigger interrupts for no reason. These interrupts are caused by "trash" on the lines; as a rule, serial port incoming lines were not terminated (electronically closed). Overflowing interrupts can disturb program execution and lead to significant loss of performance.
Notes
Important! In contrast to other programming languages, like Basic, com_Open() and com_Init() do not affect any control signals. If you want to address a modem at the serial interface through CA-Clipper, you must set the DTR and every other signal using the correct CA-Clipper Tools functions.
■ Buffer size can be between 100 bytes and 64 kByte. Settings
too large or too small are corrected, increased or decreased, accordingly.
■ To ensure compatibility with earlier versions of CA-Clipper
Tools, the nComPort, nBufferIn, and lTrapMode parameters can be used without nBufferOut (see the example).
Examples
■ Open a port with monitoring:
IF com_Num() > 0
nBuffSize := 4000 // 4000 byte buffer
ComOk := com_Open(1, nBuffSize) // Open COM1
IF .NOT. ComOk
? "Port cannot be opened !"
ENDIF
ENDIF
■ Open COM3 with the corresponding send and receive buffer:
? com_Open(3, 1000, 1000) // .T. when successful
■ Trigger interrupts for incoming data only, not for
transmission failure (receiving buffer 1000 characters, normal
transmission):
? com_Open(3, 1000, .T.) // .T. when successful
nComPort Designates the port (1 to 4) that is read.
nLength Designates the number of the characters in the buffer that are read. The default value reads all characters.
lNoDelete Designates whether or not characters are removed from the buffer as they are read. The default setting removes all characters from the buffer as they are read. However, if the parameter is .T., the characters remain in the buffer as long as it is not full.
Returns
The returned string contains the corresponding characters from the receiving buffer.
Description
All characters arriving at the serial port are stored in the appropriate buffer under interrupt control. It is possible to determine the number of characters in the buffer and to read one, several, or all of the characters. If the nLength parameter is not specified, then all the characters in the buffer are read.
Notes
■ Remember that you can receive additional characters between
Wait until at least 10 characters have been received:
DO WHILE com_Count(1) < 10 // Wait until 10
// characters in buffer
*...
ENDDO
cInput := com_Read(1, 10) // Read in 10 characters
? cInput // Display characters
// that are read
nComPort Designates the port (1 to 4) where an external line termination character is established.
nCharacter|cCharacter Designates a line termination character, which could be a numeric value or a character. When it is not specified, the existing line termination character (if any) is canceled. The default character is the no line termination character.
Returns
com_Remote() returns .F. if the specified port is invalid.
Description
When longer text is sent, the receiver should be able to break off the transmission session or to delete the sending buffer. To do this, a character can be defined as an external line termination character. If this character is received, it deletes the background buffer of the sending station, as if you had called com_SFlush(). The sending CA-Clipper program no longer concerns itself with this session.
com_SMode() can help you determine if the buffer of the remote station has been deleted.
Notes
■ Before a binary file transfer, an existing line termination
character should be canceled because the transmission could be terminated accidentally.
Examples
■ The remote station can terminate using Ctrl-X (Port 2):
com_Remote(2, 24)
com_Send(2, cLongText)
IF IsBit(com_SMode(2), 4)
? "Sending buffer is deleted automatically by remote station!"
ENDIF
■ Eliminate the external line termination character:
com_Remote(2)
nComPort Designates the port (1 to 4) on which the ring line is tested.
Returns
A return of .T. indicates that the ring line is active (MSR bit-7 = 1). A return of .F. indicates that the ring line is inactive (MSR bit-7 = 0).
Description
com_Ring() lets you check the ring line of a port from within a program.
Notes
■ When TERI (Trailing edge ring) is required, use the com_MSR()
function.
Examples
Modems generally show the ring signal of an incoming call. This does
not mean that a trouble free connection has been established.
DO WHILE .NOT. com_Ring(1) // Wait for call (RING)
* ...
ENDDO
? "Call detected..."
nComPort Designates the port (1 to 4) where the RTS signal is queried or changed.
lNewRTSStatus Designates the RTS signal status. When the parameter is .T., the function activates the RTS signal. When the parameter is .F., the function deactivates the RTS signal. If no parameter is specified, CA-Clipper Tools does not affect the current DTR output signal setting.
Returns
The returned status corresponds to the RTS signal status prior to the new setting.
A return of .T. indicates that the RTS signal is active (MCR Bit-2 = 1). A return of .F. indicates that the RTS signal is inactive (MCR Bit-2 = 0).
Description
com_RTS() queries or changes the status of the Request To Send signal (RTS). If lNewRTSStatus is not specified, the RTS status remains unchanged.
Notes
■ The com_Close() function resets (deactivates) the RTS signal.
The com_Open() function does not automatically activate it!
Examples
Set an individually programmable hardware handshake:
com_RTS(2, .T.) // Request to send a port 2
DO WHILE .NOT. com_CTS(2)
*...
ENDDO
com_Send(2, "The quick brown fox jumps over the lazy dog")
Counts the number of characters in the background sending buffer
Syntax
com_SCount(<nComPort>) → nLength
Arguments
nComPort Designates the port (1 to 4) for which the send buffer length is returned.
Returns
com_SCount() returns the number of characters in the sending buffer of the selected port.
Description
com_SCount() determines the number of characters in one of the four possible sending buffers. This is only possible when the com interface is interrupt controlled, meaning that data is sent in the background.
Notes
■ If you attempt to determine the character count in a port that
is not open, the function returns a value of -1.
Examples
nCharacter := com_SCount(1) // Number of characters
// in Port 1
com_Send(<nComPort>,<cString>) → nLength
Tip: An enhancement over previous versions is that there are no new
parameters!
Arguments
nComPort Designates the port (1 to 4) from which transmission occurs.
cString Designates the string that is transmitted by the selected port. If you only need to transmit a single character, then the second parameter can also be numeric and thereby pass the ASCII character code directly.
Returns
When transmission is successful, a 0 is returned. If transmission is not successful, the number of characters that have not been transmitted or could not be placed in the sending buffer is returned.
Description
com_Send() transmits one or more characters from one of four ports. This transmission can be interrupt driven (i.e. occurs in the background). The third parameter of com_Open() determines whether or not the transmission is direct or occurs in the background.
"Normal" Transmission During "normal" transmission, program execution can continue only when all of the characters have been sent to the port. A unique situation presents itself when the hardware handshake is activated. As soon as the receiving station deactivates the CTS signal from the sending station, any transmission is immediately stopped. To prevent the CA-Clipper program from hanging, com_Send() is terminated and a numeric value representing the number of characters not yet sent is returned. com_CTS() can determine if CTS input has been deactivated by the remote station. The software handshake is not supported in this mode!
Background Transmission The background mode supports software and hardware handshakes. The handshake automatically occurs in the background. Several new functions are available to help you maintain control of the transmission buffer in this situation. For example, com_SMode() allows you to determine if the buffer is waiting for an XON character to release the software handshake. Since this kind of wait can prove futile, you can use com_Flush() from within the program to empty the transmission buffer.
Notes
■ The handshake is only supported when the transmission buffer
is sending in the background. Use small packets during direct transmissions, and regularly query com_Soft_R().
■ Software and hardware handshakes are switched on using the
■ This is an example of "normal" transmission at port 1, with no
transmission buffer open:
com_Open(1, 1000) // Receiving buffer only
com_Hard(.T.) // Hardware handshake
ACCEPT "Please input name " TO cInput
nRest := com_Send(1, cInput) // 1st attempt to transmit
DO WHILE nRest > 0
cInput := Right(cInput, nRest) // Characters not yet sent
nRest := com_Send(1, cInput)
ENDDO
■ Here is an example for background or interrupt controlled
transmission at port 1. Everything else can proceed through "normal"
transmission:
com_Open(1, 1000, 1000) // 1000 byte transmission buffer
nRest := com_Send(1, "Attempt") // Place characters in buffer
nComPort Designates the port (1 to 4) for which a new I/O address is selected.
nIOPort|cIOPort Designates a valid I/O address for the selected port. The parameter can be a decimal or hexadecimal string. For information about the default value, see the Introduction this chapter.
Returns
com_SetIO() returns .T. if the new I/O address is successfully set.
Description
As is the case for other interface card settings, no true standard exists for I/O addresses. This is particularly true for the COM3 and COM4 ports. By using com_SetIO(), CA-Clipper Tools software can be adapted to the I/O addresses of the most eccentric interface card.
Notes
■ The function tests to see if there is a port available at the
selected I/O address. com_SetIO() returns .T. or .F. accordingly.
Examples
■ This is an example of a setting for port 2, with the I/O
address as a decimal:
com_SetIO(2, 504) // Address 1F8h
■ This is an example of a setting for port 4, with the I/O
address as a hexadecimal:
com_SetIO(4, "1F8") // .T.
■ This is an example of an invalid I/O address; the value
exceeds 1023:
com_SetIO(4, "10F8") // .F.
nComPort Designates the port (1 to 4) where the interrupt request (IRQ) is set.
nIRQ|cIRQ Designates the new IRQ number for the selected port. This parameter can be a decimal or a hexadecimal string and can be from 2 to 15.
Returns
The function returns .T. when the new IRQ has been successfully set.
Description
Unfortunately, there is not a binding standard for serial ports, particularly for COM3 and COM4.
Each interface card uses an interrupt request line to advise the interrupt controller that a character has been received. The controller then passes this information on to the CPU, which calls a service routine through the corresponding interrupt vector. XT systems have eight such interrupt lines available. AT systems have more than 16 available interrupt lines, some of which are usually occupied with other peripherals. The allocation of a new IRQ is no small matter and requires considerable technical expertise. Determining which IRQ is available and is not currently in use can usually be done by studying the configuration of all external devices and the technical documentation that accompanies your computer system. Typically IRQ's 0 and 1 are used for internal purposes (timer), 2 and 9 for network adapters, 5 and 7 for the printer, and 6 and 14 for floppies or hard disks.
Tip: As you will notice from the default setting in the Introduction to this chapter, it is possible for multiple ports to use the same IRQ (interrupt sharing). While CA-Clipper Tools functions do support this process, standard port hardware usually does not. However, special multiple port cards for this purpose are offered by a variety of manufacturers.
Notes
■ Please notice that the base settings that CA-Clipper Tools
uses for COM1 to COM4 are described in the Introduction to this chapter.
■ com_SetIRQ() does not test to see if a port is actually
serving the selected IRQ.
Examples
■ Set COM3 and COM4 to IRQ 5. This example requires two calls:
? com_SetIRQ(3, 5) // .T.
? com_SetIRQ(4, 5) // .T.
■ Set port 4 to IRQ 10. IRQ in hex:
? com_SetIRQ(4, "A") // .T.
■ This is an example of an incorrect value for IRQ:
? com_SetIRQ(2, 0) // Timer tick not allowed .F.
? com_SetIRQ(3, "10") // This would be decimal 16 .F.
nComPort Designates the port (1 to 4) for which the sending buffer is deleted.
Returns
If the selected sending buffer is successfully deleted, the function returns a .T.
Description
com_SFlush() eliminates all the characters in a sending buffer. This can be useful when the send routine has been futilely waiting for an XON character (bad software handshake).
Notes
■ A com_SFlush() to a closed port does not work.
■ It is not necessary to test for characters in the sending
buffer to carry out a com_SFlush().
Examples
When the sending buffer is waiting for an XON character and the
transmission has been delayed 30 seconds, the sending buffer is deleted:
nStart := Seconds() // When sent
com_Send(2, cSendText)
IF IsBit(com_SMode(2), 2) // Waiting for XON?
IF Seconds() - nStart > 30 // 30 second delay ...
com_SFlush(2) // Delete sending buffer
ENDIF
ENDIF
nComPort Designates the port (1 to 4) that is monitored in the background during transmission.
nKeyValue1|cKeyValue1 Designates the key code placed in the keyboard buffer as soon as the port send buffer has been cleared. Like the values available in CA-Clipper's SET KEY TO command, the key value can be a numeric value or an individual character. When this parameter is not passed, the supervision of buffer overflow can be switched off.
nKeyValue2|cKeyValue2 Designates the key code that the function places in the keyboard buffer at the start of a software or hardware handshake. Like the values in CA-Clipper's SET KEY TO command, the key value can be a numeric value or an individual character. When this parameter is not passed, the supervision of buffer overflow can be switched off.
Returns
com_SKey() returns .T. when the selected character is placed in the keyboard buffer by the corresponding event.
Description
This function allows you to monitor a transmission in the background with regard to the hardware or software handshake and the contents of the buffers. If you have designated nKeyValue1, it is deposited in the keyboard buffer as soon as the sending buffer is empty.
If the software or hardware handshake has been implemented by com_Soft() or com_Hard(), then the COM interface program places nKeyValue2 in the keyboard buffer when an XOFF is encountered or the CTS input is deactivated. If you have passed nKeyValue1, it is deposited in the keyboard buffer as soon as the sending buffer is empty.
Both events can prove very effective when combined with a CA-Clipper key trap. In this way the program does not constantly have to review the status of the sending buffer; it simply "takes note" when something happens. The specific event is then determined with com_SMode() within the called procedure.
Notes
Important! After each execution of a trap, com_SKey() must be reactivated.
Examples
■ Determine if the port 2 buffer is empty:
com_SKey(2, , 225) // Place code 225
■ Monitor the software and hardware handshakes for port 2:
SET KEY 225 TO HANDSHAKE
? com_SKey(2, , 225) // OK when returns .T.
com_Soft(2, .T.) // Software handshake on
com_Hard(2, .T.) // Hardware handshake on
com_Send(2, LongText) // Transmit something...
■ It is important that you always send the parameter:
PROCEDURE HANDSHAKE(A, B, C)
* Your Program
com_SKey(2, 225) // Must be reactivated
RETURN
Determines the current status of a background transmission
Syntax
com_SMode(<nComPort>) → nSendMode
Arguments
nComPort Designates the port (1 to 4) for which the background transmission status is returned.
Returns
com_SMode() returns a number for which the bits represent various meanings shown in the table below.
Description
The ability to transmit in the background demands the ability to control the sending buffer. For example, com_SMode() allows you to check to see if the sending buffer is waiting for an XON character when the software handshake is enabled. The bits in the returned value represent the different modes:
Table 3-7: Coding the Sending Mode
Bit Symb. Const. Definition
1 SMODE_EMPTY Sending buffer empty
2 SMODE_SOFT Wait for software handshake release(XON)
4 SMODE_HARD Wait for hardware handshake release(CTS)
8 SMODE_RFLUSH Deleted from remote station
Notes
■ If no sending buffer has been set up for the designated port
using com_Open(), the function returns a value of 0.
Examples
■ Determine whether the port 2 sending buffer is empty:
IF IsBit(com_SMode(2), 1)
? "Port 2 sending buffer empty!"
ENDIF
■ Wait 20 seconds while the send buffer for port 2 is waiting
for an XON, then release:
WaitPeriod(2000)
DO WHILE IsBit(com_SMode(2), 2) .AND. WaitPeriod()
*...
ENDDO
■ Clear the send buffer when XON is not received:
IF IsBit(com_SMode(2), 2)
com_SFlush(2) // Clear send buffer port 2
ENDIF
Tests to see if an XOFF character has been received
Syntax
com_Soft_R(<nComPort>,[<lXOFFFlag>]) → lXOFFFlag
Arguments
nComPort Designates the port (1 to 4) for which the XOFF flag is tested.
lXOFFFlag Designates whether the flag is set (.T.) or reset (.F.). The default value (.F.) resets the flag.
Returns
This function returns .T. after the last inquiry or after you open the port when the port has received an XOFF character (Ctrl-S). Subsequently the port does not receive an XON character (Ctrl-Q).
Description
If the software handshake is turned on, the receipt of an XOFF character is noted with an internal flag. This flag can be queried using com_Soft_R(). The receipt of an XON character resets that flag again. Since in some situations an XON character is never transmitted by the remote station, the flag can be reset using the second parameter.
Notes
■ If incoming XOFF characters are monitored, then it is best to
transmit relatively small strings through com_Send(). You can use com_Soft_R() to monitor between incoming XOFF characters.
Examples
■ First open the port:
com_Open(1, 1000)
■ Transmit until an XOFF character is recognized:
nPos := 1
DO WHILE .NOT. com_Soft_R() .AND. nPos <= Len(cString)
com_Send(1, SubStr(cString, nPos, 1))
nPos := nPos + 1
ENDDO
Tests to see if the buffer has automatically sent an XOFF character
Syntax
com_Soft_S(<nComPort>) → lXOFFFlag
Arguments
nComPort Designates the port (1 to 4) for which the XOFF flag is tested.
Returns
This function returns .T. when the remote station indicates that the buffer is 75% or more full.
Description
If the software handshake has been selected and the buffer is more than 75% full, an XOFF character is automatically transmitted to the remote station. This is noted with an internal flag, which can be queried using com_Soft_S(). When the buffer empties to 50% or less, it generates the transmission of an XON character, and this flag is reset.
Notes
■ When selecting the size of the buffer, decide whether the
remaining 25% will be sufficient at high baud rates.
Examples
Test to see if a 75% full buffer automatically transmits an XOFF
character:
IF = com_Soft_S(1)
? "It's time to empty the buffer! "
...
ENDIF
nComPort Designates the port (1 to 4) for which the software handshake is set.
lNewHandshake Designates whether the handshake is on (.T.) or off (.F.). If this parameter is omitted, the function returns the current setting.
cXONchar Designates any character you choose as an XON character. The default character is ASCII 19 - Ctrl-S.
cXOFFchar Designates any character you choose as an XOFF character. The default value is ASCII 17 - Ctrl-Q.
Returns
The function returns the previously set value.
Description
With modem connections, a hardware handshake is impossible, which is why we are making a software handshake available with this function. When a buffer is 75% full, an XOFF character (Ctrl-Q) is transmitted to the remote station. As soon as the buffer has again been emptied to 50% or less, the XON character (Ctrl-S) is transmitted. You can use characters other than Ctrl-S or Ctrl-Q for individual protocols, which would then be taken into account in the situations described above.
Notes
■ The software handshake only supports background transmission
(when com_Open() has been implemented with the third parameter nBufferOut).
■ When you want to transmit binary data, the software handshake
cString Designates the character string that you choose to center.
nLength Designates the length of the line within which the cString sequence is centered.
cPadCharacter Designates the character with which the cString sequence is centered. The default character is a space.
lMode Designates whether only the beginning, or both sides of cString are padded. The default value (.F.) only fills the beginning.
Returns
The processed string is returned.
Description
The Center() function provides a simple way to center text in any line. Center() is able to pad only on the left or on the left and right using any selected character. Leading and trailing blanks (if any) are replaced with the new character.
When nLength is not specified, Center() assumes the maximum available line width to be MaxCol() + 1, so that the correct output appears in the windows. Additionally, the current cursor position or the column position selected through a SAY command is also noted. So, if there is an output on an 80-column line that begins at column 20, a section of 40 characters from column 20 is used to center the output.
Notes
■ If the sum of the pad characters is odd, then one more
character is inserted at the beginning of the character string.
Examples
■ Center the output with an available line length of 10, and
insert the leading characters:
? Center("xx", 10) // " xx"
■ Fill on the left and on the right:
? Center("xx", 10, .T.) // " xx "
■ When characters that match the <cPadCharacter> are present,
these characters are removed prior to centering:
? Center("xx ", 10, .T.) // " xx "
■ Fill with other characters:
? Center("xx", 10, ".") // "....xx"
? Center("xx", 10, ".", .T.) // "....xx...."
? Center("x", 10, ".", .T.) // ".....x...."
■ In the following example, the "X" is intended to represent a
40-character wide screen. The string "CLIPPER" is centered there
with the "." character, starting at position 10:
@@ 1, 10 SAY Center("CLIPPER", ".", .T.)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXX.......CLIPPER......XXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
lMonochromeMode Designates the 40ûcharacter mode. If this parameter is .T., the function switches to the monochrome CGA 40-character mode. If this parameter is.F., the function switches to the 40-character color mode. The default value is .F..
Returns
CGA40() returns .T. if the screen adapter you use permits a switch.
Description
This function can be used with any screen adapter that has CGA emulation capability. You can switch to CGA 40-character mode, color or monochrome. The function IsColor() also returns .T. in the monochrome mode because this option activates a "color summing" of the screen adapter and does not switch to the monochrome mode for a hercules adapter or a monochrome text adapter.
Notes
Important! This function cannot be implemented when windows are open.
■ Modes set through this function can also be combined with
lMonochromeMode Designates the 40ûcharacter mode. If this parameter is .T., the function switches to the monochrome CGA 80-character mode. If this parameter is .F., the function switches to the 80-character color mode. The default value is .F..
Returns
CGA80() returns .T. when the screen adapter you use permits a switch.
Description
This function can be used with any screen adapter that has CGA emulation capability. You can switch to CGA 80-character mode, color or monochrome. The function IsColor() also returns .T. in the monochrome mode because this option activates a "color summing" of the screen adapter and does not switch to the monochrome mode for a hercules adapter or a monochrome text adapter.
Notes
Important! This function cannot be implemented when windows are open.
■ A call with .T. corresponds to BIOS mode 2. A call with .F.
corresponds to BIOS mode 3.
Examples
■ Switch to 80-character mode (color):
? CGA80() // .T., if successful
■ Switch to 80-character mode (monochrome):
? CGA80(.T.) // .T., if successful
cString1 [@] Designates the character string to which values from a second character string cString2 are added.
cString2 Designates the character string that is added, character for character, to cString1.
Returns
The processed character string is returned.
Description
You can use CharAdd() to produce simple character string coding. The function can prove very useful when processes are coded by individual characters in a string.
Notes
■ When both character strings are the same length, then the
first byte of cString1 can be linked with the first byte of cString2, and the second byte of cString1 can be linked with the second byte of cString2, and so on. If cString2 is shorter than cString1, then as soon as the last byte of cString2 is reached, the process continues and starts again with the first byte of cString2. However, if cString1 is shorter than cString2, the process terminates with the end of cString1.
■ Values greater than 256 can result when adding values. The
new value is then formed based on the following formula:
(Asc(Character1) + Asc(Character2))% 256.
■ Implementing CSetRef() can suppress the return value for this
function to save room in working memory.
Examples
■ Add a value of 1 to each character:
? CharAdd("01234", Chr(1)) // "12345"
■ Adding a value of 255 to each character corresponds to
subtracting 1:
? CharAdd("12345", Chr(255)) // "01234"
Links corresponding ASCII codes of paired strings with an AND operation
Syntax
CharAnd(<cString1>,<cString2>) → cString
Arguments
cString1 [@] Designates the character string to which characters are added.
cString2 Designates the character string that contains the characters that are added to the characters in cString1.
Returns
The processed string is returned.
Description
CharAnd() can be used as a simple way to reset the high bit for all the characters in a string. The function joins (links bit by bit using an AND operation) each character in cString1 with the corresponding character in cString2.
Notes
■ When both character strings are the same length, then the
first byte of cString1 can be linked with the first byte of cString2, and the second byte of cString1 can be linked with the second byte of cString2, and so on. If cString2 is shorter than cString1, then as soon as the last byte of cString2 is reached, the process continues and starts again with the first byte of cString2. However, if cString1 is shorter than cString2, the process terminates with the end of cString1.
■ Implementing CSetRef() can suppress the return value for this
function to save room in working memory.
Examples
The second parameter is shorter than the first parameter in this
example. As a result, the "1", the "a", and the first blank are joined
with AND to the "1" in "123"; the "2", the "b", and the second blank are
joined with AND to the "2" in "123"; and the "3", the "c", and the third
blank are joined with AND to the "3" in "123":
? CharAnd("123abc ", "123") // "123!"# "
Returns characters in the even positions of a string
Syntax
CharEven(<cString>) → cString
Arguments
cString Designates the character string from which all even characters are returned.
Returns
CharEven() returns a string containing all the even characters of cString.
Description
CharEven() assembles all even characters within a string into a new character string. This allows you to process variables consisting of the characters and attributes of a video screen's contents very simply. This function can be implemented in conjunction with functions from the video section. You can return the attributes from a screen string, with all the characters removed.
Notes
■ The first position in a string is 1, and therefore is not
even.
Examples
■ Assemble all even characters:
? CharEven("1234a") // "24"
■ Return the expanded text to "normal":
? CharEven(" H e l l o") // "Hello"
CharList() returns a list in which each character in cString appears only once.
Description
CharList() determines the list of characters that appear in the cString. Each character only appears in the list once.
Notes
■ The CharList() function's return value is never longer than
256 characters.
■ If you sort this result with CharSort(), you have an ascending
list of characters.
Examples
■ What letters are contained in the text?
? CharList("Hello goodbye") // "Helo gdby"
■ Show a sorted list of all letters in a text:
? CharSort(CharList("Hello goodbye")) // "Hbdegloy"
cString [@] Designates the character string that is mirrored.
lBlank Designates whether the function mirrors everything (.F.) or does not mirror the blanks at the end of a character string (.T.). The default value is .F..
Returns
CharMirr() returns the processed cString.
Description
CharMirr() reverses a string. The function returns a palindrome of cString.
The optional logical parameter allows you to mirror a string and ignore the blanks. This permits you to build index entries that end with a particular sequence.
Notes
■ The returned value of this function can be suppressed by
implementing CSetRef() to save room in working memory.
Examples
■ This example shows a simple exchange:
? CharMirr("abc321") // Result: "123cba"
■ This example shows one of the best known palindromes:
? CharMirr("ABLE WAS I ERE I SAW ELBA")
■ When you index, you must do it without spaces because this is
the only way a reverse string can be searched for:
INDEX ON CharMirr(Field, .T.) TO Index
■ Search for all expressions in the mirrored index, ending in
"per":
SEEK "rep"
cString1 Designates a string that is mixed with cString2.
cString2 Designates a string that is mixed with cString1.
Returns
CharMix() returns a string that is double the length of cString1, assuming that cString2 contains at least one character.
Description
This function allows you to mix the characters from two character strings together. The characters from cString1 and cString2 appear alternately in the result string. The length of cString1 forms the basis for the maximum count of the resulting mix. A longer cString2 string is cut down to the length of cString1. A shorter cString2 is processed from beginning to end, wrapping to the beginning again until there are no more characters in cString1.
Notes
■ This function can be used to recombine strings extracted by
■ This is an example of a simple mix:
? CharMix("ABC", "123") // "A1B2C3"
■ This is a mix where the second string is shorter:
? CharMix("ABCDE", "12") // "A1B2C1D2E1"
■ This is a mix where the second string is longer:
? CharMix("AB", "12345") // "A1B2"
■ What you can do with this?
? CharMix("HELLO". " ") // "H E L L O"
■ If the second parameter is null, then the first parameter is
returned unchanged:
? CharMix("HELLO", "") // "HELLO"
Lists the characters that do not appear in a string
Syntax
CharNoList([<cString>]) → cNotContained
Arguments
cString Designates the string that is processed. The default value is for an empty string.
Returns
CharNoList() returns a character string that contains all characters not found in cString.
Description
This function determines all characters that are not contained in cString. The resulting characters might be used as replacement characters or for complex deletion procedures.
Examples
■ Delete all characters except "XYZ":
String := "ABXCDYEF"
? CharRem(CharNoList("XYZ"), String) // "XY"
■ Generate a list of all 256 ASCII characters:
? CharNoList()
■ To save text to a memo field, all null characters (Chr(0))
must be exchanged for a character that is not being used:
cNoList := CharNoList(cMemoText)
cNoChar := SubStr(cNoList, 1, 1)
CharRepl(Chr(0), @cMemoText, cNoChar)
cString [@] Designates the string that is negated.
Returns
The processed cString is returned.
Description
This function negates each bit in cString. This makes it possible to get a decreasing index sequence.
Notes
■ The returned value of this function can be suppressed by
implementing CSetRef() to save room in working memory.
Examples
When a character string that has already been negated is negated again,
the result is identical to the original:
CharNot("123ABCabc") // " ¥£ "
CharNot(" ¥£") // "123ABCabc"
Returns characters in the odd positions of a string
Syntax
CharOdd(<cString>) → cString
Arguments
cString Designates the character string from which all the odd characters are returned.
Returns
CharOdd() returns a character string that contains all the odd characters from cString.
Description
CharOdd() assembles all odd characters within a string into a new character string. This allows you to process variables where screen content, consisting of characters and attributes, is saved. This function can then be used in conjunction with functions from the video section.
Notes
■ The first position in a string is 1, and therefore is odd.
Examples
■ Assemble all odd characters:
? CharOdd("1234a") // "13a"
■ Return the expanded text to "normal":
? CharOdd("H e l l o ") // "Hello"
cDeleteCharacter Designates the characters that have their adjoining duplicates removed from cString. The default value removes all adjoining duplicate characters.
cString Designates the character string that is processed.
Returns
The processed cString is returned.
Description
CharOne() searches within the cString for repetitions of adjoining characters. When a character is removed, all of the characters but the first are deleted. This differs significantly from the CharList() function, where multiple occurrences of characters within the context of the string are removed.
Notes
■ Without the cDeleteCharacter parameter, all the repeating
characters are removed. If the parameter is specified, only those characters in cDeleteCharacter are removed.
Examples
■ Check for double occurrences of each character in the
character string:
? CharOne("122333a123") // "123a123"
? CharOne("A B CCCD") // "A B CD"
■ Delete multiple side-by-side blanks:
? CharOne(" ", "A B A B") // "A B A B"
■ Make the letter "o" only appear once in the character string:
? CharOne("o", "122oooB12o") // "122oB12"
Determines the common denominator between two strings on the basis of individual characters
Syntax
CharOnly(<cString1>,<cString2>) → cString
Arguments
cString1 Designates a sequence of characters that are not removed from cString2.
cString2 Designates the string that is processed.
Returns
CharOnly() returns the processed string cString2.
Description
CharOnly() removes all characters from cString2 that are not in cString1. The function is particularly useful when comparing data that should have a standard format but has been input by different people. This category can consist of things like telephone numbers, part numbers, customer numbers, etc. (see example).
Examples
Since numbers are the only characters that are relevant in a telephone
number, any characters that are not numbers are removed. The result in
each case is "2133907923":
? CharOnly("0123456789", "213 - 39 07 923")
? CharOnly("0123456789", "213 / 390 7923")
Joins the corresponding ASCII code of paired strings with an OR operation
Syntax
CharOr(<cString1>,<cString2>) → cString
Arguments
cString1 [@] Designates the string upon which the OR operation is performed.
cString2 Designates the characters that are used when performing the OR operation on cString1.
Returns
CharOr() returns the processed cString1.
Description
The function joins (links bit by bit using an OR operation) each character in cString1 with the corresponding characters in cString2. CharOr() can therefore place particular bits within the characters.
Notes
■ If both character strings are the same length, then the first
byte of cString1 is linked with the first byte of cString2, and the second byte of cString1 is linked with the second byte of cString2, etc.. If cString2 is shorter than cString1, then when the last byte of cString2 is reached, it continues with the first byte of cString2. However, if cString1 is shorter than cString2, the process terminates at the end of cString1.
■ The return value of this function can be suppressed by
implementing CSetRef() to save room in working memory.
Examples
■ Both bytes in the first parameters are joined with OR using
the "0" character. This means that Chr(1) is converted into the
ASCII character æ1", Chr(2) into the ASCII character "2", etc.:
? CharOr(Chr(1) + Chr(2), "0") // "12"
■ All bytes in the first parameters are joined (OR) with Chr(32)
(set bit 5 only):
? CharOr("123ABCC[\]abc", CHR (32)) // "123abc(|)abc"
cString Designates the character string that is packed.
nMethod Designates which pack algorithm is used on the designated character string. The default value is method 0.
Returns
CharPack() returns the compressed string.
Description
This function allows you to compress (pack) the contents of strings. The function supports two different pack methods:
Table 4-2: Pack Methods Supported
<nMethod> Pack Algorithm
0 Modified run length encoding
1 Bit oriented algorithm
Notes
Important! A packed string can contain Chr(0) or other control characters.
Examples
Using the bit pack method, compress a text from a DOS file:
Var := CharPack(FileStr("C:\TEXT\TEST.TXT"), 1)
StrFile(Var, "C:\TEXT\TEST.PAK") // New save
CharPix() returns a value that corresponds to the number of pixel lines per character.
Description
Different screen adapters build characters from a different numbers of pixel lines. Based on the installed mode, the number of pixel lines for a particular type of screen adapter may also vary.
Use CharPix() to determine the number of pixel lines available in the currently installed mode. This information is useful when used in conjunction with SetCursor().
Examples
Display the number of pixel lines:
? CharPix() // VGA, no mode change - 16
cSearchFor1 Designates the character that is searched for in cString1.
cString1 Designates the character string to search with cSearchFor1.
cSearchFor2 Designates the character that is searched for in cString2.
cString2 Designates the character string to search with cSearchFor2.
Returns
CharRelA() returns the positions where cSearchFor1 and cSearchFor2 occur in the corresponding character strings.
Description
This function builds a relationship (CHAR RELAtion) between two character strings. It determines the positions where the characters in cSearchFor1 appear in cString1 and where the characters in cSearchFor2 appear in cString2.
Notes
■ The function returns a value of 0 if no relationship is found.
Examples
Search for the first position in which a "b" appears in the first string
and a "1" appears in the second:
? CharRelA("b", "b b b b", "1", "bbb11111") // 5
cSearchFor1 Designates one or more characters within cString1 for which to search.
cString1 Designates the character string where cSearchFor1 is found.
cSearchFor2 Designates one or more characters within cString2 for which to search.
cString2 [@] Designates the character string where cSearchFor2 is found.
cReplaceExpression Designates one or more characters to replace those at the established corresponding position within cString2.
Returns
The processed cString2 is returned.
Description
This function is easier to use than it seems. If we proceed on the assumption that both search expressions and the replacement expression are only one character long, then the following steps occur:
■ All positions are determined where cSearchFor1 is found
within cString1.
■ All positions are found where cSearchFor2 is found within
cString2.
■ The character in the cString2 string is replaced by the
character in the cReplaceExpression.
This function can be used to simplify work with variables that contain screen memory. If cPict1 contains the character "|"at position 34 and cPict2 contains the character "-" at the same position, then this position within cPict2 can be replaced with a new character, "+"', which represents the combination of the two.
Multiple Exchanges Both search expressions and the replacement expression can be longer than one character. The previously described exchange procedure occurs repeatedly — initially with the first character in the three character strings, then with the second, and so on. The number of iterations is regulated by the length of cSearchFor1. If cSearchFor2 or the cReplaceExpression are shorter, then the last byte is used again.
Notes
■ The length of cString2 determines the number of search
procedures at any one time. The length of cSearchFor1 determines the number of possible exchanges.
■ The return value of this function can be suppressed by
implementing CSetRef() to save space in working memory.
■ A use for multiple replacement using CharRelRep() can be found
in the accompanying sample programs.
Examples
Determine every position where a "b" occurs in the first string and a
"1" occurs in the second string. The respective character is then
exchanged for the one designated as the fifth parameter.
? CharRelRep("b", "b b b b", "1", "bbb11111", "x")
//"bbb1x1x1"
cDelCharacterstring Designates the characters that are removed from cString.
cString Designates the string that is processed.
Returns
The processed cString is returned.
Description
With this function you can remove particular characters from any position in cString. It is possible to ensure that the character string does not contain these characters later.
Notes
■ No changes occur if you pass invalid or incorrect parameters.
Examples
■ Remove the blanks from a string:
? CharRem(" ", " 1 2 ") // "12"
■ Remove the number "3" and the letter "y":
? CharRem("3y", "xyz123") // "xz12"
cSearchFor Designates a list of characters to search for in cString.
cString [@] Designates the character string within which to search for and replace the characters in cSearchFor.
cReplaceExpression Designates the character list that replaces characters in cString.
lMode Designates whether multiple replacements are made.
lMode Designates one pass of the cString (.T.) or multiple replacements (.F.). The default value is for .F..
Returns
The processed cString is returned.
Description
This function allows you to carry out very complex replacement procedures. Every character in the cSearchFor is searched for within the cString. If found, the character is replaced by the corresponding character in the cReplaceExpression.
If lMode is not passed, characters are exchanged repeatedly as required. This means that the function goes through each individual character in the found characters in sequence, and then searches the entire cString, exchanging cSearchFor for corresponding characters in cReplaceExpression. When you use this technique, characters that have already been replaced are exchanged again if the replacement character also appears in the search list.
However, if the optional lMode parameter is specified, the function proceeds differently. It goes through each character in cString in sequence, determining whether or not it should be replaced. Characters that have been replaced are not replaced again.
As a rule, if the same characters appear within cReplaceExpression and cSearchFor, you must check very closely to determine which lMode parameter should be used (see example).
Notes
■ If the cReplaceExpression sequence is shorter than
cSearchFor, the characters that do not have a corresponding replacement in cReplaceExpression are replaced with the last character of cReplaceExpression (see example).
■ The return value of this function can be suppressed by
implementing CSetRef() to save space in working memory.
Examples
■ The number "1" is replaced with the letter "a", the number "2"
with the letter "b", etc.. If the number "4" appeared in the
character string, it would be replaced with a "d":
? CharRepl("1234", "1x2y3z", "abcd") // "axbycz"
■ The letters a-j are replaced with the numbers 0-9; for
example, an "f" is replaced with a "6":
? CharRepl("abcdefghij", "jhfdb", "1234567890") // "08642"
■ The third parameter makes fewer characters available for the
exchange. Therefore the letters f-j are replaced with the last
characters from "12345":
? CharRepl("abcdefghij", "jhfdb", "12345") // "55542"
■ Here is an example of the difference between a specified
<lMode> parameter (.T.) and the default parameter (.F.):
? CharRepl("1234", "1234", "234A") // "AAAA"
? CharRepl("1234", "1234", "234A", .T.) // "234A"
CharSort(<cString>,[<nElementlength>],
[<nComparisonlength>],[<nIgnore>],
[<nElementPosition>],[<nSortlength>],
[<lDescending>]) → cString
Note: This version of CA-Clipper Tools contains an optional
parameter that previous versions did not include.
Arguments
cString [@] Designates the character string that is sorted.
nElementlength Designates the length of the sorting element. The default value is for 1 character.
nComparisonlength Designates the number of characters that a sorting element takes into account in a comparison. The default value is nElementlength characters.
nIgnore Designates the number of characters at the beginning of the cString that should not be taken into account in the sorting.
nElementPosition Designates an offset. This parameter designates from what position within the sorting element the comparison is made. The default value is the first character (0).
nSortlength Designates the length of the sort area relative to the nIgnore offset.
lDescending Designates whether the function sorts in ascending or descending order. If this parameter is not specified, or is specified as .F., then the function sorts in ascending order. When specified as .T., the function sorts in descending order. The default value is .F..
Returns
The sorted cString is returned.
Description
CharSort() allows you to sort the characters in a string in many different ways. Everything from the length of the sorting elements to the sort sequences is taken into account.
Notes
■ Invalid parameters return a null string.
■ The function uses a fast sort algorithm.
■ The return value of this function can be suppressed by
implementing CSetRef() to save space in working memory.
Examples
■ Sort characters in a string according to their ASCII code:
? CharSort("qwert") // "eqrtw"
■ Sort 2-byte length elements:
? CharSort("qwert", 2) // "erqwt"
■ Sort 2-byte length elements, but only use the first character
for the comparison:
? CharSort("bla4a3a2a1", 2, 1) // "a2a1a3a4b1"
■ Sort individual characters, excluding the first three:
? CharSort("XXXqwert", 1, 1, 3) // "XXXeqrtw"
■ Sort paired sequences for the entire string, where only the
second character within each sequence is used:
? CharSort("bla4a3a2a1", 2, 1, 0, 1) // "a1b1a2a3a4"
■ Sort only the first four characters within a string:
? CharSort("384172852", 1, 1, 0, 0, 4) // "134872852"
■ Sort in descending order:
? CharSort("qwert", .T.) // "wtrqe"
cString Designates a character string that is expanded with spaces or cCharacter|nCharacter characters to nLength length.
nLength Designates the length of the return string.
cCharacter|nCharacter Designates the fill character and token delimiter. It can be a numeric value or a character. If it is a numeric value, it must be between 0 and 255. The default value is a space Chr(32).
Returns
CharSpread() returns the expanded string.
Description
CharSpread() expands a string to a preset length. However, it behaves differently than the Expand() function.
CharSpread() uses cCharacter|nCharacter as the character to insert during the expansion. The string is expanded between tokens delimited by this character up to the length specified by nLength. This is similar to full justification in a text editor.
Notes
■ Previously existing fill characters cCharacter|nCharacter
are not taken into account in the redistribution (see examples). If this procedure is not satisfactory to you, then you can call the CharOne() for the string before you call CharSpread().
Examples
For clarity, these examples do not contain blanks.
■ When the delimiter does not appear in the string, no expansion
takes place:
? CharSpread("123456", 20, ".") // "123456"
■ This example shows a numeric code for the (".") character:
? CharSpread("1.2.3.4.5.6", 20, 46) // "1...2...3..4...5...6"
■ In this example, the fill character is already there:
? CharSpread("11..22..33", ".") // "11.......22.......33"
? CharSpread("11.22........33", 20, ".")
// "11....22..........33"
cString [@] Designates the character string that is processed.
Returns
The processed character string is returned.
Description
CharSwap() takes all neighboring characters in cString and exchanges them. As a result, bytes in even positions are exchanged for those in odd positions.
CharSwap() is very important when you use string integers generated by the CA-Clipper I2Bin() function that must be saved or sorted. The CharSwap() exchange must be carried out prior to calling CharSort() (low/high ordering of 16-bit integers) to achieve an accurate result.
Notes
■ Since the length of the character string is not changed, a
call by reference is recommended. This increases the speed of the function.
■ The value this function returns can be suppressed by setting
idPackCharacterstring Designates a string that was previously compressed with the CharPack() function.
Returns
CharUnpack() returns an uncompressed string.
Description
This function unpacks strings compressed by the CharPack() function. Notice that the related pack method is automatically recognized. Since we presuppose that the CharUnpack() string parameter was compressed previously with CharPack(), it is assured that the returned string is not longer than the maximum permitted under CA-Clipper.
Examples
The CharUnpack() function recreates a string:
? CharUnpack(CharPack("AAAAAAAAAAAA")) // "AAAAAAAAAAAA"
nTopline Designates the line for the top-left corner of the area.
nLeftcolumn Designates the column for the top-left corner the area.
nBottomline Designates the line for the bottom-right corner of the area.
nRightcolumn Designates the column for the bottom-right corner of the area.
cNewcharacter|nNewcharacter Designates the new character for the screen area. Specify the parameter as a numeric in the range of 0 to 255 or as a character string. The default value is the CLEARB.
cOldcharacter|nOldcharacter Designates which character to exchange. Specify the parameter as a numeric in the range of 0 to 255 or as a character string. The default is to exchange all characters.
() When no parameter is designated, the function replaces all characters in the screen area with CLEARB.
Returns
The function always returns a null string.
Description
Within a screen area, CharWin() replaces all characters or just a particular character with a new one. If cNewcharacter|nNewcharacter is not designated, the function uses the character set with SetClearB(), where the preset value is Chr(255). The upper-left and lower-right corner rows and columns are given for the borders of the area. If these arguments are missing, then the entire screen area is exchanged.
Examples
■ Exchange all characters for CLEARB:
SetClearB("X") // Exchanges within CharWin() entire screen
■ Exchange all "A" for "B":
CharWin(10, 10, 20, 70, "B", "A") // Always returns a ("") null
// string
■ Numeric characters can also be designated:
CharWin(10, 10, 20, 70, 66, 65) // A = 65, B = 66
Joins corresponding ASCII codes of paired strings using an exclusive OR operation
Syntax
CharXor(<cString1>,<cString2>) → cString
Arguments
cString1 [@] Designates the character string on which the exclusive OR (XOR) operation is performed.
cString2 Designates the characters that are joined using XOR with cString1.
Returns
The processed cString1 is returned.
Description
The function performs an exclusive OR operation on each character in cString1 with the corresponding characters in cString2.
You can use CharXor() to code passwords and text. The advantage of this function is that it can be used for both encryption and decryption.
Notes
■ If both character strings are the same length, then the first
byte of cString1 is linked with the first byte of cString2, and the second byte of cString1 is linked with the second byte of cString2, etc.. If cString2 is shorter than cString1, then when the last byte of cString2 is reached, it continues with the first byte of cString2. However, if cString1 is shorter than cString2, the process terminates at the end of cString1.
■ The return value of this function can be suppressed by
implementing CSetRef() to save room in working memory.
Examples
■ CharXor() returns the coded value once. The password should
be as long as possible:
? CharXor("Secret", "Password")
■ Call CharXor() twice to return the initial value:
? CharXor(CharXor("Secret", "Password"), "Password")
■ A double encryption is also possible:
? CharXor(CharXor("Secret", "Password"), "A12B44")
Calculates the checksum for a character string (algorithm)
Syntax
Checksum(<cString>) → nCheckSum
Arguments
cString Designates the character string for which the checksum is computed.
Returns
The number returned is the checksum for the cString.
Description
Checksum() calculates the checksum for a character string. This checksum can determine if a character string has been changed, or transmitted or typed incorrectly. Checksum() is position dependent, so the likelihood of error recognition is greater than with AsciiSum().
Notes
■ The return value is a 32-bit whole number.
■ The checksum cannot be used for definitive coding of data
because the calculated sum for two different character strings could be the same. For example, the checksum for "PASTETEN" and "PERSONAL" are identical.
■ If character strings have different lengths, the strings
cannot have identical values.
Examples
■ In this example, AsciiSum() would have returned identical
results:
? Checksum("abc") // Result: 247334
? Checksum("cba") // Result: 246822
■ Different character strings of identical length can produce
identical results:
? Checksum("PASTETEN") // Result: 530020
? Checksum("PERSONAL") // Result: 530020
■ A null string returns a result of 0:
? Checksum("") // Result: 0
nLONG|cHexLONG Designates either a decimal number or hexadecimal character string.
nBitPos32 Designates the bit numbers to delete.
Returns
ClearBit() returns a value in which the designated bits are cleared.
Description
ClearBit() resets particular bits within a field to change something like a serial port register. In contrast to NumAnd(), the bit numbers are given and do not need to be converted beforehand. The value 1 represents the bit with the lowest value, and the value 32, the bit with the highest value.
Notes
■ An invalid parameter returns a result of -1.
Examples
Bits 3, 4, and 6 are cleared in a bit pattern:
nBitPattern := 255
nBitPattern := ClearBit(nBitPattern, 3, 4, 6) // Result: 211
nRow Designates the line to be erased. The default is the cursor line.
nColumn Designates the column where the erasure is to begin. The default is the cursor column.
cAttrn|nAttr Designates the attribute used to clear. The default is CLEARA.
cCharacter|nCharacter Designates the character used to clear. The default is CLEARB.
Returns
ClearEol() always returns a null string.
Description
Use ClearEol() to clear a specific line from a given position to the end of that line. If arguments are not specified, then the current nRow cursor line and nColumn cursor column are used as the starting location. The clear always goes to the end of the line specified with the CLEARA attribute and CLEARB character, or with the Attr|nAttr attribute and cCharacter|nCharacter character.
ClearEol() has some advantages over the CA-Clipper @ Row, Column commands:
1. It lets you take the returned value of the character string type and
combine it with string outputs (e.g., LIST...ClearEol()).
2. The cursor position is not affected.
3. The arguments are optional. If they are not specified, the function
clears from the current cursor position with the CLEARA attribute and CLEARB character.
Notes
■ You can specify the cAttr|nAttr attribute and the
cCharacter|nCharacter character in a number of ways. Please refer to the chapter introduction.
■ Default attribute and character can be set with SetClearA()
■ If no arguments are specified for line or column, then the
function will automatically orients itself to the current cursor position.
Examples
■ Clear from the cursor position to the end of the line with the
CLEARB character and CLEARA attribute:
ClearEol()
■ Do the same for line 23 from the current cursor position:
ClearEol(23)
■ Do the same as before, but begin the erasure at column 55:
ClearEol(23, 55)
■ The attributes can be specified in different ways. In the
following three examples, the clear character is set with
SetClearB():
ClearEol(23, 55, 4) // red on black
ClearEol(23, 55, "4/7") // red on white
ClearEol(23, 55, "B/W") // blue on white
■ Clear with special attribute and character:
ClearEol(23, 55, "3/1", ":")
ClearEol(23, 55, "B/W", "+")
nDelay Designates the time delay in milliseconds for the individual steps in the delete procedure. The value is in the range of 1 to 65535.
nTopline Designates the line for the top-left corner of the area. The default value is the topmost line.
nLeftcolumn Designates the column for the top-left corner of the area. The default value is the leftmost column.
nBottomline Designates the line for the bottom-right corner of the area. The default value is the bottommost line.
nRightcolumn Designates the column for the bottom-right corner of the area. The default value is the rightmost column.
cCharacter|nCharacter Designates the character to use to clear the screen. The character can be numeric in the range of 0 to 255 or a character string. The default is the character set using SetClearB().
Returns
The function always returns a null string.
Description
ClearSlow() clears a screen area from the outside in, step by step, with time delays. You can designate the delay in milliseconds. If the parameters for the area coordinates are left out, the function clears the entire screen. In this case, the delete character set through SetClearB() is used. The preset value is Chr(255). CA-Clipper Tools uses this character because, in contrast to Chr(32), it accepts a color attribute on all screen adapters.
Notes
■ If no screen coordinates are designated, the entire screen is
cleared.
Examples
■ Use Chr(255) to clear the entire screen with a 50-millisecond
delay:
ClearSlow(50) // Always returns ""
■ Clear an area with spaces and use a 10-millisecond delay:
ClearSlow(10, 4, 4, 20, 76, 32) // Delete character 32 (Blank)
nTopLine Designates the topmost line where clearing is to begin. The default value is the cursor line.
nLeftCol Designates the leftmost column from which clearing is to begin. The default value is the cursor column.
nBottomLine Designates the bottommost line to clear. The default is the last screen line or window line.
nRightCol Designates the rightmost column to clear. The default is the right screen border or window border.
cAttr|nAttr Designates the attribute to use to clear. The default is the standard attribute CLEARA.
cCharacter|nCharacter Designates the character to use to clear. The default is the standard character CLEARB.
Returns
ClearWin() always returns a null string.
Description
ClearWin() clears a specified screen area. This area extends from
< nTopLine> to nBottomLine and from nLeftCol to nRightCol.
Without these parameters, the line and column that correspond to the current cursor position for nTopLine and nLeftCol, and the bottommost line and rightmost column are used for nBottomLine and nRightCol.
You can clear with the standard attribute and character (CLEARA and CLEARB), or with the cAttr|nAttr attribute and the cCharacter|nCharacter character.
Notes
■ The cAttr|nAttr attribute and cCharacter|nCharacter
character are specified in different ways. Please refer to the Introduction of this chapter for more details
■ The standard attribute and character are set with SetClearA()
■ If no parameters are specified for the line or column, the
function automatically orients itself to the current cursor position.
Examples
■ Clear from the cursor position to the end of the line with the
CLEARB character and CLEARA attribute:
ClearWin()
■ Do the same for line 23 from the current cursor position:
ClearWin(23)
■ Clear a window between line 23, column 15 and line 24, column
70:
ClearWin(23, 15, 24, 70)
■ You can specify the attributes in different ways. In the
following three examples, the CLEARB() clear character is used.
ClearWin(23, 15, 24, 70, 4) // red on black<
ClearWin(23, 15, 24, 70, "4/7") // red on white
ClearWin(23, 15, 24, 70, "B/W") // blue on white
■ Clear when specifying attribute and character:
ClearWin(23, 15, 24, 70, "B/W", "+") // blue on white
Clears characters and attributes to the end of a line
Syntax
ClEol([<nRow>], [<nColumn>]) → cNull
Arguments
nRow Designates the line to clear. The default is the cursor line.
nColumn Designates the column from which to clear. The default is the cursor column.
Returns
ClEol() always returns a null string.
Description
Implement the ClEol() function when you need to clear to black and cannot use the standard attribute and character. This function is especially useful with a monochrome video card. A significant advantage of ClEol() over ClearEol(), is the omission of the cAttr|nAttr and cCharacter|nCharacter parameters, which increase the speed of ClEol(). The function is faster because it does not note the CLEARA and CLEARB settings.
ClEol() has some advantages over the CA-Clipper @ Row, Column commands:
1. The function allows you to take the returned value of the character
string type and combine it with string outputs (e.g., LIST...ClEol()).
2. The cursor position is not affected.
3. The parameters are optional. If they are not specified, the function
clears from the current cursor position with the CLEARA attribute and the CLEARB character.
Notes
■ If no parameters are specified for line or column, the
function automatically orients itself to the current cursor position.
Examples
■ Clear from the current cursor position to the end of the line:
ClEol()
■ Clear line 23, starting from the cursor column position to the
end of the line:
ClEol(23)
■ Clear line 23 from column 15 to the end of the line.
ClEol(23, 15)
nTopLine Designates the topmost line where clearing should begin. The default is the cursor line.
nLeftCol Designates the leftmost column where erasure should begin. The default is the cursor column.
nBottomLine Designates the bottommost line to clear. The default is the last screen line or window line.
nRightColumn Designates the rightmost column to clear. The default is the right screen border or window border.
Returns
ClWin() always returns a null string.
Description
Implement ClWin() when you need to clear to black without the use of the standard attribute and character. This function is helpful when you use a monochrome video card. A significant advantage of ClWin() over ClearWin(), is the omission of the cAttr|nAtt and cCharacter|nCharacter parameters, because it increases the speed of ClWin(). The function is faster because it does not note the CLEARA and CLEARB settings.
ClWin() has some advantages over the Clipper @ Row, Column commands:
1. This function takes the returned value of the character string type
and combines it with string outputs (e.g., LIST...ClWin()).
2. The cursor position is not affected.
3. The parameters are optional. If they are not specified, the function
clears from the current cursor position.
Notes
■ If no parameters are specified for the line or column, the
function automatically orients itself to the current cursor position.
Examples
■ Clear from the cursor position to the end of the screen area:
ClWin()
■ Do the same from the current cursor position in line 23:
ClWin(23)
■ Clear from line 23, column 15, to the end of line 24:
ClWin(23, 15, 24)
■ Clear a window between line 23, column 15, and line 24, column
70:
ClWin(23, 15, 24, 70)
Closes the socket and all connected IPX/SPX handles
Syntax
CLOSESOCK(<nSocket>) → NIL
Netware: 2.2 and 3.11
Arguments
nSocket Designates the number of the socket that is closed.
Returns
CLOSESOCK() always returns NIL when closing a socket according to IPX.
Description
CLOSE SOCKETCLOSESOCK() allows you to close a socket that is used for IPX/SPX communication. At the same time, all IPX/SPX communication buffers for which nSocket has been specified as the source socket are closed. The related communication handles are then invalid.
Examples
Open and close the IPX receiving buffer with source socket 20000:
nHandle=IPXOPEN(20000,2000)
CLOSESOCKET(20000) // nHandle is now invalid
cNewAttr|nNewAttr Designates the new attribute. The default is CLEARA.
cOldAttr|InOldAttr Designates the old attribute to exchange. The default is all existing attributes.
Returns
ColorRepl() always returns a null string.
Description
ColorRepl() simplifies screen handling. This function exchanges all occurrences of the cOldAttr|nOldAttr attribute for the cNewAttr|nNewAttr attribute.
For example, after a READ, you could take the colors in all input fields, (assuming they have a common attribute), and change them. This designates these fields as no longer active.
Notes
■ If the cOldAttr|nOldAttrparameter is not specified, then all
screen attributes (without exception) are exchanged for cNewAttr|nNewAttr. If cNewAttr|nNewAttr is also missing, then cOldAttr|nOldAttr is exchanged for the CLEARA standard attribute.
Examples
■ Exchange the attribute 7 (white on black) for 0 (black on
black= invisible):
ColorRepl(0, 7)
■ Replace all attributes for attribute 116 (red on white):
ColorRepl(116)
■ Exchange the attribute "7/0" (white on black) for 116 (red on
white):
ColorRepl(116, "7/0")
■ Exchange all attributes for the CLEARA standard attribute:
ColorRepl()
■ Change the display from white on black to black on white. You
can specify different parameters:
ColorRepl("0/7", "7/0")
ColorRepl(112, 7)
■ Mixed formats are also possible:
ColorRepl("0/7", 7)
Converts NN/NN or CC/CC color values into numeric values
Syntax
ColorToN(<cAttr>) → nAttr
Arguments
cAttr Designates the alphanumeric color attribute that is converted in NN/NN or CC/CC form.
Returns
ColorToN() returns a number that corresponds to the combined numeric color attribute.
Description
COLOR TO (N)umeric The function changes an alphanumeric color attribute from NN/NN or CC/CC into a combined numeric attribute. These combined attribute values are useful with the CA-Clipper Tools functions StrScreen(), ScreenMix(), ScreenAttr(), and the CA-Clipper commands SAVE/RESTORESCREEN.
ColorToN() makes it easy to create numeric attributes for the CA-Clipper Tools functions.
Notes
■ If you specify an invalid attribute string, ColorToN() returns
the numeric attribute 0, meaning black on black (invisible).
Examples
■ Show the "normal" display (white on black); all alphanumeric
forms yield 7:
? ColorToN("07")
? ColorToN("07/00")
? ColorToN("W/N")
■ Display red on white; all alphanumeric forms yield the numeric
attribute 116:
? ColorToN("04/07")
? ColorToN("R/W")
■ If the foreground color is missing, 0 is assumed. Here it
corresponds to an inverse video display:
? ColorToN("/7")
■ High intensity (+) and flashing (*) are also recognized:
? ColorToN("BR+")
? ColorToN("BR+*")
? ColorToN("G/BR+*")
? ColorToN("+G*/BR")
■ An invalid parameter returns 0:
? ColorToN()
■ Parameters of the <cAttr|nAttr> type are allowed. A numeric
attribute remains numeric.
? ColorToN(112) // Result: 112
nTopLine Designates the topmost line to begin processing. The default is the cursor line.
nLeftCol Designates the leftmost column to begin processing. The default is the cursor column.
nBottomLine Designates the bottommost line that is processed. The default is the last screen line or window line.
nRightCol Designates the rightmost column to clear. The default is the right screen border or window border.
cNewAttr|nNewAttr Designates the new attribute to replace the old one. The default is the standard attribute CLEARA.
cOldAttr|nOldAttr Designates the old character to exchange. The default is "exchange all attributes".
Returns
ColorWin() always returns a null string.
Description
ColorWin() exchanges all occurrences of cOldAttr|nOldAttrfor the cNewAttr|nNewAttr attribute, within a particular screen or window area. The function operates in a similar way to ColorRepl(), except with ColorWin() you can define the screen area to work on.
The parameters nTopLine and nLeftCol define the row and column for the top-left corner; nBottomLine and nRightCol define the row and column for the bottom-right column.
Notes
■ If cOldAttr|nOldAttr is not specified, all attributes are
exchanged for cNewAttr|nNewAttr; if cNewAttr|nNewAttr is not specified, the attributes are exchanged for CLEARA.
Examples
■ Exchange attribute 7 (white on black) for 0 (black on black =
invisible) from the current cursor position to the end of the screen
area:
ColorWin(0, 7)
■ Exchange all attributes in the area from line 23, column 15 to
line 24, column 70 for the standard attribute CLEARA:
ColorWin(23, 15, 24, 70)
■ Replace all attributes for attribute 116 (red on white) in the
region from line 23, column 15 to line 24, column 70:
ColorWin(23, 15, 24, 70, 116)
■ Change the white on black display to black on white. You can
specify different parameters:
ColorWin(23, 15, 24, 70, "0/7", "7/0")
■ Mixed formats are also possible:
ColorWin(23, 15, 24, 70, "0/7", 7)
expValue[@] Designates any valid expression of any data type to form a complement value. Complement() only allows a character string to be passed by reference.
Returns
Complement() returns the complement value that corresponds to the same data type for expValue.
Description
Complement() returns the respective opposite value of the expValue parameter. In contrast to CharNot(), which only permits character strings, this function permits all data types. The result is the same data type as the parameter. For example, a date returns a date as a result. It corresponds to the difference between the indicated date and 12/31/2999.
■ The complement of a logical value corresponds to the use of
.NOT.:
? Complement(.T.) // .F.
? Complement(.F.) // .T.
■ Numeric values change sign:
? Complement(99) // -99.00
? Complement(0) // 0
? Complement(-99) // 99.00
? Complement(-9.9) // 9.90
? Complement(9.9) // -9.9
■ With strings, the function works like CHARNOT:
? Complement("123ABCabc") // " <157><156>"
■ The difference between 1/1/1900 and 01/01/3000:
SET CENTURY ON
? Complement(CToD("01/01/00")) // 12/31/1099
■ An empty or invalid date gives the same result -- 01/01/3000:
SET CENTURY ON
? Complement(CToD(" / / ")) // 01/01/3000
? Complement(CToD("77/77/77")) // 01/01/3000
CountGets() returns the number of currently posted fields within a READ.
Description
CountGets() determines how many GET fields are currently open in a VALID UDF or within a KEYTRAP procedure. Posted means the GET fields have been recently defined before with @ ...GET ...
Examples
■ Display the number of GET fields that are currently posted
from within a valid UDF:
@ 10, 10 GET Field1
@ 10, 20 GET Field2 VALID MYFUNC()
@ 10, 30 GET Field3
READ
RETURN
■ Returns CountGets() within the UDF:
FUNCTION MYFUNC
? CountGets() // Result: 3
RETURN(.T.)
cString Designates the character string in which the cCharacter|nCharacter character is counted.
cCharacter|nCharacter Designates the character at the beginning of the cString that is counted. The default value is a space, Chr(32).
Returns
CountLeft() returns the number of cCharacter|nCharacter characters that appear in an uninterrupted sequence at the beginning of cString.
Description
While RemLeft() removes leading characters from the cString, CountLeft() only determines the number of leading cCharacter| nCharacter characters appearing in an uninterrupted sequence at the beginning of the cString.
Examples
■ Count the blanks:
? CountLeft(" 123") // Result: 3
■ Count the "." characters:
? CountLeft("..4.123", ".") // Result: 2
■ In this example, there is nothing to count:
? CountLeft("123456") // Result: 0
cString Designates the character string in which the cCharacter|nCharacter character is counted.
cCharacter|nCharacter Designates the character at the end of the cString that is counted. The default value is a space, Chr(32).
Returns
CountRight() returns the number of cCharacter|nCharacter characters that appear in an uninterrupted sequence at the end of the cString.
Description
While RemRight() removes trailing characters from the cString, CountRight() only determines the number of trailing cCharacter| nCharacter characters appearing in an uninterrupted sequence at the end of the cString.
Examples
■ Count the blanks:
? CountRight("abc ") // Result: 3
■ Count the "." characters:
? CountRight("abc.d..", ".") // Result: 2
■ In this example, there are no spaces to count:
? CountRight("123456") // Result: 0
CPUType() returns a numeric code that identifies the microprocessor in use.
Description
This function determines which microprocessor is in use. For instance, a PC may use a Vnn microprocessor or an AT may use a 386 microprocessor. The microprocessors have the following codes:
Table 12-1: Microprocessor Coding
Value Symb. constant Processor
0 CPU_8088 8088
1 CPU_8086 8086
2 CPU_V20 V20
3 CPU_V30 V30
4 CPU_80188 80188
5 CPU_80186 80186
6 CPU_80286 80286
7 CPU_80386 80386
8 CPU_80486 80486
Examples
What type of microprocessor is on the AT?
IF CPUType() == CPU_80386
? "A 386 ..."
ENDIF
cString Designates the string that is that is encrypted.
cKeystring Designates the password with which the string is encrypted.
Returns
Crypt() returns the encrypted string.
Description
In contrast to a simple lock using CharXor(), this function has a random number generator that uses a "random seed" algorithm. This makes the lock even more secure, at least as long as this additional algorithm is not known. Of course, this additional security costs some computer time.
Encrypted character strings can be decrypted with the same password. With multiple encryptions, the decryption must occur in reverse order.
Notes
■ Passwords should be as long as possible — a minimum of six
characters, preferably more.
■ The return value of this function can be suppressed by
implementing CSetRef() to save space in working memory.
Examples
■ This example shows a simple encryption:
cVar:= Crypt("CLIPPER", "CA")
■ This example shows the decryption:
? Crypt(cVar, "CA") // "CLIPPER"
Determines the setting of the multi-pass mode for ATXXX() functions
Syntax
CSetAtMupa(<lNewMode>) → lOldMode
Arguments
lNewMode Designates the setting for the multi-pass switch for all AT functions. The default value (.F.) sets the multi-pass switch to off
Returns
If lNewMode is not specified, the current setting is returned. If lNewMode is specified, CSetAtMupa() returns the previous setting.
Description
CSetAtMupa() sets a switch, internal to CA-Clipper Tools, that affects the operation of several other CA-Clipper Tools functions. These functions permit targeted, extremely flexible substring manipulation. The affected functions are:
CSetKey(<nKeyValue>) → cProcedureName
* This function is retained for compatibility purposes. Use the
CA-Clipper Set() function to develop future applications.
Arguments
nKeyValue Designates the Inkey() for which the associated procedure name is determined.
Returns
CSetKey() returns a character string that names the procedure associated with nKeyValue.
Description
This function queries the setting for SET KEY..TO.
Notes
■ To use this function, you must include the ct.ch file at the
beginning of your program with the command:
#include "CT.CH"
Find more information on this function in CH.CH.
Examples
Save the assignment for the function key F2:
cOldF2Proc := CSetKey(-1)
Determines whether or not reference sensitive functions return a value
Syntax
CSetRef([<lNewSwitch>]) → lOldSwitch
Arguments
lNewSwitch Designates whether the return value is suppressed for specified functions. When this parameter is .T., it suppresses the return value of the functions listed below. When the parameter is .F. (default value), these functions return a value.
Returns
If no parameter is specified, the function returns the current setting. If a parameter is specified, the function returns the previous setting.
Description
A series of CA-Clipper Tools functions enable you to pass parameters by reference. After executing the function, the passed parameter already contains the result. However, each of these functions also returns this result as a value. A copy of the passed string exists for a short time in working memory, but it is invisible to you. In the worst possible case, two adjoining memory blocks would require up to 64 kB.
This behavior can be influenced by implementing CSetRef(.T.). Then the group of affected string functions no longer return a value, which can save you up to 64k of memory with large strings.
■ If, in spite of having CSetRef(.T.), you need one of the
previously listed functions to return a value, then the target variable contains .F. instead of the anticipated string.
Examples
■ Here is how CSetRef() is set to .F.:
CSetRef(.F.)
cStr1 := "HAGBDCFE"
cStr2 := CharSort(@cStr1)
? cStr1, cStr2 // "ABCDEFGH" - cStr1,cStr2 are identical
■ Here is how CSetRef() is set to .T.:
CSetRef(.T.)
cStr1 := "HAGBDCFE"
cStr2 := CharSort(@cStr1)
? cStr1 // "ABCDEFGH" - Sort cStr1
? cStr2 // .F.
■ Determine when memory will be needed:
cStr1 := Space(32000) // Create large string
CSetRef(.F.)
CharSort(@cStr1) // Additional 32000 bytes
CSetRef(.T.)
CharSort(@cStr1) // Needs no additional memory
lNewSwitch Designates whether existing files should not be overwritten during CA-Clipper Tools file operations. Designates .F. for yes; .T. for no.
Returns
CSetSafety() returns the current setting for the CA-Clipper Tools safety mode switch; or if lNewSwitch is passed, the previous setting.
Description
CSetSafety() returns a logical value for the current setting of the CA-Clipper Tools internal safety mode switch. If you designate CSetSafety() as .T., the CA-Clipper Tools functions do not overwrite existing files.
Notes
Warning! CSetSafety() only works with CA-Clipper Tools functions..
Examples
■ Query the SAFETY function:
lSafety:= CSetSafety()
■ Turn safety mode on and save the previous status:
lOldSafety:= CSetSafety(.T.)
cNewSwitchList Designates in a specific format (shown in the tables on the next page), which switches are to be on or off.
Returns
CSETALL() returns the current setting of all ON/OFF switches when no parameter is specified. When the parameter is specified, the function returns the previous setting.
Description
This function allows you to query the current setting for all CA-Clipper ON/OFF switches and change them. Since you can save 21 different switches, the function returns a 21-character string made with 0's and 1's, rather than logical values. This function makes it easy to save all the ON/OFF switches in a CA-Clipper error trap, and reset them when you exit. The following switches are contained in the character string (in the order they occur in the returned string):
Table 11-1: Clipper Switch Status
Byte Function Clipper Switch
1 CSETALTE() SET ALTERNATE
2 CSETBELL() SET BELL
3 CSETCARR() SET CARRY
4 CSetCent() SET CENTURY
5 CSETCONF() SET CONFIRM
6 CSETCONS() SET CONSOLE
7 CSetCurs() SET CURSOR
8 CSETDELE() SET DELETED
9 CSETDELI() SET DELIMITERS
10 CSETDEVI() SET DEVICE
11 CSETESCA() SET ESCAPE
12 CSETEXAC() SET EXACT
13 CSETEXCL() SET EXCLUSIVE
14 CSETFIXE() SET FIXED
Table 11-2: Clipper Switch Status
Byte Function Clipper Switch
15 ReadInsert() INSERT Mode
16 CSETINTE() SET INTENSITY
17 CSETPRIN() SET PRINT
18 CSETSCOR() SET SCOREBOARD
19 CSETSOFT() SET SOFTSEEK
20 CSETUNIQ() SET UNIQUE
21 CSETWRAP() SET WRAP
Notes
■ If you specify an invalid parameter, the function returns a
null string and does not reset any switch.
Examples
Display the current bell status:
cSwitches := CSETALL() // 010000000000000000000
IF SubStr(cSwitches, 2, 1) == "1"
? " BELL is on!"
ENDIF
Determines the content of CA-Clipper environmental variables
Syntax
CSETCLIP(<cEnvParameter>) → nEnvParameterValue
Important! CA-Clipper no longer supports all possible settings for
environmental variables in the CA-Clipper Summer 1987 release.
Therefore, CSETCLIP() is modified to reflect these changes.
Arguments
cEnvArguments Designates which SET CA-Clipper setting to return.
Returns
SETCLIP() returns the setting of the requested SET CLIPPER= option.
Description
The CA-Clipper environmental variable contains settings for a CA-Clipper application. Use CSETCLIP() to query these values from within the application. The letter you use for the respective SET CLIPPER= option is given as a parameter. This value cannot be set from a running program since memory allocation is already determined. (You must determine memory allocation before you start an application.)
Notes
■ Uppercase or lowercase letters have no impact on the
parameter.
Examples
■ Uppercase or lowercase letters do not impact the parameter:
? CSETCLIP("F") // SET CLIPPER= Fnnn
? CSETCLIP("e") // SET CLIPPER= Ennn
? CSETCLIP("X") // SET CLIPPER= Xnnn
? CSETCLIP("SWAPK") // SET CLIPPER= SWAPK:nnn
■ With an invalid parameter:
? CSETCLIP("z") // -1
CSETFUNC(<nFunctionKey>) → cCharacterString
* This function is retained for compatibility purposes. Use the
CA-Clipper Set() function to develop future applications.
Arguments
nFunctionKey Designates the function key for which the associated character string is determined.
Returns
CSETFUNC() returns the character string associated with nFunctionKey.
Description
This function queries the setting for SET FUNCTION TO.
Notes
■ To use this function, you must include the ct.ch file at the
The F10 key is assigned to Ctrl-C. The setting changes in a function
Test(). Since it is saved, you can restore it upon return:
SET FUNCTION 10 TO Chr(3)
cOldFunc := CSETFUNC(10) // Save assignment
Test() // Call UDF
SET FUNCTION 10 TO cOldFunc
CSETRDONLY([<lR/O-NewMode>]) → lR/O-OldMode
* This function is retained in CA-Clipper Tools II/5.0 for
compatibility purposes. Use the READ-ONLY clause of the
CA-Clipper USE command to develop future applications.
Arguments
lR/O-NewMode Designates the new switch status. .T. turns the read-only mode on; .F. turns it off. The default value is off.
Returns
If no parameter is passed, the function returns to the current switch setting; otherwise, it returns the previous setting.
Description
Important! Please note the changes in the CA-Clipper USE command!
This function was implemented in the CA-Clipper Summer 1987 release to allow you to open files in read-only mode. This function was also useful for CD-ROM access and the enabled you to open a network database if you lacked write permission.
However, in CA-Clipper READONLY you can append to the USE command and do not have to implement CSETRONLY(). The switch has been retained in this release to insure compatibility with previous versions of CA-Clipper Tools. You can still use it to query, but it no longer has direct impact on the open mode.
This switch functions in the enclosed CA-Clipper Tools ct.ch definition file.
Notes
■ For new applications, use the read-only key word in
conjunction with the USE command.
Examples
Set the read-only mode switch (it only functions when you use the ct.ch
header file):
? CSETRDONLY(.T.) // Returns old setting
USE .... // Open with READ ONLY access
CSETSNOW([<lNewSwitch>]) → lOldSwitch
* This function is retained in CA-Clipper Tools for compatibility
purposes. Use the CA-Clipper NoSnow() function to develop future
applications.
Arguments
lNewSwitch Designates the new status for "Snow Prevent". A .T. signifies on; .F. means off. The default value for Snow Prevent is off (.F.).
Returns
CSETSNOW() returns the current setting, when no parameter is designated; otherwise, it returns the previous setting.
Description
Snow tends be is especially bad in CGA card screen output. To prevent it, set the CSETSNOW switch.
Use the CA-Clipper NoSnow() function for new applications.
Notes
■ CSETALL() does not acknowledge the CSETSNOW() setting.
Examples
■ Output with Snow Prevent on:
CSETSNOW(.T.) // Returns old setting
■ Acknowledge existing hardware:
CSETSNOW(IsCGA()) // Snow prevent if CGA card
Queries the SET position of a particular ON/OFF switch and provides the option to set it
Syntax
CSETxxxx([<lNewSwitch>]) → lOldSwitch
* This function is retained in CA-Clipper Tools for compatibility
purposes. Use the CA-Clipper Set() function to develop future
applications.
Arguments
lNewSwitch Designates the new status for the SET xxxx command. .T. corresponds to on; .F. signifies off.
Returns
If no parameter is passed, the function returns the current setting; otherwise, it returns the previous setting.
Description
This is a group of 20 functions. If you call all these functions the same way, they return the same value. Each function name consists of "CSET", and the first four characters of the respective CA-Clipper set condition:
Table 11-4: Functions to Query Clipper Set Conditions
Function Set Condition
CSETALTE() SET ALTERNATE ON/OFF
CSETBELL() SET BELL ON/OFF
CSETCARR() SET CARRY ON/OFF (See note)
CSetCent() SET CENTURY ON/OFF
CSETCONF() SET CONFIRM ON/OFF
CSETCONS() SET CONSOLE ON/OFF
CSetCurs() SET CURSOR ON/OFF
CSETDELE() SET DELETED ON/OFF
CSETDELI() SET DELIMITERS ON/OFF
CSETDEVI() SET DEVICE TO PRINT (.T.)/SCREEN (.F.)
CSETESCA() SET ESCAPE ON/OFF
CSETEXAC() SET EXACT ON/OFF
CSETEXCL() SET EXCLUSIVE ON/OFF
CSETFIXE() SET FIXED ON/OFF
CSETTINTE() SET INTENSITY ON/OFF
CSETPRIN() SET PRINT ON/OFF
CSETSCOR() SET SCOREBOARD ON/OFF
CSETSOFT() SET SOFTSEEK ON/OFF
CSETUNIQ() SET UNIQUE ON/OFF
CSETWRAP() SET WRAP ON/OFF
Notes
■ CSETCARR() is not useful in CA-Clipper. Since this function
was in CA-Clipper Tools and also occupies a position in CSETALL(), it is retained for compatibility purposes.
Examples
■ Switch SET UNIQUE on:
? CSETUNIQ(.T.) // Returns previous setting
■ Save a setting:
lOldWRAP:= CSETWRAP()
cCharacterstring Designates a character sequence. When this sequence occurs in the second character string, each corresponding bit is set to 1.
cBitpattern Designates a sequence, with a maximum of 16 characters, from which the bit position is assigned.
Returns
CToBit() returns a number in the range of 0 to 65535 that corresponds to the created bit pattern.
Description
The CToBit() function delivers a bit pattern that corresponds to a string of individual characters. When used in conjunction with its sister function BitToC(), it facilitates work with such bit-coded information as file attributes.
Notes
■ Characters in cCharacterstring that are not found in
cBitpattern are ignored.
Examples
■ The second bit in the resulting value is set, since the letter
"H" appears in the next-to-last position in "ADVSHR":
? CToBit("H", "ADVSHR") // Result: 00000010
■ Two characters also in ADVSHR, appear at the first and final
positions in this 6-character string:
? CToBit("RA", "ADVSHR") // Result: 00100001
■ <cBitpattern> ignores previously unavailable characters:
? CToBit("XRYA", "ADVSHR") // Result: 00100001
Converts the name of the day of the week into a corresponding number
Syntax
CToDoW(<cDayofWeek>) → nDayofWeek
Arguments
cDayofWeek Designates a character string that contains the name of a day of the week.
Returns
CToDoW() returns the number of the day for the day name.
Description
Use CToDoW() to change the name of a day of the week to a number. Sunday corresponds to 1, Monday 2, etc.. If the function returns a 0 value, an invalid parameter has been passed. You can shorten the day names, but these abbreviations must be explicit to return an accurate value.
Notes
■ Uppercase and lowercase letters do not affect the name of the
day of the week.
■ The function's operation depends on the country-specific
adaptation of your CA-Clipper compiler. With an English version of CA-Clipper, only English day names are recognized.
Examples
■ What number of the day of the week is Sunday?
? CToDoW("Sunday") // Result: 1
■ Show several ways to get the day of the week for Wednesday:
? CToDoW("WEDNESDAY") // Result: 4
? CToDoW("Wednesday") // Result: 4
? CToDoW("Wed") // Result: 4
■ What number of the day of the week is Monday?
CToDoW("M") // Result: 2
cFloatingPointNumber Designates an 8-byte character string that contains a CA-Clipper number in the 64-bit floating point format.
Returns
CToF() returns the number that corresponds in the passed string.
Description
Character strings created with FToC() or XToC() are changed into CA-Clipper numbers. Note that when you use XToC(), character strings or portions of character strings, can be switched back, if they have been displayed as CA-Clipper floating point numbers.
Examples
■ Change a number and then change it back:
CToF(FToC(1234.55)) // Result: 1234.55
■ This also works for XToC():
? CToF(XToC(1234.55)) // Result: 1234.55
Converts the name of the month into a corresponding number
Syntax
CToMonth(<cMonth>) → nMonth
Arguments
cMonth Designates the name of one of the 12 months.
Returns
CToMonth() returns the number for the designated month name.
Description
Use CToMonth() to change the name of a month into a number. January corresponds to 1, February 2, etc.. If the function returns a 0 value, then an invalid parameter has been passed. If you shorten the month name, use explicit abbreviations to return an accurate return value.
Notes
■ Uppercase and lowercase letters do not affect the name of the
month.
■ The function's operation depends on the country-specific
adaptation of your CA-Clipper compiler. With an English version of CA-Clipper, only English month names are recognized.
Examples
■ Show the number for January:
? CToMonth("January") // Result: 1
■ Show several ways to determine the month number for August:
? CToMonth("AUGUST") // Result: 8
? CToMonth("August") // Result: 8
? CToMonth("Au") // Result: 8
■ The number for April:
?CToMonth("A") // Result: 4
cNumericstring Designates a numeric string to convert into a number in base nBase.
nBase Designates the number base to use in the conversion. Can be in the range of 2 to 36. The default is the decimal system, base 10.
lMode When designated as .T., allows a negative result. The default allows only positive results.
Returns
CToN() returns the converted number that corresponds to the string. The values lie in the range of 0 and 65535 or, if lMode is .T., in the range of -32768 and +32767.
Description
CToN() offers a number of ways to covert a number string into numeric data format. Almost any number can be converted, as long as the base nBase for the number system lies between 2 and 36.
Notes
■ The cNumericstring string is automatically TRIMmed left and
right.
■ If you have invalid parameters or combinations, the function
returns a value of 0.
Examples
■ Convert to base 10:
? CToN("60000") // Result: 60000
■ Convert to base 2:
? CToN("11", 2) // Result: 3
? CToN("1110101001100000", 2) // Result: 60000
■ Convert to base 16:
CToN("A", 16) // Result: 10
? CToN("ABCD", 16) // Result: 43981
? CToN("FFFF", 16, .T.) // Result: -1
■ Convert to base 36:
? CToN("XXP", 36) // Result: 43981
DATATYPE(<expValue>) → nDataType
* This is retained in CA-Clipper for compatibility purposes. Use the
CA-Clipper ValType() function to develop future applications.
Arguments
expValue Designates any valid CA-Clipper expression.
Returns
DATATYPE() returns a value that corresponds to the data type in expValue.
Description
DATATYPE() is similar to the CA-Clipper Type() function, but returns more extensive information in numeric value form. The bits in the result correspond to specific data types. Two bits can be set at the same time. It is easy to recognize specific data types with the IsBit() function. The following codes apply:
Table 13-2: Data Type Coding
Value Symb. Const. Data Type
0 TYPE_UNDEF Undefined
1 TYPE_STR Character string
2 TYPE_NUM Numeric
4 TYPE_LOG Logical
8 TYPE_DATE Date
16 TYPE_ALIAS Alias
64 TYPE_MEMO Memo field
128 TYPE_WORD Word
512 TYPE_ARRAY Array
4096 TYPE_BLOCK Code block
In addition, DATATYPE() returns the respective data type for a CA-Clipper Tools function or one of your own UDF's. This is impossible with Type().
Notes
■ An invalid expValue output results in a runtime error.
■ The function cannot determine if a parameter has passed to a
function by reference (32 + type), because this information is no longer available in CA-Clipper.
Examples
Return values of DATATYPES() used for different data types:
? DATATYPE() // 0, undefined
? DATATYPE("XXX") // 1, string
? DATATYPE(123) // 2, numeric
? DATATYPE(DoY()) // 2, numeric result
? DATATYPE(.T.) // 4, logical
? DATATYPE(3 > 2) // 4, logical expression
? DATATYPE(Eof()) // 4, logical result
? DATATYPE(Date()) // 8, date
? DATATYPE(memofld) // 1, memo field
? DATATYPE(@crlf) // 33, reference to string
? DATATYPE(@array) // 544, reference to array
? DATATYPE(array[1]) // 2, numeric element
? DATATYPE(array[2]) // 1, string element
? DATATYPE(myfunc()) // type for your own UDF
Determines the size of a selected (.dbf) file in memory
Syntax
DbfSize() → nFileSize
Returns
DbfSize() returns the byte size of the current database in working memory.
Description
DbfSize() determines how much room a database occupies, before you write this file to a disk. The function is also useful when used in conjunction with DBFDSKSIZE(). When the results for both functions indicate there is a deviation in the size of a database, this means a portion of the data is not yet written to the floppy/hard disk. You can also determine if and when new input is written to a floppy/hard disk.
Notes
■ This function always operates on the currently SELECTed work
area.
Examples
Can a (.dbf) file be copied to the target disk?
USE DATA.
IF DiskFree("A") < DbfSize().
? "The file can not be copied.".
? "Insufficient space remaining on disk.".
ELSE.
COPY TO A:COPY.
ENDIF
Determines the size of a selected (.dbf) file on a disk drive
Syntax
DBFDSKSIZE() → nFileSize
Returns
DBFDSKSIZE() returns the size of the current database on the floppy or hard disk (i.e., how many bytes are saved in this file).
Description
One of the DBFDSKSIZE() function's most useful applications is when it is used in conjunction with DbfSize(). When the results for both functions indicate there is a deviation in the size of a database, this means a portion of the data is not yet written to the floppy/hard disk. You can also determine if and when new input is written to a floppy/hard disk.
Notes
■ This function operates on the currently SELECTed work area.
Examples
Determine if a portion of data input has been written out to disk yet:
SIZEIF Dbf() - DBFDSKSIZE() >= 512
* COMMIT // Warning! Works only with DOS 3.3 and up
USE File
ENDIF
DeleteFile() returns a code that signifies its completion status:
Table 7-1: DeleteFile() Error Codes
Code Symb. constants Definition
0 NO_DISK_ERR No error occurs
-2 ER_FILE_NOT_FOUND File not found
-3 ER_PATH_NOT_FOUND Path not found
-5 ER_ACCESS_DENIED Access denied (e.g., file is read-only)
Description
In contrast to FileDelete(), which permits you to specify file groups with wildcards, DeleteFile() only accepts specific file names. However, the function avoids all DOS error messages and returns an error code directly to the calling program. This makes error-tolerant erasures in networks possible (see Examples).
Notes
■ You can use a drive designator and path name, but no
wildcards.
Examples
■ How NOT to delete a file in a network environment:
IF FILE ("TEST.DBF")
* Is it actually possible to delete the file?
DELETE FILE TEST.DBF
ENDIF
■ This is a better way:
nStatus := DeleteFile("TEST.DBF")
IF nStatus == 0
? "File deleted."
ELSE
IF nStatus == -5
? "ACCESS DENIED!"
? "File in use elsewhere!"
ENDIF
ENDIF
cDirectory Designates the path of the directory that is changed.
Returns
DirChange() returns a 0 when it successfully changes the directory; otherwise, an error code is passed. The codes are defined as follows:
Table 7-2: DirChange() Error Codes
Code Symb. constants Definition
0 NO_DISK_ERR No error occurred
-2 ER_FILE_NOT_FOUND File not found
-3 ER_PATH_NOT_FOUND Path not found
-5 ER_ACCESS_DENIED Access denied (e.g., in network)
DirChange() changes the current subdirectory or determines if a directory exists. This allows DOS error messages to be intercepted. (See also DirMake()).
Notes
■ cDirectory may contain a drive designator and a path.
Wildcards are not allowed.
Examples
Change to the "\DATA" directory:
IF DirChange("\DATA") == 0
? "Current directory is now: " + DirName()
ENDIF
cDirectory Designates the directory name to create.
Returns
DirMake() returns a 0 when it has successfully created the directory; otherwise, an error code is passed. The codes are defined as follows:
Table 7-3: DirMake() Error Codes
Code Symb. constants Definition
0 NO_DISK_ERR No error occurred
-2 ER_FILE_NOT_FOUND File not found
-3 ER_PATH_NOT_FOUND Path not found
-5 ER_ACCESS_DENIED Access denied (e.g., in network)
Description
When you install the program, directories must be the first thing you create. The DirMake() function allows you to create new directories from within your CA-Clipper application.
Notes
■ cDirectory can contain a drive designator and a path,
wildcards are not allowed.
Examples
Change to the "\DATA" directory:
IF DirChange("\DATA") == -3 // Path not found
DirMake("\DATA")
ENDIF
cDrive Designates which disk drive that you want to use.
Returns
DiskChange() returns .T., when the designated disk drive is successfully changed.
Description
DiskChange() allows you to change from the current disk drive to another. To do this, call DiskChange() with the disk drive identifier (A,B,C, etc.). The drive identifier can be specified with a colon (:).
Examples
Change to drive C:
? DiskChange("C") // Returns .T. when successful
Determines the space available on a floppy or hard disk
Syntax
DiskFree([<cDrive>]) → nFreeByte
Arguments
cDrive Designates for which drive (A, B, C, etc.) the open capacity is determined. The default value is the current drive.
Returns
DiskFree() returns the available memory capacity of the selected drive.
Description
DiskFree() determines if a disk has sufficient storage capacity for a file.
Notes
■ When cDrive is not specified, the function automatically
uses the current drive.
Examples
Determine if there is enough space to copy a database:
Required := DbfSize() // Database size
IF DiskFree("A") < Required
? "Insufficient disk space for copying!"
ENDIF
Determines the total capacity of a floppy or hard disk
Syntax
DiskTotal([<cDrive>]) → nTotalSpace
Arguments
cDrive Designates the drive for which memory capacity is determined. The default is the current drive.
Returns
DiskTotal() returns a value that corresponds to the total capacity of the data carrier in the selected drive. The default is the current disk drive.
Description
DiskTotal() determines if the capacity of the disk in use is sufficient for back up. The advantage of DiskTotal() over any capacity determined by the system, is that it recognizes bad sectors and does not include them.
Examples
Determine if disk capacity is sufficient:
nRequired := DbfSize()
IF DiskTotal("A") < nRequired
? "Error! Insufficient disk capacity!"
ENDIF
cDrive Designates which drive (A, B, C, etc.) you want to check.
nStartSector Designates a sector to serve as a starting point to check the disk in the direction of the first sector.
Returns
DISKCHECK() returns a number that corresponds to a checksum for the data carrier in cDrive. If read errors occur, the function returns a negative number when the first bad sector is found.
Description
DISKCKECK() begins its check with the last sector of the designated drive or with the nStartSector value, and works in the direction of the first sector. If a sector is found to contain errors, then it returns a negative value.
If it returns a -1, continue to check for other errors (such as a missing disk). The CA-Clipper Tools function ERRORCODE() is quite useful here. Error code returns a value that symbolizes the most-recent DOS error.
Since DISKCHECK() returns a checksum, it is easy to check for disk changes.
Notes
■ You must specify the cDrive parameter. If you omit it or
specify an unavailable drive, DISKCHECK() returns an error code of - 1. DISKCHECK() takes more time to check a hard disk.
Examples
■ Create a checksum for a floppy:
Checksum := DISKCHECK("A")
■ Show that the disks are changed:
IF DISKCHECK("A") == Checksum
? "You have not changed disks!"
ENDIF
cDrive Designates the disk drive to format. Only a floppy drive is permitted. You may optionally specify a colon (:).
nCapacity Designates the appropriate disk capacity for the disk you are about to format. Possible values are 160, 180, 320, 360, and 1200 for 5.25"; 720 and 1440 for 3.5" disks. The default is the maximum drive capacity.
cUDF Designates the name of a user-defined function call before each format step (track or head change). The default is no UDF called.
cBootText This optional parameter designates text, with a maximum of 255 characters, to display if the formatted disk is booted. The default is described in the "Notes" section on the following page.
nRepetitions Designates the number of repeat attempts you should make, to format a track before the function aborts. The default is one repetition.
Returns
The function returns 0 when the disk is successfully formatted.
Table 7-5: DISKFORMAT() Error Codes
Error Codes Symb. constants Definition
0 NO_DISK_ERROR Format successful
-1 DF_WRONG_DRIVE Illegal drive, only A: and B: allowed
-2 DF_WRONG_DISK_SIZ kB value not supported
-3 DF_INTERRUPTED Terminated by control UDF
-4 DF_WRITE Write error
Description
DISKFORMAT() formats a disk under full CA-Clipper program control, so there is no need for a RUN FORMAT. You cannot create bootable disks, only data disks.
Since you can call a separate function (UDF) prior to every track and head change and the respective track and head number are passed, you can construct the visual display of the format process constructed as desired.
You can only format floppy disks, so even with unforeseen incorrect parameters, your hard disk is safe. All the standard floppy types are supported — 160kB, 180kB, 320kB, 360kB, 1.2MB, 720kB, and 1.44MB.
DISKFORMAT() is useful for formatting disks, at least when the preset repetition rate is retained or decreased. After an unsuccessful attempt to format a track, the process is repeated one more time. If this repetition also fails, the entire format is aborted. If you want to be as safe as possible about the quality of the disk in used, select a repetition rate of 0.
The Control UDF
DISKFORMAT() calls the control UDF, which is specified as the third parameter, prior to each head and track change. Both values, head and track, are passed as a parameter to the function. As soon as all tracks are formatted and DISKFORMAT() has initialized the FAT and directory area, a value of -1 is passed for both parameters to the UDF. Please be aware that both parameters must be passed.
The numeric value returned for UDF can further influence DISKFORMAT():
Table 7-6: Control UDF Returned Values
Returned Value Explanation
0 Continue format
1 Do not format this track (parameter 1)
2 Abort format
Notes
■ If the defined control UDF does not exist, the function
uninstalls itself and triggers a runtime error. If an error message concerning a missing procedure is required during linking, you can specify EXTERNALfunction in the program.
■ If you attempt to boot with a data disk created with
DISKFORMAT() and did not designate any other text for the cBootText parameter, the following text is displayed:
"No system disk. Insert new disk, press any key to continue"
■ DISKFORMAT() begins to format a disk with the highest track
number. Therefore, an existing FAT and directory label are the last items deleted.
■ DISKFORMAT() always reformats a track, even if it is already
formatted. Therefore, when a format is successful, all the data is deleted.
■ Each track is verified again after it is formatted.
■ After the last track is formatted, the function continues to
work a few seconds more. The FAT and directory must be established and the boot text must be written.
Examples
■ An example for formatting a disk in A: drive:
DISKFORMAT() first determines whether the desired capacity is
appropriate for the drive. The control UDF "CONTROL" is concerned
with the display of the track and head that are currently being
formatted. "This is a data diskette" is used as boot text for the
disk. The repeat rate is highly effective at 0. Only the highest-
quality disks are accepted.
To provide an additional example of the return value for the UDF,
only tracks 80 to 11 are formatted here, not the first 10:
CLEAR
cBootText := "This is a data diskette"
@ 10, 02 SAY "Track:
"@ 11, 02 SAY "Head:
"IF FLOPPYTYPE("A:") = 2
// 1.2 MB disk
nErrCode := DISKFORMAT("A:", 1200", CONTROL", cBootText, 0)
IF nErrCode = 0
? "Format successful!"
ENDIF
ENDIF
RETURN
FUNCTION CONTROL(nTrack, nHead)
LOCAL nRetval
IF Track >= 11
@ 10, 08 SAY Str(nTrack)
@ 11, 08 SAY Str(nHead)
nRetval := 0 // Continue format
ELSE
nRetval := 2 // Abort
ENDIF
RETURN(nRetval)
■ Shown below is another variation of the UDF. Press the ESC
key to abort the format. If the format is completed, then the
function displays the FAT initialization and root directory:
FUNCTION CONTROL(nTrack, nHead)
LOCAL nRetval
IF Inkey() = 27
nRetval := 2 // Abort
ELSE
nRetval := 0 // Continue format
ENDIF
IF nTrack = -1
@ 10, 10 SAY "Initializing FAT and Root Directory!"
ENDIF
RETURN(nRetval)
cDrive Designates the drive designator (A, B, C, etc.) of the drive to test. The default is the current disk drive.
lDOS/BIOS This logical parameter allows you to designate whether you want the function tested through the BIOS (.F.) or DOS (.T.). The default is discussed in the Description below.
Returns
DISKREADY() returns .T. when the drive being tested is ready to use.
Description
To save space, you must frequently make multiple disk copies. DISKREADY() allows you to wait for a user disk change, without having to confront known DOS errors, or use CA-Clipper error trap functions. Be sure to differentiate between floppy tests and "true" hard disks and logical partitions.
DOS or BIOS
In the simplest case, this function tests the respective drive through DOS. If drive B is unavailable, the message "Please insert disk in drive B:..." is output from the operating system. When you test floppy drives, drive A: and B:, the BIOS route is recommended, since no message is output. In any event, A: and/or B: can be mapped drives within a network. Use the following logical expression for all the previous situations:
(NetDisk(cDrive) .OR.cDrive >= "C")
This logical expression returns .T. when the respective drive is either on the network or has a drive identifier of C: or higher.
Examples
The system waits between individual copy procedures until drive A: is
ready again:
DO Copy // Call copy procedure
? "Please insert a disk in Drive A:!"
DO WHILE .NOT. DISKREADY("A")
*...
ENDDO
DO Copy // Call copy procedure
cDriveId Designates which drive designator (A, B, C, etc.) to query. The default value is the current disk drive.
lDOS/BIOS This logical parameter allows you to specify whether you want to query the function through the BIOS (.F.) or DOS (.T.). The default is described in the Description below.
Returns
DISKREADYW() returns .T. when you query a drive that is operational and can be written to.
Description
As with DISKREADY(), this function determines if a drive is ready to use. DISKREADYW() also determines if you can write to a drive. DISKREADY() cannot tell if a disk has a write-protect marker on it. In this case, drive A: might be ready, but you could not write to it. Use this function to build write-protect detection for important disks into the program.
Network Drives
In general, drives mapped within networks are viewed by the function as accessible and return .T. as a result. For a disk, "accessible" means you can create, open, and delete files. You can clearly differentiate these rights within networks such as Novell NETWARE. Therefore, you must test for these accordingly.
DOS or BIOS
In the simplest case, this function always tests the respective drive through DOS. If drive B: is unavailable, the message "Please insert disk in drive B:" is output from the operating system. When you test floppy drives drive A: and B:, the BIOS route is recommended, since no message is output. In any event, A: and/or B: can be mapped drives within a network. Use the following logical expression to cover all the previous situations:
(NetDisk(cDrive) .OR.cDrive >= "C")
This logical expression returns .T. when the respective drive is either on the network or has a drive identifier of C: or higher.
Notes
■ Research indicates work in the OS/2 compatibility box must be
in the BIOS mode.
Examples
Determine if you can write a file to A: drive:
IF DISKREADY("A")
IF NETDISK ("A")
IF NNETRIGHTS ("A:\") // complete path
* ...
ENDIF
ELSE
IF DISKREADYW("A")
? "Disk is not write protected!"
ELSE
? "Disk is write protected!"
ENDIF
ENDIF
ELSE
? "Disk drive not ready!"
ENDIF
cDrive Designates for which physical drive identifier (A, B, C, etc.) to determine the speed. You do not need to use the colon (:).
Returns
DISKSPEED() returns a percentage comparison value to a floppy drive of a 4.77 MHz PC, which corresponds to 100%.
Description
Use this function when you want to calculate the approximate duration of such complex file operations as INDEX or SORT. Since the total duration always depends upon the remaining computer speed, you should also use the SPEED() function..
If the designated drive is unavailable or cannot be checked (network drive), the function returns a 0 value.
Notes
■ You can only implement DISKSPEED() for physical drives, not
network drives.
Examples
■ Show the speed of drive A:
? DISKSPEED("A") // depends on drive
■ Show the factor for your hard disk:
? DISKSPEED("C") // e.g. 720 Factor 7.2
cDrive Designates the drive designator (A, B, C, etc.) of the drive for which the status of the last operation is determined. The default is the current disk drive.
Returns
DISKSTAT() returns the status of the floppy or hard disk operation as a number. The bits have the following meanings:
Table 7-7: Drive Status Coding
Bit Symb. constants Definition
1 DST_INVALID Unknown command
2 DST_READONLY Address marker not found
3 DST_SECTOR Sector not found
4 DST_DMA DMA overflow
5 DST_CRC CRC error
6 DST_CONTROLLER Controller error
7 DST_SEEK Seek operation failure
8 DST_TIMEOUT Timeout error
Description
When DOS returns a "block device error" message (See ERRORORG()) and DISKSTAT() to determine a more detailed cause of the error).
Notes
■ This function passes the system status to a CA-Clipper
application. The system saves a status value for all floppy and hard disk operations. When you reaccess a floppy disk drive from within your program, the previous disk operation status is lost. The same applies to hard disk status.
Examples
Determine if the system was unable to find an address marker:
IF ERRORORG() == DST_READONLY
DiskError := DISKSTAT("A")
ENDIF
249 DT_35_SEC_9 Double sided 3.5" 9 sectors (ident. to 5.25"
HD)
240 DT_35_SEC_18 Double sided 3.5" 18 sectors
248 DT_HARDDISK Hard disk
Description
If a 360K floppy is written on an AT in a 1.2 MB drive, you may not be able to read it on other systems, particularly on PC XTs. This function determines how the floppy you are about to use is formatted and provides the corresponding warning.
Examples
Determine if an XT disk is being written to an AT:
IF IsAt() .AND. DISKTYPE("A") == DT_DS_SEC_9
? "Warning!"
? "Under certain circumstances this disk not"
?? " readable on other systems!"
ENDIF
dDate Designates the date from which to create a string. The default is the system date.
lMode Designates whether to insert a period (.) after the day (see Examples). The default is no period (.F.).
Returns
DMY() returns a character string in "DD[.] Month YY" format or "DD[.] Month YYYY" format.
Description
Use DMY() to return the date as a character string using the day, name of month, and year. The CA-Clipper SET CENTURY ON/OFF switch determines whether or not the year is displayed in two or four digits. If the lMode parameter is designated .T., the function builds in a "." after the day designation. If no date is designated as a parameter, the function automatically uses the current system date.
Notes
■ The month name returned depends on which CA-Clipper nations
module is in use.
Examples
■ Display the system date (1/1/89):
SET CENTURY OFF
? DMY() // 1 January 89
■ With ".":
? DMY(.T.) // 1. January 89
■ Display a different date:
SET CENTURY ON
? DMY(CToD("02/01/89"), .T.) // 1. February 1989
DosParam() returns the parameters from the DOS command line.
Description
DosParam() returns all the parameters passed from the DOS command when you run the application. Use DosParam() when you do not want the parameters to be separated. With this function, it is no longer necessary to check each individual parameter in a loop.
Notes
■ With the Token() function, it is easy to break down the
returned character string. It can also use your own rules.
Examples
Given the DOS command line C>MyApp A: C: /a ,
the following is true:
DosParam() // "A: C: /a"
TOKEN(DosParam()) // "A"
This way, it is easy to break down parameter lines according to your own
rules.
Determines the day of the year for a specific date
Syntax
DoY([<dDate>]) → nDayOfYear
Arguments
dDate Designates which date to use to calculate the day of the year. The default is the system date.
Returns
DoY() returns a calendar day number that specifies which day of the year dDate represents.
Description
If you frequently work with time periods, then this function is quite useful. DoY() lets you assign a calendar day number to a date that relates to the beginning of the year.
Notes
■ When no date is specified, DoY() uses the system date.
January 1 is always 1, December 31 is 366 in a leap year; otherwise, it is 365. An empty date returns a 0 result.
Examples
How long is it until Christmas?
? "There are", NToC(DoY(CToD("12/24/91"))- DoY()) ;
, " days until Christmas!"
cDrive Designates the drive (A, B, C, etc.) for which the type is determined. The default is the current drive.
Returns
DriveType() returns a numeric value for the drive type. The following codes apply:
Table 7-9: Drive Type Coding
Code Definition
0 RAM Disk
1 Floppy Disk (disk change cannot be established by system)
2 Floppy Disk (disk change can be established by system)
3 Hard Disk
Description
Warning! Only for AT-class computers.
This function determines if you are dealing with a floppy drive, a hard disk, or a RAM disk.
Notes
■ Although DriveType() returns a 0 value for logical DOS
partitions, RAM floppies, and unavailable drives, you must also differentiate with DISKTYPE(). Here, each hard disk partition returns a 248 value. A RAM floppy created with VDISK.SYS behaves like a single-sided floppy with eight sectors, which returns a 254 value. If there is an unavailable drive, the DISTYPE() returns a value of 0.
Examples
Determine if the drive is a RAM floppy:
IF DriveType() == 0 .AND. DISKTYPE() == 254
? "Drive " + DiskName() + ": is a RAM-disk!"
ENDIF
lNewKeyboardMode Designates whether the extended keyboard input mode is on (.T.) or off (.F.). The default value (.T.) designates that the extended keyboard input mode is on.
Returns
When called without the parameter, this function returns the current setting for DSetKBIOS(). If you pass a parameter, then it returns the previous setting.
Description
Beginning with CA-Clipper 5.0, all keyboard entries are read through the BIOS instead of DOS. The default setting for DSetKBIOS() is now the opposite of what it was in previous versions. The default setting for the enhanced keyboard is on (.T.). When the enhanced keyboard mode is off, keyboard entries are redirected through DOS. This function is very useful if file inputs must be read at program start.
Notes
■ Symbolic constants for keyboard coding are found in the
CTSCAN.CH include file and in Appendix A.
Examples
■ This example shows a keyboard entry that is redirected through
DOS:
C:\>TEST < KEYS.DAT
■ This example shows the application TEST.EXE:
DSetKBIOS(.F.) // Switch to DOS input mode
ACCEPT "" TO cInput
lNewLFMode Designates whether the next line feed for the screen is ignored (.T.) or not (.F.). The default value (.F.) designates that the next line feed is not ignored.
Returns
When called without a parameter, the function returns the current setting for DSETNOLINE(). If a parameter is passed, it returns the previous setting.
Description
DSETNOLINE() can be used in conjunction with a LIST command when you have empty lines you want overwritten by the next line (see example). You can also suppress a line feed issued by CA-Clipper before each LIST. This makes it possible to begin LIST output on line 0.
Examples
When you use DSETNOLINE(), records with the Art_nr field empty are
written to the screen but are overwritten by the next record where
Art_nr is present:
LIST Art_nr, Art_bez, DSETNOLINE(Empty(Art_nr))
Creates a protocol file when the program ends normally
Syntax
DSETQFILE([<lNewQuitMode>]) → lOldQuitMode
Arguments
lNewQuitMode Designates whether the automatic QUIT file is created (.T.) or not (.F.). The default value (.F.) does not create an automatic QUIT file.
Returns
When called without parameter, the function returns the current DSETQFILE() setting. If a parameter is passed, it returns the previous setting.
Description
This function allows for the creation of a QUIT file. This file can be used to determine if an application has been terminated normally or not (i.e. Ctrl-Alt-Del). When the program ends, the contents of the keyboard buffer are written to a file. This allows you to determine what keyboard input the user made, which can be used to trace errors and reconstruct files. The size of the QUIT file corresponds to the size of the keyboard buffer. To save more than the 16 default characters, you must increase the keyboard buffer size with SET TYPEAHEAD. (The maximum buffer size 32768 keystrokes.)
The name for the QUIT file is normally constructed from the name of the .EXE file with a .Q extension. SETQNAME() lets you use any file name you choose.
Notes
■ The keyboard data appears in KEYREAD() format in the QUIT file
■ Only those keyboard inputs already processed by the program
are written to the QUIT file.
■ An existing QUIT file is overwritten automatically if it has
the same name as the QUIT file that is currently being written.
Examples
■ This statement causes the program to create a standard QUIT
file when you exit the program:
DSETQFILE(.T.) // QUIT file will be created
■ Select the name of the QUIT file:
SETQNAME("C:\LOGS\PROTO.LOG")
DSETQFILE(.T.) // QUIT file will be created
// with an alternate name
Determines the size of the keyboard buffer (SET TYPEAHEAD TO)
Syntax
DSETTYPE() → nBufferSize
Returns
DSETTYPE() returns the current size of the CA-Clipper keyboard buffer.
Description
DSETTYPE() allows you to determine what size the CA-Clipper keyboard buffer has been set to with SET TYPEAHEAD TO. You can use the function to determine the number of characters that can be placed in the keyboard buffer using KEYSEND().
Notes
■ The keyboard buffer is made of memory that is internal to
CA-Clipper, which is independent of the system buffer. In CA-Clipper, the standard setting for TYPEAHEAD is 16 characters. (This corresponds to the size of the system buffer.)
■ For every character that is processed in a CA-Clipper program,
two bytes must be allocated in the keyboard buffer. DSETTYPE() determines the number of CA-Clipper characters, not the number of bytes! The standard buffer size is not 16, but 32 bytes.
Examples
The current size of the keyboard buffer is queried and increased if
needed:
nSize := DSETTYPE()
IF nSize < 256
SET TYPEAHEAD TO 256
ENDIF
Reroutes external functions and programs to a window
Syntax
DSETWINDOW([<lNewDisplayMode>]) → lOldDisplayMode
Arguments
lNewDisplayMode Designates whether the screen output from external programs or other language UDF's displays in the current window.
Returns
When called without a parameter, the function returns the current setting for DSETWINDOW(). If a parameter is passed, it returns the previous setting.
Description
DSETWINDOW() allows you to determine if only CA-Clipper screen outputs should appear in a window, or if all outputs (all external modules and programs, including DOS) should appear. If you would like to implement a subroutine for screen handling with CA-Clipper Tools window functions, you can use this switch to turn off these functions for a short time.
Important! Before you call external programs using RUN, you should set DSETWINDOW() to .F.; if you do not, some programs will not run correctly.
Notes
Important! The standard setting for DSETWINDOW() is on. This means that all program output, not written directly into the screen memory, displays in the currently active window.
■ CA-Clipper screen output is always written in a window if one
is open and active. Only screen output from external routines (like Assembler or C UDF's, or external programs called using RUN) can be affected. CA-Clipper Tools functions are also viewed as foreign or external.
■ If you call DSETWINDOW() with .T., a change in cursor position
in an external module or program also affects the cursor position in CA-Clipper. If you do not want to change the cursor position in CA-Clipper, then set DSETWINDOW() to .F. so that the CA-Clipper cursor position remains unchanged. If you still want to pass the cursor position to CA-Clipper, then use the SetRC() function without parameters.
■ Some CA-Clipper Tools functions ignore this switch because
they work directly with the physical screen memory.
■ CA-Clipper Tools has a public variable available for your own
Assembler or C routines to affect the DSETWINDOW() function. It can be addressed as follows:
EXTR _WINDOW:WORD MOV _WINDOW, 0 // Window functions OFF, all
// other values switched ON!
■ If the switch is set to on, then interrupt 16 (10h, video) and
function 19 (13h, write string), normally only available on AT's, become available on PC XT's.
Examples
■ Do not reroute other program output to the selected window:
DSETWINDOW(.F.)
■ Do a test to see if ANSI.SYS has been linked in to CONFIG.SYS:
lVar := DSETWINDOW(.F.)
? ISANSI()
DSETWINDOW(lVar) // Reset to old status
Angle Designates a valid angle measurement in degrees.
Returns
DToR() returns the radian of the specified value.
Description
In addition to expressing angle measurements in degrees, you may also need to express an angle in radians. With DToR(), you can convert degree measurements into radians.
EGA43() returns .T. if the screen graphics adapter successfully switched to the 43-line mode.
Description
This function can be used with either an EGA or VGA card. A 43-line mode is requested, and the maximum number of coordinates for the CA-Clipper screen output is automatically increased. It isn't necessary to also call the SETMAXROW() and SETMAXCOL() functions.
Notes
Important! This function cannot be implemented when windows are open.
Examples
The following example switches to 43-line mode, making lines 0 to 42
available:
IF IsEGA()
EGA43()
ENDIF
@ 42, 10 SAY "CA-Clipper" // Last line
WAIT
CGA80() // Return to 25-line mode
EGAPALETTE([<cColor1|nColor1>, [<nPalette>])
→ lValid
or
EGAPALETTE([<cColor1|nColor1>, [<cColor2>]])
→ lValid
Arguments
cColor1|nColor1 Designates the color to change as a CA-Clipper color code or a numeric in the 0 to 15 range. If only this color is given, the accompanying palette is reset to its default value.
nPalette Designates which color palette the color cColor1|nColor1 is assigned to. May be in the range of 0 to 63.
cColor1|nColor1, cColor2 If a color is also designated as a second parameter, then that color's palette is designated as cColor1|nColor1.
() When no parameters are designated, all color palettes are reset to their default values.
Returns
EGAPALETTE() returns .T. when the selected setting is successfully implemented.
Description
EGAPALETTE() allocates one of the 16 colors available to another color palette. Since the function changes the screen adapter, everything on the screen designated with cColor1|nColor1 also changes.
Instead of a palette value, you can designate a second color. Its palette setting is allocated to the one designated in cColor1|nColor1, so that two of the 16 colors are identical.
If only the cColor1|nColor1 parameter is given, then the accompanying palette is reset to its default value. When calling the function without parameters, all palettes are reset.
Notes
■ You can also implement EGAPALETTE() in VGA mode, although
■ Redefine the color blue to dark blue:
SET COLOR TO B // Set blue
? "Nantucket" // Appears in blue
EGAPALETTE("B", 8) // Affects everything blue.
■ Reset the palette for the color blue:
EGAPALETTE("B")
Reset all palettes
EGAPALETTE()
Selects the enhanced color value for SET COLOR TO output
Syntax
Enhanced() → cNull
Returns
Enhanced() always returns a null string
Description
Use Enhanced() to specify the color attribute designated as enhanced (second color value), with SET COLOR TO as the active attribute for CA- Clipper @...SAY and ? output. Use Standard() to switch back to the default attribute.
Reads the entire DOS environment table into a string
Syntax
EnvParam() → cEnvironment
Returns
EnvParam() returns a string that corresponds to the complete environment table.
Description
This function returns the entire DOS environment table. The DOS Chr(0) delimiter, which follows each variable and its setting, is replaced with CR/LF. This allows the returned string to work well with the CA-Clipper Tools string functions (especially the tokenizer).
Notes
■ With the CA-Clipper function GetEnv(), you can query
individual parameters from the environment. Initially, this may seem convenient, but there is a problem because no blanks are allowed before and after the '='.
Examples
Read in the environment and analyze it:
cVar := EnvParam() // CR/LF as delimiter
TOKENINIT (@cVar, Chr(13) + Chr(10),2) // CR/LF as delimiter,
skip 2
DO WHILE .NOT. TokenEnd()
Env := TokenNext(cVar)
? Env
ENDDO
dDate Designates the date for the last day of the quarter in which it lies, is calculated. The default is the system date.
Returns
EoQ() returns the last day for the quarter that contains dDate.
Description
EoQ() determines when the current quarter that contains dDate ends. For example, it lets you calculate the number of days that remain before the end of the quarter.
Notes
■ If you do not specify a date, the function automatically uses
the system date. An empty date parameter results in an empty date.
Examples
The last day of the current quarter is:
? "The last day of the current quarter is:", EoQ()
Recommends an action for a DOS error that has occurred previously
Syntax
ERRORACT() → nActionCode
Warning! This function requires DOS 3.1 or higher.
Returns
ERRORACT() returns a numeric code that provides more information on how to react to the last DOS error. Coding is as follows:
Table 12-2: DOS Error Action Codes
Code Definition
1 Try several times, then ask user
2 Try several times with pauses, then ask user
3 Ask user for data
4 Leave program normally
5 Leave program as soon as possible
6 Ignore
7 User should correct error and try again
Description
DOS reacts to errors in several ways. One of the best known and least preferred by programmers is the question: "(A)bort, (R)etry, (I)gnore". ERRORACT() tells you how the application should react to the last DOS error that occurred.
Examples
Show an error that requires the program to terminate:
nAction := ERRORACT()
IF nAction = 4
? "Unfortunately, the program must be terminated!"
QUIT
ENDIF
ERRORBASE() → nErrorCode
Warning! This function requires DOS 3.1 or higher.
Returns
ERRORBASE() returns a numeric code that provides additional information about the cause of the error. These codes and their definitions are in the table below:
Table 12-3: Causes for DOS Errors
Code Definition
1 Insufficient memory
2 Access temporarily denied
3 No access for this user
4 Internal error, system software
5 Hardware error
6 Error in system software
7 Error in applications program
8 File not found
9 Wrong file format or type
10 File is protected
11 Incorrect medium in drive
12 Other error
Description
If an error is detected with ERRORCODE(), use ERRORBASE() for more information about the cause of the error, from within the data returned by DOS.
Examples
Determine the cause for an error:
nCause := ERRORBASE()
IF nCause = 3
? "Access denied!"
ENDIF
Identifies a DOS error that has occurred previously
Syntax
ERRORCODE([<lKeep>]) → nDosErrorCode
Warning! This function requires DOS 3.1 or higher.
Arguments
lKeep When this parameter is designated as .T., the function returns the internal error code memory value.
Returns
ERRORCODE() returns a value that represents the error code that occurred during the most-recently executed DOS function.
Description
If you do not specify a parameter or if the parameter is .F., then ERRORCODE() calls the DOS error function (INT 21h, 59h) and returns the code value stored for the most-recent error. DOS stores the most-recent error code until a new error occurs. If your operation is error free, this value is not reset.
To take this situation into account, ERRORCODE() can alternatively be called with lkeep set to .T.. If called like this, the error code always relates to the last CA-Clipper Tools function that was executed. Since the respective CA-Clipper Tools function behavior is stored at an internal memory location, it is impossible to implement this option with regular CA-Clipper functions.
Notes
■ You can find a table that contains all the error codes in
Appendix B: Error Codes.
Examples
■ This example attempts to copy a file. If an error occurs,
FileCopy() returns a value of 0 which offers no specific error
information:
nBytes := FileCopy("TEST\TEST.PRG", "NEW.PRG")
IF nBytes = 0 .AND. ERRORCODE() = 3
? "File path not found!"
ENDIF
■ An example of two file copies is illustrated below:
The first file is unsuccessful, but the second file is not:
FileCopy("XXXXX.TXT", "YYYY.TXT")
? ERRORCODE(.T.) // 2 - File not found
? ERRORCODE() // 2 - File not found
FileCopy("SOURCE.TXT", "TARGET.TXT")
? ERRORCODE(.T.) // 0 - Last Tools
// function was successful
? ERRORCODE() // 2 - File not found
Warning! Any CA-Clipper Tools function that contains a DOS call
resets the internal variable retrieved by setting <lKeep> . The
following call series never returns the desired result, because the
first call of ERRORCODE() contains a DOS call:
? ERRORCODE(), ERRORCODE(.T.) // Result: x, 0
ERRORORG() → nError
Warning! This function requires DOS 3.1 or higher.
Returns
ERRORORG() returns a numeric code that provides more information about the device on which the error occurred. The table below details this information:
Table 12-4: Origin of DOS Errors
Code Definition
1 Unknown
2 Block device (floppy, hard disk, etc.)
3 Network
4 Character device (COM, SCRN, etc.)
5 RAM
Description
ERRORORG() tells what type of device generated the most-recent DOS error. This essential information allows you to handle the error in an appropriate way.
Examples
Determine the source of an error:
nSource := ERRORORG()
IF nSource = 3
? "Error is on the network!"
ENDIF
Returns name and directory of the current CA-Clipper program
Syntax
ExeName() → cProgram
Returns
ExeName() returns the name and path of the current .EXE program.
Description
This function determines the name and path of the CA-Clipper application in use.
Notes
■ Use the Token() function to determine the name portion of a
program within a path.
Examples
Determine if the name or path of an EXE file has changed:
cOrigPath := "C:\DATA\ADDRESS.EXE"
IF ExecName() <> cOrigPath
? "Program name or directory have been changed!"
QUIT
ENDIF
nNumber Designates the number of the cCharacter|nCharacter characters that are inserted between each character in the cString. The default value is one character.
cCharacter|nCharacter Designates the character that is inserted between each character in cString. The default value is a space, Chr(32).
Returns
The processed cString is returned.
Description
Expand() can be used to justify text output, although the text is stored normally. This saves memory capacity with text constants or in databases.
Notes
■ Expansion only takes place when the cString contains at
least two characters.
■ To fill out a character string at the ends, use the PadLeft()
■ Use the default value and expand with one space:
? Expand("123456") // "1 2 3 4 5 6"
■ Expand with two spaces:
? Expand("123456", 2) // "1 2 3 4 5 6"
■ Expand with a ".":
? Expand("123456", ".") // "1.2.3.4.5.6"
■ Expand with two "."s:
? Expand("123456", 2, ".") // "1..2..3..4..5..6"
Determines the exponent of a floating point number (base 2)
Syntax
Exponent(<nFloatingPointNumber>) → nExponent
Arguments
nFloatingPointNumber Designates any decimal number.
Returns
Exponent() returns the exponent of the nFloatingPointNumber number in base 2.
Description
CA-Clipper stores all numbers in a floating point format (called "double" in C). Exponent() only returns exponents in this format, and they are always expressed in base 2.
Notes
■ The expression Exponent(0) returns a value of 0. However, the
expression 20 returns a value of 1. In this case, the mantissa must also equal 0 (see Mantissa()).
Examples
■ The following calculation produces the original number:
^2 Exponent(nValue) * Mantissa(nValue)= nValue
? Exponent(0) // Result: 0
? Exponent(Infinity()) // Result: 1023
? Exponent(100) // Result: 6
■ The sign for nValue will not be considered:
? Exponent(-100) // Result: 6
? Exponent(-1.01) // Result: 0
? Exponent(-2.01) // Result: 1
■ Values in the range of -1 < nValue < +1, yield negative
exponents regardless of the sign:
? Exponent(0.01) // Result: -7
? Exponent(-0.01) // Result: -7
Fact() returns the factorial of the specified value.
Description
Fact() computes the factorial of a value in the range of 0 to 21. Since results for factorials over 21 are too large, the function returns -1 to indicate an error.
Examples
Show some factorials:
? Fact(1) // Result: 1
? Fact(5) // Result: 120
? Fact(21) // Result: 51090942171709440000
? Fact(25) // Result: -1 (Value too large !)
? Fact(0) // Function returns 1
Determines the number of decimal places in a field
Syntax
FieldDeci(<nField>) → nDecimalPlaces
Arguments
nField Designates for which numeric data field to determine the number of decimal places.
Returns
When a field number is valid, FieldDeci() returns the number of decimal places in a numeric data field.
Description
It is important to know how many decimal places are in a data field so you can limit the input of significant digits in the corresponding number. FieldDeci() determines the number of decimal places available. This allows you to tailor inputs to the database without changing the program.
Notes
■ If you have an invalid field number, the function returns a
value of 0.
Examples
Convert the second field to a string with the correct number of decimal
places:
@ 0, 60 SAY "Price: " + Str(cField2, 8, FieldDeci(2))
Determines the field number for a specific field in a database file
Syntax
FieldNum(<cFieldName>) → nFieldNumber
Arguments
cFieldName Designates to the field name.
Returns
FieldNum() returns the number of the data field.
Description
FieldNum() is the exact opposite of the CA-Clipper Field() function. Use this function when you need a data field number instead of the data field name. FieldNum() determines if a symbol name pertains to a data field or a memory variable (see Examples).
Notes
■ If a data field with the name cFieldName is not available,
the function returns a value of 0.
Examples
Is it a field or a variable?
IF FieldNum("cName") > 0.
REPLACE cName WITH Upper(cName).
ELSE.
cName := Upper(cName).
ENDIF
nField Designates the number of the field to evaluate.
Returns
FieldSize() returns a numeric value that corresponds to the field length of a valid field number.
Description
Use FieldSize() to determine the length (or size) of data field of desired data types. This determines the window width needed for output to appear without a line break, or the length needed for an input to automatically fit in the database.
Notes
■ If there is an invalid data field number, the function returns
a value of 0.
Examples
Determine the total length of fields 3 to 5:
nLength := 0
FOR I = 3 TO 5
nLength := nLength + FieldSize()
NEXT
nField Designates the data field for which the data type is determined.
Returns
FieldType() returns a single character that designates the data type of the data field (assuming the data field number is valid). FieldType() returns the following characters for the various data field types:
Table 10-1: Coding for Data Field Types
Character Data Type
C Character string
N Numeric
D Date
L Logical
M MEMO
Description
FieldType() operates in a similar fashion to the CA-Clipper Type() function. With Type(), you must always know only the name of the data field. However, FieldType() requires that you only know the data field, not its name. Use the function to confirm data types for data fields when a program is working with different databases that have different field names.
Notes
■ If there are invalid data field numbers, the function returns
a null string.
Examples
Data type for field number 5:
IF FieldType(5) = "C"
? "Field No. 5 is a character field!"
ENDIF
cSourceFile Designates the file that is appended to cTargetFile.
cTargetFile Designates the file to which cSource is appended. Drive and path designation are permitted for both files, wildcards are not.
Returns
FileAppend() returns the number of characters appended on to cTargetFile.
Description
FileAppend() takes fragmented files, split them up on different floppies and reassemble them. This sort of fragmented file could be created with the FileCopy() system described in this chapter. You only need explicit information, such as VOLUME labels, to recognize the different disks. If the target file does not exist, it is created with FileAppend(). If an error occurs while appending to the target file, the file deletes completely to avoid accidental and incorrect results.
Never append data to file if there is no backup copy.
Notes
■ Use SetFCreate(), if FileAppend() creates a new file and an
alternative attribute needs to be specified.
■ Use SETSHARE() to protect a target file from access, if it is
on a network drive.
Examples
Shown below is a simplified program to reassemble a file that is divided
among several disks by a FileCopy() backup.
A catalog contains a list of the disks used during backup in the form of
volume labels and backup file names.
Structure of the DISKLIST catalog:
Table 7-10: DISKLIST File Structure
<table>
Field Name Field Content
VolLabel Back up disk drive and volume label
BackupName Back up file name, incl. drive and path
</table>
The data in DISKLIST is created by a FileCopy() backup:
USE DISKLIST // Saved volume labels
cTargetFile := "C:\TARGET.TXT"
DO WHILE .NOT. Eof()
IF .NOT. Empty(FileSeek(cVolLabel, 8) // Correct disk ?
FileAppend(cBackupName, cTargetFile) // Yes, append data
SKIP
ELSE
? "Please insert the correct disk !"
ENDIF
ENDDO
cFile Designates the file name, including the path and drive designation.
Returns
FileAttr() returns the attributes for the researched entry or the attribute from the FileSeek() buffer (when called without a parameter).
Description
FileAttr() is implemented alone or in conjunction with FileSeek(). If the function is called with the cFile parameter, it returns the attribute of the first entry found. If no acceptable entry is available, a value of 0 is returned.
When called without a parameter, FileAttr() returns the attribute for the most-recent file located with FileSeek(). When used with FileSeek(), you can determine the attribute for file groups (wildcards).
When you call FileAttr() with the cFile parameter, the function internally passes 63 (all attributes) as a mask. When used in conjunction with FileSeek(), you should also designate all 63 as an attribute mask, if all files are to be acknowledged.
Table 7-11: Coding the File Attribute
Value Symb. constants Assigned attribute
0 FA_NORMAL
1 FA_READONLY READ ONLY (Read-only)
2 FA_HIDDEN HIDDEN (Hidden files)
4 FA_SYSTEM SYSTEM (System files)
8 FA_VOLUME VOLUME (Name of a floppy/hard disk)
16 FA_DIRECTORY DIR (Directory)
32 FA_ARCHIVE ARCHIVE (Changes since last backup)
If multiple attributes are implemented for a file, the value of each corresponding attribute is added.
Examples
■ Show the attribute of a specific file:
? FileAttr("C:\TEXT\TEXT.TXT") // 32 ARCHIVE
■ The attribute for an ARCHIVE/HIDDEN file:
? FileAttr("C\HIDE.TXT") // 34 HIDDEN + ARCHIVE
■ Used in conjunction with FileSeek():
cFile := FileSeek("C:\TEXT\TEXT.TXT")
DO WHILE .NOT. EMPTY (cFile)
? cFile, FileAttr() // Name & file attribute
cFile := FileSeek() // Search for next entry
ENDDO
FileCCLose() returns .T., when the the file that was opened with FileCopy() is successfully closed.
Description
FILE COPY CLOSE After you copy on multiple disks, this function should be routinely called. This is to prevent the source file, previously designed with FileCopy(), from remaining open. For example, this may occur if you terminate the copy procedure.
Notes
■ Regardless of the share mode, all other users are not allowed
access. This situation stays this way without needing a file handle.
Examples
Show a back up with FileCopy(). After terminating, close the source
file:
FileCopy(cSource, cTarget, .T.) // Back up mode
DO NEXTDISK // When terminated Terminated =
.T.
DO WHILE FileCOpen() .AND. .NOT. Terminated
FileCCont(cTarget) // Next disk, new name
DO NEXTDISK // Request for disk exchange
ENDDO
IF Terminated
FileCCLose() // Close source file!
ENDIF
cFile Designates the file name for the target file.
Returns
FileCCont() returns the number of bytes copied.
Description
FILE COPY CONTINUE Use this function primarily after a FileCopy(). As much as possible of the remaining data is written to a new disk. If the remaining data still does not fit on the designated target disk, call this function repeatedly until it writes all the remaining data. Each time you call FileCCont(), a new name can be designated for the target file. These files are then numbered consecutively (see Examples).
Notes
■ If a copy procedure on multiple disks terminates for any
Show a back up with FileCopy(). After terminating, close the source
file:
FileCopy(cSource, cTarget, .T.) // Back up mode
DO NEXTDISK // When terminated Terminated = .T.
DO WHILE FileCOpen() .AND. .NOT. Terminated
FileCCont(cTarget) // Next disk, new name
DO NEXTDISK // Request for disk exchange
ENDDO
IF Terminated
FileCCLose() // Close source file!
ENDIF
Determines whether a source file's date and time stamp or the system's date and time stamp, should be used to create or copy a file. Use original or
Syntax
FileCDaTi([<lNewMode>]) → lOldMode
Arguments
lNewMode Designates the new status for FileCDaTi(). When .T. is designated, the target file contains the source file date; when it is .F., the system date. The default is the source file date (.T.).
Returns
If no parameter is designated, FileCDaTi() returns the current setting for FileCDaTi(); otherwise, it returns the previous setting.
Description
FILE COPY DATE TIMEFileCDaTi() determines which date the target file contains with a FileCopy(). When you partition to several disks in backup mode, this concerns all target files. The CA-Clipper Tools default is .T., where the target file contains the date and time of the source file. If you call FileCDaTi() with the parameter designated .F., then the target file contains the system date and time.
■ Query the FileCDaTi() setting:
? FileCDaTi() // The current setting
■ The target file is to contain the system date and time:
? FileCDaTi(.F.) // Returns the previous setting
cSourceFile Designates the source file. Drive and path designations are permitted, but not wildcards.
cTargetFile Designates the target file. Drive and path designations are permitted, but not wildcards.
lMode Designates the backup mode on when designated as .T. The default is no backup mode (.F.).
Returns
FileCopy() returns the number of bytes copied.
Description
This function has additional uses besides allowing you to quickly copy files. When you use the optional lMode parameter, a unique backup mode is switched on. This allows files that are larger than the target disks to be copied. This function writes the maximum possible number of bytes to a disk. FileCOpen() allows you to determine whether all data from the source file has been copied. It then continues with the next disk. The target disks should contain unique labels and be saved to a catalog.
Notes
■ The attribute to be used when newly creating a file can be
specified with SETCREATE().
■ As a minimum, the share mode recommends that you do not write
other program source and target files.
■ This function acknowledges the CSetSafety() setting, and as a
result, cannot overwrite a target file.
Examples
■ Show a simple copy:
? FileCopy("A:\TEXT.TXT", "C:\TEST.TXT") // Bytes copied
■ A back up using FileCopy():
nCounter := 1 // "BIG.001" etc.
cTargetFile := "BIG" + NToC(nCounter, 10, 3, "0")
FileCopy("BIG.DBF", "A:\" + cTargetFile, .T.)
// Back up mode
DO WHILE FileCOpen()
DO NEXTDISK // Request disk change
nCounter := nCounter + 1
cTargetFile := "BIG" + NToC(nCounter, 10, 3, "0")
FileCCont(cTargetFile) // Next disk - new name
ENDDO
RETURN
PROCEDURE NEXTDISK
? "Please insert new diskette in Drive A:!"
WAIT
RETURN
Tests to see if the file is still open in the backup mode
Syntax
FileCOpen() → lOpenFile
Returns
FileCOpen() returns .T. when all data is not copied during a FileCopy() or FileCCont().
Description
FILE COPY OPENFileCOpen() determines whether all data is copied. This concerns the source file, which is specified when the FileCopy() function is called. FileCOpen() returns .T. until all the data in the source file is read, whether by FILECOPY or the follow-on function FileCCont()
Notes
■ If you must abort the copy process, and FileCOpen() continues
Show a back up with FileCopy():
nCounter := 1 // "BIG.001" etc.
cTargetFile := "BIG" + NToC(nCounter, 10, 3, "0")
FileCopy("BIG.DBF", "A:\" + cTargetFile, .T.)
// Back up mode
DO WHILE FileCOpen()
DO NEXTDISK // Request disk change
nCounter := nCounter + 1
cTargetFile := "BIG" + NToC(nCounter, 10, 3, "0")
FileCCont(cTargetFile) // Next disk - new name
ENDDO
FILECCLOSE // For safety
cFileMap Designates a file name, including its path and drive designation.
nFileAttr Designates the file attribute explained in the table below. The default value is 0.
() If you call this function without parameters, it returns the file date from the current FileSeek() buffer.
Returns
FileDate() returns the date of the searched for entry, the date from the FileSeek() buffer (when called without parameters), or an empty date.
Description
You can implement FileDate() alone or in conjunction with FileSeek(). If you use the cFileMap parameter to call this function, it returns the date of the first entry found. If a suitable entry is not present, an empty date is returned.
When called without parameters, FileDate() returns the date of the last file it located with FileSeek(). You could also determine the dates for a file group (wildcards), when used it in conjunction with FileSeek().
The attribute for the desired file can be specified in numeric form:
Table 7-12: Coding the File Attribute
Value Symb. constants Assigned attribute
0 FA_NORMAL
1 FA_READONLY READ ONLY (Read-only)
2 FA_HIDDEN HIDDEN (Hidden files)
4 FA_SYSTEM SYSTEM (System files)
16 FA_DIRECTORY DIR (Directory)
32 FA_ARCHIVE ARCHIVE (Changes since last backup)
To find a file, specify only the SYSTEM, HIDDEN, VOLUME, or DIR attributes. If multiple attributes are implemented simultaneously, the table values are added accordingly. Of course, not all combinations are useful.
Examples
■ Show the date of a particular file:
? FileDate("C:\TEXT\TEXT.TXT") // The date
■ The date of an ARCHIVE/HIDDEN file:
? FileDate("C:\HIDE.TXT", 34) // The date
■ Used in conjunction with FileSeek():
cFile := FileSeek("C:\TEXT\*.TXT")
DO WHILE .NOT. Empty(cFile)
? cFile, FileDate() // Name & date of file
cFile := FileSeek() // Search for next entry
ENDDO
nFileAttr Designates one of the following file attributes. The default value is 32.
Table 7-13: File Attribute Coding
Value Symb. constants Definition
0 FA_NORMAL
1 FA_READONLY Read-only
2 FA_HIDDEN HIDDEN (Concealed files)
4 FA_SYSTEM SYSTEM (System files)
8 FA_VOLUME VOLUME (Name of floppy/hard disk)
32 FA_ARCHIVE ARCHIVE (Changed since last backup)
Returns
FileDelete() returns .T. when at least one or more files are deleted; otherwise, .F. is returned.
Description
Occasionally, you will need to clean up a floppy or a hard disk or delete whole file groups. This function deletes entire file groups with a function call, without using the RUN command.
Notes
Warning! FileDelete() can also delete system files.
■ The default standard attribute is archive (32). Drive and
path designations, and wildcards are permitted.
■ Subdirectories must be deleted with the help of the
cSourceFile Designates the name and the path of the source file.
cTargetFile Designates the name and the path of the target file.
Returns
FileMove() returns a value of 0 when the file can be moved; otherwise, an error code is returned. The codes are defined below:
Table 7-14: FileMove() Error Codes
Code Symb. constants Definition
0 NO_DISK_ERR No errors
-2 ER_FILE_NOT_FOUND File not found
-3 ER_PATH_NOT_FOUND Access path not found
-5 ER_ACCESS_DENIED Access denied (e.g., network)
-17 ER_DIFFERENT_DEVICE Target file not on same drive
Description
If a file is to be copied within a drive and then deleted it from the original position, it is quicker to move the file. FileMove() makes this possible. The directory entries are also changed, which is much quicker than copying and deleting.
Notes
■ You can use drive designators and access paths in
cSourceFile and cTargetFile file names. Wildcards are not permitted.
■ You can only move a file within a drive. If the target
directory already contains a file with the same name as the one from cSourceFile, the move is not completed. In this case, FileMove() returns a value of -5. The only option available in this situation, is to delete the file in the target directory.
Examples
Move a file from "\OLD" to "\NEW":
IF FileMove("\OLD\CUST.DBF", "\NEW\CUST.DBF") = 0
? "The file is now in the \NEW directory"
ENDIF
cFileName Designates the name and path of the screen file.
nOffset Designates from which part of the file offset the screen is to be read. The default is the beginning of file.
Returns
FileScreen() returns the number of bytes read.
Description
FILESCREEEN() is the opposite of ScreenFile(). Use FileScreen() to read and display a screen stored with ScreenFile(). Use the nOffSet parameter to indicate an offset from which the file is to be read. Since the number of bytes written with ScreenFile() is known, you can compute the location within the file of the beginning of the new screen. This allows you to save multiple screens in a single file.
Notes
■ The file read with FileScreen() can also contain end of file
markers. The read procedure does not end prematurely as a result, since the function always reads 4000 bytes.
Examples
■ Read a screen from the beginning of a file:
FileScreen("screen.tst")
■ Read the second screen. Since the offset is specified as
4000, the first screen is skipped:
FileScreen("screen.tst", 4000)
■ Drive and path are permitted:
FileScreen("\screen.tst")
FileScreen("a:screen.tst")
■ Wildcards are not permitted:
FileScreen("screen.*") // Result: 0
cFileMap Designates a file name including its path and drive designation. It may contain wildcards.
nFileAttr Designates the file attribute that corresponds to the ones described in the table on the next page. The default value is 0.
lExact If you designate .T. as the optional parameter, FileSeek() also checks for the exact agreement of the file attributes of the respective file with the value passed by nFileAttr.
() If you call the function without parameters, it serves as a sequential call for a FileSeek() with file specifications, and returns sequential entries as long as these are found.
Returns
FileSeek() returns the name of the first or next entry (when called without parameter) located in the selected directory.
Description
FileSeek() provides the foundation for a variety of functions. As a group, they permit access to desired information about directory entries. Implement the FileSeek() function when you want information about a file group (wildcards). When you call it with the cFileMap parameter, it searches for the first entry in the designated directory. If you call it without parameters, it searches for the next matching entry in the directory. If no more entries are present, it returns a null string. An attribute mask can further define a file group that is being searched for. The desired file attributes are coded as follows:
Table 7-15: Coding the File Attribute
Value Symb. constants Assigned attribute
0 FA_NORMAL
1 FA_READONLY READ ONLY (Read-only)
2 FA_HIDDEN HIDDEN (Hidden files)
4 FA_SYSTEM SYSTEM (System files)
8 FA_VOLUME VOLUME (Name of a floppy/hard disk)
16 FA_DIRECTORY DIR (Directory)
32 FA_ARCHIVE ARCHIVE (Changes since last backup)
If you implement multiple attributes simultaneously, the table values are added accordingly. Of course, not all combinations are useful.
Exact File Attributes
DOS does not make an exact comparison with a designated attribute mask and attributes actually found in a file. Specify only the SYSTEM, HIDDEN, VOLUME, or DIR attributes for an entry to be found. Files with only one other attribute bit set are always returned, regardless of the value specified in the attribute mask. This way, a function call with a mask value of 16 returns not only subdirectories, but all files without a set attribute (e.g., all the ARCHIVE and R/O files).
To avoid this, you can designate .T. as the third parameter. The function itself also reviews the designated attribute mask with the actual file attributes, for an exact agreement. Then, the designation of a 16 mask and .T., only returns subdirectories.
Internal Data Buffer
Every time you use FileSeek() all the data for a directory entry is saved to an internal buffer. Individual information such as size, time, or date is easily accessible. To do this, the FileTime(), FileDate(), etc., functions are called without parameters; otherwise, it requires another call to the disk, instead of taking the data from an internal buffer.
Notes
■ Use the recursive sample function SCANFILES() in the
accompanying Tooldemo.prg file, to produce the most effective programs to work with entire directory structures.
■ Display the date and size of all files with the extension .TXT
in a directory:
cFile := FileSeek("C:\TEXT*.TXT") DO WHILE.NOT. Empty(cFile)
? FileSize() // Size of file in buffer ? FileDate() // Date of file in buffer cFile := FileSeek() // Search for next entry
ENDDO
■ Display system files in the root directory. Attribute: READ
ONLY, HIDDEN, SYSTEM, ARCHIVE → 39, although 6(2 + 4) will suffice as an attribute:
cFile := FileSeek("C:*.*", 39) DO WHILE.NOT. Empty(cFile)
? cFile // File name cFile := FileSeek() // Look for next entry
ENDDO
■ Only query the subdirectory:
cSubDir := FileSeek("C:*.*, 16, .T.) DO WHILE.NOT. Empty(cSubDir)
? cSubDir // Name of the directory cSubDir := FileSeek() // Search for next directory
cFileMap Designates the file name, path, and drive designation.
FileAttr Designates the file attribute that is explained in the table below. The default value is 0.
() If the function is called without parameters, it returns the file size from the current FileSeek() buffer.
Returns
FileSize() returns the designated file's size, the size from the FileSeek() buffer (when called without a parameter), or -1.
Description
Implement FileSize() alone or in conjunction with FileSeek(). If the function is called with the cFileMap parameter, it returns the size of the first entry found. If no matching entry is available, then a value of -1 is returned
When called without parameters, FileSize() returns the size of the most recent file found with FileSeek(). Used in conjunction with FileSeek(), you can also determine the size of file groups (wildcards).
You can designate the attribute for the desired file in numeric form:
Table 7-16: Coding the File Attribute
Value Symb. constants Assigned attribute
0 FA_NORMAL
1 FA_READONLY READ ONLY (Read-only)
2 FA_HIDDEN HIDDEN (Hidden files)
4 FA_SYSTEM SYSTEM (System files)
32 FA_ARCHIVE ARCHIVE (Changes since last backup.)
Specify only the SYSTEM, HIDDEN, VOLUME, or DIR attributes for an entry to be found. If multiple attributes are implemented simul-taneously, the table values are added accordingly. Of course, not all combinations are useful.
Examples
■ Show the size of a particular file:
? FileSize("C:\TEXT\TEXT.TXT") // File size or -1
■ The size of an ARCHIVE/HIDDEN file:
? FileSize("C:\HIDE.TXT", 34") // File size or -1
■ Used in conjunction with FileSeek():
cFile := FileSeek(C:\TEXT.TXT")
DO WHILE .NOT. Empty(cFile)
? cFile, FileSize() // File name and size
cFile := FileSeek() // Search for next entry
ENDDO
Specifies the maximum number of files that can be open at one time
Syntax
FileSMax() → nMaxHandles
Returns
FileSMax() returns the maximum number of files that can be open at once.
Description
The value set for FILES= within the CONFIG.SYS, and the number of available handles, influences the maximum number of files that can be open simultaneously. The maximum number is determined by the smaller of the two values respectively.
Notes
■ The returned value is subtracted from the handles already
occupied by the operating system. This value is usually 5.
■ This function cannot determine if an additional operating
system adaptation (Novell's SHELL.CFG) has been made under a Novell network. These adaptations are only used for the current network drive under Novell.
Examples
How many files can be opened in the system?
? FileSMax() // e.g. 100
cFile Designates the file from which a string is read.
nLength Designates how many characters you want to read from a file (up to a maximum of 65520 bytes). The default is read all characters.
nOffset Designates an offset within the file from which the nLength characters or the rest of the file, are read. The default is from the first character (0).
lCtrl-Z If this parameter is designated as .T., only data up to the first Ctrl-Z is read in. The default is read all data (.F.).
Returns
FileStr() returns the string read in from the designated file.
Description
FileStr() also offers the capability to read files or a portion of them, into a string. This is only possible with a function call, where the file name may contain a drive and path designation. If you implement the lCtrl-Z parameter, you can be sure the function only reads data up to the first Ctrl-Z and ignores whatever might remains in of the file.
In contrast to the CA-Clipper Fxxxx() functions, a disadvantage of FileStr() is a slower access speed, since the file you want to read cannot be held open.
Notes
■ This function reads all available bytes in working memory (up
to 65520). The amount of available free memory is determined by calling Memory(1).
■ As recommended in share mode, no other programs should write
in the net through SETSHARE(2) for the duration of the read.
Examples
■ Read in a file completely:
? FileStr("C:\TEXT\TEST.TXT") // Displays file text
■ Read in everything to the first Ctrl-Z:
cVar := FileStr("C:\TEXT\TEST.TXT", .T.)
■ The file TEST.TXT contains "ABCDEFGHIJ". Four characters,
beginning from position 3, are to be read:
? FileStr("C:\TEXT\TEST.TXT", 4, 3) // "CDEF"
■ Read the maximum that fits into the available working memory:
cVar := FileStr("C:\TEXT\TEST.TXT", Memory(1) *1024 -100)
cFileMap Designates the file name, including the path and drive designation.
nFileAttr Designates the file attribute explained in the table below. The default value is 0.
() If the function is called without parameters, it returns the file time from the current FileSeek() buffer.
Returns
FileTime() returns the clock time for the "searched for" entry, the clock time from the FileSeek() buffer (when called without parameters), or a null string.
Description
Implement FileTime() alone or in conjunction with FileSeek(). If the function is called with the cFileMap parameter, it returns the time of the first entry found. If no matching entry is available, a null string is returned.
When called without parameters, FileTime() returns the clock time of the last file found with FileSeek(). You can also determine the clock time of file groups (wildcards) when the function is used in conjunction with FileSeek().
You can designate the attribute for the desired file in numeric form:
Table 7-17: Coding the File Attribute
Value Symb. constants Assigned attribute
0 FA_NORMAL
1 FA_READONLY READ ONLY (Read-only)
2 FA_HIDDEN HIDDEN (Hidden files)
4 FA_SYSTEM SYSTEM (System files)
16 FA_DIRECTORY (Subdirectory)
32 FA_ARCHIVE ARCHIVE (Changes since last backup)
Only the SYSTEM, HIDDEN, VOLUME, or DIR attributes must be specified for an entry to be found. If multiple attributes are implemented simultaneously, the table values are added accordingly. Of course, not all combinations are useful.
Examples
■ The clock time of a particular file:
? FileTime("C:\TEXT\TEXT.TXT") // File clock time or ""
■ The clock time of an ARCHIVE/HIDDEN file:
? FileTime("C:\HIDE.TXT", 34") // File clock time or ""
■ Used in conjunction with FileSeek():
cFile := FileSeek(C:\TEXT.TXT")
DO WHILE .NOT. Empty(cFile)
? cFile, FileTime() // File name and clock time
cFile := FileSeek() // Search for next entry
ENDDO
Calculates/computes/determines a checksum for a file
Syntax
FILECHECK(<cFile>) → nCheckSum
Arguments
cFile Designates which file name (with path, if required), to check.
Returns
FILECHECK() returns a checksum value for cFile.
Description
FILECHECK() determines if there have been changes or read errors in a file, and then takes note of data backup. This also allows you to protect your hard disk from simple viruses (see Examples).
Notes
■ You must specify the argument. If it is omitted or an
unavailable file is specified, FILECHECK() returns an error code of - 1. You may use a drive and access path, but no wildcards.
Examples
■ Check database for changes:
IF FILECHECK("CUST.DBF") <> Old_ChkSum
? "Warning! Data back-up required."
ENDIF
■ Check COMMAND.COM for changes:
IF FILECHECK("\COMMAND.COM") <> Cmd_ChkSum
? "COMMAND.COM has been changed! Caution, Virus!"
ENDIF
FILESFREE() returns the number of available handles.
Description
This function returns the number of available handles that correspond to the number of files you can open. This enables you to avoid DOS error 4.
Notes
■ Immediately after you start a CA-Clipper application, a value
— smaller than that of FileSMax() — is returned. This happens because the operating system and application itself is already using handles.
Examples
■ Can I still open a file?
IF FILESFREE() > 0 // At least 1 handle free?
USE CUSTOMER // Open a file
ENDIF
■ Be careful when you open multiple indexes at the same time!
IF FILESFREE() > 1 // At least 2 handles free?
USE CUSTOMER INDEX CUSTNR // Open 2 files
ENDIF
cFileName Designates the file name you want to test for validity.
Returns
FILEVALID() returns .T. when the designated name is valid.
Description
FILEVALID() determines if a string contains a valid file name. You could also test the validity of user input in this way. If necessary, path and drive designations must be removed from the string. The tokenizer described in the string chapter is available for this purpose (see Examples).
Examples
The last token in a string with drive and path designations should
contain the file name:
ACCEPT "Target_File " TO cVar
cFileName := TOKEN(cVar, " \:") // Last token
DO WHILE .NOT. FILEVALID(cFileName)
* Error message ...
ACCEPT "Target_File " TO cVar
cFileName := TOKEN(cVar, "\:") // Last token
ENDDO
nFirstNewColumn Designates which column is the first visible column on the left side of a virtual screen.
Returns
If the parameter is passed, the function returns the previous setting. If no parameter is passed, it returns the current setting.
Description
This function is important for use in setting virtual screen size in conjunction with SETMAXROW() and SETMAXCOL(). You can select the first column that you would like to be visible on the left side of the screen. In this way the screen can be moved in any direction.
Notes
■ To simplify programming, values outside of the permissible
range are automatically corrected to the maximum or minimum values (see example).
Examples
The following example sets up a screen with 100 lines and 120 columns.
To help you with screen orientation, the current column number is
displayed at three locations on this virtual screen. The virtual screen
can be moved in any direction using cursor keys and PgUp and PgDn:
SETMAXROW( 99) // screen with 100 lines
SETMAXCOL(119) // and 120 columns
CLEAR
FOR nCount = 0 TO MaxRow() // Build screen
@ nCount, 0 SAY "Line" + NToC(nCount, 10, 4)
@ nCount, MaxCol()/2 -5 SAY "Line" + NToC(nCount, 10, 4)
@ nCount, MaxCol() -10 SAY "Line" + NToC(nCount, 10, 4)
NEXT nCount
@ 99, 00 SAY Center("This is the last line")
nKeyVal := 0
DO WHILE nKeyVal <> 27
nKeyVal := Inkey(0)
DO CASE
CASE nKeyVal = 5
FIRSTROW(FIRSTROW() -1)
CASE nKeyVal = 24
FIRSTROW(FIRSTROW() +1)
CASE nKeyVal = 4
FIRSTCOL(FIRSTCOL() +1)
CASE nKeyVal = 19
FIRSTCOL(FIRSTCOL() -1)
CASE nKeyVal = 18
FIRSTROW(FIRSTROW() -10)
CASE nKeyVal = 3
FIRSTROW(FIRSTROW() +10)
ENDCASE
ENDDO
FIRSTROW(0) // reset
FIRSTCOL(0)
SETMAXCOL(79)
SETMAXROW(24)
CLEAR
nFirstNewLine Designates which line is displayed as the top line on the virtual screen.
Returns
If the parameter is passed, the function returns the previous setting each time. If no parameter is passed, it returns the current setting.
Description
This function is important for use in setting virtual screen size in conjunction with SETMAXROW() and SETMAXCOL(). You can select the first line that you would like to have visible at the top side of the screen. In this way the screen can be moved in any direction.
Notes
■ To simplify programming, values outside of the permissible
range are automatically corrected to the maximum or minimum values (see example).
Examples
The following example sets up a screen with 100 lines and 120 columns.
To help you with screen orientation, the current column number is
displayed at three locations on this virtual screen. The virtual screen
can be moved in any direction using cursor keys and PgUp and PgDn:
SETMAXROW( 99) // screen with 100 lines
SETMAXCOL(119) // and 120 columns
CLEAR
FOR nCount = 0 TO MaxRow() // Build screen
@ nCount, 0 SAY "Line" + NToC(nCount, 10, 4)
@ nCount, MaxCol()/2 -5 SAY "Line" + NToC(nCount, 10, 4)
@ nCount, MaxCol() -10 SAY "Line" + NToC(nCount, 10, 4)
NEXT nCount
@@ 99, 00 SAY Center("This is the last line")
nKeyVal := 0
DO WHILE nKeyVal <> 27
nKeyVal := Inkey(0)
DO CASE
CASE nKeyVal = 5
FIRSTROW(FIRSTROW() -1)
CASE nKeyVal = 24
FIRSTROW(FIRSTROW() +1)
CASE nKeyVal = 4
FIRSTCOL(FIRSTCOL() +1)
CASE nKeyVal = 19
FIRSTCOL(FIRSTCOL() -1)
CASE nKeyVal = 18
FIRSTROW(FIRSTROW() -10)
CASE nKeyVal = 3
FIRSTROW(FIRSTROW() +10)
ENDCASE
ENDDO
FIRSTROW(0) // reset
FIRSTCOL(0)
SETMAXCOL(79)
SETMAXROW(24)
CLEAR
cDrive Designates the drive (A, B, C, etc.) for which you want a type determined. The default is the current disk drive.
Returns
The function returns the exact type of the designated disk drive, coded as follows:
Table 7-18: Coding of Drive Types
Code Definition
0 No floppy drive
1 360-kB drive
2 1.2-MB drive
3 720-kB drive
4 1.44-MB drive
Description
This function gives you a numeric value that specifies exact type and capacity of the selected floppy drive. Whether or not the device is a floppy drive, is determined beforehand by DriveType().
Notes
■ The drive type is determined without actually accessing the
drive. Therefore, a disk does not have to be in the drive.
Examples
Is the current disk drive a floppy and what type?
IF DriveType() = 1 .OR. DriveType() = 2
DO CASE
CASE FLOPPYTYPE() = 0
? "No floppy drive!"
CASE FLOPPYTYPE() = 1
? "360 kB drive"
CASE FLOPPYTYPE() = 2
? "1.2 MB drive"
CASE FLOPPYTYPE() = 3
? "720 kB drive"
CASE FLOPPYTYPE() = 4
? "1.44 MB drive"
ENDCASE
ENDIF
cFileName Designates the name and path of the font file.
nFontArea Designates the number of the specified font area. For EGA, the values 1 to 4 are allowed, or whatever values MAXFONT() permits. For VGA, the values 1 to 8 are allowed, or whatever MAXFONT() permits.
nOffset Designates from what character position the screen adapter font table is overwritten. The default value is 0.
nCounter Designates how many characters to load from the new font. The default value is 256.
lOtherPixelHeight Designates .T. to allow the function to modify the pixel height. This leads to a mode change and character count. Please note that you must designate both nOffset and nCounter to implement this parameter.
Returns
The function returns an error code which corresponds to the explanation below:
Table 6-1: Values returned for FONTLOAD()
Error Code Explanation
0 Font loaded successfully
-2 Impossible in current video mode
-3 Font file not found
-4 The <lOtherPixelHeight> mode is not possible (the Extended
Drivers are not linked in)
Description
FONTLOAD() allows you to load the font definitions from a file into the font area of an EGA or VGA card. Use FONTSELECT() to determine which fonts serve as normal and high density for output.
You may already have some of these fonts on the CA-Clipper Tools disk, and others can be created with the accompanying font editor.
Technical Background
The EGA and VGA cards permit you to modify a portion or all 256 characters of the character generator with software. To do this, a previously created pixel pattern for the character is loaded in the corresponding position in a font area on the screen card. Normally, an EGA card has a maximum of four font areas and a VGA has eight, within which you can redefine all 256 characters. Use MAXFONT() to determine the exact count of font areas.
Building fonts into a program requires unnecessary memory space. Constructing fonts as a string within a program is also awkward. With the GETFONT() and SetFont() functions, you can load a font from a screen card into a string variable, or from such a variable, into a font area on the card. However, FONTLOAD() only allows you to load a font from a file into a particular area of the screen card. In both cases, use ONTSELECT() to activate the loaded font.
On the CA-Clipper Tools sample disk, you will find a font editor to construct new fonts in CA-Clipper source code.
Variable Pixel Height
In principle, EGA and VGA screen adapters provide the opportunity to display fonts with 2 to 32 pixels per character (1 pixel/character only, when there are 200 scan lines). ROM fonts are only available for pixel heights of 8, 14 and 16, which accounts for the great expansion of the EGA 25-/43-line modes and VGA 25-/28-/50-line modes. You must construct individual fonts for all other pixel heights. The CA-Clipper font editor can make this easy.
When FONTLOAD() loads a font, it also computes the pixel height from the font data length. Since a font file always contains all 256 character definitions, there is a formula:
Pixel height = Len(Font-Data)/256
The lOtherPixelHeight parameter determines whether the fonts that do not match the pixel height just set are accepted. This must be explicitly indicated, since the line count and screen mode will change. For this reason, you must always link in the CTUS.LIB Extended Drivers (see Table 6-1, returned value -4).
Notes
■ You cannot use FONTRESET() when a font is loaded for which
there is no associated ROM font (all pixel heights except 8, 14, 16). Prior to a FONTRESET(), switch back to a permissible mode.
■ All previously successful FONTSELECT() settings are discarded
again during FONTLOAD().
■ If an EGA card does not span the entire memory range, then you
can reduce a maximum of four available font areas. MAXFONT() determines the number of available fonts.
Examples
■ Load all 256 characters of an EGA font in area 2:
? FONTLOAD("\FONTS\OLDENG.014", 2) // 0 OK<
FONTSELECT(2)
■ Exchange the fonts for the upper 128 characters in area 3:
? FONTLOAD("\FONTS\OLDENG.EGA", 3, 128, 128) // 0 OK
FONTSELECT(3) // Select
■ Load a 24-pixel font in the last font area:
? FONTLOAD("\FONTS\PC.024", MAXFONT(), .T.)
Resets all font and palette changes to the ROM defaults
Syntax
FONTRESET() → lReset
Returns
FONTRESET() returns .T. when all font and palette settings are reset.
Description
This function resets all the settings implemented with FONTLOAD(), SetFont(), and FONTSELECT(). Settings implemented with EGAPALETTE() or VGAPalette() are also reset. In addition, the border color set with SET COLOR TO is reset.
Table 6-2: Settings affected by FONTRESET()
Settings Functions concerned
All font information FONTLOAD(), FONTSELECT, SetFont()
All palette information. EGAPALETTE(), VGAPalette()
Border attribute CA-Clipper: SET COLOR TO
Notes
■ No ROM fonts exist for screen modes that are not based on 8,
14 or 16 pixels. You cannot implement FONTRESET() in this situation.
Examples
Reset all changes to fonts and palettes:
? FONTRESET() // .T., if ok
cFontstring[@] Designates the font in character string form, within which the characters are rotated or mirrored.
nTurnDirection Designates the rotation axis or rotation direction in numeric form with a value from 1 to 3 (see Description).
nPixelHeight Designates the accompanying pixel height and number of bytes that represent an individual character within a font string. This is only necessary for modes 1 and 3.
nStart (This is for only for mode 1.) Designates from which pixel line (from which byte), the 8 bytes are rotated. Based on nPixelHeight, the bytes before and after this range are deleted (set to 0). The first byte of the character corresponds to the 0 value.
Returns
If CSetRef() is not implemented, FONTROTATE() returns an amended font string.
Description
FONTROTATE() rotates the characters within a font string in different directions. Rotation direction affects the number of characters that can rotate.
Constructing Fonts
If a font is transferred to a string with GETFONT() and the same number of bytes are used for an individual character each time, as specified by the current font height from CharPix(). For example, if a 14-pixel font is installed, then the font string contains 256 groups of 14 bytes. Each of these bytes represents a horizontal pixel line. Since the characters are always 8 pixels wide, one bit always represents this pixel.
Direction of Rotation 1
If a font uses GETFONT() to transfer a string, then a comparable number of bytes are used each time for an individual character, as specified by the current font height in CharPix(). Since only an 8-pixel width is ever available, only 8 bytes are rotated for each character every time. To determine these bytes, you must designate the pixel height nPixelheight and the start of the 8-byte area
nStart . All bytes above and below the rotation are cleared (set to
0). The rotation point is determined by the computation nStart + 4.
Direction of Rotation 2
In this mode, the characters are rotated 180 degrees on the vertical axis (the Y-axis), and thereby mirrored. The nPixelheight and nStart parameters are unnecessary, since only the bits in each byte are mirrored.
Direction of Rotation 3
In this mode, the characters are rotated 180 degrees on the horizontal axis (X-axis), and thereby mirrored in the other direction. You must specify the nPixelheight parameter. The nStart parameter is not needed, since the character is affected through its entire height.
Combinations
Since modes 1 to 3 support all three rotation directions, multiple function calls allow you to combine the rotation operations and create rotated and mirrored characters.
Notes
■ The entire string is always worked on. If you only want to
change a region of characters on the screen, it can be done easily and is regulated by the SetFont() optional parameter, when you write the font back to the screen adapter.
■ If the parameter is passed by reference, use CSetRef() to
suppress the return value and increase the speed.
Examples
In the following example, the screen is first filled with characters and
then rotated. This is particularly useful in the VGA 50-line mode,
since it has an 8 x 8 pixel matrix and none of the characters are cut
off.
All parameters for FONTROTATE() are designated in such a generalized
manner that you can use them for other pixel relationships.
CSetRef(.T.) // Optimize by reference method
nMODE := GETSCRMODE() // Save old mode
VGA50()
FOR I := 0 TO MaxRow() // Build screen
@ I, 0 SAY Center("ABCDEFGHIJKLMNOPQRSTUVWXYZ- 1234567890")
NEXT I
nPixel := CharPix() // Determine font pixel count
cFont := GETFONT() // Load font to variable
nKey := 0
DO WHILE Key <<>> 27
Millisec(100) // Time delay
FONTROTATE(@cFont, 1, nPixel, (nPixel-8)/2)
SetFont(cFont)
nKey := Inkey()
ENDDO
SETSCRMODE(nMODE) // Reset to original mode
RETURN
nFontArea Designates which font area the normal output mode should use.
nIntensiveFontArea Designates which font area the higher- intensity output mode should use. The default is nFontArea.
Returns
FONTSELECT() returns an error code with the following meaning:
Table 6-3: Error code definitions
Code Definition
0 Font loaded successfully
-1 Invalid font area specified
-2 Impossible in current video mode
Description
This function selects the font areas for both normal output and higher- intensity output. Use SET COLOR TO with "+", to bring up to 512 different characters to the screen at the same time. The second font is displayed at a higher intensity. If this is not what you want, you can change the display (not the attribute itself) with EGAPALETTE()/VGAPalette(). The system is preset for both output modes and corresponds to a call of FONTSELECT(1, 1).
Notes
■ After you change the video mode with SETSCRMODE(), the fonts
must be re-selected.
Examples
■ Show font area 1 with normal output and area 4 with high
intensity:
? FONTSELECT(1, 4) // 0 OK
SET COLOR TO W
? "Nantucket" // Output over font 1
SET COLOR TO W+ // Output over font 4
■ Show font area 2 for both output modes:
? FONTSELECT(2)
nFloatingPointNumber Designate any CA-Clipper number.
Returns
FToC() returns an 8-byte character string.
Description
CA-Clipper internal numbers are displayed as 64-bit floating point numbers. FToC() returns these 64 bits as an 8-byte string. In this way, numbers can be locked and/or saved more compactly.
Notes
■ The XToC() function converts floating point numbers in the
same way.
Examples
It is not useful to display the return value on the screen:
NumberString := FToC(274711.335) // 8 byte string
nInstall Designates the installment amount to pay for the period.
nInterestRate Designates the interest rate calculated for the payment period. 1 corresponds to 100%.
nNumberofPayments Designates the number of payments.
Returns
FV() returns the future capital value of the total deposits, plus the interest generated.
Description
FUTURE VALUEFV() returns the capital available after the nNumberofPayments total installments at nInstall payment, at an nInterestRate interest charge for the period.
Examples
What amount would you save, if you pay $150.00 per month for 3 years
into a fund that pays an annual interest rate of 6%?
nRate : 0.06/12 // Monthly interest rate
? FV(150, nRate, 36) // Result: 5900.42
Queries the current attribute for the clearing functions
Syntax
GetClearA() → nClearAttribute
Returns
GetClearA() returns the value of the current standard attribute.
Description
GET CLEAR (A)ttribute This function determines the standard attribute for some CA-Clipper Tools functions with screen output. In this discussion, the attribute is referred to as CLEARA and the character as CLEARB. GetClearA() queries the current standard attribute.
Notes
■ The standard attribute is 7 (white on black), if no other
Queries the default character for the clearing functions
Syntax
GetClearB() → nClearCharacter
Returns
GetClearB() returns the value of the current standard character CLEARB.
Description
GET CLEAR (B)yte This function determines the standard character for some CA-Clipper Tools functions with screen output. In this discussion, the attribute is referred to as CLEARA and the character as CLEARB. GetClearB() queries the current standard character set as CLEARB.
Notes
■ The standard character is Chr(255) when no other character is
nField Designates the number of the GET field for which the screen column is determined. The default is the currently active field.
Returns
GetFldCol() returns the screen column for the first position of the currently active or the specified field. If there is an invalid parameter, a value of -1 is returned.
Description
GET FIELD COLUMN This function determines the first column of an input field. If the nField parameter is not specified, the function returns the column for the currently active field. With an invalid field number or in a situation where there is no active field, a value of -1 is returned.
Examples
■ Display the screen column for the second posted GET:
@ 10, 10 GET....
@ 10, 20 GET....
@ 10, 30 GET.....
? GetFldCol(2) // Result: 20
■ Display the column for the currently active GET field:
READ // Assuming field 1 is active
Within a UDF or KEYTRAP procedure:
? GetFldCol() // Result: 10
nField Designates the number of the GET field for which the screen is determined. The default is the currently active field.
Returns
GetFldRow() returns the screen row for the first position of the currently active or specified field. If there is an invalid parameter a value of -1 is returned.
Description
GET FIELD ROW This function determines the first row of an input field. If the nField parameter is not specified, the function returns the row for the currently active field. When nField is an invalid field number or if there are no active GET fields, a value of -1 is returned.
Examples
■ Display the row for the second posted GET:
@ 10, 10 GET....
@ 11, 20 GET....
@ 12, 30 GET.....
? GetFldRow(2) // Result: 11
READ // Assuming field 1 is active
? GetFldRow() // Result: 10
nField Designates for which number of the GET field to determine the name of the accompanying variable. The default is the currently active field.
Returns
GetFldVar() returns the name for the first position of the currently active or specified field. If there is an invalid parameter, a value of -1 is returned.
Description
GET FIELD VARIABLE This function determines the name of an input field. If the nField parameter is not specified, the function returns the name for the currently active field. With an invalid field number or if there is on active field, a value of -1 is returned
Examples
■ Display the name of the variable associated with the second
posted GET:
@ 10, 10 GET VAR1
@ 10, 20 GET VAR2
@ 10, 30 GET VAR3
? GetFldVar(2) // "VAR2"
■ Display the name for the active field:
READ // Assuming field 1 is active
? GetFldVar() // "VAR1"
■ Within a UDF or KEYTRAP procedure:
? GetFldVar() // "VAR1"
cDefault Designates the content and length of the input field.
nRow Designates the row in which the input occurs. The default is the current cursor position.
nColumn Designates the column in which the input occurs. The default is the current cursor position.
lSAY When you specify .T. and close GetInput(), the actual data input is displayed with the standard color attribute.
cPrompt Designates text to display in front of the input field at the selected coordinates. The default is no prompt text.
Returns
GetInput() returns the input string.
Description
If you call this function, a simple input field is made available. All control keys are interpreted exactly as in a CA-Clipper GET mask. The length and default for the string are specified in the cDefault parameter. This allows you to portray a normal input field with VAR= Space(length). The input field starts at the current cursor position or at the designated row and column. Similar to @ ... SAY...GET, you can also display text just before the input text. The field starting position is moved accordingly.
In the CA-Clipper SET COLOR TO command, the first color you designate stands for screen output; the second for input fields. GetInput() uses these color designators exactly like CA-Clipper. If you designate the lSAY parameter as .T., you can determine (as with a SAY), whether to redisplay the data in its amended form at the point of input. After data input is complete, the data displayed on the screen is the same as the values returned by the function. This is useful when an input breaks off due to an ESC. For example, the data is "the quick brown fox" and you change it to "the slow brown fox". If lSAY is .T. and you press escape, the original data (the quick brown fox) is restored. The affected area also contains the default color attribute.
Notes
■ GetInput() uses the CA-Clipper console input internal routines
and supports the INS display in SCOREBOARD. In addition, the SET ESCAPE, SET BELL, SET INTENSITY, SET DELIMITERS, and SET CONFIRM switches are acknowledged.
■ Key traps may occur within GetInput() when the cursor position
within a field is saved. GetInput() is then called recursively, as long as sufficient stack memory is available.
Examples
■ Input at the current cursor position:
cVar := Space(20) // 20 position input field
cVar := GetInput(cVar) // Retain input attribute
■ Input a 10 space field, row 10, column 20:
cVar := GetInput(Space(10), 10, 20)
■ After input is finished, the actual data input is redisplayed
on the screen. This area contains the standard color attribute. The
input is moved by the text preceding the input field:
SET CONFIRM ON // Close with RETURN
cVAR := "Default text"
GetInput(cVar, 10, 20, .T., "Please input: ")
nKeyValue Designates the original key code so that its current value can be tested for translation or lock out.
Returns
GetKXLat() returns the status of the key designated by nKeyValue. A return value of 0 indicates that there is no translation. A return value of -1 indicates that the key is locked out. And any other return indicates that the designated key is translated into that key value.
With Chr(NumLow(nkeyValue)) + Chr(NumHigh(nkeyValue)) the return value can be converted to the form used in the include file ctscan.ch
Description
GetKXLat() allows you to test to see if a key designated under SetKXLat() has been locked out or translated. nKeyValue is the original key code. The key codes used are described in detail in the SetKXLat() function.
Notes
■ Symbolic constants for key codes can be found in the ctscan.ch
file.
■ You can also use the symbolic constants from the CA-Clipper
Has the "A" key been locked out or translated?
nVar := GetKXLat(KS_A)
IF nVar <> 0
* Undo translation/lock out for "A"
SetKXLat(KS_A) // "A" returns to "A"
ENDIF
GetKXTab() returns a character string that contains all of the previously defined key translations.
Description
A CA-Clipper Tools key table can be as large as the maximum allocatable string. The number of translations corresponds to:
((Memory(1) * 1024)/4),
where the required memory is allocated dynamically. The key code translations can be done through SetKXLat() or SetKXTab().
GetKXTab(), in contrast to GetKXLat(), always returns a table of all defined key code translations as a string. A translation table can then be saved in a variable and reset using SetKXTab().
Examples
Save the entire key table and reinstall it later:
cKXTab := GetKXTab()
DO KEYCHANGE
SetKXTab(cKXTab)
GetPrec() returns the level of precision currently installed for CA-Clipper Tools trigonometric functions. The value corresponds to the number of digits to the right of the decimal in the range of 1 to 16.
Description
GET PRECISIONGetPrec() queries the currently installed precision level for CA-Clipper Tools trigonometric functions. The returned value corresponds to the number of digits to the right of the decimal, that are being worked with. Although the default is 16, you can change this value with SetPrec().
Examples
What precision has been set?
? GetPrec() // e.g. 10
cDefault Designates the length and contents of the input field.
nRow Designates the row in which the input occurs. The default is the current cursor position.
nColumn Designates the column in which the input occurs. The default is the current cursor position.
lSAY When you specify .T. and close GetSecret(), the actual data input is displayed with the default color attribute.
cPrompt Designates the text to display in front of the input field at the selected coordinates.
Returns
GetSecret() returns the input string.
Description
If you call this function, a simple input field is made available. All characters input are displayed as asterisks (*) to hide the actual input. All control keys are interpreted exactly as in a CA-Clipper GET mask.
The length and default for the string are specified in the cDefault parameter. This allows a normal input field to be portrayed with VAR = Space(length). The input field starts at the current cursor position or at the designated row and column.
Similar to @ ... SAY ... GET, you can also display text just before the input field. The field starting position is moved accordingly
In the CA-Clipper SET COLOR TO command, the first color you designate is used for screen output; the second for input fields. GetSecret() uses these color designators exactly like CA- Clipper. If you designate the lSAY parameter as .T., you can determine (as with a SAY), whether the data is redisplayed in its amended form at the point of input. However, GetSecret() only displays asterisks to hide this data. This is useful when input breaks off due to an ESC, because at least the correct number of asterisks is displayed. The affected area also contains the standard color attribute.
Notes
■ GetSecret() uses the CA-Clipper console input internal
routines and supports the INS display in SCOREBOARD. In addition, the SET ESCAPE, SET BELL, SET INTENSITY, SET DELIMITERS, and SET CONFIRM switches are acknowledged.
■ Key traps may occur with GetSecret() when the cursor position
within a field is saved. You can then call GetSecret() recursively, as long as sufficient stack memory is available.
Examples
■ Show the secret field at the current cursor position:
cVar:= Space(20) // 20 position secret field
cVar:= GetSecret(cVar) // Retain input attribute
■ Show the secret a 10-space field, row 10, column 20:
cVar:= GetSecret(Space(10), 10, 20)
■ After input is finished, the actual data input is redisplayed
on the screen. This area contains the standard color attribute. The
input is moved by the text preceding the input field:
SET CONFIRM ON // Close with RETURN
cVar:= "Default text"
GetSecret(cVar, 10, 20, .T., "Please input: ")
GETBOXGROW() returns the value set in SETBOXGROW() for the delay in creating a box.
Description
GETBOXGROW() retrieves the time delay that a box in "grow" mode has when it is opened.
Examples
Here is an example of a box with 10 milliseconds between each growth
step:
SETBOXGROW(10)
WOpen(2, 2, 23, 78) // Sets box coordinates only
WBox() // Generates box with delay
? GETBOXGROW() // Result: 10
GETCURSOR([<lMode>]) → nCursorForm
* This function has been retained for compatibility reasons only.
Its use in development of future applications is not recommended.
For future applications use the SetCursor() function.
Arguments
lMode Sets the cursor form to the overwrite (.F.) or the insert (.T.) mode. The default value (.F.) sets the cursor form to the overwrite mode.
Returns
The returned value designates how many scan lines are used to display the cursor.
Description
GETCURSOR() allows you to save the current cursor form for an input field in a function called with a VALID, before you change it in a UDF. GETCURSOR() then allows you to restore its old form before returning to the GET field.
CA-Clipper Tools stores the form for two cursor displays: one for overwriting and one for inserting. If lMode is .F. or omitted, then the overwrite cursor form is returned. If lMode is .T., then the insert cursor form is returned. (See the note with SetCursor()).
The cursor is broken down into lines on the screen called scan lines. The form and height of the cursor are specified by two instructions that correspond to the first and the last line used for the cursor display. GETCURSOR() returns both numbers combined into one value, according to the following formula:
(Starting Line * 256) + Final Line
The NumHigh() and NumLow() functions let you separate the starting and final lines very easily.
Notes
■ The word "line" here does not mean a screen (output) line, but
the scan or pixel lines from which screen characters are created.
■ This function works independently of the SET CURSOR setting.
Examples
Break down cursor information into a starting line and a final line:
nCursor := GETCURSOR()
? NumHigh(nCursor) // Cursor start line
? NumLow(nCursor) // Cursor final line
GETMODE() returns a character string that represents the active mode. The character string corresponds to the CA-Clipper Tools function call used to switch to that mode.
Description
This function substitutes for a difficult to understand numeric code for the return value of a function. This character string corresponds to the function call used to switch to the current mode. The returned value can be held in a variable, and this function can be called later using the compile and run operator.
Notes
Important! You must declare all function calls for setting a mode which could occur as a return value from this function as EXTERNAL.
Examples
Notice the mode and reset it later:
cVar := GETMODE() // Save current mode
? cVar // For example "CGA80(.T.)"
CGA40(.T.) // Select other mode
? &(cVar) // Reset old mode.
lHiddenPage Designates an optional parameter. If this parameter is .T., the function returns the number of the currently hidden page. If this parameter is .F., the function returns the number of the visible screen page. The default value is .F..
Returns
GETPAGE() returns the number of the currently set screen pages.
Description
GETPAGE() allows you to determine which screen page is currently available. The screen page that is currently available can be switched by using the SETPAGE() function.
Since screen output can be directed to a hidden screen page, you can determine the number of this hidden page by setting the parameter to .T.
Examples
Determine the active screen page:
? GETPAGE() // i.e. 2
GETPBIOS() returns the setting made in SETPBIOS() as a numeric value between 0 and 3.
Description
This function allows you to determine the current setting for rerouting the printer through extended drivers. If the function returns a value of 0, the print output is through DOS. If the value is between 1 and 3, the output is through the BIOS on the corresponding printer.
Examples
Determine the current setting:
? GETPBIOS() // 0 Output via DOS
GETPXLAT() returns the entire print table or returns an empty character string if a print table has not been defined.
Description
GETPXLAT() retrieves the current printer table set by SETPXLAT(). The string returned can be assigned to a variable and restored later. If you use a printer with different font styles, this function allows you to switch print tables as required.
Examples
■ Save the existing table:
cOldTab := GETPXLAT()
■ Install new table:
SETPXLAT(......)
SETPXLAT(......)
SETPXLAT(......)
■ Output to another printer:
SET PRINTER TO LPT2
■ Restore the old table starting at position 0:
SETPXLAT(0, cOldTab)
The function returns the mode number of the currently set video mode.
Description
In contrast to GETMODE(), GETSCRMODE() returns the current video mode as a numeric value. This allows you to query special modes for particular screen adapters and reset them using SETSCRMODE(). The following modes are accommodated by other functions within CA-Clipper Tools:
Table 2-1: Modes and Their Coding
Mode Mode Number
CGA40 Monochrome 0
CGA40 Color 1
CGA80 Monochrome 2
CGA80 Color 3
Monochrome 7
EGA43 (EGA only) 299 (43+256)
VGA28 (VGA only) 284 (28+256)
VGA50 (VGA only) 306 (50+256)
Notes
■ GETSCRMODE() returns the value previously set with
SETSCRMODE() and the current BIOS or CA-Clipper Tools mode. If you switch into a special mode for a particular screen adapter, there is no guarantee that this is the mode number that GETSCRMODE() returns. This is a factor of the unique behavior of the specific screen adapter.
Examples
■ Set the EGA 43-line mode:
EGA43()
■ The current video mode is saved:
nOldMode := GETSCRMODE()
■ The current video mode is restored later:
SETSCRMODE(nOldMode)
Queries screen output that was redirected by SETSCRSTR()
Syntax
GETSCRSTR() → cHiddenCharacterstring
Returns
GETSCRSTR() returns the content of the internal memory area determined by SETSCRSTR().
Description
GETSCRSTR() returns the contents of the internal memory area (determined by SETSCRSTR(.T.)) for hidden screen output . This return value has a length that always corresponds to SCREENSIZE(.T.). You can pass it to a variable and after the mode is switched off, transfer it to the CA- Clipper RestScreen() function. The variable must be passed before the redirected output mode is shut off with SETSCRSTR(.F.). Otherwise, the internal memory area is deallocated and GETSCRSTR() returns a null string.
Notes
■ Since the entire screen output is always redirected
(independent of its actual size), you should always call RestScreen() with the maximum coordinates of 0, 0, MaxRow(), and MaxCol()
Examples
■ Show hidden output, switched back to the physical screen, if
the need should arise:
WSelect(0)
? SETSCRSTR(.T.) // .T., when mode on
@ 10, 10 SAY "XXXXXXX" // Normal screen output
*...
@ 15, 10 SAY "YYYYYYY"
■ Always call the GETSCRSTR() function before SETSCRSTR(.F.)
cVar := GETSCRSTR()
? SETSCRSTR(.F.) // .F. when mode off
RestScreen(0, 0, MaxRow(), MaxCol(), cVar)
GETTAB() returns the currently installed tab locations for CA-Clipper screen output in the form of a character string.
Description
This function gives the tab definitions specified in SETTAB() for CA-Clipper screen output. You can use this function to save the active tab definitions.
GETTIC() returns the number of timer ticks executed since the last SETTIC (.T.).
Description
Use this function in conjunction with SETTIC(). At any given time, it returns the number of completed timer ticks since the timer was set in motion (by calling SETTIC(.T.)).
Examples
An individual UDF is to be measured in ticks. The tick rate counter is
started with the SETTIC(.T.) call, then stopped after execution of the
UDF (by passing .F. to SETTIC()) and the number of completed ticks is
queried:
SETTIC(.T.)
MY_UDF(I)
SETTIC(.F.)
? " Required ticks:", GETTIC()
nColor|cColor Designates a color represented by a number in the range of 0 to 15, or a color code that corresponds to the one in SET COLOR TO.
cRGB May designate as R, G, or B to determine the corresponding palette value.
Returns
GETVGAPAL() returns the red, green, or blue palette value for the designated color. When invalid paramerters are specified, a value of -1 is returned.
Description
On a VGA adapter, each color is a combination of the three values for red, green and blue. Each value can be in the range of 0 to 63, to permit you to install different color palettes.
GETVGAPAL() queries the R, G, and B values for all 16 colors. The individual color can be a number in the range of 0 to 15, or represented as a color code corresponding to the CA-Clipper SET COLOR TO.
Notes
■ This function is implemented in the enclosed Colorpal.prg
program.
Examples
Determines the palette value of red in the color cyan:
GETVGAPAL("BG", "R")
Converts a hexadecimal string into a byte sequence
Syntax
HexToStr(<cHex>) → cBytes
Netware: 2.2 and 3.11
Arguments
cHex Designates a character string of which two characters are recognized as a hexadecimal form of a byte. cHex can contain only the characters "0" to "9" and "A" to "F".
Returns
HexToStr() returns a character string that contains a byte sequence in which each byte corresponds to two characters of its hexadecimal form. The return value is half as long as cHex.
Description
HexToStr() is useful when working with the internet addresses that are required in conjunction with the IPX/SPX functions of Point To Point communication.
Examples
Convert the hexadecimal string into a byte sequence:
? HexToStr('4130') // "A0"
nUnsigned|cHexUnsigned Designates either a numeric value or hexadecimal digit string to convert into a 16-bit or 32-bit signed integer.
32Bit If this optional parameter is designated as .T., the function processes the designated value as a 32-bit unsigned integer. The default value is a 16-bit unsigned integer (.F.).
Returns
IntNeg() returns a signed 16-bit or 32-bit integer.
Description
This function converts unsigned integers into signed integers.
All 16-bit or 32-bit integers are accepted, depending on whether there is a second parameter and the logical value is assigned. For the 16-bit variant, all values for nUnsigned|cHexUnsigned that are less than or equal to +32767 (hex=7FFF), are positive. Values in the range of +32768 (hex=8000) to +65535 (hex=FFFF), have a negative result. When you work with 32-bit values, the positive range goes to 2147483647 (inclusive). All values beyond that are negative.
Notes
■ The function returns a value of 0 for invalid, too large, or
nUnsigned|cHexUnsigned Designates either a numeric value or hexadecimal digit string to convert into a 16-bit or 32-bit unsigned integer.
l32Bit If this optional parameter is designated as .T., the function processes the designated value as a 32-bit signed integer. The default value is a 16-bit signed integer (.F.).
Returns
IntPos() returns an unsigned 16-bit or 32-bit integer.
Description
This function converts signed 16-bit or 32-bit integers into the corresponding unsigned number. Based on the optional parameter and the logical value it is assigned, you can work with 16-bit or 32-bit values.
For the 16-bit variant, all values in the 0 to 32767 range are unchanged. However, all negative values from -1 to -32768 are changed. When the optional parameter is designated as .T., the range of values stretches from -2147483648 to +2147483647.
Notes
■ This function returns a 0 result for invalid paramerters.
Examples
■ Show simple conversions:
? IntPos(-1) // 65535
? IntPos(-2) // 65534
? IntPos(30000) // 30000
? IntPos(60000) // 60000
Warning! When working with 16-bit values IntPos(0) = IntPos(65536):
? IntPos(0) // 0
? IntPos(65536) // 0
■ Show values larger than 65536 in 16-bit mode. For example,
the difference between 90000 and 65536 is 24464:
? IntPos(90000) // 24464
■ However, in 32-bit mode:
? IntPos(90000, .T.) // 90000
? IntPos(-1, .T.) // 4294967295
// (largest 32-bit number)
? IntPos(-60000, .T.) // 4294907296
? IntPos(-90000, .T.) // 4294877296
Inverts the foreground and background of an attribute
Syntax
InvertAttr(<cAttr|nAttr>) → nInvertAttr
Arguments
cAttr|nAttr Designates the attribute to process.
Returns
InvertAttr() returns the value of the inverted attribute.
Description
InvertAttr() returns a value that corresponds to the opposite of an individual screen attribute. This is same as if you were to exchange the foreground color for the background. For example, red characters on a white background, become white characters on a red background.
■ The flashing and high-intensity attributes are not affected.
■ The result is always numeric, regardless of the parameter's
data type.
Examples
■ Invert the attributes at the current cursor position. In
doing so, the attribute is not set:
? INVERATTR(ScreenAttr())
■ You can represent the attribute in a number of different ways.
The returned value is always numeric:
8 // Result: 30
■ An invalid attribute:
? InvertAttr("xx/yy") // Result: 0
nPort|cHexPort Designates a port address from which a byte is read. This value can be a decimal integer or hexadecimal string.
Returns
INBYTE() returns the byte read from the specified port; or a value of - 1, if a parameter error occurs.
Description
CA-Clipper Tools always attempts to offer finished solutions at the highest-possible level for such standared hardware as a serial interface port. However, if you read a highly specialized systems and their ports from CA-Clipper, use INBYTE() or INWORD().
Notes
■ A random return value is produced for a nonexistent port or
one that cannot be read.
Examples
These examples read the first port address of the first serial interface
port. This is only an example, since the CA-Clipper Tools contains
special port functions.
■ With a decimal parameter:
? INBYTE(1016) // 1st Port (COM1)
■ With a hexadecimal parameter:
? INBYTE("3F8") // Also 1st Port (COM1)
The function returns the same key code as Inkey().
Description
This function operates in essentially the same way as Inkey(). It supports the same time delays and returns the same key codes as values. The most significant difference to Inkey() is that all key traps defined using SET KEYKeyTOProcedure are supported. This function saves the programmer time; for example, the programmer does not have to develop extensive CASE constructs after each Inkey().
Notes
■ After the trap procedure ends, the nDelay time is reset.
Examples
SET KEY 28 TO HELP // F1 Key
nVar := INKEYTRAP(10) // 10-second delay
RETURN
PROCEDURE Help(a, b, c) // Parameter c is always
// a null string
("")
* Program code desired
RETURN
Determines the previously active or the currently active input mode
Syntax
INPUTMODE([<lActiveMode>]) → nInputMode
Arguments
lActiveMode Designates an optional parameter. If this parameter is .T., the function returns the currently active mode.
Returns
INPUTMODE() returns a numeric value that indicates the input command for the previously active or the currently active input mode.
Description
INPUTMODE() allows you to determine what type of input command has been interrupted. When called without a parameter or with .F., the function returns the currently active mode or, if no input has occurred, the previously active input mode.
If the function is called with lActiveMode set to .T., then only the currently active input mode or 0 is returned. The following table shows the return values as well as the symbolic constants and their accompanying definitions.
Table 2-2 Coding the Input Mode
Return Symbolic Const. Definition
0 IMODE_NO No input command currently.
1 IMODE_WAIT WAIT
2 IMODE_ACCEPT ACCEPT
3 IMODE_INPUT INPUT
4 IMODE_READ READ
5 IMODE_MEMOEDIT MemoEdit()
6 IMODE_MENU MENU
7 IMODE_INKEY Inkey()
8 IMODE_DEBUG Debugger input
9 IMODE_GETINPUT Input within GetInput()
10 IMODE_GETSECRET Input within GetSecret()
Examples
PROCEDURE HELP(A, B, C)
nArea := Select()
nMode := INPUTMODE()
IF nMode = 5 // Calling from MemoEdit()
SELECT MEMOHELP
ELSE
SELECT HELP
ENDIF
SELECT (nArea)
RETURN
nPort|cHexPort Designates a port address from which a word with a 16-bit value is read. This value can be a decimal integer or hexadecimal string.
Returns
INWORD() returns the word read from the designated port, or a value of - 1 when an error occurs.
Description
CA-Clipper Tools always attempts to offer finished solutions at the highest-possible level for such standard hardware as a serial interface port. However, if you read highly specialized systems and their ports from CA-Clipper, use INBYTE() or INWORD(). INWORD() allows you to read from interfaces that return the data from a port as a 16-bit value.
Notes
■ A returns random value for a nonexistent port or one that
cannot be read.
Examples
Show a read from a 16-bit port:
■ With a decimal parameter:
? INWORD(512) // Read from an additional device
■ With a hexadecimal parameter:
? INWORD("200") // The same port address
Determines the error code of the last IPX/SPX call
Syntax
IPXERROR() → nErrorCode
Netware: 2.2 and 3.11
Returns
IPXERROR() returns the error code of the previous IPX/SPX call by a CA-Clipper Tools function. There is a table containing the error codes in Appendix D.
Description
IPXERROR() allows you to locate the source of an error that occurred during the execution of a CA-Clipper Tools function for IPX/SPX communication (for example IPXOPEN() or SPXESTBCON()). If the IPX/SPX call has been terminated without an error, IPXERROR() returns 0.
IPXERROR() returns an error code that is the direct result of an IPX/SPX call. If the IPX/SPX call initiates the interrupt controlled receiving of a packet, the error code cannot return any information about the success or failure of the receiving process. You can use the PPCRECERR() and PPCSNDERR() functions to determine this information.
Examples
Open the socket. If an error occurs, determine the reason for the
error:
IF OPENSOCK(20000)=0 // Error?
IF IPXERROR()=254
? 'Local socket table full!'
ENDIF
ENDIF
IPXOPEN(<nSourceSocket>,[<nRecBuffer>],
[[<nSendBuffer>],[<cTargetAddr>]],
[<nTargetSocket>],[<nPacket>],[<lHeader>])
→ nHandle
Netware: 2.2 and 3.11
Arguments
nSourceSocket Designates the number of the communication's source socket.
nRecBuffer Designates the selected size of the receiving buffer. If no value is passed for nRecBuffer, no receiving buffer is established. The minimum size of the receiving buffer is nPacket. If the value for nRecBuffer is too small, it is changed automatically by IPXOPEN(). The maximum size of the receiving buffer is 64 KByte.
nSendBuffer Designates the selected size of the sending buffer. If no value is passed for nSendBuffer, no sending buffer is established. The minimum size of the sending buffer is nPacket. If the value for nSendBuffer is too small, it is changed automatically by IPXOPEN(). The maximum size of the sending buffer is 64 KByte.
cTargetAddr Designates the target address for the sending operations. The target address is a 20-character string that represents a 10-character hexadecimal byte sequence. The leading eight characters of cTargetAddr specify the network number of the target. The following 12 characters contain the station ID of the target station (node address). cTargetAddr is mandatory to establish a sending buffer.
nTargetSocket Designates the number of the communication's target socket. The default value is nSourceSocket.
nPacket Designates the packet size in bytes of the data that is sent. The packet size can be between 1 and 546 bytes. Values outside this range are changed automatically. The default value is 546 Bytes.
lHeader Designates whether the data and the header (.T.), or the data (.F.) alone, are transmitted to the receiving buffer.
Returns
If an operation is successful, IPXOPEN() returns a communication handle. The return value contains a numeric value that is greater than 0. You should store the handle in a variable because all further operations that refer to an established buffer require a communication handle. If an error occurs, the function returns 0.
Description
IPXOPEN() allows you to establish a communication buffer for an IPX communication with other workstations in the network. The communication buffer can contain a sending and receiving buffer through which data is processed.
nSourceSocket is the socket address of the process that transmits the data (see the Introduction to this chapter). The socket can be opened with the function OPENSOCK() before the call of IPXOPEN(). If nSourceSocket has not been opened, it is automatically opened by IPXOPEN(). If nSourceSocket is passed with 0, IPXOPEN() opens an available socket.
The parameters nRecBuffer and nSendBuffer determine the size of the receiving and sending buffers. The buffers are automatically designed for one IPX packet. Each buffer can be up to 64 KByte. However, the size of the buffer that is allocated by IPXOPEN() depends on the application and the configuration of the computer used.
The parameter cTargetAddr is mandatory to establish a sending buffer. All following sending operations are addressed to cTargetAddr. Remember that an IPX communication is implemented as a pseudo Point-To- Point communication. Data is received by any station addressed to the current workstation but is sent only to a defined target address. The target address must be passed as a 20- character string (for example, "4921750400001B025A99"), where two characters represent one byte in hexadecimal code.
If the current workstation is logged in to a Netware server, the destination's network address can be determined with NNETADR() , using the user name. However, the target workstation must be logged in. Under Netware Lite, the leading eight characters of cTargetAddr must be passed with 0. A character string consisting of "FFFFFFFFFFFFFFFFFFFF" specifies all stations within an internal network as the target address (broadcast packages).
nTargetSocket allows you to determine the communication's target socket. The default value is nSourceSocket.
nPacket determines the maximum size of the data range of the IPX packets that are sent or received. The maximum value (and the default value) is 564 bytes. The value of nPacket is also valid for sending data.
With lHeader you can determine if the header (30 bytes) of an IPX packet is transmitted to the receiving buffer. The header can contain important information about the received packet. For a description about the header structure, see the Introduction to this chapter.
If the buffer has been established successfully, IPXOPEN() returns an integer value that is greater than 0, called a communication handle. If a value has been passed for nRecBuffer, IPXOPEN() initiates an interrupt controlled receiving mechanism that receives incoming packets in the background and then copies to an receiving buffer. The data can then be read with the PPCREAD() function within a CA-Clipper application. If the receiving buffer is full, incoming data is discarded without notifying the sender. Data should be removed from the receiving buffer and processed as soon as possible. You should either read the contents of the buffer periodically (polling) or supervise the buffer on an event-oriented basis: for example, with the function PPCKEY().
Notes
■ IPX is a protocol that is not based on a connection. There is
no guarantee or verification of a successful delivery to the target workstation. The implementation of specific protocols with the aid of CA-Clipper Tools functions can be necessary. (For your information: Netware usually uses IPX communication, and Netware Lite exclusively uses IPX communication, which is now available under CA-Clipper with the IPXOPEN() function.)
■ Several communication buffers can be established for one
source socket. However, you cannot know when you establish the communication buffers how the data will be distributed to the receiving buffers.
■ Network addresses can be determined under Netware with
"USERLIST /A", and under Netware Lite with "NET ULIST".
Examples
■ Open the 5 KByte IPX receiving buffer for socket 20000:
nHandle=IPXOPEN(20000,5120)
IF nHandle=0
? 'Buffer could not be established!'
ENDIF
■ Open the 2 KByte IPX sending buffer for socket 20000. The
target address is "4921750400001B025A99":
nHandle=IPXOPEN(20000,,2048,"4921750400001B025A99")
■ Open the 1 KByte IPX sending and receiving buffer for socket
20000. The target address is the first workstation where user MIKE
is currently logged in:
nHandle=IPXOPEN(20000,1024,1024,NNETADR("MIKE"))
■ For this example, the current workstation must be logged into
a file server. As NNETADR() is based on Netware-API, this call
cannot be used under Netware Lite.
IsAt() returns .T. value when the program is running on an AT-compatible system.
Description
IsAt() determines if your CA-Clipper application is running on an AT-class system.
Notes
■ The function also returns .T. for systems with an 80386 or
80486 processor.
Examples
Since you can set the hardware clock on an AT (in contrast to an XT),
use IsAt() to determine if SetDate() and SetTime() function properly:
IF IsAt()
? "The internal clock can be changed."
ELSE
? "Time and date will be lost after booting!"
ENDIF
Tests for presence of a CGA card or if one can be emulated
Syntax
IsCGA([<lMode>]) → lCGA
Arguments
lMode When designated as .T., tests to see if a CGA card is available. The default value of .F. tests to see if a CGA adapter can be emulated.
Returns
Depending on the lMode parameter, IsCGA() returns .T. when a CGA card is available, or if a CGA adapter can be emulated.
Description
You can determine two things with this function. When designated as .F. or when called without a parameter, IsCGA() tests it see if a CGA adapter can be emulated. This can be the case with an EGA or VGA card. When designated as .T., the function determines if a CGA card is available.
Notes
■ Use GETMODE() to determine which mode is active.
Examples
Can CGA be emulated?
IF IsCGA()
*...
ENDIF
CGA-Card?
IF IsCGA(.T.)
*...
ENDIF
Determines if an EGA card is present or can be emulated
Syntax
IsEGA([<lMode>]) → lEGA
Important! Contains <lMode>, an additional optional parameter over
and above the original CA-Clipper Tools.
Arguments
lMode When designated as .T., determines if an EGA card is present. The default value of .F. tests to see if an EGA adapter can be emulated.
Returns
In conjunction with the lMode parameter, IsEGA() returns .T. when an EGA card is present or an EGA adapter can be emulated.
Description
This function determines two things. When lMode is designated as .F. or the function is called without a parameter, IsEGA() determines if an EGA adapter can be emulated. This could be the case with a VGA card. When lMode is .T., it determines if an EGA card present.
Determines if a HERCULES card is present or can be emulated
Syntax
IsHercules([<lMode>]) → lHERCULES
Important! Contains <lMode>, an additional optional parameter over
and above the original CA-Clipper Tools.
Arguments
lMode When designated as .T., determines if a HERCULES card is present. The default value .F. tests to see if a Herculess adapter can be emulated.
Returns
In conjunction with the lMode parameter, IsHercules() returns a .T. when a HERCULES card is present or a HERCULES adapter can be emulated.
Description
This function determines two things. When lMode is designated as .F., or the function is called without parameter, IsHercules() determines if a HERCULES adapter can be emulated. This could be the case with a VGA or EGA card. When lMode is .T., it determines if there is a HERCULES card present.
Warning! Although our function implies it, not all EGA and VGA cards can emulate HERCULES. In most cases, a HERCULES emulation on a VGA card is possible , but it cannot be determined with absolute certainty. As long as the text is output under CA-Clipper, working with IsMono() should be sufficient
Examples
Can HERCULES be emulated?
If IsHercules()
* ...
ENDIF
HERCULES card?
IF IsHercules(.T.)
* ...
ENDIF
dDate Designates whether or not the specified date is in a leap year. The default is the system date.
Returns
IsLeap() returns .T. when dDate lies in a leap year; otherwise, it returns .F..
Description
A number of technical financial calculations need to know if a year has 365 or 366 days. IsLeap() determines this.
Notes
■ When parameters are missing, the function automatically uses
the system date. You must adhere to all rules for leap year tests. In the rare occurrence of a century change, the function also returns a correct result.
Examples
Determine if the following dates are in a leap year:
? IsLeap(CToD("01/01/1901")) // .F., No leap year
? IsLeap(CToD("09/30/1988")) // .T., leap year
? IsLeap(CToD("01/01/2000")) // .T., leap year
Determines if an MCGA card is present or can be emulated
Syntax
IsMCGA([<lMode>]) → lMCGA
Arguments
lMode When designated as .T. tests to see if an MCGA card is actually available. The default value of .F. tests to see if a monochrome adapter can be emulated.
Returns
Depending on the lMode parameter, the function returns .T. when a MCGA card is available or if an MCGA adapter can be emulated.
Description
You can determine two things with this function. When designated as .F. or when called without a parameter, IsMCGA() tests to see if a monochrome adapter can be emulated. This can happen with a HERCULES, EGA, or VGA card. When designated as .T., the function determines if a Monochrome card is available.
Determines if a monochrome card is present or can be emulated
Syntax
IsMono([<lMode>]) → lMonochrome
Arguments
lMode When designated as .T., tests to see if a monochrome card is available. The default value of .F. tests to see if a monochrome card can be emulated.
Returns
Depending on the lMode parameter, IsMono() returns .T. when a monochrome card is available, or if a monochrome adapter can be emulated.
Description
This function determines two things. When designated as .F. or when called without a parameter, IsMono() tests to see if a monochrome adapter can be emulated. This can be the case with a HERCULES, EGA, or VGA card. When designated as .T., the function determines if a monochrome card is available.
Determines if a PGA card is present or can be emulated
Syntax
IsPGA([<lMode>]) → lPGA
Arguments
lMode When designated as .T., tests to see if a PGA card is available. The default value of .F. tests to see if a PGA adapter can be emulated.
Returns
Depending upon the lMode parameter, IsPGA() returns .T. when a PGA card is available or if a PGA adapter can be emulated.
Description
This function can determine two things. When designated as. F. or when called without a parameter, IsPGA() tests to see if a PGA adapter can be emulated. This can be the case with an EGA or VGA card. When designated as .T., the function determines if a PGA card is actually available.
Tests to see if the ANSI screen driver is installed
Syntax
ISANSI() → lInstalledDriver
Returns
ISANSI() returns .T. when ANSI.SYS or a comparable driver has been loaded from CONFIG.SYS.
Description
ISANSI() determines if ANSI.SYS or another comparable driver has been loaded from CONFIG.SYS. Some full-page displays require the ANSI driver. If the driver is present, the display is fully operational.
Notes
Warning! You must implement DSETWINDOW(.F.) for ISANSI() to return a correct result.
Examples
If ANSI.SYS is present, output through DOS. This allows a simple
terminal emulation:
IF ISANSI() // ANSI driver present?
com_DosCon(dDate) // Output via DOS
ELSE
*... // Individual ANSI handling
ENDIF
ISDBT() returns .T., if a database has a memo file associated with it.
Description
ISDBT() determines if a database has a memo file associated with it, and allows you to compress that memo file.
Examples
If the database has a memo file, the database is copied to minimize the
memo file:
USE DATA
IF ISDBT()
COPY TO TEMP
CLOSE DATABASES
DeleteFile("DATA.DBF")
DeleteFile("DATA.DBT")
RenameFile("TEMP.DBF", "DATA.DBF")
RenameFile("TEMP.DBT", "DATA.DBT")
ENDIF
Determines if the debugger is available in the application
Syntax
ISDEBUG() → lDebugger
Returns
ISDEBUG() returns a value that signifies if the CA-Clipper debugger is available.
Description
This function determines if the debugger is available in an application. This enables a program to acknowledge this special situation and then conditionally execute or ignore portions of the program.
Notes
■ This is not a CA-Clipper switch. This information is provided
by CA-Clipper Tools.
Examples
Indicate if the debugger is active:
IF ISDEBUG()
? "The debugger is being used!"
ENDIF
ISIPX() returns .T. if IPX support is available. The IPX communication functions of CA-Clipper Tools can be used.
Description
ISIPX() allows you to check to see if IPX support is available. If it is not, an application can be terminated.
Examples
Check to see if IPX support is available. If it is not, terminate the
program:
IF ISIPX()
nHandle=IPXOPEN(20000,2000)
ELSE
? 'IPX support not available, load IPX.COM!'
QUIT
ENDIF
ISNETBIOS() returns .T. if NetBIOS support is available. If the function returns .T., the NetBIOS communication functions of CA-Clipper Tools can be used.
Description
ISNETBIOS() allows you to check to see if NetBIOS support is available. If it is not, an application can be terminated.
Examples
Check to see if NetBIOS support is available. If it is not, terminate
the program:
IF ISNETBIOS()
nHandle=NBDOPEN("STAT1",2000)
ELSE
? 'NetBIOS support not available!'
QUIT
ENDIF
ISSPX() returns .T. if SPX support is available. The SPX communication functions of CA-Clipper Tools can be used.
Description
ISSPX() allows you to check to see if SPX support is available. If it is not, an application can be terminated.
Examples
Check to see if SPX support is available. If it is not, terminate the
program:
IF ISSPX()
nHandle=SPXLISTCON(20000,2000)
ELSE
? 'SPX support not available, load IPX.COM!'
QUIT
ENDIF
cString [@] Designates the string that is processed.
cCharacter|nCharacter Designates the character that is moved from the beginning of the cString to the end. The default value is a space, Chr(32).
Returns
The processed cString is returned.
Description
JustLeft() moves the characters specified in cCharacter|nCharacter from the beginning of a character string to the end. Then the remaining text in the character string is left justified, without affecting the length.
Notes
■ If the cCharacter|nCharacter parameter is not specified,
spaces are automatically moved.
■ The return value for this function can be suppressed by
implementing CSetRef() to save room in working memory.
Examples
■ Move the blanks:
? JustLeft(" 123") // "123 "
■ Move the "." character:
? JustLeft("..123"," ".) // "123.."
cString [@] Designates the string that is processed.
cCharacter|nCharacter Designates the character that is moved from the end of the cString to the beginning. The default value is a space, Chr(32).
Returns
The processed cString is returned.
Description
JustRight() moves the characters specified in cCharacter| nCharacter from the end of a character string to the beginning. Then the remaining text in the character string is right justified, without affecting the length.
Notes
■ If the cCharacter|nCharacter parameter is not specified,
spaces are automatically moved.
■ The return value for this function can be suppressed by
implementing CSetRef() to save room in working memory.
Tests for key shift state status, such as Ctrl and Shift
Syntax
KbdStat() → nKeyStatus
Returns
KbdStat() returns a numeric code that corresponds to the status of certain keys.
Description
This function determines the status of all shift state keys (e.g., Ctrl, Shift or Alt, Scroll-Lock or Num-Lock). The information KDBSTAT() returns depends on the keyboard itself.
Table 13-5: Applies to all Keyboards
Bit Key
1 Right shift currently pressed
2 Left shift currently pressed
3 Ctrl currently pressed (left or right)
4 Alt currently pressed (Alt or Shift-Alt)
5 Scroll-Lock ON/OFF
6 Num-Lock ON/OFF
7 Caps-Lock ON/OFF
8 Insert ON/OFF
Notes
■ Since KbdStat() depends on the type of keyboard, use KBDTYPE()
to determine whether or not the left and right Ctrl or Alt keys are valid return values.
Examples
This example tests the Alt key. You could use it to display an
additional prompt menu when the Alt key is depressed:
IF IsBit(KBSTAT(), 4)
* . . .
ENDIF
lSwitch Designates whether the keyboard is switched on (.T.) or off (.F.).
Returns
KBDDISABLE() always returns a null string.
Description
With the help of this function, the keyboard can be turned on or off. This allows you to prevent any user input for a specific time through program control (even Ctrl-Alt-Del).
Notes
■ Be sure the program reenables the keyboard and does not leave
it locked when the program terminates.
Examples
Switch off the keyboard for 5 seconds:
KBDDISABLE(.F.) // Turn off keyboard
Inkey(5) // Can't be shortened by input!
KBDDISABLE(.T.) // Turn on keyboard
Inserts characters into the BIOS keyboard buffer to emulate keyboard input
Syntax
KBDEMULATE(<cListKeyValue>) → nValue
Arguments
cListKeyValue Designates a keyboard input sequence to emulate. Use a maximum of 15 characters.
Returns
KBDEMULATE() returns the number of key codes it could not place in the BIOS buffer.
Description
KBDEMULATE() emulates keyboard input at a very low level. This function uses the BIOS input buffer to emulate input. This emulated input can then be used by another program. For example, you might stuff the next DOS command prior to the end of the application. Keyboard input for programs that use RUN() to be called is also feasible. The buffer capacity is a maximum of 15 characters. Some of the key codes may vary from keyboard to keyboard, but they still correspond to the values returned by SCANKEY(). Construct the codes as follows:
Chr(ASCII code) + Chr(Scan code)
As a rule, a scan code that is transmitted this way cannot be acknowledged by CA-Clipper or any subsequent program. For example, a DOS command can be passed as a string with spaces at each even position. This emulation of a scan code with a value of 32, would only cause problems when a subsequent program also checks the scan code (see Examples on the next page).
Notes
■ You can find the symbolic constants for key codes in the
■ Problems may arise if you have incompatible hardware/BIOS, or
programs that extend the keyboard buffer.
■ Even though these emulated inputs occur at a low level, the
code translations defined with SetKXLat() still function.
Examples
■ These two programs always call each other reciprocally.
Before returning to DOS, each program wedges the keys necessary to
execute the other program in the BIOS buffer:
Program 1 (PROG1.EXE)
CLEAR
@ 10, 10 SAY "Here is program 1 !"
Inkey(5) // Wait a while...
KBDEMULATE("P R O G 2 " + Chr(13)) // Start PROG2 in DOS
RETURN
Program 2 (PROG2.EXE)
CLEAR
@ 10, 10 SAY "Here is program 2 !"
Inkey(5) // Wait a while...
KBDEMULATE("P R O G 1 " + Chr(13)) // Start PROG1 in DOS
RETURN
■ This program returns to DOS and then re-calls itself. In this
case, the desired extra byte is created with the Expand() function.
The last token in the full path is the EXE name which includes the
file extension. The first token is the file name:
xeName := TOKEN(ExeName(), ":\")
ExeName := TOKEN(ExeName, ".", 1)
KBDEMULATE(Expand(ExeName + Chr(13))) // Expansion with blanks
QUIT
■ The correct way to implement Expand():
* WRONG! No blank before Chr(13)
KBDEMULATE(Expand("TEST") + Chr(13))
* RIGHT! Blank before Chr(13)
KBDEMULATE(Expand("TEST" + Chr(13)))
KBDSPEED(<nDelay>,<nFrequency>) → lAmended
Warning! Use AT keyboards only.
Arguments
nDelay Designates the amount of delay before you begin auto repeat. Possible values are from 0 to 3. The default value is 1.
nFrequency Designates the number of times a character repeats per second. Possible values are from 0 to 31. The default value is 12.
Returns
KBDSPEED() returns .T. when a new repeat rate is set successfully.
Description
KBDSPEED() sets the auto repeat rate for AT keyboards. Both the time delay and repeat rate for auto repeat can be set. The table below provides the values, their corresponding times, and repeat rates:
Table 13-3: Auto Repeat Time Delay
<nDelay> Delay Time
0 250 millisecond
1 500 millisecond
2 750 millisecond
3 1000 millisecond
Table 13-4: Repeat Rate for Depressed Keys
<nFrequency> Repeat Rate
0 30 characters per second
12 10 characters per second
31 2 characters per second
Notes
■ It is best to determine valid values experimentally.
Examples
The quickest setting possible:
IF KBDTYPE() >0 // Only possible for AT's
KBDSPEED(0, 0)
ENDIF
KBDTYPE() returns a value that corresponds to the type of keyboard.
Description
KBDTYPE() determines the type of keyboard in use. This lets you check if the keyboard has F11/F12 keys available (which the CA-Clipper Tools supports). The possible keyboard values are:
Table 13-7: Coding of Keyboard Types
Value Keyboard Type
0 PC keyboard
1 AT keyboard
2 Extended keyboard w/101/102 keys, F11/F12
Notes
■ This function has been thoroughly tested, but there may be
problems with keyboards that are not fully compatible.
Examples
Query the keyboard:
? KBDTYPE() // 2 Extended keyboard
nKeyValue Designates the key code to place in the keyboard buffer.
nTime Designates the time, in seconds, after which the character is placed in the buffer. Negative values correspond to multiples of 1/18.2 seconds.
nCounter Designates the number of times the function occurs before it uninstalls itself. A value of -1 indicates that KeySec() will continue until it is specifically uninstalled. The default value is "Uninstall after the first call" (1).
lMode Designates whether the internal time counter restarts at the beginning (.T.) or not (.F.), after you press a desired key. The default value is "No new start with key stroke" (.F.).
() When called without parameters, the function is completely uninstalled.
Returns
KeySec() returns a value of .T. when installed correctly, so that the desired character will be placed in the keyboard buffer after the specified time.
Description
This function is useful in DEMO programs. If used in conjunction with KEYSEND(), you can simulate any keyboard input with time delays.
Use KeySec() in conjunction with CA-Clipper's SET KEY..TO, for key traps (just like KeyTime()). For example, this makes it possible to automatically write data still in the DOS buffer, to the hard drive at specific intervals during a GET..READ.
As soon as the character is placed in the keyboard buffer nCounter times, KeySec() uninstalls itself.
If the lMode parameter is specified as .T., the elapsed time counter is reset when you press any key.
If you want to specifically uninstall the function from the program, call it without parameters.
Notes
Warning! Always uninstall the function before you leave the program or use the CTUS.LIB Extended Drivers found in CA-Clipper Tools. The function changes interrupt vectors, and if the previous status is not restored before you exit the program, the system will eventually crash.
■ Only one time delay can be active. A new KeySec() deactivates
the previous one.
■ You can use any symbols defined in the CA-Clipper file
INKEY.CH. You can set any other keys described in the CA-Clipper Tools header file ctscan.ch.
Examples
■ Place Chr(7) in the keyboard buffer three times, every 5
seconds:
? KeySec(7, 5, 3) // (.T.)
■ Place Chr(255) in the keyboard buffer every 60 seconds until
an uninstall occurs:
? KeySec(255, 60, -1) // (.T.)
■ As soon as a key is pressed, the internal counter restarts
from the beginning:
? KeySec(13, 60, -1, .T.) // (.T.)
nKeyValue Designates the character to place in the keyboard buffer.
cClocktime Designates the specified time to place the character in the keyboard buffer.
() When called without parameters, the function completely uninstalls.
Returns
KeyTime() returns a .T. to indicate the specified character was placed in the keyboard buffer at the desired time.
Description
Warning! Use on AT-class systems only!
KeyTime() executes a specific program at an indicated time. To do this, the function places the desired key code in the keyboard buffer at the selected clock time. If a procedure is established with SET KEY..TO, CA-Clipper calls the procedure if, or when, you are in a wait state. This allows you to perform specific tasks at a particular time of day such as file backups.
There is also a special variant over and above an exact time designation. You can specify "99" for hours, minutes, or seconds, which modifies the interpretation of this portion of the time designation. A time string of "10:99:00" instructs the function to trigger a key trap every minute between 10:00 and 10:59.
If you want to specifically uninstall the function from the program, call it without specifying parameters.
Notes
Warning! Always uninstall the function before you leave the program or use the CTUS.LIB Extended Drivers found in CA-Clipper Tools. This function changes the interrupt vectors, and if the previous status is not restored before you leave the program, a system crash will eventually occur.
■ Only one time monitor can be active at any given time. A
subsequent call to KeyTime() deactivates the previous one.
■ You can use any symbols defined in the CA-Clipper file
INKEY.CH. You can set any other keys described in the CA-Clipper Tools header file ctscan.ch.
Examples
■ Place key code 7 in the keyboard buffer at 12:30:
? KeyTime(7, "12:30:00") // .T.
■ Place key code 255 in the keyboard buffer at 2:00 PM:
? KeyTime(255, "2") // .T.
■ Place key code 7 in the keyboard buffer at midnight:
? KeyTime(7, "00:00:00") // .T.
■ Set a key trap every second, starting at 11:59 PM:
? KeyTime(7, "11:59:99") // .T.
■ Set a key trap every full hour:
? KeyTime(7, "99:00:00") // .T.
■ Call with an invalid time:
? KeyTime(7, "25:30:00") // .F.
■ Uninstall KeyTime():
? KeyTime() // .F.
The returned string contains the characters from the CA-Clipper keyboard buffer that have already been read and processed by the program.
Description
With KEYREAD() you can read the keys that have already been processed by your application from the keyboard buffer. KEYREAD() offers the possibility of "looking into the past" of the current program execution so you can determine what the user has done up to that point. This gives you the ability to repeat particular actions, perform and undo functions, or build keyboard macros. KEYREAD() can also be very useful in searching for errors.
Notes
■ All the keys processed since the last execution of SET
TYPEAHEAD TO or KEYSEND() are placed in the keyboard buffer. Characters already in the buffer, but not yet read by a CA-Clipper program through an input instruction, are ignored by KEYREAD(). If the keyboard buffer is empty (as at program start, or after executing a KEYSEND() or SET TYPEAHEAD TO), the function returns a null string.
■ In contrast to the Clipper release form the Summer of 1987,
KEYREAD() in CA-Clipper returns the entire BIOS key code as defined in the ctscan.ch include file. If complete key code compatibility is required for an existing application, the ct.ch include file must be included. The ctscan.ch file also contains information regarding new keyboard function behavior.
Examples
cHistory := KEYREAD() // Prior input
IF Right(cHistory, 2) == cSequence
? "You have left MEMOEDIT using Ctrl-END!"
ENDIF
cKeyValue Designates one or more sequences that are placed in the keyboard buffer.
lAdditiveMode Designates an optional parameter. If this parameter is .T., then the key codes passed are added to the contents of the keyboard buffer. If the parmeter is .F. or if no parameter is passed, the contents of the keyboard buffer are overwritten.
Returns
When the string has been placed successfully in the CA-Clipper keyboard buffer, the function returns a value of .T.. If an error occurs, the return value is .F..
Description
KEYSEND() works similarly to the CA-Clipper KEYBOARD command. However, it allows you to use other codes for the characters that are stuffed. Symbolic constants for these key codes can be found in the ctscan.ch include file and in Appendix A. By using this unique coding for characters in the keyboard buffer, KEYSEND() allows you to place keys in the buffer that CA-Clipper's KEYBOARD command does not permit, such as codes smaller than 0 or greater than 255 (e.g. all function keys and most Alt combinations). This unique coding is also helpful for two keys that have the same Inkey() value and cannot be differentiated with the KEYBOARD command.
If you want to place normal characters like letters and numbers in the keyboard buffer, it is better to use the CA-Clipper KEYBOARD command. Using CA-Clipper Tools functions for normal characters provides no real advantage. If, on the other hand, you want to simulate other keyboard input, like function or control keys, then KEYSEND() is best to use because function and control keys can be clearly differentiated.
As with the CA-Clipper KEYBOARD command, the entire contents of the keyboard buffer are cleared as soon as KEYSEND() passes a new character. If lAdditiveMode is .T., the function adds the key codes to the current buffer contents.
Notes
■ Key codes in CA-Clipper Tools have been extended, but the old
codes are still valid (see include file ctscan.ch).
■ The maximum length of the string to be saved is now calculated
as follows:
maximum allocatable memory / 2
Examples
Simulate the function key Alt-F10:
KEYSEND(KS_ALT_F10)
dDate|nMonth Designates either a date or the number of a month. The default is the system date.
Returns
LastDayOM() returns the number of days in the month specified by dDate|nMonth.
Description
To administer due dates and other similar dates, it is useful to know the number of days that remain in a month. Specify either the day's date or month as a parameter, and you get the length of the month in days. If you subtract the number of days until today's date, you are left with the days that remain until month end.
Notes
■ Without the dDate|nMonth parameter, the function
automatically uses the system date. If there is an invalid number of months, LastDayOM() returns 0 as an error code.
Examples
How many days remain before the end of the month?
? "There are " + Str(LastDayOM() - Day(), 2) +;
" days until the end of the month"
Returns the line number of the most-recent key trap
Syntax
LASTKLINE() → nLineNumber
Returns
LASTKLINE() returns a source code line number.
Description
This function notes the program lines where KeyTime(), KeySec(), com_Key(), or com_SKey() placed a key code in the keyboard buffer. With CA-Clipper, key traps only become active when a wait state is triggered. This function differs from the CA-Clipper ProcLine() function because it returns the line number where the respective result occurs, rather than the line of the input command that triggered the trap.
Notes
■ LASTKLINE() returns a value, only if the program compiles
without the compiler switch value of -l (suppress line number information).
■ The function returns a value of 0 when the executed line is in
CA-Clipper Tools, the external function, or -1 option.
Examples
Return the line number of the last key trap:
? "Trap by", LASTKFUNC(), "in line", LASTKLINE()
LASTKPROC() returns the name of the procedure or function (KeyTime(), KeySec(), com_Key(), or com_SKey()) that places a character in the keyboard buffer when executed.
Description
CA-Clipper Tools notices when other procedures or functions encounter an interrupt. LASTKPROC() does not return the procedure name triggered by an input field key trap (as with GET..READ); instead, it returns the procedure name that was interrupted.
Notes
■ This function also returns the names of user-defined functions
(UDFs).
Examples
Return the procedure name that was interrupted:
IF LASTKPROC() = "INPUT"
* Note to user
@ 24, 30 SAY "One moment please!"
ENDIF
Compares character strings using wildcard characters
Syntax
Like(<cString1>,<cString2>) → lEqual
Arguments
cString1 Designates the wildcard string for comparison. All wildcards must be in this character string.
cString2 Designates the string to compare to cString1.
Returns
Like() returns .T. when, after taking wildcards into account, both character strings are equal.
Description
This function allows you to compare two character strings with one another, where the first can contain wildcard characters. This is similar to the way wildcard characters are used in conjunction with DOS commands but not identical. Any single character matches a "?" in the first string (see examples). The "*" within cString1 can be placed anywhere and matches multiple characters. You can also use multiple "*".
Notes
■ You can also use wildcard characters in conjunction with an
array of other string functions by using the SetAtLike() switch, but only for the "?".
Examples
■ This example shows differences from DOS:
Dir XYZ?.DBF // shows XYZ.DBF and XYZ1.DBF
? Like("XYZ?", "XYZ") // .F.
? Like("XYZ?", "XYZ1") // .T.
■ This example shows other combinations:
? Like("*OG.*", "PROG.PRG") // .T.
? Like("*OG.*", "LOG.PRG") // .T.
? Like("*R*T*", "PROTO") // .T.
? Like("*R*T*?", "PROTO") // .F.
? Like("*R*T*?", "PROTO2") // .T.
■ Use wildcards in the first parameter only:
? Like("*PER", "CLIPPER") // .T.
? Like("CLIPPER", "*PER") // .F.
lValue Designates the logical value that is converted. The default value is .F..
Returns
The character returned corresponds to the logical value specified in the parameter.
Description
In contrast to the LToN() function, which converts a logical value into a number, LToC() returns a value for the type character string. This can be particularly helpful with combined index keys.
Examples
■ Without parameters, .F. is assumed:
? LToC() // "F"
■ Return a letter that corresponds to the specified logical
value:
? LToC(.F.) // "F"
? LToC(.T.) // "T"
■ Other functions can return the logical value:
? LToC(Deleted()) // "T" or "F"
lMode When .F. is passed, or when no parameter is specified, the function returns the highest column number of the selected window. When .T. is passed, it returns the highest column number for the entire screen. The default value (.F.) returns the highest column number for the selected window.
Returns
MaxCol() returns the highest column number available within a window or within the physical screen.
Description
MaxCol() is also a CA-Clipper function. Without parameters, or when specifying .F., MaxCol() always returns a value for the selected window. In the absence of CA-Clipper Tools, this value is always Window 0, which is exactly the same size as the entire screen. However, if the extended driver CTUS.LIB and the CA-Clipper Tools window functions are implemented, this value can change. If you want the highest column for the entire screen, regardless of the window selected, you can pass .T. for the optional lMode parameter.
Notes
■ The explanation of this function was taken from the Video
Functions chapter and placed in the Extended Driver chapter. Now all CA-Clipper Tools functions that replace and/or extend CA-Clipper functions when CTUS.LIB is linked in are in the same chapter. The extensions to the CA-Clipper versions of these functions are only of interest when used in conjunction with the other extended driver functions and their accompanying windows.
Examples
Display the highest column number:
WOpen(10, 10, 20, 70) // Open a window
? MaxCol() // Relates to a window
? MaxCol(.T.) // Back to the physical screen
The function returns the maximum line length necessary to display the cString text without automatic line breaks.
Description
MaxLine() looks for the longest line within a character string. This allows you to determine the required width for a window to display text (MEMO fields). In this way the text can be displayed without additional line breaks.
Notes
■ With the exception of the carriage return and the line feed,
this function treats all characters as printable with a width of 1. If the cString text contains tabs, then you must first use the TabExpand() function to expand the tabs to spaces.
Examples
A function, based on the maximum line length, automatically performs a
suitable call of MemoEdit():
FUNCTION SHOWMEMO(cMemo)
LOCAL cMessage, nHeight, nWidth
nHeight := Min(NumLine(cMemo), MaxRow() -1)
nWidth := Min(MaxLine(cMemo), MaxCol() -1)
IF nWidth = 0
cMessage := "The memo field is empty"
ELSE
cMessage := ""
@ 0, 0 TO nHeight +1, nWidth +1 DOUBLE
MemoEdit(cMemo, 1, 1, nHeight, nWidth, .F.)
ENDIF
RETURN(cMessage)
lMode Designates the highest row nmber for the selected window or for the entire screen. When .F. is passed, or when no parameter is specified, the function returns the highest row number of the selected window. When .T. is passed, it returns the highest row number for the entire screen. The default value (.F.) returns the highest row number for the selected window.
Returns
MaxRow() returns the highest row number available within a window or within the physical screen.
Description
MaxRow() is also a CA-Clipper function. Without parameters, or when you specify .F., MaxRow() always returns a value for the selected window. In the absence of CA-Clipper Tools, this value is always Window 0, which is exactly the same size as the entire screen. However, if the extended driver CTUS.LIB and the CA-Clipper Tools window functions are implemented, this value can change. If you want the highest row for the entire screen, regardless of the window selected, you can pass .T. for the optional lMode parameter.
Notes
■ The explanation of this function was taken from the Video
Functions chapter and placed in the Extended Driver chapter. Now all CA-Clipper Tools functions that replace and/or extend CA-Clipper functions when CTUS.LIB is linked in are in the same chapter. The extensions to the CA-Clipper versions of these functions are only of interest when used in conjunction with the other extended driver functions and their accompanying windows.
Examples
Display the highest row number:
WOpen(10, 10, 20, 70) // Open a window
? MaxRow() // Relates to a window
? MaxRow(.T.) // Back to the physical screen
MAXFONT() returns the number of fonts you can load simultaneously within the screen card in use.
Description
Depending upon the screen adapter and its available memory, a various number of screen fonts can be loaded simultaneously. MAXFONT() returns the maximum number of loadable fonts and is very helpful when used in conjunction with FONTLOAD() or SetFont().
Notes
■ As a rule, EGA adapters support four different font areas and
VGA adapters support eight.
Examples
■ Load a font in the highest font area available...
FONTLOAD("ITALIC.016", MAXFONT())
■ ...and then select that font:
FONTSELECT(MAXFONT())
This function returns the number of the maximum available video "pages". A return of 0 means that only one page is available; so, the actual number of available pages is MAXPAGE() +1.
Description
MAXPAGE() allows you to determine the number of screen pages that are available for use on the display adapter. This information can be particularly valuable when you use the SETPAGE() or PAGECOPY() function.
Examples
Find the maximum number of available screen pages:
? MAXPAGE() // Result 3 means 4 pages
dDate Designates the date from which to create a string. The default is the system date.
Returns
MDY() returns a character string in Month DD, YY, or "Month DD, YYYY" format.
Description
MDY() returns the date in a character string that contains the day, name of month, and year. The CA-Clipper SET CENTURY ON/OFF switch determines whether or not the year is displayed in 2 or 4 digits.
If the function is called without a parameter, it automatically uses the current system date.
Notes
■ The returned month name always depends on which CA-Clipper
nations module is in use. A German or French version of CA-Clipper returns the appropriate month names, despite its characteristically American display.