How I can build …

Building Harbour, HMG, Projects 

How I can build Harbour and / or HMG ?

How I can build a Harbour applications ?

How I can build a HMG applications ?

How I can build a console application via HMG ? 

How I can make an .exe ?

Print File

 Send a file to printer

Once builded a file contains lines to print, seems it’s easy sending that file to printer :

COPY FILE command send entire file to another file or a device :

COPY FILE <xcSourceFile> TO <xcTargetFile>|<xcDevice>

Arguments:

<xcSourceFile> is the name of the source file to COPY including the extension.

<xcTargetFile> is the name of the target file including the extension.

<xcDevice> is the name of the device where all subsequent output will be sent. You can specify a device name as a literal character string or a character expression enclosed in parentheses. Additionally, a device can be either local or network. If you COPY TO a non-existing device you create a file with the name of the device. When specifying device names, do not use a trailing colon.

Example :

COPY FILE Prnfile.txt TO LPT1

Remember that above last command doesn’t work under Windows. Almost all Clipper commands and functions are usable in Harbour. You can apply above tests with Harbour too. And the result not changed again. Because problem isn’t compiler, but hardware and OS difference. Harbour offers additional (extended) easy ways to manage printer(s) :

 WIN_PRINTEREXISTS()     (old name: PRINTEREXISTS())
 WIN_PRINTERSTATUS()     (old name: XISPRINTER())
 WIN_PRINTERPORTTONAME() (old name: PRINTERPORTTONAME())
 WIN_PRINTERLIST()       (old name: GETPRINTERS())
 WIN_PRINTERGETDEFAULT() (old name: GETDEFAULTPRINTER())
 WIN_PRINTERSETDEFAULT() (old name: SETDEFAULTPRINTER())
 WIN_PRINTFILERAW()      (old name: PRINTFILERAW())
For sending a file to printer we need only two of above function :
 WIN_PRINTERGETDEFAULT() 
 WIN_PRINTFILERAW()

If we have alredy above Prnfile.txt, sending it to printer seems easy :

 cDefaultPrinter := WIN_PRINTERGETDEFAULT() 
 WIN_PRINTFILERAW( cDefaultPrinter, Prnfile.txt )

Is that all ?

WIN_PRINTFILERAW() returns 1 if sending to printer was successful. If you test this, probably you will get 1.

May be easy like this ?

Unfortunatelly answer is “sometime” …

Although WIN_PRINTFILERAW() said “sending is successful” you may get nothing from printer.

What is meaning of “sometime” ? May be “sometime” in physic ?

In physic no, but in Windows yes !

What ?

Because some printers or some versions of Windows due to something obscure …

… doesn’t support “raw” printing 😦

And a more interesting thing :

You may send your “raw” file to printer via NotePad program of Windows :

cOutFName := "Test_Raw.txt"
cCmd := "NOTEPAD /P " + cOutFName

RUN ( cCmd)

( The “/P” parameter / switch means direct printing;  without NotePad open)

When sent this file by WIN_PRINTFILERAW() to printer noting happen, but by above (notepad) way sending is successful 😦

It seems that NOTEPAD build a “printable” document from our “raw” file and send this document to printer instead of our file.

However, NOTEPAD always add print file name to top, and page number to bottom of document; and treats our “printer control codes” as data, so printers never use them in “right”  way.

Other ways :

EXECUTE FILE "NOTEPAD.EXE" PARAMETERS cFileName

(  EXECUTE FILE   is a HMG command.

SHELLEXECUTE( 0, "print", cFileName )

Send to file

Write data to a file

Sending lines to a file is quite easy :

In addition of SET PRINTER on | OFF | <xlToggle> command, SET PRINTER, (like many other SET commands,) has a second form distinguished by TO keyword:

SET PRINTER TO [<xcDevice> | <xcFile> [ADDITIVE]]

The on|OFF form of SET PRINTER controls whether the output of console commands is echoed to the printer.

TO <xcDevice> identifies the name of the device where all subsequent printed output will be sent.

TO <xcFile> identifies the name of the output file. ( If a file extension is not specified, (.prn) is assumed.)

By using that last method we can send our lines to a file, instead of sending directly to printer:

 SET PRINTER TO Prnfile.txt
 SET DEVICE TO PRINTER
 SET PRINTER ON
 //
 @ 0, 0 SAY "This goes to Prnfile.txt"
 ? "So will this!"
 //
 SET DEVICE TO SCREEN
 SET PRINTER OFF
 SET PRINTER TO // Close the print file

Note that, though our target is not printer, we have use a SETting printer ON.

We have another method for sending someting to a file may be SET ALTERNATE command:

 SET ALTERNATE TO [<xcFile> [ADDITIVE]]
 SET ALTERNATE on | OFF | <xlToggle>

SET ALTERNATE is a console command that lets you write the output of console commands to a text file. Commands such as LIST, REPORT FORM, LABEL FORM, and ? that display to the screen without reference to row and column position are console commands. Most of these commands have a TO FILE clause that performs the same function as SET ALTERNATE. Full-screen commands such as @…SAY cannot be echoed to a disk file using SET ALTERNATE. Instead you can use SET PRINTER TO <xcFile> with SET DEVICE TO PRINTER to accomplish this.

SET ALTERNATE has two basic forms. The TO <xcFile> form creates a DOS text file with a default extension of (.txt) and overwrites any other file with the same name. Alternate files are not related to work areas with only one file open at a time. To close an alternate file, use CLOSE ALTERNATE, CLOSE ALL, or SET ALTERNATE TO with no argument.

The on|OFF form controls the writing of console output to the current alternate file. SET ALTERNATE ON begins the echoing of output to the alternate file. SET ALTERNATE OFF suppresses output to the alternate file but does not close it.

Examples :

This example creates an alternate file and writes the results of the ? command to the file for each record in the Customer database file:

 SET ALTERNATE TO Listfile
 SET ALTERNATE ON
 USE Customer NEW
 DO WHILE !EOF()
 ? Customer->Lastname, Customer->City
 SKIP
 ENDDO
 SET ALTERNATE OFF
 CLOSE ALTERNATE
 CLOSE Customer

A single difficulty may be making choose the best between possible methods

You can download a working example prg with a sample .dbf from here :

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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

How I can migrate ?

How I can migrate DOS  to Windows ?

By principle, Harbour  can compile every Clipper Language program; and Harbour applications can run under Windows ( besides many other platforms ) with no problem. This is one of main goals of Harbour project.

Furthermore, Harbour compiled executables will be 32 bit, not 16 😉

Maybe your application include many ( or too many ) .prg file; no problem; (almost) no modification required on your source code; nor extra scripts for compile. ( Thanks to Viktor Szakáts for really wonderful MAKE utility : HBMK2. )

Only  care is :  if “main” prg of your application doesn’t have a “main” module , add one PROCEDURE or  FUNCTION statement to most top of your “main” .prg.

PROC MAIN

That’s all 🙂

You can build your application via HMG by a .bat file (or direct command in the DOS box) such as :

CALL C:\hmg\build.bat /c <mainPrgName>

or via Harbour:

SET PATH=C:\harbour\bin;C:\hmg\mingw\bin;%PATH%
hbmk2 <mainPrgName> -RUN

or the simplest way :

    C:\harbour\bin hbmk2 <mainPrgName> -RUN

( hbmk2 will find all necessary  paths / files 🙂 )

Of course, you need supply name of your main .prg file in place of <mainPrgName>. You may also want to  change  “C:\hmg” and “C:\hmg\harbour” according to your install configuration.

Please be careful about PATH command : If you call the the .bat file from Windows explorer, no problem. If you are working on command (DOS) box, calling repetitively .bat file may cause problem by grown of PATH . In this case you may build a separate .bat for only PATH command and call it only once at beginning of DOS session.

If you want convert a text (console) based application to GUI ( Graphical User Interface ) based Windows application, this is another thing and there isn’t any automatic way for this.  You have need first a GUI library can be used into Harbour. After selecting which library is convenient to your needs and learning  this library, you may begin planing steps of converting process. Writing your application from scratch may be longest but most secure way.

There are links to some articles  about migration in the Links page; looking at this will be useful.

Building console application

How I can build a console application via HMG ?

We have a paradox here: though HMG is a GUI library, we are requesting a non-GUI service; since console means non-GUI.

But don’t wory, this is possible; even very easy, such as any HMG application, and with more than one method.

Method 1: Batch processing:

( Assuming HMG root folder is C:\hmg and name of your console application project file name is ConsOnly.HbP and your main prg file name is ConsOnly.Prg )

call c:\hmg\build.bat /c ConsOnly

( No matter ConsOnly is a project or program file. )

If your project has more than one .prg file, you may use build.bat such ways:

1- call c:\hmg\build.bat /c progr1 progr2 prog3 ...

.OR.

2- First build a .hbp file contains such as:

progr1
progr2
prog3

and say name is “ConsOnly.Hbp” then invoke build.bat:

call c:\hmg\build.bat /c ConsOnly

The /c ( or /C ) switch inform build.bat about console.

You can omit this switch, by adding this line to top of your .prg file:

REQUEST HB_GT_WIN_DEFAULT

Method 2: Via HMG-IDE:

First you need add abowe

REQUEST HB_GT_WIN_DEFAULT

line to top of your .prg file.

And then, building a project file ( .hbp ). For example if your .prg file name is ConsOnly.prg, you may use a ConsOnly.HbP  file contains one line:

ConsOnly.prg

If your project has more than one .prg file, your project file contains a list of that .prg files. For example:

progr1
progr2
prog3

You may build this project file simply writing with a text editor or by selecting “New Project” within HMG-IDE.

And only thing is pressing “Run” button.

Yo don’t need any other thing.

Caution:

Don’t include

#include <hmg.ch>

line into console-only .prg’s.

Technically no problem, you can add. Moreover with this  way, though project is console mode,   you can see error messages in GUI mode. But has a risk: may be some HMG functions have same names with Harbour and if you include “hmg.ch”, HMG functions will override others; an example may be  BROWSE(). If this is your intend,  no problem. But this situation sometime may be a nightmare.