TBrowse class compatibility to Cl*pper 5.3

807 views
Skip to first unread message

Kristian

unread,
Apr 4, 2014, 12:53:36 PM4/4/14
to harbou...@googlegroups.com
Hi Folks,

I am just trying to migrate to Harbour due to our WinXP -> Win7 upgrade. I should mention that I am no programming expert, but I have done Cl*pper programming for 25 years to create my own accounting and other database applications. I have been hesitant to use harbour, and it has been a difficult start, but I have successfully compiled one of my simpler applications, and it seems to work.

For most others of my applications, I am encountering a problem. It appears that the class definitions for the tBrowse object have been modified. I cannot find a documentation of the object anywhere (something like the .ng files for Cl*pper would be great) but in the debugger and in the tbrowse.prg I can see a number of new properties and methods. However, it appears that the "hack" to the object's internals as Hannes Ziegler described in his tbinfo.txt and tbmore.txt does no longer work. This is a pity because I have written a whole library of supporting functions for tBrowse objects, like placing a bar in the columns heading to mark the sorting column, placing sums or other data in additional footlines etc. One of the most important tasks is to find the actually visible columns and their positions on the screen. It was possible to copy the object into an array with a simple ACOPY and to find a huge number of interesting internal variables in there.

Now I have the impression that a variety of these data is now available directly, and I may rewrite my libraries using harbour's new tBrowse properties. But this is some effort, and it would mean to abandon the perfectly functioning code that is already written. What I would actually want to do is to maintain and extend my applications on a WinXP system and use harbour only to produce a 32bit release for the other workstations when the job is done.

In the tbrowse.prg it says that the first 18 elements of the class description are identical to Cl*pper, and it appears that the internal variables I am referring to are now packed into a property called "dummy". But that variable is always empty. And my first attempt to read out a column position by accessing tbrowse:acellvalues[x,y] results in a BASE/42 protected error. It seems to me that I will take a long time to gather all the information I need to get something running on harbour with a lot of modifications that is running smoothly now. Which would be tedious and a one-way I would want to avoid.

Harbour has such a huge number of options, packages, and single widespread documentations that I might be missing a simple switch to make harbour behave 100% compatible to Cl*pper so that my applications need no modification and I can get this done quickly.

Is there a way to make tBrowse in harbour behave like in Cl*pper?

Thanks for any suggestions,
Kristian

Nenad Batocanin

unread,
Apr 4, 2014, 1:13:50 PM4/4/14
to harbou...@googlegroups.com

Maybe to make your TBrowse class that inherits the original TBrowse and add missed properties?

 

Regards, NB

--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Francesco Perillo

unread,
Apr 4, 2014, 1:21:26 PM4/4/14
to harbou...@googlegroups.com

Yes, i think the best way is subclass and add what you miss.

Anyway it seems to me you were using clipper internals.... using internals is always dangerous.

Przemyslaw Czerpak

unread,
Apr 4, 2014, 3:34:10 PM4/4/14
to harbou...@googlegroups.com
On Fri, 04 Apr 2014, Kristian wrote:

Hi,

> For most others of my applications, I am encountering a problem. It appears
> that the class definitions for the tBrowse object have been modified. I
> cannot find a documentation of the object anywhere (something like the .ng
> files for Cl*pper would be great) but in the debugger and in the
> tbrowse.prg I can see a number of new properties and methods. However, it
> appears that the "hack" to the object's internals as Hannes Ziegler
> described in his tbinfo.txt and tbmore.txt does no longer work. This is a
> pity because I have written a whole library of supporting functions for
> tBrowse objects, like placing a bar in the columns heading to mark the
> sorting column, placing sums or other data in additional footlines etc. One
> of the most important tasks is to find the actually visible columns and
> their positions on the screen. It was possible to copy the object into an
> array with a simple ACOPY and to find a huge number of interesting internal
> variables in there.

In general it's this hack is not longer necessary.
In Harbour or classes use native interface so they can be subclassed
as is without any hacks and pseudo intermediate classes which were
necessary for Class(y). This should not be a problem for you.

The one problem I can see is strict Class(y) compatibility. Neither
Harbour nor xHarbour are Class(y) compatible. The main difference is
in class class. Such concept is not implemented at all so class object
and class functions are not supported. Harbour supports shared instance
variables (fully shared in all ancestors and only in given class - two
different declarations) which can be accessed by standard object messages.
Anyhow missing class object causes that it's not possible to create
different methods for class and class instance with the same name, i.e.
in Harbour NEW is object not class object message.

I have in my TODO list full support for Class(y) like object system
but so far number of Class(y) users which exploited all its functionality
was two small to have enough feedback and take my attention ;-)

> Now I have the impression that a variety of these data is now available
> directly, and I may rewrite my libraries using harbour's new tBrowse
> properties. But this is some effort, and it would mean to abandon the
> perfectly functioning code that is already written. What I would actually
> want to do is to maintain and extend my applications on a WinXP system and
> use harbour only to produce a 32bit release for the other workstations when
> the job is done.

Keeping existing code AS IS is the main reason to work on Class(y)
compatibility. Class(y) is 3-rd party extension so compatibility with
it was never the main goal for [x]Harbour anyhow it was the only one
completed OOP interface for Cl*pper so it has for sure high priority
in extension list. But we need advanced users for tests and force some
modifications in core behavior. To introduce full Class(y) compatibility
we have to disable some existing hacks introduce for other less advanced
OOP Cl*pper extensions.
And the most important: I can implement anything but now I do not have
such many spare time as in the past to make exact tests to replicate the
behavior of some original code (i.e. to rewrite old buggy TBROWSE
implementation I was writing different test code for Clipper for more
then a month). I need precise information about some exact Class(y)
behavior to start changes. Maybe some of you has some contact with
Class(y) author and can ask him to show the exact class object API
just to replicate it for Harbour. Of course if he can agree that the
final work will be published on Harbour open source license (GPL +
Harbour extension). Or maybe he is interested in creating Class(y)
for Harbour. In such case I can help in it.

> In the tbrowse.prg it says that the first 18 elements of the class
> description are identical to Cl*pper, and it appears that the internal
> variables I am referring to are now packed into a property called "dummy".

It was one of my goal to replicate exactly the positions of
Cl*pper TBROWSE instance variables with their functionality.
Anyhow things like item 14 are "Terra incognita" for me.
I've never seen Cl*pper's internals and I'm not interesting
in it. Anyhow if you can give us some information about this
item which does not volatile any license or intellectual
property law then I'm interesting in them.

> But that variable is always empty. And my first attempt to read out a
> column position by accessing tbrowse:acellvalues[x,y] results in a BASE/42
> protected error. It seems to me that I will take a long time to gather all
> the information I need to get something running on harbour with a lot of
> modifications that is running smoothly now. Which would be tedious and a
> one-way I would want to avoid.

Can you give me some links to tbinfo.txt and tbmore.txt?
Maybe I can replicate documented behavior here.
BTW Maybe Hannes is reading this text and can answer?

> Harbour has such a huge number of options, packages, and single widespread
> documentations that I might be missing a simple switch to make harbour
> behave 100% compatible to Cl*pper so that my applications need no
> modification and I can get this done quickly.
> Is there a way to make tBrowse in harbour behave like in Cl*pper?

Read above.
AFAIK it is Cl*pper compatible in the officially documented area.
For sure it's not exact Cl*pper implementation because it's result
of my own work which tries to mimic Cl*pper. If I missed sth and
you can give some more info about it then I'll try to add missing
functionality.

best regards,
Przemek

Aníbal Villalobos

unread,
Apr 4, 2014, 4:12:04 PM4/4/14
to harbou...@googlegroups.com

frank van nuffel

unread,
Apr 5, 2014, 5:40:27 AM4/5/14
to harbou...@googlegroups.com


Op vrijdag 4 april 2014 21:34:10 UTC+2 schreef druzus:
 
And the most important: I can implement anything but now I do not have
such many spare time as in the past to make exact tests to replicate the
behavior of some original code (i.e. to rewrite old buggy TBROWSE
implementation I was writing different test code for Clipper for more
then a month). I need precise information about some exact Class(y)
behavior to start changes. Maybe some of you has some contact with
Class(y) author and can ask him to show the exact class object API
just to replicate it for Harbour. Of course if he can agree that the
final work will be published on Harbour open source license (GPL +
Harbour extension). Or maybe he is interested in creating Class(y)
for Harbour. In such case I can help in it.

+1 no doubt, you're able to achieve a compatible result, but if it's alright for Class(y)'s author ... i have been working with Class(y) for years, special type of application of classes, OO support for native types, all works fine
 
i can do tests, but as stated in the,past, i'll gladly await the moment for anyone in the Harbour team to engage implementing the missing functionality

just one note: Harbour compiles and links fine here (from GIT/SVN) but i have no working experience with Harbour

i agree though Class(y) to be thé OO extension for CA-Clipper, its importance is like if part of core imho

Best regards

frank

Kristian

unread,
Apr 7, 2014, 11:57:03 AM4/7/14
to harbou...@googlegroups.com
First of all, thanks to all who responded to my request, especially to you Przemek, for the time you took for a long answer.

Unfortunately, I do not understand most of what has been written. For instance, I do not know what class(y) is and how to handle it, I do not know how to set up a new object, inherit what is there and add what I need. Since I was accessing Cl*pper internals that could simply be copied to an array and then read out as needed - a functionality that is no longer there - I think this is no solution anyway.

I have a notion, however, that the information I require can be legally accessed with properties of the tBrowse object that have been added in Harbour. Basically, I need column positions as they are visible on the screen in order to add customized footlines, graphical elements in the column headings, and frame elements. This was tedious in Cl*pper, especially when my columns required less space than 80 characters and it was not predictable where whitespaces would be padded in.

I think the easiest solution for my needs is to maintain all those functions and to replace only the code where I get the column positions. Here is a simple example of a function that returns an array of column start positions:

FUNCTION TBSepPos ( oTBrowse, nMode )                  // TBrowse Separator Positions()
// retrieves the screen col position for actual start of displayed columns
// including the padding spaces that stabilize() may have added
// mode 1 (or NIL): start of nth displayed column, regardless of freeze()
// mode 2:          start of nth defined column, may not be currently visible
// mode 3:          start of nth defined columns in [n,1], boolean if currently visible in [n,2]
LOCAL  aPositions := { }
...
RETURN aPositions

This would be a function that could stay as it is. The actual work in [...] was done by a call to TBColInfo() which read the needed information from the said internals. This would be the function to replace. In the future, I would keep a TBInfo.obj for compiling in Cl*pper and a new TBInfo.lib for compiling in Harbour. I optimistically anticipate that there is Harbour functionality to get everything I need.

I am willing to try this out and cause no work to anybody else. However, my first attempts are frustrating, and I ask for patience with a newbie... Whenever I try to read out a property of the current oBrowse, I get Error BASE/42 with a "protected" message. What is wrong with passing a defined oBrowse to a function and doing e.g. this:

FUNCTION inspectBrowse ( oBrowse )
LOCAL cFoo
cFoo := oBrowse:colorspec
RETURN cFoo

I am a bit embarrassed to ask about basics, but I find the whole package poorly documented. Not willing to be offensive; I am grateful for people who spend their work for an open source project. But so far, I have found no comprehensive documentation e.g. for the tBrowse object, explaining its properties and methods. All I can do is look through the source files and try to find out how it's done. I am willing to "read the f* manual" instead of asking simple questions here, but it does not seem to be in the package... Something like the Norton Guides for Cl*pper to be read with WEG would be soooo helpful!

Your support is appreciated.
Thanks,
Kristian

Francesco Perillo

unread,
Apr 7, 2014, 4:16:49 PM4/7/14
to harbou...@googlegroups.com
Hi Kristian,
there is no "manual". The people at xHarbour created a manual and they sell it. It is for xHarbour but a lot can be used for Harbour, expecially for standard libraries.

You used internals of TBrowse and/of Clipper.  Internals cannot be kept compatible... it would be a gigantic job of almost no value (unless for you, of course).

I think that you should start in this way:
step 1: study how OOP (object oriented programming) is done correctly in harbour, what PROTECTED mean, how object can be subclassed, etc.
step 2: subclass TBrowse and add the methods you need, adding functionality to harbour TBrowse.
step 3: enjoy Harbour power !


Just as an example (code not tested, just typed in this message):

#include "hbclass.ch"
CREATE CLASS KBrowse FROM TBRowse
   METHOD getColorspec
END CLASS

METHOD getColorspec CLASS KBrowse
  RETURN ::colorspec

 

But what I don't understand is when you say that this code gives you error:

FUNCTION inspectBrowse ( oBrowse )
LOCAL cFoo
cFoo := oBrowse:colorspec
RETURN cFoo

looking at tbrowse source code, I see that colorspec is an EXPORTEG SETGET method. So it is really strange that you get that error... unless you had :cColorSpec that is really a PROTECTED member.




Klas Engwall

unread,
Apr 7, 2014, 7:06:22 PM4/7/14
to harbou...@googlegroups.com
Hi Kristian,

> Unfortunately, I do not understand most of what has been written. For
> instance, I do not know what class(y) is and how to handle it, I do not
> know how to set up a new object, inherit what is there and add what I
> need.

I second Francesco's suggestion to study OOP. It is by far the best
investment you can make. Class(y) was the most popular class creation
library for Clipper. It is now freeware and can be downloaded from the
Oasis at http://the-oasis.net/ftpmaster.php3?content=ftplib.htm

The library itself is of no use in the Harbour environment, but the
manual is excellent. Not everything from Class(y) is implemented in
Harbour, but you can apply all the basic stuff from the manual and get
started writing OOP applications with Harbour in no time.

Then you can subclass tBrowse like Francesco showed and add any methods
you want. I don't know if all the internals you access in Clipper have
equivalents in Harbour's tBrowse, but you should be able to mimic most
of them, I think.

Additionally, while talking about OOP in general, you can study the
examples in the source tree, for example tBrowse and the tIP classes
(the hbtip contrib).

Assuming, *very* theoretically :-), that the only thing you need to add
is a method to get the color string, then write your own subclass like
in Francesco's example ...

//----------------------------------
#include "hbclass.ch"
CREATE CLASS KBrowse FROM TBRowse
METHOD getColorspec
END CLASS

METHOD getColorspec CLASS KBrowse
RETURN ::colorspec() // the method
// or even:
// RETURN ::cColorspec // the protected variable
//----------------------------------

... and then, instead of setting up an object of the tBrowse class, you
do the same thing with your KBrowse class, and it will inherit all of
the functionality from tBrowse:

//----------------------------------
procedure main()
local oBrowse := KBrowse():New()
? oBrowse:getColorspec()
return
//----------------------------------

That is all there is to it. Compile and link those two code snippets
together, and you have a working mini application. Then add the other
methods you need to your new subclass.

> I am willing to try this out and cause no work to anybody else. However,
> my first attempts are frustrating, and I ask for patience with a
> newbie... Whenever I try to read out a property of the current oBrowse,
> I get Error BASE/42 with a "protected" message. What is wrong with
> passing a defined oBrowse to a function and doing e.g. this:
>
> FUNCTION inspectBrowse ( oBrowse )
> LOCAL cFoo
> cFoo := oBrowse:colorspec
> RETURN cFoo

I tested your code with the added main() procedure below, and I received
a standard comma-separated color string, as expected. But as Francesco
said, if your code said "cFoo:=oBrowse:cColorspec" instead, then you
would get a scope violation error because you are accessing the
protected variable from "the outside". But as I showed above, accessing
the variable from a subclass works just fine. Adding an empty
parenthesis to "colorspec" is a good practice, as it is easier to see
that it is a method and not an instance variable.

//----------------------------------
procedure main()
local oBrowse := tBrowse():New()
? inspectBrowse( oBrowse)
return

FUNCTION inspectBrowse ( oBrowse )
LOCAL cFoo
cFoo := oBrowse:colorspec()
RETURN cFoo
//----------------------------------

(sorry about the mixed style :-) )

> I am a bit embarrassed to ask about basics,

Don't worry :-)

> but I find the whole package
> poorly documented. Not willing to be offensive; I am grateful for people
> who spend their work for an open source project. But so far, I have
> found no comprehensive documentation e.g. for the tBrowse object,
> explaining its properties and methods. All I can do is look through the
> source files and try to find out how it's done. I am willing to "read
> the f* manual" instead of asking simple questions here, but it does not
> seem to be in the package... Something like the Norton Guides for
> Cl*pper to be read with WEG would be soooo helpful!

Yeah, that would be great :-). The problem is that nobody seems to have
the time to write all those docs. There have been many discussions here
about this topic, but sadly, most of the time they have focused on how
to make the docs accessible (web, wiki, NG, pdf, etc), not about
actually writing them. We need volunteer documenters!

But you have to take into consideration that the Harbour community is a
small one, and there is sooo much ground to cover. There are some
attempts, however. Basic docs were written when the project was new, but
they are now incomplete, and in many places obsolete and incorrect. They
exist in the doc and doc\en directories. One very interesting piece is
Przemek's doc\xhb-diff.txt which compares Clipper, Harbour and xHarbour
from many different angles. And I have heard that the xHarbour manual
(commercial) is quite good, although it naturally misses the differences
between the projects.

Giovanni Di Maria has made those old docs, and some other info, easily
accessible at http://www.elektrosoft.it/tutorials.asp

FiveTechSoft also has the old docs online at
http://www.fivetechsoft.com/harbour-docs/harbour.html

José Quintas recently started a new doc project at
http://www.harbourdoc.com.br/
So far, most of his docs are of the old variety, but we are hoping ...

Alexander Kresin has a manual for Harbour beginners at
http://www.kresin.ru/en/hrbfaq.html

Just to mention a few. But most of the info is still unwritten. And that
can only happen as a community effort.

Of course, the old Clipper Norton Guides have all the Clipper compatible
info, and WEG is a great tool for reading them, as you mentioned yourself.

You can also search the newsgroup for earlier discussions. This is a
Google group, you know, and they are pretty good at search :-)

Other than that, do what you already do, read the f* code :-). I find
myself doing that every single day. And don't forget the changelog. And
read the developer group (moderated) too so you know what is going on in
the next Harbour version.

Regards,
Klas

Przemyslaw Czerpak

unread,
Apr 8, 2014, 9:29:59 AM4/8/14
to harbou...@googlegroups.com
On Fri, 04 Apr 2014, Aníbal Villalobos wrote:

Hi,
Thank you very much.
Really interesting information. Probably knowing these texts when I was
working on new TBROWSE implementation I would design some internals
to make them more strictly Cl*pper compatible. At least I would replicate
some internal variables.
Anyhow if someone is using functions created by Hannes then it's quite
easy to rewrite them for Harbour TBROWSE object. Looks that the same
results can be achieved. In theory it's possible to also build online
string with C structure used by Clipper in item 14 anyhow it would
cause serious overhead to encode all elements just to decode only few
bytes in a loop so I strongly suggest to create new functions using
Harbour OOP API. Some elements are protected in Harbour so it maybe
necessary to wrap TBROWSE object into some subclass with set of friend
functions or add new functions as friend ones to TBRWOSE class definition
by __clsAddFriend( <hClass>, <sFuncSym> ), i.e.:

INIT PROCEDURE CLIPINIT
LOCAL hClass := TBrowseNew():classH

__clsAddFriend( hClass, @TBPending() )
__clsAddFriend( hClass, @TBHeadRows() )
__clsAddFriend( hClass, @TBFootRows() )
__clsAddFriend( hClass, @TBScreenLen() )
__clsAddFriend( hClass, @TBRowLen() )
__clsAddFriend( hClass, @TBToggleColor() )
__clsAddFriend( hClass, @TBColorSpec() )
__clsAddFriend( hClass, @TBColorRect() )
__clsAddFriend( hClass, @TBHeadColSep() )
__clsAddFriend( hClass, @TBFootColSep() )

RETURN

And now the main question: Is anyhow interesting in writing above 10
functions for Harbour so we can create contrib library with them?

Below are 1-st three functions. They have to be verified yet and
results compared with Clipper (objects with and without header,
footers, separators, forward and backward skipping, etc.)

*****************************************
// Number of pending skips that must be
// performed before TBrowse is stable
*****************************************
FUNCTION TBPending( oBrw )
LOCAL nCount := 0
AEval( ::aCellStatus, { |x| iif( !x, ++nCount, ) } )
RETURN nCount

*****************************************
// Number of rows used for heading region
// excluding TBrowse/TBColumn:headSep
// ( Count starts at 0 !!)
*****************************************
FUNCTION TBHeadRows( oBrw )
RETURN oBrw:nHeadHeight - 1

******************************************
// Number of rows used for footing region
// excluding TBrowse/TBColumn:footSep
******************************************
FUNCTION TBFootRows( oBrw )
RETURN oBrw::nFootHeight

best regards,
Przemek

Przemyslaw Czerpak

unread,
Apr 8, 2014, 9:35:31 AM4/8/14
to harbou...@googlegroups.com
On Sat, 05 Apr 2014, frank van nuffel wrote:

Hi,

> > +1 no doubt, you're able to achieve a compatible result, but if it's
> alright for Class(y)'s author ... i have been working with Class(y) for
> years, special type of application of classes, OO support for native types,
> all works fine
>
> i can do tests, but as stated in the,past, i'll gladly await the moment for
> anyone in the Harbour team to engage implementing the missing functionality
>
> just one note: Harbour compiles and links fine here (from GIT/SVN) but i
> have no working experience with Harbour
>
> i agree though Class(y) to be thé OO extension for CA-Clipper, its
> importance is like if part of core imho

Thank you Frank,
I'll try to work on it.
The internal low level code is in practice ready.
It gives even wider functionality then Class(y) so the most important
things are Class class and Object class with exactly the same functionality
as the ones used by Class(y). Then it's necessary to make only few
modifications in hbclass.ch and we will have final result.

best regards,
Przemek

Massimo Belgrano

unread,
Apr 8, 2014, 9:54:32 AM4/8/14
to harbou...@googlegroups.com
Can we import for classy also the doc?



--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Massimo Belgrano
Delta Informatica S.r.l. (Cliccami per scoprire 

frank van nuffel

unread,
Apr 8, 2014, 11:29:47 AM4/8/14
to harbou...@googlegroups.com
Hi Przemek,

fyi, my project needed extra TBrowse functions too to

* determine in which TBrowse cell the mouse was clicked
  tb:: mouRow2u() and tb:: mouCol2u() but not screen coord based, rather in which (visible) TBColumn and which TBrowse row

* how many rows the header and footer occupy (these are also mentioned by Hannes)
  tb:: hrCount_u9T() [Header Row Count]
  tb:: frCount_u9T() [Footer Row Count]

the code in attachement is also based on Hannes' outline (note the diff offsets 5.2/5.3)

afaik, however, tb:: mouRow2u() and tb:: mouCol2u() are not (yet) totally correct (when the TBrowse first column doesn't start at TBrowse:nLeft + 1, due to not fitting exactly)

main reason for mentioning is the different offsets under 5.2 and 5.3 (i think this was not in Hannes' writings afair)

best regards,

frank

Op dinsdag 8 april 2014 15:35:31 UTC+2 schreef druzus:
tb.txt

Pritpal Bedi

unread,
Apr 8, 2014, 5:12:45 PM4/8/14
to harbou...@googlegroups.com
Hi Przemek

 
I'll try to work on it.


When you are into it, a feature request, to add some method 
to make footers and headers dynamic.

What I am hacking in TBrowse.prg right now: 

   IF ::nFootHeight > 0
      _DISP_FHNAME( ::n_Bottom - ::nFootHeight + 1, ::nFootHeight, ::n_Left, ::n_Right, _TBCI_FOOTING, ;
                    iif( ::lFootSep, _TBC_CLR_FOOTING, _TBC_CLR_STANDARD ), ;
                    ::aColors, ::aColData )
   ENDIF


=>


   IF ::nFootHeight > 0
      _DISP_FHNAME( ::n_Bottom - ::nFootHeight + 1, ::nFootHeight, ::n_Left, ::n_Right, _TBCI_FOOTING, ;
                    TBC_CLR_FOOTING, ;
                    ::aColors, ::aColData )
   ENDIF


I want to display totals on the fotting but without footing separators.
Then in PRG I issue this construct to force footer to be changed 
dynamically ( it is a hack because of the nature of headers and footers 
being constants ):

STATIC FUNCTION BrwCalculateTotals( b, nCol )
   LOCAL i, nTotal, nFld, c

   IF SetTransTotals()
      FOR i := 1 TO b:colCount
         c := b:getColumn( i )
         IF i == 1
            c:defColor := { 1, 2, 1, 13 }
            nTotal     := Len( b:atcArray_ )
            c:footing  := Transform( nTotal, "@Z 999" )
         ELSE
            IF c:cargo[ X_PRN_TOTALS ]
               c:defColor := { 1, 2, 1, 13 }
               nTotal     := 0
               nFld       := c:cargo[ X_NATURAL_ORD ]
               AEval( b:atcArray_, {|e_|  nTotal += e_[ nFld ] } )
               c:footing := Transform( nTotal, c:cargo[ X_PICTURE ] )
            ENDIF
         ENDIF
      NEXT
#ifdef __SOMETHING__
      b:footSep := MY_FSEP
#endif
      b:configure()       // THIS IS WHAT I WANT TO AVOID
   ENDIF

   RETURN NIL



Regards
Pritpal Bedi
a student of software analysis & concepts


PS: to maintain Clipper compatibility, there could be additional methods to accomplish the same.

Przemyslaw Czerpak

unread,
Apr 8, 2014, 5:22:43 PM4/8/14
to harbou...@googlegroups.com
On Tue, 08 Apr 2014, Massimo Belgrano wrote:

Hi,

> Can we import for classy also the doc?

It depends on its author. For sure we cannot take it without
his approval.
Anyhow the final Class(y) implementation in Harbour should exactly
replicate documented Class(y) behavior so for sure existing
documentation will be fully usable for all Harbour users with few
minor exceptions we can easy document, i.e.:
1) Harbour does not have Cl*pper limits on message name length.
2) Harbour does not have any reserved names so it's not necessary
to make some tricks with method names like SET.
3) Harbour has native type for SYMBOL item which can be used as
replacement for Class(y) SYMBOL class.
4) Harbour has fully functional clodeblock scoping which inherits
scope from the method where they are created.
5) In Harbour scoping allows to resolve message name conflicts
without explicit supercasting.
6) Harbour supports friend functions.
7) Harbour supports automatic destructors.
8) In Harbour it's possible to define more then one class in single
file without any limitations.
9) Harbour supports operators overloading
etc...

best regards,
Przemek
> Delta Informatica S.r.l. (*Cliccami per scoprire
> <http://www.deltain.it/mbelgrano>*)

Przemyslaw Czerpak

unread,
Apr 8, 2014, 5:25:46 PM4/8/14
to harbou...@googlegroups.com
Hi Frank,

In Harbour we already support basic mouse functionality from CL53
TBROWSE class. Look at :mRowPos(), :mColPos() and :hitTest() method
and TBMouse() function.
If it's not enough then we can extend it.

best regards,
Przemek
> --
> --
> You received this message because you are subscribed to the Google
> Groups "Harbour Users" group.
> Unsubscribe: harbour-user...@googlegroups.com
> Web: http://groups.google.com/group/harbour-users
>
> ---
> You received this message because you are subscribed to the Google Groups "Harbour Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

> fyi, my project needed extra TBrowse functions too to
>
> * determine in which TBrowse cell the mouse was clicked
> tb:: mouRow2u() and tb:: mouCol2u() but not screen coord based, rather in
> which (visible) TBColumn and which TBrowse row
>
> * how many rows the header and footer occupy (these are also mentioned by Hannes)
> tb:: hrCount_u9T() [Header Row Count]
> tb:: frCount_u9T() [Footer Row Count]
>
> the code below is also based on Hannes' outline (note the diff offsets 5.2/5.3)
>
> afaik, however, tb:: mouRow2u() and tb:: mouCol2u() are not (yet) totally
> correct (when the TBrowse first column doesn't start at TBrowse:nLeft + 1, due
> to not fitting exactly)
>
> .oO i hope not to confuse with these oceans names:
> tb:: t_u9 -> TBrowse:nTop
> tb:: l_u9 -> TBrowse:nLeft
> tb:: b_u9 -> TBrowse:nBottom
> tb:: r_u9 -> TBrowse:nRight
> tb:: ccCount_u9T -> TBrowse:colCount
> tb:: crCount_u9T -> TBrowse:rowCount
>
> main reason for mentioning is the different offsets under 5.2 and 5.3 (i think
> this was not in Hannes' writings afair)
>
> /// *************************************************************************
> /// clipper 5.2(e) TBrowse internals
> /// *************************************************************************
> #define MAGICSTRINGNO 14
>
> #define OFFSET4TCINFO 85
> #define LENGTH4TCINFO 12
>
> #define BLOCKNO4HEADSEP 29
> #define BLOCKNO4FOOTSEP 31
> #define BLOCKNO4DATAROW 33
> #define BLOCKNO4FOOTROW 45
> /// *************************************************************************
> /// clipper 5.3(b) TBrowse internals
> /// *************************************************************************
> #define MAGICSTRINGNO 14
>
> #define OFFSET4TCINFO 85 + 6
> #define LENGTH4TCINFO 12 + 6
>
> #define BLOCKNO4HEADSEP 29
> #define BLOCKNO4FOOTSEP 31
> #define BLOCKNO4DATAROW 33
> #define BLOCKNO4FOOTROW 45
> /// *************************************************************************
> /// common oceans source (clipper 5.2/5.3)
> /// *************************************************************************
>
> __9 o ::u6T (tb):: hrCount_u9T () { ;
>
> ___r ( headRows2u( self ))
>
> } __p( (tb):: hrCount_u9T )
>
> /// *************************************************************************
>
> __9 o ::u6T (tb):: frCount_u9T () { ;
>
> ___r ( footRows2u( self ))
>
> } __p( (tb):: frCount_u9T )
>
> /// *************************************************************************
>
> __2 o ::u6T :: mouRow2u ( ;// STATIC FUNC
> ;
> tb ::O6T self ;
> , o ::u6T mouRow_u7 ;
> ;
> ) {
>
> __7 o ::c6T info_c7T ;
> := self[ MAGICSTRINGNO ] ;
>
> __7 o ::u6T headSepRow_u7 ;
> := BIN2I(( info_c7T ) . c:: sub9c( BLOCKNO4HEADSEP )) ;
>
> __7 o ::u6T footSepRow_u7 ;
> := BIN2I(( info_c7T ) . c:: sub9c( BLOCKNO4FOOTSEP )) ;
>
> mouRow_u7 -= headRows2u( self )
>
> __8i( headSepRow_u7 < 0 ) {
> mouRow_u7 -= 1
> }
>
> ___r ( _7j( mouRow_u7 >= 1 ;
> , mouRow_u7 < self . tb:: b_u9 - self . tb:: t_u9 + 1 - footRows2u( self ) - ;
> _9j( footSepRow_u7 < 0 )( 0, 1 )) ;
> ( mouRow_u7, 0 ))
>
> } __p( :: mouRow2u )
>
> /// *************************************************************************
>
> __2 o ::u6T :: mouCol2u ( ;// STATIC FUNC
> ;
> tb ::O6T self ;
> , o ::u6T mouCol_u7T ;
> ;
> ) {
>
> __7 o ::c6T info_c7T ;
> := self[ MAGICSTRINGNO ] ;
>
> __7 o ::u6T colCount_u7T ;
> := self . tb:: ccCount_u9T ;
> ;
> , tcMin_u7 ;// Table Column Minimum
> := 1 ;
> , tcMax_u7 ;// Table Column Maximum
> := 1 ;
> ;
> , vsLen_u7T ;// Virtual Screen Length
> := BIN2I(( info_c7T ) . c:: sub9c( 13 )) ;
>
> __0f( u7, 1, colCount_u7T ) {
>
> tcMax_u7 += ( BIN2I(( info_c7T ) . c:: sub9c( OFFSET4TCINFO + vsLen_u7T + ( u7 - 1 ) * ( LENGTH4TCINFO ))) + 1 )
>
> __7i( mouCol_u7T >= tcMin_u7 ;
> , mouCol_u7T < tcMax_u7 ) {
> ___8
> }
>
> tcMin_u7 += ( BIN2I(( info_c7T ) . c:: sub9c( OFFSET4TCINFO + vsLen_u7T + ( u7 - 1 ) * ( LENGTH4TCINFO ))) + 1 )
>
> }
>
> ___r ( _9j( u7 > colCount_u7T )( 0, u7 ))
>
> } __p( :: mouCol2u )
>
> /// *************************************************************************
> /// number of rows used for heading region excluding TBrowse/TBColumn:headSep
> /// *************************************************************************
>
> __2 o ::u6T :: headRows2u ( ;// STATIC FUNC
> ;
> tb ::O6T self ;
> ;
> ) {
>
> __7 o ::c6T info_c7T ;
> := self[ MAGICSTRINGNO ] ;
>
> __7 o ::u6T headSepRow_u7 ;
> := BIN2I(( info_c7T ) . c:: sub9c( BLOCKNO4HEADSEP )) ;
>
> __9i( headSepRow_u7 < 0 ) {
> headSepRow_u7 := BIN2I(( info_c7T ) . c:: sub9c( BLOCKNO4DATAROW ))
> }
>
> ___r ( headSepRow_u7 )
>
> } __p( :: headRows2u )
>
> /// *************************************************************************
> /// number of rows used for footing region excluding TBrowse/TBColumn:footSep
> /// *************************************************************************
>
> __2 o ::u6T :: footRows2u ( ;// STATIC FUNC
> ;
> tb ::O6T self ;
> ;
> ) {
>
> __7 o ::c6T info_c7T ;
> := self[ MAGICSTRINGNO ] ;
>
> __7 o ::u6T hFootRow_u7T ;// first Foot Row
> := BIN2I(( info_c7T ) . c:: sub9c( BLOCKNO4FOOTROW )) ;
>
> ___r ( self . tb:: b_u9 - self . tb:: t_u9 + 1 - hFootRow_u7T )
>
> } __p( :: footRows2u )
>
> /// *************************************************************************
> /// clipper 5.2(e) TBrowse internals (transpile output)
> /// *************************************************************************
>
> STATIC FUNCTION u2mouRow (self,t7u_mouRow) ; local _ := (NIL,NIL )
>
> local T7c_info:=self[ 14 ]
>
>
> local t7u_headSepRow:=BIN2I((SUBSTR (T7c_info ,29 )))
>
>
> local t7u_footSepRow:=BIN2I((SUBSTR (T7c_info ,31 )))
> t7u_mouRow -= u2headRows(self )
>
> if((!(t7u_headSepRow < 0 )) )
> t7u_mouRow -= 1
> end
>
>
>
>
> return iif(t7u_mouRow >= 1 .AND.t7u_mouRow < self : t9u_b - self : t9u_t + 1 - u2footRows(self ) - iif(t7u_footSepRow < 0,0,1),t7u_mouRow,0)
>
> return NIL
>
>
>
>
>
>
>
>
> STATIC FUNCTION u2mouCol (self,T7u_mouCol) ; local _ := (NIL,NIL )
>
>
>
> local T7c_info:=self[ 14 ]
>
>
>
>
>
>
>
>
>
>
> local T7u_colCount:=self : T9u_ccCount,t7u_tcMin:=1,t7u_tcMax:=1,T7u_vsLen:=BIN2I((SUBSTR (T7c_info ,13 )))
> for t7u := 1 to T7u_colCount step 1
>
> t7u_tcMax += (BIN2I((SUBSTR (T7c_info ,85 + T7u_vsLen + (t7u - 1 ) * (12 ) ))) + 1 )
>
>
> if(((T7u_mouCol >= t7u_tcMin) .AND.(T7u_mouCol < t7u_tcMax ) ) )
> exit
> end
>
> t7u_tcMin += (BIN2I((SUBSTR (T7c_info ,85 + T7u_vsLen + (t7u - 1 ) * (12 ) ))) + 1 )
>
> end
>
> return iif(t7u > T7u_colCount,0,t7u)
>
> return NIL
>
>
>
>
>
>
>
>
>
> STATIC FUNCTION u2headRows (self) ; local _ := (NIL,NIL )
>
>
>
> local T7c_info:=self[ 14 ]
>
>
> local t7u_headSepRow:=BIN2I((SUBSTR (T7c_info ,29 )))
> if(t7u_headSepRow < 0 )
> t7u_headSepRow := BIN2I((SUBSTR (T7c_info ,33 )))
> end
>
> return t7u_headSepRow
>
> return NIL
>
>
>
>
>
>
>
>
>
> STATIC FUNCTION u2footRows (self) ; local _ := (NIL,NIL )
>
>
>
> local T7c_info:=self[ 14 ]
>
>
> local T7u_hFootRow:=BIN2I((SUBSTR (T7c_info ,45 )))
> return self : t9u_b - self : t9u_t + 1 - T7u_hFootRow
>
> return NIL
>
>
> /// *************************************************************************
> /// clipper 5.3(b) TBrowse internals (transpile output)
> /// *************************************************************************
>
> STATIC FUNCTION T9u_hrCount() ; local self := qself() ; local _ := (NIL,NIL )
> return u2headRows(self )
>
> return NIL
>
>
>
>
> STATIC FUNCTION T9u_frCount() ; local self := qself() ; local _ := (NIL,NIL )
> return u2footRows(self )
>
> return NIL
>
>
>
>
>
>
>
>
> STATIC FUNCTION u2mouRow (self,t7u_mouRow) ; local _ := (NIL,NIL )
>
>
>
> local T7c_info:=self[ 14 ]
>
>
> local t7u_headSepRow:=BIN2I((SUBSTR (T7c_info ,29 )))
>
>
> local t7u_footSepRow:=BIN2I((SUBSTR (T7c_info ,31 )))
> t7u_mouRow -= u2headRows(self )
>
> if((!(t7u_headSepRow < 0 )) )
> t7u_mouRow -= 1
> end
>
>
>
>
> return iif(t7u_mouRow >= 1 .AND.t7u_mouRow < self : t9u_b - self : t9u_t + 1 - u2footRows(self ) - iif(t7u_footSepRow < 0,0,1),t7u_mouRow,0)
>
> return NIL
>
>
>
>
>
>
>
>
> STATIC FUNCTION u2mouCol (self,T7u_mouCol) ; local _ := (NIL,NIL )
>
>
>
> local T7c_info:=self[ 14 ]
>
>
>
>
>
>
>
>
>
>
> local T7u_colCount:=self : T9u_ccCount,t7u_tcMin:=1,t7u_tcMax:=1,T7u_vsLen:=BIN2I((SUBSTR (T7c_info ,13 )))
> for t7u := 1 to T7u_colCount step 1
>
> t7u_tcMax += (BIN2I((SUBSTR (T7c_info ,85 + 6 + T7u_vsLen + (t7u - 1 ) * (12 + 6 ) ))) + 1 )
>
>
> if(((T7u_mouCol >= t7u_tcMin) .AND.(T7u_mouCol < t7u_tcMax ) ) )
> exit
> end
>
> t7u_tcMin += (BIN2I((SUBSTR (T7c_info ,85 + 6 + T7u_vsLen + (t7u - 1 ) * (12 + 6 ) ))) + 1 )
>
> end
>
> return iif(t7u > T7u_colCount,0,t7u)
>
> return NIL
>
>
>
>
>
>
>
>
>
> STATIC FUNCTION u2headRows (self) ; local _ := (NIL,NIL )
>
>
>
> local T7c_info:=self[ 14 ]
>
>
> local t7u_headSepRow:=BIN2I((SUBSTR (T7c_info ,29 )))
> if(t7u_headSepRow < 0 )
> t7u_headSepRow := BIN2I((SUBSTR (T7c_info ,33 )))
> end
>
> return t7u_headSepRow
>
> return NIL
>
>
>
>
>
>
>
>
>
> STATIC FUNCTION u2footRows (self) ; local _ := (NIL,NIL )
>
>
>
> local T7c_info:=self[ 14 ]
>
>
> local T7u_hFootRow:=BIN2I((SUBSTR (T7c_info ,45 )))
> return self : t9u_b - self : t9u_t + 1 - T7u_hFootRow
>
> return NIL
>
> /// *************************************************************************
>

frank van nuffel

unread,
Apr 8, 2014, 5:42:13 PM4/8/14
to harbou...@googlegroups.com

Hi again,

Thank you for the Harbour pointers (TBMouse is new to me)

It was a hack for mouseing in Clipper 5.2e too (also working in 5.3 with only diff offsets) and yes, :mRowPos/:mColPos from 5.3 do similar that i was aware of :-)

btw, Anton's website is not accessible for me (since quite some time) - i had him updated about my project's site twice (in past two years), but i never spoke to him (i won't be of much help mediating)
otoh, my project's docs already include the Class(y) docs, by his own writing (in the Class(y) site) falling under GNU Free Documentation License version 1.1, 2000 March/GNU Free Documentation License version 1.3, 2008 November
i got no response, but pbly no news means no objection
perhaps this answers Massimo's question

best regards,

Frank

Op dinsdag 8 april 2014 23:25:46 UTC+2 schreef druzus:

medhome

unread,
Sep 6, 2017, 10:49:00 AM9/6/17
to Harbour Users

Hi,

     I tried to use  mouCol2u(), It does not work at all. Is there any update ?   I have a Clipper 5.2e and I use grumpfish Mouse Lib

Best Regards

Med

 STATIC FUNCTION mouCol (self,nmcol)     // nMcol is mouse coordinate column 
 
  local c_info:=self[ 14 ]
 local nMin:=1,  nMax:=1, vsLen:=BIN2I((SUBSTR (c_info,13 ))),i

    for i:= 1 to self:colCount
        nMax += (BIN2I((SUBSTR (c_info ,85 + vsLen + (i- 1 ) * 12 ))) + 1 )
     
        if(((nMcol >= nMin) .AND.(nMcol<nMax ) ) )
            exit
        end

        nMin += (BIN2I((SUBSTR (c_info ,85 + vsLen + (i - 1 ) * (12  ) ))) + 1 )

    next

    return iif(i>self:colcount,0,i)



 

frank van nuffel

unread,
Sep 12, 2017, 11:38:40 AM9/12/17
to Harbour Users

Addressed in comp.lang.clipper (off-topic in this group)

Op woensdag 6 september 2017 16:49:00 UTC+2 schreef Ben:
Reply all
Reply to author
Forward
0 new messages