Fox Pro

last modified: March 15, 2012

FoxPro, or VisualFoxPro, is an object-oriented ISAM DBMS currently owned by, but not originating from Microsoft. It's a derivation of early ExBase.


from Microsoft

Well, not really. From David Fulton's "Fox Software" originally based in Ohio. Microsoft bought them when they were clearly kicking everyone else's butt in the desktop DBMS space.

MS purchased FoxPro for two purposes it appears: First, as a hedge in case MS-Access didn't fly in the market (it was in production at the time), and second, to obtain the "Rushmore" performance enhancement technology, which was used in other MS products.

It is first a language (a dialect of xBase), second a DBMS. It doesn't get down on the hardware, but boy, can it sling data.

The "object-oriented" overlay has really done little to enhance the language or the engine.

Yes, the last two versions from FoxSoftware before MicroSoft bought them (2.0 & 2.5) added the table-based storage of screens and reports as well as a subset of SQL (nicely enhanced with some language integration features).


This stuff was deleted for some reason. I put it back.

I think FoxPro blew an opportunity to maximize the use of DataDictionary(s) and ControlTables in place of objects for GUI's, reports, etc. Version 2.6 actually used tables to store screen and report setups (although it was not documented in the formal manuals and appeared a little rushed); but they did not continue with that tradition when they OO'd it for version 3 and on. It could have been something unique, instead becoming a me-too product.

The above statement is incorrect. The Visual versions still store screens, report, visual class libraries, project and intellisense information in Fox tables. They are 'free' tables not tables that belong to a database container. Someone may have deleted the statement because it is incorrect.

It can tend to polarize conversations. ("It's a toy." - "No, it's not." - "Is too." - "Is not.")

As a language xBase sucked. In that sense it *was* a toy. However, its strength was integrating tables into the language and making tables easy to create, browse, and program. If you use tables to organize your applications, then the weakness of the language mattered less. However, it generally lacked views and other virtual tools of relational theory. But that also made it fast in the age of 386's. They later added SQL support, I would note.

I fed my family for almost 10 years with this toy. Not bad for a "hopelessly inadequate" language/DBMS as some of its critics have termed it. Its ability to interactively debug a concept before committing to an approach was something I valued highly.


For an (admittedly poor) example of FoxPro 2.5 (for MsDos) code, see http://josako.freeservers.com/tech/FoxPro/ - JayOsako


RPN Calculator Example (originally posted on usenet)

Here is a quicky FoxPro-based Reverse Polish calculator script that uses a table to define the buttons and their action. Given a choice, I would probably have used parameters to pass around more record references instead of leaving it to global context (one of XBase's S.E. weaknesses) For example, passing around a PHP-style associative array for references to the looked-up Keys (a table) record.

It only does integers, and the validation is rather skimpy. Also, I don't really need the "Op" column since the operations happen to fit the display characters. However, I assumed that they could be different, such as displaying "X" for multiplication instead of an asterisk.

(Shayne originally requested floating point. I skipped that this time around and just did integers because it would have added more validation and formatting nitty gritty that I thought perhaps distracted from structural issues. I hope this is not a problem. Also, some news-readers may mangle the formatting and indentation. If so, I apologize. Try a Courier font if you have problems. Tabs also somehow got mixed in, and you know what they do to formatting.)

Regarding this line here:

calc = operand1 &theOp operand2

The single ampersand implies a syntactical substitution. Thus, if theOp is "+", then this gets executed:

calc = operand1 + operand2

Note that I still don't consider this example very representative of applications that I encounter. But, I thought it might be interesting to see what and how people think of it.

(begin program code)

***** Procedure calculator

set compatible foxplus
set readborder on
set deleted on
set exact on
set confirm on
set safety off

close data
select a
use keys.dbf alias keys
select b
use stack.dbf alias stack
zap

butno = 0
dusplay = ""      && number display ("display" is a reserved word)

*---define GUI window and event handling
IF NOT WEXIST("form1")
 DEFINE WINDOW form1 ;
  AT 8, 40 ;
  SIZE 14,28 ;
  TITLE "Calc" ;
  FONT "Courier New", 10 ;
  FLOAT ;
  CLOSE ;
  MINIMIZE ;
  SYSTEM ;
  COLOR RGB(,,,192,192,192)
ENDIF

activate window form1

&& displays buttons generated from table

select keys
scan
  temp = charcode
  tempparm = '"' + charcode + '"'
  @ Yloc, Xloc get butno ;
    picture "@*HN " + temp valid butpress(&tempparm)
endscan

activate window form1
read cycle modal

return
*--------------------
procedure butpress
parameter theKey
 select keys
 locate for upper(keys->charcode) = upper(thekey)
 do case
 case keys->optype = 'K'     && digit constants
   dusplay = dusplay + charcode
 case keys->optype = 'C'     && commands
   do commands 
 case keys->optype = 'P'     && math operation
   do operations with keys->op
 endcase
 &&----display update
 @ 1,1 say dusplay + space(25 - len(dusplay))
 show gets
return
*--------------------------
procedure commands
 do case
 case keys->charcode = 'P'     && push
   do push with dusplay
   dusplay = ""
 case keys->charcode = 'C'     && clear
   dusplay = ""
 case keys->charcode = 'Q'     && quit
   deactivate window form1
   close all
   cancel
 endcase
return
*--------------------------
procedure operations
parameter theOp
   raw1 = pop()
   raw2 = dusplay
   raw1 = iif(empty(raw1),'0',raw1)  && convert blank to zero
   raw2 = iif(empty(raw2),'0',raw2)  
   operand1 = val(raw1)    
   operand2 = val(raw2)
   && [insert division by zero check here]
   calc = operand1 &theOp operand2
   dusplay = ltrim(str(int(calc)))
return
*--------------------------
procedure push(pushme)
 select stack
 append blank
 replace thevalue with pushme
return
*--------------------------
function pop
 select stack
 result = ""
 goto bottom
 if .not. eof()
   result = stack->thevalue
   delete
 endif
return(result)
*--------------------------

(end program code)

 Table: Keys

 Charcode Optype Op Descript        Xloc      Yloc

 0        K                         5.00     10.00
 1        K                         5.00      4.00
 2        K                        10.00      4.00
 3        K                        15.00      4.00
 4        K                         5.00      6.00
 5        K                        10.00      6.00
 6        K                        15.00      6.00
 7        K                         5.00      8.00
 8        K                        10.00      8.00
 9        K                        15.00      8.00
 P        C         Push           10.00     10.00
 +        P      +  Plus           20.00     10.00
     -        P      -  Minus          20.00      4.00
 *        P      *  Times          20.00      6.00
 /        P      /  Divide         20.00      8.00
 C        C         Clear          15.00     10.00
 Q        C         Quit            5.00     12.00

The other table, "stack", has only one column, "theValue".

[formatting re-work in progress]

-Top-


For anyone who cares, I have a tape calculator I wrote back in the Cretaceous (Fox 2.5b), that exhibits fairly ordinary desktop 10-key calculator behavior, except that it allows editing of the tape.

-- GarryHamilton


See also VisualFoxPro, ExBase


CategoryProgrammingLanguage, CategoryExample


Loading...