Format of xBase Files

xBase File Format Description

xBase File Types

xBase File  Types and Extensions

Ext. File Type  Introduced or used by
.$$$ temporary file  dBASE III
.$db temporary file  dBASE IV
.act FoxDoc Action Diagrams  FoxPro
.app application object file  dBASE Appl. Generator
.app generated application  FoxPro
.bak Backup file  dBASE
.bar horizontal bar menu object file  dBASE Appl. Generator
.bin Binary files  dBASE
.bch batch process object file  dBASE Appl. Generator
.cac executable when caching on/off  dBASE IV
.cat catalog  dBASE III, IV
.cdx compound index  FoxPro
.ch header file  Clipper
.cht interface file for ChartMaster  dBASE
.clp compiler script file (clip list)  Clipper
.cmd command  dBASE – Waffle
.cod template source file  dBASE Appl. Generator
.cpt encrypted memo file  dBASE
.crp encrypted database  dBASE IV
.ctl control file  dBASE IV – Aldus Setup
.cvt backup file for CONVERTed database file  dBASE IV
.db configuration  dBASE
.db$ temporary file  dBASE
.db2 database  dBASE II
.db3 database  dBASE III
.dbf database file  dBASE – FoxPro
.dbk database backup  dBASE IV
.dbo compiled program  dBASE IV
.dbt FoxBASE+ style memo  FoxPro
.dbt memo file for database w/same name  dBASE – Clipper
.def Definitions list  dBASE
.dif Data Interchange Format. For APPEND FROM, COPY  dBASE – VisiCal
.doc Documentation text file  dBASE Appl. Generator
.fil files list object file  dBASE Appl. Generator
.fky macro file  FoxPro
.fmo compiled format file  dBASE IV
.fmt format file  dBASE – FoxPro – Clipper
.fp configuration file  FoxPro
.fpc catalog  FoxPro
.fpt memo  FoxPro
.fr3 renamed dBASE III+ form file  dBASE IV
.frg uncompiled report file, code fragment file  dBASE IV
.frm report file  dBASE – Clipper
.fro compiled report file  dBASE IV
.frt report memo  FoxPro
.frx report  FoxPro
.fw2 Framework spreadsheet or database file  Framework – dBASE
.fxp compiled format  FoxPro
.gen compiled template  dBASE Appl. Generator
.idx index (many)  FoxPro
.ind include index  dBASE IV
.inx index  FoxBase
.key Key macro library  dBASE
.lbg label generator data  dBASE IV
.lbl label  dBASE – Clipper
.lbo compiled label  dBASE IV
.lbt label memo  FoxPro
.lbx label  FoxPro
.ld1 overlay file  dBASE
.log Transaction log file  dBASE
.mbk multiple index file backup  dBASE IV
.mdx multiple index file  dBASE IV
.mem memory variable save file  dBASE – FoxPro
.mnt menu memo  FoxPro
.mnx menu  FoxPro
.mpr generated program  FoxPro
.mpx compiled menu program  FoxPro
.ndx index file  dBASE
.npi source for DGEN.EXE interpreter  dBASE Appl. Generator
.ntx index file  Clipper
.pjt project memo  FoxPro
.pjx project  FoxPro
.plb library  FoxPro
.pll pre-linked library  Clipper
.plt pre-linked transfer file  Clipper
.pop pop-up menu object  dBASE Appl. Generator
.ppo pre-processor output  Clipper
.pr2 printer driver  dBASE IV
.pr3 PostScript printer driver  dBASE IV
.prf printer driver  dBASE IV
.prg program source file  dBASE – FoxPro – Clipper
.prs procedure  dBASE IV
.prt Print dump  dBASE
.prx compiled program  FoxPro
.qbe saved query (Query By Example)  dBASE IV – Quattro Pro
.qbo compiled query  dBASE IV
.qpr generated query program  FoxPro
.qpx compiled query program  FoxPro
.qry query  dBASE IV
.res dBASE resources  dBASE IV
.rpd Rapid file. For IMPORT/EXPORT,APPEND  FROM, COPY  dBASE
.sc3 renamed dBASE III screen mask file  dBASE IV
.scr screen – screen snapshot  dBASE IV
.sct screen memo  FoxPro
.scx screen  FoxPro
.spr generated screen program  FoxPro
.spx compiled screen program  FoxPro
.str structure list object file  dBASE Appl. Generator
.t44 Temporary file for Sort or Index  dBASE IV
.tbk memo backup  dBASE IV – FoxPro
.tvf table view settings  dBASE
.upd update data  dBASE
.upo compiled update data  dBASE
.val values list object file  dBASE Appl. Generator
.vew view file  Clipper, Lotus Approach
.vue view  dBASE IV – FoxPro
.w44 temporary file for Sort or Index  dBASE
.wfm form object  dBASE Form Designer
.win window file  FoxPro – dBASE

Source :  http://www.clicketyclick.dk/databases/xbase/format/index.html

Notes:

–          Such a list can’t be perfect. Some item may be obsolete / forgotten and something may not exist when this list compiled.

–          “Clipper” may not include all versions of Clipper.

–          Most of Clipper files are supported by Harbour.

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

       or

   – 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:

myprog01.prg
myprog02.prg
myprog03.prg
myprog04.prg

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:

STATIC FUNCTION OpenTable()

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:

Typical_1

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.

Typical_2

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 :

Typical.prg
DataBase.prg

And recall hbmk2 without any modification :

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

That’s all !

Congratulations !

Now you have a multiple-prg project  !

How I can make an .exe ?

Making .exe (executable) means building application. So you may find answer of this question here.

Anyway I will work to re-describe the process by a simpler way:

Almost every HMG sample have two .bat file: build.bat and ide.bat and using these files are quite simple:

Open command / console window, go to directory ( by CD command) of the sample you want to compile, and enter a simple command :

build demo <- will build demo.exe from demo.prg
or
ide demo <- open HMG-IDE with demo.prg

( IDE will wait your “run” command by pressing “run” button.)

So you may use this two .bat files for your projects too.

Copy build.bat and / or ide.bat to your working <dir>, and modify them this way:

build.bat :

call c:\hmg\build.bat <myProject> | <myProgram>

ide.bat :

c:\hmg\ide\ide.exe <myProject> | <myProgram>

Note : in this syntax “|” means “or”; you don’t need enter both project and program file names nor this sign; simply enter either one or other.

Change:

– “c:\hmg\” depending on your environment (installation); such as c:\hmg.3.1.1\ or antything else;

– <myProject> | <myProgram> to your project / program file name.

Project file is a text file with “.hbp” extension and contains a list of name(s) of your program file(s).

After building such .hbp file, you may open it from directly HMG-IDE ( by “open project command) and again, you may build your .exe by  pressing “run” button.

HMG Message functions

As noticed in Hello Word – 3 sample, HMG has a lot of message functions with name prefixed by “Msg”:

MsgBox() :

Shows a Message Box

Syntax: MsgBox(<cMessage>,[<cTitle>]) –> Nil

Example : MsgBox( “This a simple message”, “MsgBox Example” )

MsgExclamation() :

Shows a message box with an exclamation icon and a special sound.

Syntax: MsgExclamation(<cMessage>,[<cTitle>]) –> Nil

Example : MsgExclamation( “Wrong selection !”, “MsgExclamation Example” )

MsgInfo() :

Shows a message box with an information icon and a special sound.

Syntax: MsgInfo (<cMessage>,[<cTitle>]) –> Nil

Example : MsgInfo( “For your information”, “MsgInfo Example” )

MsgStop() :

Shows a message box with an stop icon and a special sound.

Syntax: MsgStop(<cMessage>,[<cTitle>]) –> Nil

Example : MsgStop( “End of file reached”, “MsgStop Example” )

MsgOkCancel() :

Shows a message box with [Ok] and [Cancel] buttons

Syntax: MsgOkCancel(<cMessage>,[<cTitle>]) –> lResponse

Example : MsgOkCancel( “Are your to exit ?”, “MsgOkCancel Example” )

MsgRetryCancel() :

Shows a message box with [Retry] and [Cancel] buttons

Syntax: MsgRetryCancel(<cMessage>,[<cTitle>]) –> lResponse

Example: MsgRetryCancel( “File open error !”, “MsgRetryCancel Example” )

MsgYesNo() :

Shows a message box with [Yes] and [No] buttons

Syntax: MsgYesNo( <cMessage> , <cTitle> ) –> lResponse

Example: MsgYesNo( “Are you sure to delete file ?”, “Confirm Delete” )

Like MsgBox(), all message functions accept parameters as a string constant representing the message itself. All message functions also have a second parameter, again a string constant representing the title of message box.

As noticed in syntax, the first four message functions returns NIL, and the last three returns a logical value.

<lResponse> is .T. when selected first option; Ok, Retry and Yes.

Try and observe results.

Hints :

– As a rule, every HMG project must have one and only one “Main” window. This message functions are exception of this rule. If you have only message function(s) you can build a program without main window.

– For multiple lines message body you may use CRLF. CRLF is a predefined constant in HMG. If required you may define it:

CRLF := HB_OsNewLine()

Example :

MsgBox( "This is a" + CRLF + "multiple line" + CRLF + ;
        "message", CRLF + "Multi-Line" )

– Since message function accept only “C” ( Character ) type arguments as <cMessage> and <cTitle>; for messaging other that ‘C’ type arguments, you may use appropriate function to convert  to character type. See below for an example.

Example :

/*
 HMG Message functions
*/
#include <hmg.ch>

dToday := DATE()
lMaried := .T.
nSalary := 123.456

PROCEDURE Main()
  SET DATE GERM
  SET CENT ON

  dToday := DATE()
  lMaried := .T.
  nSalary := 123.456
  DEFINE WINDOW frmMsgFuncs ;
     AT 0,0 ;
     WIDTH 400 ;
     HEIGHT 200 ;
     TITLE 'Message Functions' ;
     MAIN
     DEFINE MAIN MENU

        DEFINE POPUP '&Test'

          ITEM 'Msg&Box' ACTION ;
                MsgBox( "This a simple message", "MsgBox Example" ) 
          ITEM 'Msg&Exclamation' ACTION ;
                MsgExclamation( "Wrong selection !", "MsgExclamation Example" ) 
          ITEM 'Msg&Info' ACTION ;
                MsgInfo( "For your information", "MsgInfo Example" )
          ITEM 'Msg&Stop' ACTION ;
                MsgStop( "End of file reached", "MsgStop Example" ) 
          ITEM 'Msg&OkCancel' ACTION ;
                MsgOkCancel( "Are your to exit ?", "MsgOkCancel Example" ) 
          ITEM 'Msg&RetryCancel' ACTION ;
                MsgRetryCancel( "File open error !", "MsgRetryCancel Example" )
          ITEM 'Msg&YesNo' ACTION ;
                MsgYesNo( "Are you sure to delete file ?", "Confirm Delete" )
 ITEM 'Multiple &Line' ACTION ; 
       MsgBox( "This is a" + CRLF + "multiple line" + CRLF + ;
               "message", CRLF + "Multi-Line" ) 
 ITEM 'Non-Character' ACTION ; 
       MsgBox( "Today : "   + DTOC( dToday ) + CRLF +;
               "Married : " + IF( lMaried, "Yes", "No" ) + CRLF +;
               "Salary : "   + LTRIM( STR( nSalary ) ) ,;
               "Non-Char" )
 SEPARATOR

 ITEM "E&xit" ACTION ThisWindow.Release

END POPUP // File

END MENU // Main()

END WINDOW // Main

CENTER WINDOW frmMsgFuncs

ACTIVATE WINDOW frmMsgFuncs

RETURN // Main()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._-._.-._.-._.-._.-._.-._.-._.-

Hello World – 3

Don’t worry ! This is the last; and important.

Extract DEFINE LABEL – END LABEL structure or @ …,… LABEL command ( which one is currently exist) and then instead of them place this line :

MsgBox( "Hello World !" )

In HMG, there are a lot of message functions, with name prefixed by “Msg“; for details please look at HMG Message Functions page.

After building and running, try a more important feature: reduce your program to these minimum size:

#include <hmg.ch>
PROCEDURE Main
   MsgBox( "Hello World !" )

RETURN // Main()

In fact, as a rule, every HMG project must have one and only one “Main” window. This message functions are exception of this rule. If you have only message function(s) you can build a program without main window.

Hello World – 2

In the our first example in first Quick Start page, we wrote the “Hello World” clause on the title bar. Now, let’s put it on the form.

Build a new project with “HelloWorld2” name, copy HelloWord.prg to HelloWorld2.prg and change it as below:

#include <hmg.ch>
PROCEDURE Main()
   DEFINE WINDOW frmHWLabel ;
      AT 0,0 ;
      WIDTH 400 ;
      HEIGHT 200 ;
      TITLE 'Hello World-2' ;
      MAIN 

      DEFINE LABEL lblHello
         ROW 75
         COL 125
         VALUE "Hello World !"
         FONTNAME "Lucida"
         FONTSIZE 16
      END LABEL

    END WINDOW 

    ACTIVATE WINDOW frmHWLabel

RETURN // Main()

DEFINE LABEL and END LABEL statements are for “Label” definition structure for the a window ( in this example Windows named as “frmHWLabel ” ). Label itself must have a name (“lblHello” in this example), and this name must be unique, such as a variable name. Beginning these names with a descriptive prefix ( “lbl” in the example) is a good programming practice.

Between DEFINE – END statements there are main properties of this label. Row, col numbers ( in pixels of course),value (for labels, value is a string constant to write in the your form/window) and font properties (NAME and SIZE)

Almost every GUI control definitions HMG have two syntax : With DEFINE and END structure and with @ command.Thus in the above example instead of DEFINE LABEL and END LABEL structure, you can use alternate @ syntax :

@ 75, 125 LABEL lblHello ;
          VALUE "Hello World !" ;
          FONT "Lucida" ; 
          SIZE 16

A last note for this example : place

CENTER WINDOW frmHWLabel

statement END WINDOW statement and notice that how much HMG is powerful.

HelloWordLabel

PutFile() with 5th parameter

Beware : This article posted on  February 2, 2013 and than with HMG 3.1.3 release on 23 May 2013 added 5th and 6th parameters to that function by our genius Dr. Soto …

Look at changelog of HMG.

 

PutFile() is a HMG function that :

Opens ‘Save As’ System Dialog And Returns The Saved File name

Syntax:

PutFile ( acFilter , cTitle , cIniFolder , lNoChangeDir ) –> cSavedFileName

Although its name is “Put”, this function doesn’t “put” anything to anywhere; that is don’t write anything to disk. It only return a file name ( or empty string if user not selected / typed anything). File that name returned by PutFile() may exist or not. This is only difference between PutFile() and GetFile(); the second return only name of an existing file.

Therefore PutFile() function doesn’t check overwrite status. This is totally responsibility of programmer and if not care, PutFile() become a dangerous tool. The “Default File Name” and network environments will increase the risk. Of course no problem for intentionally overwrite.

As a result, PutFile() open a “Save As…” dialog box and returns a file name to save, selected / typed by user.

As above syntax indicated, this function has four parameters.

Whereas sometime required a bit more info : default file name.

When program suggest a default file name, in addition to select / type a new file name, user may feel more comfortable by only confirm (verbatim or after typing something) suggested file name.

This is a bit modified version of PutFile() (with a small test program); since accept default file name as 5th parameter, name is PutFile5P()

Note : This work is superseded by adding two parameters to official PutFile() function at HMG 3.1.4 2013/06/16.

Happy HMG’ing 😀

PutFile5P

~~~~~~~~~~~~~~~~

/*

  HMG Common Dialog Functions 
  PutFile5P() Test prg.

*/
#include "hmg.ch"
PROCEDURE Main()
  LOCAL nTask
  DEFINE WINDOW Win_1 ;
     AT 0,0 ;
     WIDTH 400 ;
     HEIGHT 400 ;
     TITLE 'PutFile with Default File Name' ;
     MAIN
     DEFINE MAIN MENU
        POPUP 'Common &Dialog Functions'
           ITEM 'PutFile5P()'ACTION MsgInfo( Putfile5P( ;                       
                { {'Text Files','*.txt'} },; // 1° acFilter ;
                   'Save Text',;             // 2° cTitle 
                   'C:\',;                   // 3° cIniFolder 
                   ,;                        // 4° lNoChangeDir 
                  "New_Text.TXT" ) )         // 5° cDefaultFileName
       END POPUP
    END MENU
  END WINDOW
  ACTIVATE WINDOW Win_1
RETURN // TestPF5P.PRG
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*-----------------------------------------------------------------------------*
FUNCTION Putfile5P ( aFilter, title, cIniFolder, nochangedir, cDeFilName )
*-----------------------------------------------------------------------------*
   LOCAL c:='' , n

   IF aFilter == Nil
      aFilter := {}
   EndIf

   IF HB_ISNIL( cDeFilName )
      cDeFilName := ''
   ENDIF 

   FOR n := 1 TO Len ( aFilter )
       c += aFilter [n] [1] + chr(0) + aFilter [n] [2] + chr(0)
   NEXT

RETURN C_PutFile5P ( c, title, cIniFolder, nochangedir, cDeFilName )
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma BEGINDUMP
#define HB_OS_WIN_USED
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include "hbapi.h"
#include "hbapiitm.h"

HB_FUNC ( C_PUTFILE5P )
{

 OPENFILENAME ofn;

 char buffer[512];

 int flags = OFN_FILEMUSTEXIST | OFN_EXPLORER ;

 if ( hb_parl(4) )
 {
 flags = flags | OFN_NOCHANGEDIR ;
 }

 if( strlen( hb_parc( 5 ) ) != 0 )
 strcpy( buffer, hb_parc( 5 ) );
 else
 strcpy( buffer, "" );

 memset( (void*) &ofn, 0, sizeof( OPENFILENAME ) );
 ofn.lStructSize = sizeof(ofn);
 ofn.hwndOwner = GetActiveWindow() ;
 ofn.lpstrFilter = hb_parc(1) ;
 ofn.lpstrFile = buffer;
 ofn.nMaxFile = 512;
 ofn.lpstrInitialDir = hb_parc(3);
 ofn.lpstrTitle = hb_parc(2) ;
 ofn.Flags = flags;

 if( GetSaveFileName( &ofn ) )
 {
 hb_retc( ofn.lpstrFile );
 }
 else
 {
 hb_retc( "" );
 }
}
#pragma ENDDUMP

HbRun

HbRun is a console interpreter and program ( command file / script file / .prg / .hrb ) runner for the Harbour Language.

Addendum: a clarification by Przemek:

HBRUN is a simple wrapper to Harbour compiler so the same syntax as in
Cl*pper is supported:

DO <filename>[.prg]

only .prg is accepted as extension and it’s default so you do not
have to set it explicitly.

( In Harbour Users Google group, under “hbmk2 and the Dot Prompt” topic:

It can work as interpreter when invoked without parameters or can execute xBase / Harbour source code in .prg file or compiled Harbour Portable Objects (.hrb) file given as parameter.

Type of file is recognized by extension used with <file> parameter. If not given then .hrb is used.

In other words, HbRun can be use in both interpret  and batch mode.

Regarding parameter given or not, when calling HbRun this ‘mode’ determined by program itself. If a parameter ( usually a .prg or .hrb file name ) given, program run in ‘batch’ mode, runs (executes) given script file and end. If no parameter given, program enter interpreter mode.

Using HbRun as an interpreter, may be very useful, productive, and educative for xBase programmers. Too many xBase programmers was learned everything, including   DBF file system and xBase programming language by famous “dot prompt”. Today many xBase programmers uses HbRun daily basis.

When HbRun begin, open a console screen with two basic area: status bars at top and dot prompt line at bottom.

Status bars :

 hbrunStatLines

Dot prompt is quite simple visually: a dot and a  line in inverse color beginning with a blinking cursor :

 hbRunDotPrompt

You may enter here a command to see the result.

For example “DIR” command will give a list of database (.dbf) files in current directory:

hbRun_Dir

SET COLO TO “GR+/N” command will remember you old days :

hbRun_Dir2

The DIR command can be used with DOS style “filter / skeleton” parameter :

DIR *.PRG
DIR *.*

etc.

Inspecting any table ( .dbf file ) is very simple:

USE CLIENTS
BROWSE ()

 hbrunBrowse

 Expand a little:

SET COLO TO “GB+/N”
USE CLIENTS
BROWSE( 3, 10, 24, 60 )

hbrunBrowse2

If you plan to use this snap frequently, make a .prg file (say brwclien.prg) with this three line and run it with DO command:

DO BRWCLIEN

Sometime LIST command may be better:

LIST CL_ID, CLI_SNAM, CLI_NAME, CLI_TLF

hbrun_list

 You can add FOR clause to the LIST command:

LIST CL_ID, CLI_SNAM, CLI_NAME, CLI_TLF FOR RECN() < 10

or

LIST CL_ID, CLI_SNAM, CLI_NAME, CLI_TLF FOR EMPTY( CLI_TLF )

The structure info of a table frequently requires while daily work to xBase Programmers.

Here three small programs for obtain structure info of a table. Usage is quite simple: open ( USE ) your table and enter DO <prgFileName>; for example:

USE CLIENT
DO LISTSTRU
or
DO DISPSTRU
or
DO SAVESTRU

 Notes :

–      To avoid some possible screen metric conflicts caused by default console (DOS box) settings of OS, may be useful some adjusting before invoke HbRun; such as:

MODE CON LINES=48 COLS=128

–       “?” command may be useful as a built-in calculator :

? 2*2           // 4
? 2**8          // 256
? SQRT( 81 )    // 9

–      HbRun keep a “history” for commands entered (for a limited count of commands of course). You can access (and re-enter when required) by using up and down keys. Moreover this history may be usable after re-invoke HbRun.

–      Though Harbour Language is essential, some legal Harbour commands / functions may be un-recognizable by HbRun.

–      Though some legal statements works in interpret mode, may not works in batch mode (such as Browse() ).

Last Note : No further explanation required for experienced xBase programmers; try, see and learn.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Examples :

 
/*
 DispStru.prg 

 Display structure of current table ( .dbf file ) on screen.

*/
MEMVAR ASTRUCT, NTOTLEN
IF EMPTY( ALIAS() )
   SETCOLOR( "R/N" )
   ? "No active table in the current work area !", LTRIM( STR( SELECT() ) )
ELSE 
   @ 3, 0 CLEA TO MAXROW() - 1, MAXCOL()
   aStruct := DBSTRUCT()
   nTotLen := 1
   AEVAL( aStruct, { | a1Field | nTotLen += a1Field[ 3 ] } )
   AEVAL( aStruct, { | a1Field, n1FieldNo | ;
   aStruct[ n1FieldNo ] := STR( n1FieldNo, 3 ) + " " +;
                           PADR( a1Field[ 1 ], 12 ) +;
                           PADC( a1Field[ 2 ], 4 ) +;
                           PADL( a1Field[ 3 ], 5 ) +;
                           PADL( a1Field[ 4 ], 3 ) } )
   ? "Structure of database :", DBINFO( 10 )
   ? "Number of data records :", LTRIM( STR( LASTREC() ) )
   ? "Date of last update :", LUPDATE()
   ? "Fld Name Type Width Dec"
   ? "--- ---------- ---- ----- ---"
   @ 21,0 SAY "** Total ** " + PADL( nTotLen, 6 )
   ACHOICE( 8, 0, 20, 30, aStruct ) 
ENDIF
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
 ListStru.prg 

 List structure of current table ( .dbf file ) on screen.

*/
MEMVAR ASTRUCT, NTOTLEN
IF EMPTY( ALIAS() )
   SETCOLOR( "R/N" )
   ? "No active table in the current work area !", LTRIM( STR( SELECT() ) )
ELSE 
   @ 3, 0 CLEA TO MAXROW() - 1, MAXCOL()
   aStruct := DBSTRUCT()
   nTotLen := 1
   AEVAL( aStruct, { | a1Field | nTotLen += a1Field[ 3 ] } ) 
   AEVAL( aStruct, { | a1Field, n1FieldNo | ;
   aStruct[ n1FieldNo ] := STR( n1FieldNo, 3 ) + " " +;
                           PADR( a1Field[ 1 ], 12 ) +;
                           PADC( a1Field[ 2 ], 4 ) +;
                           PADL( a1Field[ 3 ], 5 ) +;
                           PADL( a1Field[ 4 ], 3 ) } )
   ? "Structure of database :", DBINFO( 10 )
   ? "Number of data records :", LTRIM( STR( LASTREC() ) )
   ? "Date of last update :", LUPDATE()
   ? "Fld Name Type Width Dec"
   ? "--- ---------- ---- ----- ---"
   AEVAL( aStruct, { | c1Field | QOUT( c1Field ) } ) 
   ? "** Total ** ", PADL( nTotLen, 5 )
ENDIF
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
SaveStru.prg

 Save structure of current table ( .dbf file ) to a file.

 Notes :

 - This program uses ListStru.prg
 - Name of target file constructed at line 18; 
   if required you may use alternate ways or
   simply using a constant.
*/
MEMVAR AlteFName
IF EMPTY( ALIAS() )
   SETCOLOR( "R/N" )
   ? "No active table in the current work area !", LTRIM( STR( SELECT() ) )
ELSE 
   AlteFName := LEFT( ALIAS(), 4 ) + "STRU" 
   SET ALTE TO &AlteFName
   SET ALTE ON
   DO LISTSTRU
   SET ALTE OFF
   SET ALTE TO
ENDIF
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~