Harbour Differences

Differences between Harbour and other compatible compilers ( xHarbour, Clipper, xBase++, CLIP, FlagShip )


Compile time support for merging multiple .prg modules
New language statements
Extended codeblocks
Hash arrays
References to variables stored in arrays
Passing array and hash items by reference
Passing object variables by reference
Detached locals and references
Declaration and initialization of variables
Functions with variable number of parameters
Hb_ArrayToParams() function
Macros with declared symbols
Macro messages
Multivalue macros
Using [] operator for string items
Negative indexes in [] operator used to access items from tail
Using one character length string as numeric value
New bit operators
IN, HAS, LIKE operators
Pre/post incrementation/decrementation and <op>= operators
Global / global external (global_extern)
Literal date and TIMESTAMP values
Extended literal string in compiler and macrocompiler
Symbol items and function references
OOP scopes
OOP and multiinheritance
OOP and private/hidden datas
OOP and class object/class messages
Typed object variables
Object destructors
Scalar classes
Runtime class modification
Array and string preallocation
DIVERT statement
Multi window GTs and runtime GT switching
Multi thread support
Thread local work areas and concurrent work area access
Harbour tasks and MT support in DOS
Background task
Codeblock serialization / deserialization
Native RDDs
Regular expressions
INET sockets
I18N (internationalization) support
ZLIB (compression/decompression)
Serial port support
Macro compiler
Compiler library
PP library
Contrib libraries
C level compatibility
Performance and resource usage

This list borrowed from Harbour github documentation; please look at there for details.


SP Functions

A2TOSING()       Copies a given element from an array of arrays
AASKIP()         Use for skipblock for arrays in Tbrowse
AAVERAGE()       Determines average of an array with condition
ABORT()          Pops up dialog box asking: Abort  Don't Abort
ADDSPACE()       Pads right of string with spaces
AEXTRACT()       Extract and return a conditional set from an array
AFDECIX()        Returns an array of field DECIMALS for current dbf
AFIELDSTYPE()    Returns an array of field names of particular type
AFIELDSX()       Returns an array of field names for current dbf
AFLENSX()        Returns an array of field LENGTHS for current dbf
AFTYPESX()       Returns an array of field types for current dbf
AKOUNT()         Counts exact matches of value in array
ALENG()          Actual length of an array, less trailing nil elements
ALLBUT()         Returns all but last x characters
AMATCHES()       Counts the matches of an array with condition
AMAVERAGE()      Average on a given element of multi-dim array
AMSG()           Pop up message box for an array of messages
AMSTDDEV()       Standard Deviation on a given element of
AMSUM()          Sum on a given element of multi-dim array
AMVARIANCE()     Variance on a given element of multi-dim array
APPENDIT()       Intelligent APPEND FROM replacement
ARRANGE()        Rearranges text in a string
ARRAY2DBF()      Replaces current record with values in an array
ASCIITABLE()     Pops up an ASCII table for character selection
ASORTMULT()      Sort multiple arrays on order of single array
ASORTMULTR()     Reverse sort multiple arrays on order of single array
ASTDDEV()        Standard deviation of an array with condition
ASUM()           Determines the sum of an array with condition
AT2CHAR()        Returns the String color equivalent of a color number
ATT()            Colors a section of the screen, leaving the text intact
AUPDATED()       Determines if array contains updated values for record
AVARIANCE()      Determines the variance of an array with condition
BEGEND()         Determines beginning or end of week,month or quarter
BIGELEM()        Returns length of longest string in an array
BLANKFIELD()     Returns a blank value corresponding to a field
BLANKREC()       Blanks out a record
BLDARR()         Builds an array from a delimited string
BLDDBF()         Create a DBF from a delimited string or an array
BLDNDX()         Interactively create a new index
BOM()            Calculates beginning of the month date
BOYEAR()         Determine beginning of year a date falls in
BROWSE2D()       Popup  tbrowse of 2 dimension array (array of arrays)
BROWSEDELIM()    Tbrowse a delimited file
BROWSESDF()      Tbrowse an SDF file
BUILDEX()        Interactively builds and returns an expression string
BUNGDROP()       Causes dropdown during BUNGEE() menu def sequence
BUNGEE()         Mouseable, multi-level dropdown menu with triggers
BUNGEEQUIT()     BUNGEEQUIT( ) is how a Bungee menu is terminated. You would normally
BUNGEETOP()      Sends the current menu back to the top level box (not all
BUNGEND()        Ends a BUNGEE() menu array definition sequence
BUNGOPTION()     Adds option during a BUNGEE() menu definition sequence
BUNGREDRAW()     Redraws the current menu, with optional change of colors
BUNGSTART()      Starts a BUNGEE() menu array definition sequence
BUNGUNDROP()     Ends dropdown during BUNGEE() menu def sequence
BXX()            Draws a box on the screen of a given color
CALCKCLR()       Clears hot keys set by CALCKSET()
CALCKSET()       Allows use of GETCALC() calculator in GETS
CALCVALID()      Uses GETCALC() calculator function as a GET VALID
CALCWHEN()       Uses GETCALC() calculator function as a GET WHEN
CALENDKCLR()     Clears hot keys set up by CALENDKSET()
CALENDKSET()     Allows use of GETDATE() calendar in GETS
CALENDVALID()    Uses GETDATE() popup calendar function as a GET
CALENDWHEN()     Uses GETDATE() function as a GET WHEN clause
CENTR()          Centers a string in x spaces
CDIR()           Change Directory
CLABEL()         Menu driven module for label management
CLS()            Clear the screen with optional color,character
COLPIK()         Allows selection of colors from a list
COPYFIELDS()     Copies selected fields of selected records to new dbf
COPYITOUT()      Copies records to a new DBF
CRUNCH()         Moves spaces in a string to end of string
CTRLW()          Sends chr(23) (Control-W) to the keyboard
CURD()           Return current drive letter
DATECALC()       Adds/subtracts days,weeks,months,years to a date
DAYSIN()         Calculates number of days in a month
DBF2ARRAY()      Returns an array of values for the current record
DBSTATS()        Statistical report on dbf, including
DELARRAY()       Deletes all elements of an array
DELREC()         Dialog box to delete/undelete current record
DOYEAR()         Calculates day of the year from date
DTDIFF()         Returns difference between dates
DTOW()           Converts date to words
DUPHANDLE()      Duplicate record finder with delete/copy options
DUPLOOK()        Locates possible duplicates based on user criteria
EDITDB()         Customized database browser with edit/add/search
EDITMEMO()       Performs a windowed memoedit() on a memo field
EDITMEMOV()      Performs a windowed memoedit() on a string
ED_G_PIC()       Returns appropriate picture for getting a field
ENDSWITH()       Determines if a string ends with another string
ENHANCED()       Returns color integer for ENHANCED setting
EVALQ()          Evaluates a logical condition in a string
EXPBLOCK()       Returns a codeblock to evaluate an expresson
FADEAWAY()       Fades screen away , alternative to restscreen()
FASTFORM()       Prints a selected formletter for current record
FIELDDECX()      Returns decimals of field
FIELDLENX()      Returns length of field
FIELDPOSX()      Returns position of field named in expression
FIELDTYPEX()     Returns type of field
FILEINFO()       Returns file date,time,size
FILEREAD()       Lists a text file of unlimited size
FILLARR()        Fill type, length, decimal arrays
FMOVE2NEXT()     Move to beginning of next line in a text file
FMOVE2PRIOR()    Moves to beginning of previous CRLF delimited
FORMLETR()       Interactive formletter and mailmerge utility
FORMULATE()      Builds a free-form formula or User Defined Field
FREQANAL()       Performs a frequency analysis on a DBF
FULLDIR()        Interactively navigate directories
GENED()          Generic dbf editing screen
GENREADER()      Creates specialized user defined get reader block
GENVAL()         Generic VALID clause validation with message
GETAKEY()        Gets intent of last keystroke
GETCALC()        Pops up a quick 'solar' calculator
GETDATE()        Point and shoot calendar
GETDFP()         Gets SET DEFAULT path
GETJUMP2()       Determines if mouse clicked on a get
GLOBREP()        Performs global selective replace of a field
HARDCOPY()       Prints current record or memo fields to printer
HELP()           Provides context sensitive popup help
HELPMOD()        Interactively build and modify help screens
IFMOUSEHD()      Checks if mouse held down,evals codeblock while it is
INITSUP()        Sets SuperLib system interface vars for MONO or COLOR
ISBLANKREC()     Determines if a record is blank
ISFIELD()        Determines if an expression is the name of a field
ISINLOOK()       Checks for existence of a value in a lookup dbf
ISLOADED()       Determines  function is loaded or not
ISMOUSEAT()      Checks for mouse click within passed coordinates
ISNOTDUP()       Checks for a duplicate field
ISPART()         Determines if a value is part of a set 
ISPRN()          Detects printer ready (or not) on LPT1, 2 or 3
ISTHISAREA()     Determines if expression is the name of a field
ISVALFILE()      Checks a file name for validity
KBDESC()         Keyboards character 27 (escape) when key pressed
LISTER()         Build, format,print SIMPLE lists to
LJUST()          Left justifies a string
MAKEBOX()        Draws a box on the screen and returns saved screen
MBRZCLICK()      Checks for mouse click on current Tbrowse row/col
MBRZMOVE()       Checks for mouse click at and moves to Tbrowse row/col
MCHOICE()        Does a boxed, achoice() style popup on an array
MENU_V()         Vertical popup menu from variable # parameters
MESSYN()         Popup YesNo prompt box
MFIELDS()        Pops up a selection box for current dbf fields
MFIELDSTYPE()    Pops up a list of fields of given type(s)
MODIFY()         Create or modify DBF structures
MOUSEHOTAT()     Checks for mouse click from array of hot coordinates
MSG()            Displays up to a 9 line message in a window
MULTIMSGYN()     Multi-line popup message - yes -no
NBR2STR()        Correctly orders numerics where negative
NKEY()           Gets key of an index file
NOZDIV()         Prevents divide-by-zero
OLD()            On Line Documentation - TOPIC oriented help system
ONE_READ()       Pop-up window with 1-4 Say/Get combinations
OPENIND()        Opens an array of indexes
PARSALIAS()      Extracts the name of the alias from an expression
PARSFIELD()      Extracts the name of the field from an expression
PICKNDX()        Allows user to select indexes to open
PICKREADER()     Creates specialized picklist reader block
PLSWAIT()        Pops up a 'Please Wait' window or removes it
PMREADER()       Creates specialized PLUS/MINUS get reader block
POPCOLSEL()      Popup color grid for selecting a single color
POPEX()          Pops up an achoice for a certain filespec
POPMONTH()       Popup month selection
POPREAD()        Pops up a box with 1-5 say-get combinations
POPUPDIR()       Popup of a given directory for file selection
POPUPKCLR()      Clears GET hotkey popups set up with POPUPKSET()
POPUPKSET()      Set a popup for hotkey access from a GET
POPUPVALID()     Allows use of a popup for a GET VALID clause
POPUPWHEN()      Allows use of a popup for a GET WHEN clause
POPVDATE()       Pops up a picklist of virtual dates
POPVYEAR()       Pops up a picklist of virtual years
PRNPORT()        Determine Printer Port to use
PRNT()           Writes a string of a given color at row, column
PRNTFRML()       Prints a formletter created by formletr()
PROGCOUNT()      Perform a count with a progress box
PROGDISP()       Displays progress bar in box created with PROGON()
PROGEVAL()       Perform a Database DBEVAL() with a progress box
PROGINDEX()      Perform an index with a progress box
PROGOFF()        Removes a progress bar box created by PROGON()
PROGON()         Initialize and display a progress bar box
PROPER()         Capitalizes first letters of string, lowers rest
PSTABMENU()      Popup tabular (grid style) )menu
PULLDN()         Pulldown menu creator, handler
PURGEM()         Deletes records
P_RDYDELAY()     Sets/returns p_ready() 'seconds' variable
P_READY()        Determines if printer is ready, prompts user
QFLDSTYPE()      Count # of fields of a given type or types
QUERY()          Popup Interactive query by example condition
QUIKREPORT()     Runtime pre-defined report printing module
RAT_AREA()       Limits the mouse to a rectangular area of the screen
RAT_COL()        Current mouse column
RAT_COLL()       Returns mouse column at the last left button press
RAT_COLR()       Returns mouse column at the last right button press 
RAT_ELBHD()      Determines if left mouse button is held down
RAT_EXIST()      Determines if a mouse is available
RAT_FORCE()      This forces a mouse present status, regardless
RAT_LBHD()       Determines if the mouse left button is currently depressed
RAT_LEFTB()      Determines if the left mouse button has been pressed
RAT_NOMOUSE()    This forces a no mouse status, regardless
RAT_OFF()        Sets the mouse cursor off
RAT_ON()         Sets the mouse cursor on
RAT_POSIT()      Positions the mouse cursor at row,column
RAT_RBHD()       Determines if the mouse right button is currently depressed
RAT_RESET()      Resets the mouse to its default values
RAT_RIGHTB()     Determines if the right mouse button has been pressed
RAT_ROW()        Current mouse row
RAT_ROWL()       Returns mouse row at the last left button press
RAT_ROWR()       Returns mouse row at the last right button press

RAT_EQMCOL() Returns mouse column at last press 

RAT_EQMROW()     Returns mouse row at last press 
RAT_ERBHD()      Determines if right mouse button is held down 
RAT_EVENT()      Event handler - inkey() with mouse awareness 
RAT_ISMOUSE()    Determines mouse usage by RAT_EVENT() 
RAT_LASTEV()     Returns the last event recorded by RAT_EVENT() 
RAT_MENU2()      Mouseable MENU TO emulation 
RAT_READ()       Mouseable read 
REPORTER()       Create, modify, execute reports 
RESTSETKEYS()    Restores set keys saved with SAVESETKEYS() 
RJUST()          Right justifies a string RRJUMP2() Jump to a new get in a RAT_READ() 
RRLASTKEY()      Retrieve the last key handled by ratapplykey() 
R_ISRATREAD()    Determines if RAT_READ() is current get system 
S1LABEL()        Prints a single label 
SACHOICE()       Achoice replacement, uses TBROWSE, codeblock 
SADD_REC()       Attempts to append a blank record 
SAPPOINT()       Appointments manager - uses popup calendar. 
SATTCOLOR()      Sets up color vars for color monitor 
SATTDIRECT()     Sets up the the color vars directly 
SATTGET()        Sets up SuperLib color vars from COLORS.DBF 
SATTGETMEM()     Sets up SuperLib color vars from old COLORS.MEM 
SATTMONO()       Sets up color vars for mono monitor 
SATTPICK()       Sets up SuperLib color vars by selecting from DBF 
SATTPICKDEL()    Picklist deletion of stored color var sets 
SATTPICKPUT()    Stores SuperLib color vars to selected record 
SATTPOP()        Pops previously pushed SuperLib color vars 
SATTPUSH()       Pushes the current SuperLib color vars 
SATTPUT()        Stores current SuperLib color vars to COLORS.DBF 
SAVESETKEYS()    Saves active set keys to an array 
SBCENTER()       Centers box coordinates 
SBCOLS()         Determine number of columns in a box 
SBREADER()       Creates specialized spacebar spinner get reader 
SBROWS()         Determine number of rows in a box 
SBSHADOW()       Draw a shadow around a box 
SBUNSHADOW()     Removes shadow drawn with SBSHADOW() 
SCMOD()          Maintains scroller.dbf - see scroller() 
SCONVDELIM()     Convert a delimited file to a DBF 
SCROLLER()       Hotkey lookup tables with dbf storage 
SEARCHME()       Search a DBF with user-specified criteria 
SEARCHMFND()     Set/return last found() status from SEARCHME() 
SEARCHMRS()      Resets all SEARCHME() settings 
SETCENT()        Determines if century is on/off 
SETCOLORS()      Interactive color setting interface 
SETEXACT()       Determines if exact is on/off 
SET_DATE()       Sets and restores date format 
SEXPORT()        Export DBF to delimited or SDF files 
SFIL_LOCK()      Attempts to lock a file 
SFREADLINE()     Reads in text up to the next CRLF in a text file 
SFRR_HCODE()     Output report definition to .PRG code 
SGETMANY()       Virtual (scrolling) gets in a popup box 
SHIFTY()         Determines shift key settings
SLOTUSMENU()     1-2-3 style menu 
SLSF_APPT()      Sets and retrieves the file name and path for the 
                 SAPPOINT() DBF files 
SLSF_COLOR()     Sets and retrieves the file name and path for the 
                 COLOR SET DBF file 
SLSF_FORM()      Sets and retrieves the file name and path for the 
                 FORMLETR() DBF file 
SLSF_HELP()      Sets and retrieves the file name and path for the 
                 HELP() DBF file 
SLSF_LABEL()     Sets and retrieves the file name and path for the 
                 LISTER() DBF file 
SLSF_LIST()      Sets and retrieves the file name and path for the 
                 LISTER() DBF file 
SLSF_OLD()       Sets and retrieves the file name and path for the 
                 OLD() help files 
SLSF_QUERY()     Sets and retrieves the file name and path for the 
                 QUERY() DBF file 
SLSF_REPORT()    Sets and retrieves the file name and path for the 
                 REPORTER() DBF file 
SLSF_SCROLL()    Sets and retrieves the file name and path for the 
                 SCROLLER() DBF file 
SLSF_TODO()      Sets and retrieves the file name and path for the 
                 TODOLIST() DBF files 
SLS_BQUERY()     Sets SuperLib global query block 
SLS_BQZAP()      Resets SuperLib's global query block 
SLS_FRAME()      A Superlib box setting function 
SLS_ISCOLOR()    Tells SuperLib if this is a color monitor 
SLS_NORMCOL()    A Superlib color setting function 
SLS_NORMMENU()   A Superlib color setting function 
SLS_POPCOL()     A Superlib color setting function 
SLS_POPMENU()    A Superlib menu setting function 
SLS_PRN()        A Superlib printer setting function 
SLS_PRNC()       A Superlib printer setting function 
SLS_QUERY()      Sets SuperLib global query string 
SLS_SHADATT()    A Superlib color setting function 
SLS_SHADPOS()    A Superlib color setting function 
SLS_XPLODE()     A Superlib box setting function 
SL_BOLD()        Sets font stroke weight to BOLD (ultra black) 
SL_BOX()         Draws a box line from row,col to endrow,endcol 
SL_COPIES()      Sets the laserjet to print n copies of each page 
SL_DOWNROW()     Move the printer cursor up/down by # rows, 
SL_EJECT()       Ejects the current page 
SL_FILL()        Fills a rectangle with shading or a pattern. 
SL_GOTO()        Move the printer cursor to row/col 
SL_HLINE()       Draws a horizontal line from row,col to row,endcol 
SL_ITALIC()      Sets font style to italic 
SL_ITALICOFF()   Sets font style to upright (non italic) 
SL_LANDS()       Sets laserjet orientation to LANDSCAPE 
SL_LEFTMARG()    Sets the left margin to the left edge of the 
SL_NORMAL()      Sets font stroke weight to NORMAL (non bold) 
SL_OVERCOL()     Move the printer cursor right/left # columns 
SL_PAGESIZE()    Sets the page size on the laserjet 
SL_POPCURS()     Pops the printer cursor position for later popping 
SL_PORT()        Sets the laserjet orientation to PORTRAIT 
SL_PUSHCURS()    Pushes the printer cursor position for later 
SL_RESET()       Resets the printer to user defaults 
SL_RIGHTMARG()   Sets the right margin to the right edge of the 
SL_SETCPI()      Sets characters per inch 
SL_SETLPI()      Sets the lines per inch for the laserjet 
SL_TOPMARG()     Designates the number of lines of top margin 
SL_UNDER()       Sets automatic text underlining on 
SL_UNDEROFF()    Sets automatic text underlining off 
SL_VLINE()       Draws a vertical line from row,col to endrow,col 
SL_WRAP()        Sets line wrapping on or off 
SMAILMERGE()     Creates mailmerge files for WordPerfect & MS Word 
SMALLKCLR()      Clears get lookup combinations set up with SMALLKSET() 
SMALLKSET()      Sets up GET-HOTKEY lookup combinations using smalls() 
SMALLS()         Lookup tables on dbf with optional hotkeys, code block 
SMALLVALID()     Uses SMALLS() lookups in a VALID condition for a GET 
SMALLWHEN()      Uses SMALLS() in a WHEN condition for a GET 
SNET_USE()       Attempts to open a DBF 
SPOPORDER()      Popup allows user to change viewing (index) order 
SPOPSEEK()       Popup seek based on present index keys 
SREC_LOCK()      Attempts to lock a record 
SS_CLOSEH()      Restores screen in a horizontal close fashion. 
SS_CLOSEV()      Restores screen in a vertical close fashion. 
SS_FADE()        Restores screen in a fadeaway fashion. 
SS_FALL()        Restores screen in a fall from top fashion. 
SS_FOLD()        Restores screen in a fold to middle fashion. 
SS_HBLINDS()     Restores screen in a horizontal blind fashion. 
SS_IMPLODE()     Restores screen in an imploding fashion. 
SS_RISE()        Restores screen in a rise from bottom fashion. 
SS_SLICE()       Restores screen in a slicing fashion. Alternative 
SS_SLIDELEFT()   Restores screen in a slide left fashion. 
SS_SPLIT()       Restores screen in a split from middle fashion. 
SS_VBLINDS()     Restores screen in a vertical blind fashion. 
SS_WIPEH()       Restores screen in a wipe from left fashion. 
SS_WIPEV()       Restores screen in a wipe from top fashion. 
STABMENU()       Tabular (grid style) menu 
STAGFIELDS()     Tag fields 
STANDARD()       Returns color integer for standard setting 
STARTSW()        Determines if a string starts with another string 
STOD()           Returns date from string in the form YYYYMMDD 
STRETCH()        Imbeds characters in a string 
STRIP_PATH()     Strip path and optionally extension from a 
STRPULL()        Extract text between 2 characters in a string 
SUBPLUS()        Returns multiple substrings 
SUM_AVE()        Interactive sum or average on a dbf field 
TAGARRAY()       Tag selected elements of an array 
TAGIT()          Tag records in a dbf for later action 
TAGMARRAY()      Tag elements in muti-dimensioned array 
TAKEOUT()        Extract a portion of a string between delimiters
TIMEPER()        Time Period (date sensitive) DBF analysis 
TODOLIST()       Simple todo list manager 
TRUEVAL()        Returns val of ALL numerics in a string 
UNBOX()          Removes a box created by makebox() 
UNIQFNAME()      Creates a unique file name 
UNSELECTED()     Returns color integer for UNSELECTED setting 
VAR2CHAR()       Converts any type variable to character type 
VARLEN()         Returns length of a variable of any type 
VERTVIEW()       Pops up a vertical view of the current record 
VIEWMEMOS()      Popup viewing (non-edit mode) of memos 
VIEWPORT()       Multi-optional data entry engine 
WGT_MEAS()       A Weights and Measures conversion metafunction 
WOMONTH()        Calculates week of the month (# of 7 day periods) 
WORKBLOCK()      Returns a set-get block for field named in an 
WOYEAR()         Calculates week of the year (# of 7 day periods) 
WRITEFILE()      Writes a line or lines to a text file 
XBXX()           Draws an exploding box on the screen of a given color 
YNREADER()       Creates specialized Yes/No get reader block 
_WILDCARD()      Wild Card String Compare

Coding Guidelines

Coding Guidelines

( by Greg Holmes )

Language Syntax 
The general rule of thumb is: built-in features in lowercase, and custom-written functions in mixed case. 
When specifying the complete syntax of a language element in documentation, the input items, parameters, and so on are referred to using the following symbols:

 Symbol  Description
< >  Indicates user input item
( )  Indicates function argument list
[ ]  Indicates optional item or list
{ }  Indicates code block or literal array
| |  Indicates code block argument list
–>  Indicates function return value
 Repeated elements if followed by a symbol
Intervening code if followed by a keyword
,  Item list separator
|  Indicates two or more mutually exclusive options
@  Indicates that an item must be passed by reference
*  Indicates a compatibility command or function

For example:

    len(<cString>|<aArray>) --> nLength

Metasymbols provide a place holder for syntax elements, and they describe the expected data types. A metasymbol consists of one or more lowercase data type designators followed by a mixed case description. This is known as Hungarian Notation.

 Designator  Description
a  Array
b  Code block
c  Character expression
d  Date expression
exp  Expression of any type
id  Literal identifier
l  Logical expression
m  Memo field
n  Numeric expression
o  Object
x  Extended expression

In this example, dnLower and dnUpper can be either date or numeric:

    @...get...range <dnLower>, <dnUpper>
Filenames and Aliases 
All filenames, in any context, are in upper case. Filenames follow DOS naming conventions (preferably limited to letters, numbers, and the underscore).

    use CUSTOMER
    nHandle := fopen('DATAFILE.DAT')

When referring to specific file types in documentation, include the period.
e.g. “A program is stored in a text file with a .PRG extension.” 
Alias names follow the same conventions as filenames, but are limited to A-Z, 0-9, and the underscore. If a filename begins with a number or contains unusual characters, an alias must be specified when the file is opened or an error will result. 
Note that CA-Clipper does not natively support Windows 95 long filenames, although third-party libraries are available to add the capability.

Fieldnames are all uppercase, and always include the alias of the table. Fieldnames may contain underscores, but should not begin with one (because the underscore is generally used to indicate an internal symbol).

    @ 10, 10 say BANKS->BRANCH
Memory Variables 
Memory variables consist of a lowercase type designator followed by a mixed case description (see Hungarian Notation). Although CA-Clipper only recognizes the first 10 characters as unique, variable names may be longer.

    cString := "Hello World"
    nYearlyAverage := CalcYearAvg()

If you use Hungarian Notation for your memory variable names and include the table alias with fieldnames, there will be no conflict between the two.

Commands, Functions, and Keywords 
All built-in commands, functions, and keywords are lowercase. In documentation, the font should be Courier or a similar font. If fonts are not available, then bold or CAPITALIZE the word for emphasis. 
Never use abbreviations — this practice is not necessary with a compiler, although it was common in the early days of dBase (which was an interpreter). 
There should never be a space between the function name and the opening parenthesis. Also, note that the iif() function should never be spelled if().

    replace CUSTOMER->CUSTNAME with cCustName
    nKey := inkey(0)

When specifying commands that have clauses in documentation, separate the keywords with an ellipsis (...) and do not include the to clause, unless it is followed by the file,print, or screen keywords.

    set message...center
Programmer-Defined Functions & Procedures 
These begin with an uppercase letter, followed by mixed case letters as appropriate.

    ? StripBlanks("Hello there, this will have no spaces.")

Function and procedure names may contain underscores, but should not begin with one (they may conflict with internal functions which often start with an underscore). There should be only one return statement per function or procedure, and it should not be indented.

    function SomeFunc (...)
      . <statements>
    return cResult

The return value of a function is not enclosed in parentheses, although parentheses may be used to clarify a complex expression.

    return nValue
    return (nCode * 47) + nAnswer
Preprocessor Directives 
Preprocessor directives are lowercase and are preceded by the # sign.

    #include 'INKEY.CH'

Optionally, you may use single quotes around header files that come with CA-Clipper and double quotes around your own. This convention is purely voluntary, but it helps to distinguish between the two. For example:

    #include 'INKEY.CH'
    #include "MY_APP.CH"

Manifest constants are uppercase.

    #define ESCAPE   27
    if lastkey() == ESCAPE

Pseudo-function names should also be uppercase.

    #define AREA(length, width)   ((length)*(width))
Local variables are grouped according to functionality, and may be declared on one or more lines. The declarations appear as the first code at the beginning of a function or procedure.

    procedure Main ( )
    local nTop, nLeft, nBottom, nRight
    local cOldScreen, cOldColor, nOldCursor

Variables may be declared one per line and accompanied by a description.

    local nCount        // Number of records found.
    local nTotal        // Sum of dollars.

The description can be omitted if better variable names are chosen.

    local nRecordCount
    local nDollarTotal

Variables can be initialized when they are declared, although it is often clearer (and safer) to initialize them immediately before they are used.

    local nRecordCount:=0
    local nDollarTotal:=0
The .T. and .F. are typed in uppercase.
The in-line assignment operator (:=) is used for all assignments, and the exact comparison operator (==) is used for all comparisons.

    lContinue := .T.
    nOfficeTotal := nRegionTotal := 0
    lDuplicate := (CUSTFILE->CUSTNAME == cCustName)
    if nLineCount == 4  ...
    if left(PRODUCT->CODE, 3) == left(cProdCode, 3)  ...

Although the compound assignment operators (+=-=*=, etc.) are convenient, they should not be used if readability suffers.

    // The traditional way to accumulate:
    nTotal := nTotal + INVDETAIL->PRICE
    // A good use of a compound assignment operator:
    nTotal += INVDETAIL->PRICE
    // But what does this do?
    nVal **= 2

The increment (++) and decrement (--) operators are convenient, but can lead to obscure code because of the difference between prefix and postfix usage.

    nY := nX-- - --nX        // Huh?
Whenever a list of two or more items is separated by commas, the commas are followed by a space.

    MyFunc(nChoice, 10, 20, .T.)

Spaces may be used between successive parentheses.

    DoCalc( (nItem > nTotal), .F. )
    cNewStr := iif( empty(cStr), cNewStr, cStr + chr(13) )

Spaces should surround all operators for readability.

    nValue := 14 + 5 - (6 / 4)

In declarations, often spaces are not used around the assignment operator. This tends to make searching for the declaration of a variable easier.

    local lResult:=.F., nX:=0

Thus, searching for “nX :=” would find the lines where an assignment is made, while searching for “nX:=” would find the declaration line (such as the local above).

Indenting control structures is one of the easiest techniques, yet it improves the readability the most. 
Indent control structures and the code within functions and procedures 3 spaces.

    procedure SaySomething
       do while .T.
          if nTotal < 50
             ? "Less than 50."
          elseif nTotal > 50
             ? "Greater than 50."
             ? "Equal to 50."

Case statements in a do…case structure are also indented 3 spaces.

    do case
       case nChoice == 1
          ? "Choice is 1"
       case ...
Do not use tabs in source code — insert spaces instead. Tabs cause problems when printing or when moving from one editor to another, because of the lack of a standard tab width between editors and printers. Typically, printers expand tabs to 8 spaces which easily causes nested control structures to fall off the right-hand side of the page. Commonly, a source code editing program will insert the appropriate number of spaces when the <TAB> key is hit.
Line Continuation 
When a line of code approaches the 80th column, interrupt the code at an appropriate spot with a semicolon and continue on the next line. Indent the line so that it lines up in a readable manner.

    set filter to CUSTFILE->NAME  == 'John Smith  ';
            .and. CUSTFILE->STATE == 'OR'

To continue a character string, end the first line with a quote and a plus sign and place the remainder on the next line. Try to choose a logical place in the string to break it, either at a punctuation mark or after a space.

    @ 10, 10 say "The lazy brown fox tripped over " + ;
                 "the broken branch."
Use double quotes for text that needs to be translated (will appear on the screen), and single quotes for other strings.

    ? "Hello World!"
    cColor := 'W+/B'

This is a simple but extremely effective technique because translation departments often want to see the messages in context (in the source code), so the different quote types indicate which messages are to be translated and which should be left alone.

Comments are structured just like English sentences, with a capital letter at the beginning and a period at the end.

    // Just like a sentence.
    /* This comment is longer. As you
       can see, it takes up two lines */

You may encounter old-style comment indicators if you maintain older (Summer’87 and earlier) code.

    && This is an older-style of comment indicator.
    *  The asterisk is also old.

For in-line comments, use the double slashes.

    use CUSTOMER            // Open the data file.
    goto bottom             // The last record.

Note that the ‘//‘ of in-line comments begins at column 40, if possible. This leaves enough room for a useful comment.

Source :  http://www.ghservices.com/gregh/clipper/guide.htm

Quick Start to Migration

Chapter I – Text to text conversion

In Clipper world, “migration” means “convert a DOS based Clipper program to Windows”. This is a dream of every Clipper – DOS programmer.

 Before all, we need clarify some terms:

May be found multiple ways for convert a DOS based Clipper program to Windows. In general, DOS programs are runs in “text” mode and Windows program runs in “Graphic” mode; and this is what meant by term “migration”.

Converting a text mode program to directly GUI (Graphical User Interface) is a painful job. First, we need to find a Compiler with GUI support, or a GUI library usable with a specific compiler. If we have more than one opportunity ( yes, it is so ) we need make a choice between them.

For make a right selection we need learn, understand specialties of each option and differences between them.

Believe me, this is an endless way 😦

Instead, let’s begin with simpler thing: convert a DOS text mode program to Windows text mode program.

Question: Without GUI, what meaning will be to migrate from DOS to Windows?

Answer: Good question and like all good question, answer isn’t easy.

First, modern OSs moves away day to day from DOS conditions; memory problems, screen problems, codepage problems, etc… By the time, building / running 16 bit executable becomes more difficult day to day.

Whereas Harbour already is a 32 / 64 bit compiler.

Second, all DOS Compilers for Clipper are commercial and registration required products; furthermore they are almost out of sold for this days; what compiler you could use?

And third, Harbour is best free compiler and the best way to use a free GUI tool for xBase language.

So, beginning with using Harbour in text mode is the best start point, I think.

First step is downloading and install HMG or Harbour. If you didn’t past this step yet please refer previous articles in this section or “Links” page of this blog.

The easiest way for using Harbour compiler is calling hbmk2, the wonderful project maker for Harbour compiler.

Depending your installation, hbmk2 may be in different locations; such as C:\Harbour\bin or c:\hmg\harbour\bin or anything else.

Hereafter I will assume that your hbmk2 is in C:\hmg\Harbour\bin. If your installation is different, please modify above examples.

Second step is assign an empty folder (directory) for work / test affairs; say C:\test.

And the third step is copying your Clipper program(s) to this folder.

But don’t rush; we have some precautions:

– Better way is starting with a single-program project; if you haven’t written a new one. Don’t uses for now projects have multiple program file.

 – Your program may have some “national” characters and these characters may be differently shown between DOS and Windows. If so, you may want fix manually these differences via a Windows based text editor. Or use a program if you have one. Harbour has a clever tool (HB_OEMTOANSI() function) is usable for this purpose.

 – In Clipper it’s possible a program file without module (procedure / function) definition. If you have such file(s), enclose your code with PROCEDURE — RETURN statement pair.

– Every Harbour project must have one and only one MAIN module (procedure / function). The first procedure / function in your single program file will be considered as MAIN module of your project. (In HMG, name of this module must be “main” also).

– Almost all Clipper commands, statement, functions, pseudo functions, manifest constants etc are usable almost in the same ways with Clipper. May be exist some very few and very rare differences, and of course solving methods for its.

For compile process we will use command box (DOS / console window) of Windows. You can open a console window, with the menu Start -> Run -> cmd or selecting it in the “Command Prompt” from the Start Menu \ All Programs.

 – “Command / console window” size may not appropriate for easy use. You may

      – use a MODE ( DOS ) command :

         MODE CON LINES=54 COLS=148


   – adding a SetMode() statement at the beginning of MAIN module of your project. For example:

       SetMode( 25,  80 )  // 25 line 80 column same as standard 
                           // DOS screen ( but not full screen ! )
       SetMode( 48, 128 )  // 48 line 128 column, may be more readable

Now, we are ready to begin: Enter this command in console window :

 C:\hmg\harbour\bin hbmk2 <mainPrgName>

You don’t need any SET command (such as PATH etc) before this command; hbmk2 will find all necessary paths / files.

For running executable after compile, add a -run switch to the command line :

 C:\hmg\harbour\bin hbmk2 <mainPrgName> -run

Of course, you need supply name of your main .prg file in place of <mainPrgName>.

Note that you don’t need a separate “linking” step; hbmk2 will do everything for you.

You may use this

 C:\hmg\harbour\bin hbmk2 <mainPrgName>

command via a batch ( .bat ) command file (such as “build.bat”) too. In this way you can apply compiling process without console window; run .bat file by double click in the Windows Explorer. In this case you may need add a PAUSE command at end of .bat file.

That’s all.

You know, a program file may contains more than one module (procedure / function). So you may develop your project by adding new modules to your single program file.

In this step you don’t need trying extra features, extensions of Harbour. Before that adventure your primary need is to convert existing project Clipper to Harbour.

When you reach a level of multiple-program file project:

– Basic rules are the same: the first module in the your program file is MAIN module of your project.

If your .prg files contains:

  SET PROCEDURE TO <procedure_File_Name>

 and / or

   #include <procedure_File_Name>

 you may or may not continue using these statement.

 – The shortest way for compiling a multiple-file project is use a .hbp ( Harbour Projet ) file. This is a text file and its simplest form is a file contains list of your .prg files. For example:


and the compile command is the same :

  C:\hmg\harbour\bin hbmk2 <mainProjectFileName>

In this case you don’t need to use SET PROC… and #include … statement and this is the better way.

Because hbmk2 applies “incremental” compiling, that is compiles only modified files.

Under normal circumstances, any module in any program file is callable in anywhere in the project. If you have some modules that exclusive to this program file, you may use STATIC keyword at the beginning of PROCEDURE / FUNCTION statement. For example:


With this syntax you will prevent calling this module outside of this .prg file and the possibility of using this module name into other .prg files.

Example :

Take “A typical Harbour Program” in the “Harbour Sample” page.

As seen at .pdf file by given link, this sample program borrowed from official reference guide of a Clipper compiler. That is, in fact this is a Clipper program and it will may compile with Harbour and run without any modification.

Let’s try.

– Copy and paste this sample and save in your PC with a name say “typical.prg”.

– Comment out the line for now.

 #include "Database.prg" // Contains generic database functions

– Call hbmk2:

 C:\hmg\harbour\bin hbmk2 typical -run

 Note: While working / playing on programs, you may encounter some error messages like:

  Error F0029  Can't open #include file xxx
  Error E0002  Redefinition of procedure or function xxx
  Error: Referenced, missing, but unknown function(s): xxx
  undefined reference to HB_FUN_xxx

 Please don’t panic !

    “Error” is salt and pepper of programming play ! 😉

 The worst situation isn’t getting error, but is unable to stay !

   The “HB_FUN_xxx” may be seen weird at first meet. The “HB_FUN_” is a prefix given by system ( compiler ) to your function; so you need search erroneous point into tour program files without this prefix.

Now, let’s continue to our “typical” program:

If you compile the program with commented out #include … line, possibly it will work, by opening main menu:


But what’s that?

When selected a menu item (except “Quit”) we can’t see other than an empty screen!

Again, don’t panic!

This situation too is not very rare !

If you use vertical scroll bar of command / console window, you will notice that your screen is considerably much longer than seen !

To avoid this conflict, ( as stated above ) we need use a SetMode() function call at top of our Main() procedure ( but AFTER LOCAL statement ! ) :

  SetMode( 24, 79 )

 And now everything is OK.


In fact, not really everything, we have a few “fine adjustment”.

Cut and paste the section after “// Database.prg” to a separate “Database.prg” file, un-comment the “#include …” line and then re-compile.

In this case we have a “multiple prg” project. As stated earlier, better way is using a .hbp file instead of “#include …” statements.

Now comment out ( or delete now ) the #include line.

Build a new text file with name “typical.hbp” and with this content :


And recall hbmk2 without any modification :

C:\hmg\harbour\bin hbmk2 typical -run

That’s all !

Congratulations !

Now you have a multiple-prg project  !

Clipper 5.x RG Summary

About This Summary









Variable Handling

Data Manipulation

Flow Control

User Interface



Global Settings


GET System

Menu System

TBrowse Classes


Database Commands and Statements

Database Functions

RDD Functions

Index Commands and Functions

File Management



Pre-processor Directives

Debugging and Error Handling

Selected Chapters (PDF)

Basic Concepts

The Structure of a Clipper Program

Functions and Procedures

Control Structures


Expressions and Data Types


The Macro (&) Operator


Code Blocks

Objects and Messages

The Database System

The Input-Output System

The Keyboard System

The Low-Level File System

The Browse System

The Get System

Serial Communications with CA-Clipper Tools

Network Programming

Using The Extend System

Extend Functions

DOS Errors

Clipper and Networking