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 ?
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 )
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 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 :
Dot prompt is quite simple visually: a dot and a line in inverse color beginning with a blinking cursor :
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:
SET COLO TO “GR+/N” command will remember you old days :
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 ()
Expand a little:
SET COLO TO “GB+/N”
USE CLIENTS
BROWSE( 3, 10, 24, 60 )
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
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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.