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. 

* I thought I spotted some tabled GUI elements in VisualFoxPro 5 also.

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