[comp.databases] dbase IV "popup" while editing data with "read" command

symons@imec.be (Jan Symons) (03/26/91)

Dear netters,

I am writing a dbase IV application which uses the "@... get"
and "read" commands for data entry. However I also want the
possibility to fill in the edited field by taking data from a 
list of keywords (from another .dbf file) using the "on popup..."   
command.

My problem is that I cannot transfer the choice of the popup
(prompt()) to the variable being edited with the "read" command.
This is roughly how the code looks like :

define popup P1 from ... prompt field keywords	
* keywords is a field in a .dbf file
on selection  popup P1 do get_key
@... say "var = " get var
on key label F7 activate P1
read
on key label F7
...

Procedure get_key
deactivate popup
thekey=prompt()
*
* How to transfer "thekey" to "var" now, soo that it looks as if the
* user typed whatever "thekey" contains ????
*
return

That's it. I'm stuck here, and would be very glad if somebody
could give me a hint....

				thanx,
				Jan Symons@imec.be

------------

daan@cwi.nl (Daan Otten) (03/28/91)

In <881@imec.UUCP> symons@imec.be (Jan Symons) writ

>> I am writing a dbase IV application which uses the "@... get"
>> and "read" commands for data entry. However I also want the
>> possibility to fill in the edited field by taking data from a 
>> list of keywords (from another .dbf file) using the "on popup..."   
>> command.
>> 
>> My problem is that I cannot transfer the choice of the popup
>> (prompt()) to the variable being edited with the "read" command.
>> ...
>> ...

Once I have written such a procedure to enter the country names
in a easy way. As far as I can recall it is not possible to assign 
the value of a menu-bar to a variable used in a screen format directly.
At least not when you want to see the result immediately.

I solved the problem by using the dbase IV command KEYBOARD 
which simulates keyboard input. The next piece of code might give you an
idea:

-----------------

procedure input
...
define popup countries from ..,.. to ..,.. prompt field countries.dbf
on key label F7 do ret_item with varread()
...
@ 1, 10 get naam
@ 2, 10 get adres
@ 3, 10 get country
read
...


procedure ret_item
parameter varread	&& the name of the currently read variable in the form
....
on key label F7  	&& deactivate the on key label
do case
   case varread = "COUNTRY"
	activate popup countries
	if lastkey() <> 27 && when popup terminates with another key than escape
	   keyboard chr(26)+chr(25)+rtrim(prompt())+chr(13) 
	   && I cannot recall why the chr(26) and chr(25). Try it out.
	endif
endcase
on key label F7 do ret_item with varread
....

-----------------

I hope this helps.

Daan Otten

tomr@dbase.A-T.COM (Tom Rombouts) (04/06/91)

In article <881@imec.UUCP> symons@imec.be (Jan Symons) writes:
>I am writing a dbase IV application which uses the "@... get"
>and "read" commands for data entry. However I also want the
>possibility to fill in the edited field by taking data from a 
>list of keywords (from another .dbf file) using the "on popup..."   
>command.
>
>My problem is that I cannot transfer the choice of the popup
>(prompt()) to the variable being edited with the "read" command.
>This is roughly how the code looks like :
>
>define popup P1 from ... prompt field keywords	
>* keywords is a field in a .dbf file
>on selection  popup P1 do get_key
>@... say "var = " get var
>on key label F7 activate P1
>read
>on key label F7
>...
>
>Procedure get_key
>deactivate popup
>thekey=prompt()
>*
>* How to transfer "thekey" to "var" now, soo that it looks as if the
>* user typed whatever "thekey" contains ????
>*
>return

This is actually much easier than you realize if you use the
VALID command and create a simple User Defined Function (UDF)
that returns the proper value.  It will be activated automatically
if the user enters a value that is not deemed "valid" by the UDF.
Also, you can set up an ON KEY handler to allow the user to 
explicitly activate it.  (We often use SHIFT-F1 to activate
picklists, to match the dBASE IV Control Center.)

Essentially, you can have the UDF() first see if the value
is in a .DBF of permissable values.  (In many cases, the dBASE IV
LOOKUP() function is used for VALID clauses)  If not, you can
activate a POPUP that uses the PROMPT FIELD <field name> option
to show a picklist from the .DBF.  The user then highlights the
one they want and presses Enter.  The UDF can then return the
PROMPT() value to put that into the GET.  

This is off the top of my head.  Send me e-mail and I can try to
dig up some real .PRG code to send you.


Tom Rombouts  Torrance 'Tater  tomr@ashtate.A-T.com

tomr@dbase.A-T.COM (Tom Rombouts) (04/06/91)

In article <1991Apr5.164724.4798@dbase.A-T.COM> tomr@dbase.UUCP (Tom Rombouts) writes:
>This is actually much easier than you realize if you use the
>VALID command  [ rest deleted ]

A minor correction to my own e-mail:  VALID is not a command, but
a keyword of the @...SAY...GET command.  That is where it is 
documented in the dBASE IV manuals.  Sorry for this extra bandwidth.

The pattern is roughly:

@ 10,10 SAY "Enter your name: " GET m->namevar VALID Myudf(namevar)

Note that the UDF after VALID must return either .T. or .F.


Tom Rombouts  Torrance 'Tater  tomr@ashtate.A-T.com

paulg@bhpmrl.oz.au (Paul Gallagher) (04/17/91)

I want to mention a few BUTs, IFs and F***s regarding this admittadly
brilliant capability of dBase IV.

I'm currently working on a couple of projects that implement nested
READs via VALIDation UDFs - the general scenario is:

   - read GETs     
   - use VALID clause to call UDF which:
        - checks user input match with "lookup" database
        - if exact match, fill in mvar 
        - if partial match, activate picklist (as described in prior messages)
        - if no match, ask user whether picklist or new entry
        - if new entry, activate new window and appropriate @...

I've nested this procedure up to three times, but in doing so, I had to
overcome some of the most frustrating, depressing, infuriating (etc)
problems I've ever seen.

Here's how it went: some time ago I implemented this procedure with
one level of nesting and thought "Wow, this is great!". Two weeks ago
I did my first implementation with two levels of nesting - you know,
cut-and-paste code etc. Disturbingly, on return from either of the
VALIDation UDFs up popped an "Unknown command code" error message
(not trapped by the debugger of course - are A-T living in this century
do you think?) After hours of code reconstruction, line-by-line - a process
which is not exactly fast especially since I am only using a 10MHz XT -
I found that by selectively commenting out MESSAGE clauses to the 
@..SAY..GETS involved I could at a whim generate any one of the
following error messages on return from the UDFs : "Unknown command code",
"Not a character expression" and "Not a numeric expression".
By removing all MESSAGE clauses, I could dispense with the errors
completely.

So, (allbeit without MESSAGES) I finally had the thing running. I've yet
to speak to A-T about this, but my best guess is that dBase IV (V1.1 btw)
was either having stack problems or perhaps not managing a lack of 
memory properly, or even not managing it's own internal memory allocation
properly. All I can say is that our local A-T help line is damned lucky
it doen't operate at 2am else they would have had one hell of an earbashing!

Now I've tempted fate (what are users for?) and tried nesting three levels
deep. The error message is different again of course (who ever heard of
systemmatic bugs!?!). Now the UDFs return .F. even though the returned
variable is _DEFINITELY_ .T. - even the "debugger" says so! BUT, this error
is not a cert. - sometimes the procedure works when following the same
steps from scratch. I've yet to resolve this problem.

On the bright side, I've probably got some of the most consistent, well
documented, standards-based code now after working through it umpteen times
to make sure the bugs weren't my fault.

PS: I've recently returned to dBase programming after a 12 month hiatus.
I remember back then, after grappling with the dBase IV V1.0 bug 
involving array assignation using macro substitution (which chewed up
memory like nothing else - and never spat it out), that I swore I'd
never touch dBase again, but if I did _always_ assume the bug's in dbase,
not your code(!), lest you wish to waste hour after frustrating hour.
Nothing dulls the memory like time of course.

Thanks for the shoulder to cry on. I'd like to hear other's experiences
along these lines though. Is this a problem someone else out there has
had?

Paul Gallagher

     /\/\       Paul Gallagher, PC Support Officer,
    / / /\      Computer Systems Group,
   / / /  \     BHP Melbourne Research Laboratories
  / / / /\ \    245 Wellington Rd Mulgrave Vic 3170 AUSTRALIA
  \ \/ / / /    Phone : +61-3-560-7066,  Fax : +61-3-561-6709
   \  / / /     ACSnet  :  paulg@bhpmrl.OZ.AU        
    \/\/\/

awd@dbase.A-T.COM (Alastair Dallas) (04/23/91)

In article <1991Apr17.110913.7460@bhpmrl.oz.au>, paulg@bhpmrl.oz.au (Paul Gallagher) writes:
> 
> I want to mention a few BUTs, IFs and F***s regarding this admittadly
> brilliant capability of dBase IV.
> 
> ...details elided...
>
> I've nested this procedure up to three times, but in doing so, I had to
> overcome some of the most frustrating, depressing, infuriating (etc)
> problems I've ever seen.

Nesting VALID clauses certainly lets you do some amazing tricks, but it
stress-tests the underlying engine, too.  Every time the interpreter
must call itself recursively, there is the chance that we'll run out of
memory (an invocation of the interpreter takes a fair amount of memory)
and sometimes recovery of the current thread of execution (what we call
the token stream) is impossible.  When this happens, the next token can
be garbage--we trap this condition (rather than executing off in deep
space) and tell you "unknown command code."  I know that is no 
consolation.

> After hours of code reconstruction, line-by-line - a process
> which is not exactly fast especially since I am only using a 10MHz XT -

One problem the software industry faces is that developers like me 
get to use way cool hardware.  The test department has machines like XTs
around, but it's not something a developer plays with regularly.  (In
fact, we have software which simulates older, slower machines on fast
new ones.)  I'm not saying you should get a faster machine to run
dBASE (obviously it's working for you as long as you don't stress it),
but I am saying that software developers at companies like A-T, Lotus,
Microsoft, etc. are going to have trouble relating to a 10MHx XT.  (Oddly,
we have trouble relating to high-end stuff, too--popular software in
general doesn't take full advantage of the latest hardware.)

> So, (allbeit without MESSAGES) I finally had the thing running. I've yet
> to speak to A-T about this, but my best guess is that dBase IV (V1.1 btw)
> was either having stack problems or perhaps not managing a lack of 
> memory properly, or even not managing it's own internal memory allocation
> properly. All I can say is that our local A-T help line is damned lucky
> it doen't operate at 2am else they would have had one hell of an earbashing!

It probably wouldn't hurt for you to call your local A-T help line, too, 
but I will pass your message on to our resident nested-VALID-clauses
expert and see if he can help.  As for "not managing a lack of memory
properly," obviously you are right and I'm sorry for any inconvenience
this caused you.  The fact is that you've caught us at a critical juncture--
the interpreter is provably recursive and the READ command can indeed
nest.  But when VALID clauses nest, and a resource error occurs, it is
just plain difficult to extract the READ from the interpreter invocation,
and the result is someone halfway around the world wants to kill someone
at 2am.  If we had seen the symptoms you are reporting, we would not 
have shipped 1.1.  In fact, I have not heard these symptoms reported
before this, but I can tell you what the error messages mean.

> Thanks for the shoulder to cry on. I'd like to hear other's experiences
> along these lines though. Is this a problem someone else out there has
> had?

I'd like to hear from anyone, as well.  We believe v1.1 is extremely 
solid, and we're working to release v1.2 a little later this year--I'm
impressed at the quality committment I feel from my management (the
folks who took over from the folks who brought you dBASE IV 1.0).
Let me know if I can help.

/alastair/

-- 
|Disclaimer: I am speaking for myself, not as a spokesman for Ashton-Tate,
|which does not monitor my outbursts here.  I reserve all rights to my
|opinions in terms of commercial endorsements.

paulg@resmel.bhp.com.au (Paul Gallagher) (05/04/91)

Alistair,

I was interested to see your response to my mailing. It's good
to get the _cause_ of a problem explained, but as you say, not much
consolation. As you suggested, I have passed on the problem to our 
local A-T hotline, but I've included some of the fruits of my own
investigation below. More of THAT problem latter...

I'm impressed by the commitment that A-T management is showing, too.
However, commitment<>success, but V1.1 is certainly a huge step in
the right direction. On the whole it is a solid product. The only
problems I have encountered are:

    (1) The nested read problem
    (2) MESSAGES often hang around after a READ has ended
        (my work-around has been to include a dummy [null]
        field at the end of the form, but this doesn't work
        if the user uses <pgdn> or <ctrlend> to exit. Is there
        any better way?)
    (3) F-DRIVER v1.12 (part of the F-PROT anti-virus package)
        causes BUILD and RUNTIME to hang unless they reside in
        the current directory (i.e. they hang if accessed on the
        PATH). I have not encountered this interference with any
        other package.

Niggles (not strictly problems) I have are :

    (1) The built in editor has to be one of the s-l-o-w-e-s-t
        pieces of junk I have ever come across! I accept your
        opinion that serious development warrants more than an
        XT, but really! This is just gratuitous slowness. I
        respect your decision to use a third party caching program -
        my question is why not do the same with the editor? There
        are plenty of programs out there that could be adapted
        at little cost.

    (2) Is BUILD/DBLINK meant for serious applications? (more
        than just "Hello, world"). I've tried 386 machines
        with 4Mb+ configured in every which way, but cannot
        build & link even the most basic application
        without getting an out-of-memory error.

Niggles-to-be:

    (1) I believe A-T is planning to use some kind of VCPI/DPMI
        extender in a new release. I would have thought that
        Lotus' experience with 123 especially would have shot
        home the fact that nowdays, users (at least the ones
        I support) want XMS 2.0 or nothing. Of course, there are
        certain types of applications that will be able to
        survive in the marketplace and still use DOS/16M or similar
        (such as dedicated data-loggers), but I don't believe
        dBase belongs in this category. For sure, it means
        bowing to the whim of Microsoft (once again), but however
        distasteful this may be, I think the memory management coup
        has already been won and lost.

THE ELUSIVE NESTED READ BUG cont'd
----------------------------------
NB: This was written before I read your message. Some
of the comments can be discounted in light of the explaination.
----------------------------------
The code provided by our A-T hotline to "prove" that
GET REQUIRED could not be nested:

    store space(1) to x,y
    @2,2 get x valid required myudf() error "wrong"
    read

    function myudf
    @3,3 get y valid y$"YN" error "really wrong"
    read
    return .t.

NB: If you take out the "REQUIRED" keyword, it works!
    Alternatively, if y is numeric and the validation
    condition is something like y>0, it works!

I was not particularly satisfied, especially since I had
a heap of code that nested READs using VALID and VALID REQUIRED
and in the most part I was able to get it to work (see my
previous message). More importantly, I couldn't believe
that such performance was in accordance with the dBase
design intent.

Since then, I've made the time to investigate the problem
in more detail. The following routines demonstrate the
inconsistent performance of dBase IV V1.1 in this area.

*********************************************************
* PROGRAM 1: This demonstrates the type of operation I
* want to code. This particular routine works OK.
  set talk off
  clear
  p_x     =space(10)
  p_y     =0
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @10,20 GET p_x  PICTURE "@s10"
  @11,20 GET p_y  PICTURE "999" ;
    VALID REQUIRED p_y>0 ;
    ERROR "must be >0"
  read
  @ 6,5 SAY p_x color n/bg
RETURN .t.
*********************************************************
* PROGRAM 2: A slight variation of program 1, but this
* doesn't work - the use of "$" in validation uncovers
* the problem.
  set talk off
  clear
  p_x     =space(10)
  p_y     =space(1)
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @10,20 GET p_x  PICTURE "@s10"
  @11,20 GET p_y  ;
    VALID REQUIRED p_y$"YyNn" ;
    ERROR "[Y/N]"
  read
  @ 6,5 SAY p_x color n/bg
RETURN .t.
*********************************************************
* PROGRAM 3: "Unknown command code" on return from UDF.
* Removing "REQUIRED" does not solve the problem.
  set talk off
  clear
  p_x     =space(10)
  p_y     =0
  p_z     =space(1)
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @10,20 GET p_z  PICTURE "@s1"
  @11,20 GET p_y  PICTURE "999" ;
    VALID REQUIRED p_y>0 ;
    ERROR "must be >0"
  read
RETURN .t.
**********************************************************
* PROGRAM 4: A variation on program 3, but this one works!
* All that has been changed is the length of memvar "p_z"
  set talk off
  clear
  p_x     =space(10)
  p_y     =0
  p_z     =space(10)
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @10,20 GET p_z  PICTURE "@s10"
  @11,20 GET p_y  PICTURE "999" ;
    VALID REQUIRED p_y>0 ;
    ERROR "must be >0"
  read
RETURN .t.
>end of examples ************************************************

CONCLUSION:
Using nested reads via VALID/VALID REQUIRED is very _flaky_.
As demonstrated, it is not easy to identify a certain
construct and say "THAT doesn't work, but THIS does". It is
not dependant upon the use of REQUIRED, "$" in validation,
MESSAGE (see my previous message), or the order and type of
@..GET, but all of these factors _can_ contribute, and
uncover the elusive nested read bug. On the other hand,
it is possible to organise these constructs so that the
routine does work.. a real black art.
I guess what is needed is for A-T to determine whether
nesting reads in this manner is indeed in accordance with
the design specification. If so - fix it, if not - MAKE it
part of the spec, coz its a real neat trick (useful too).

Regards,
Paulg.

     /\/\       Paul Gallagher, PC Support Officer,
    / / /\      Computer Systems Group,
   / / /  \     BHP Research - Melbourne Laboratories
  / / / /\ \    245 Wellington Rd Mulgrave Vic 3170 AUSTRALIA
  \ \/ / / /    Phone : +61-3-560-7066,  Fax : +61-3-561-6709
   \  / / /     ACSnet  :  paulg@resmel.bhp.com.au
    \/\/\/              :  vggalp@resmel.bhp.com.au
                        :  paulg@bhpmrl.oz.au
                Now on AARnet.

paulg@resmel.bhp.com.au (Paul Gallagher) (05/04/91)

Alastair,

THE ELUSIVE NESTED READ BUG cont'd
----------------------------------
I just realised that all of the code fragments in my previous
message were tested with ~500kb free mem. To certify the results,
I ran them through with 570kb free. In the process, I've
managed to rationalise the situation.

Operation of the following examples was consistent at both 500kb
and 570kb free memory. Unless you require >70kb to re-enter the
interpreter, a lack of memory hardly seems to be the problem.
In these examples, I discovered that the PICTURE clause in the
VALIDATED second level @..GET could be used to toggle between
error/no error. Note that in some examples, removing the clause
clears the problem, while in others, including it does the trick!
(You may remember from my previous message that in a number of
applications, I have used the MESSAGE clause to fix the problem)

It also appears that a VALIDATED second level @..GET requires
some kind of preceeding @..GET at the same level (see programs
5 & 6).

Just when I thought I was coming to an understanding regarding
the problem...

To reiterate my previous conclusions: nesting reads with VALIDation
is *flaky* !

Can you shed any light Alastair?

Regards,
Paulg.

PS: I've seen you cop alot of flak on the net, usually
    unjustifiably. Don't let it get to you. There are too
    many hypocrits out there that on the one hand want
    frank and open discussion on subjects that matter, but
    don't hesitate to shoot down in flames anyone who
    (god forbid) voices an opinion (no matter how many
    disclaimers you attach, or biases you admit).

*********************************************************
* PROGRAM 1: This demonstrates the type of operation I
* want to code. This particular routine works OK unless
* you remove the PICTURE "999" clause in which case
* an "Unrecognised command code" error is generated on
* return from getstr().
  set talk off
  clear
  p_x     =space(10)
  p_y     =0
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @10,20 GET p_x  PICTURE "@s10"
  @11,20 GET p_y  PICTURE "999" ;
    VALID REQUIRED p_y>0 ;
    ERROR "must be >0"
  read
  @ 6,5 SAY p_x color n/bg  && this is just to be pretty -
                            *  it can be removed with no effect
                            *  on the results
RETURN .t.
*********************************************************
* PROGRAM 2: p_y>0 always fails, unless the
* PICTURE "999" is removed in which case  "unknown command
* code" is generated on return from UDF
  set talk off
  clear
  p_x     =space(10)
  p_y     =0
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @11,20 GET p_y PICTURE "999" ;
    VALID REQUIRED p_y>0 ;
    ERROR "must be >0"
  read
RETURN .t.
*********************************************************
* PROGRAM 3: A slight variation of program 1. It works!
*
  set talk off
  clear
  p_x     =space(10)
  p_y     =space(1)
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @10,20 GET p_x PICTURE "@s10"
  @11,20 GET p_y   ;
    VALID REQUIRED p_y$"YyNn" ;
    ERROR "[Y/N]"
  read
  @ 6,5 SAY p_x color n/bg  && this is just to be pretty -
                            *  it can be removed with no effect
                            *  on the results
RETURN .t.
*********************************************************
* PROGRAM 4: A slight variation of program 3, but this
* doesn't work at all - "Unknown command code" is reported
* on return from getstr()
  set talk off
  clear
  p_x     =space(10)
  p_y     =space(1)
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @11,20 GET p_y  ;
    VALID REQUIRED p_y$"YyNn" ;
    ERROR "[Y/N]"
  read
RETURN .t.
*********************************************************
* PROGRAM 5: Works only if the PICTURE "999"
* clause is *removed* i.e. the opposite of program #.
* Otherwise : "Unknown command code" on return from UDF.
  set talk off
  clear
  p_x     =space(10)
  p_y     =0
  p_z     =space(1)
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @10,20 GET p_z  PICTURE "@s1"
  @11,20 GET p_y  PICTURE "999" ;
    VALID REQUIRED p_y>0 ;
    ERROR "must be >0"
  read
RETURN .t.
**********************************************************
* PROGRAM 6: A variation on program 5, but this one works
* only *with* the PICTURE "999" clause, otherwise
* an "unrecognised command code" generated.
  set talk off
  clear
  p_x     =space(10)
  p_y     =0
  p_z     =space(10)
  @ 6,5 GET p_x PICTURE "@s10" ;
    VALID REQUIRED getstr()
  read
RETURN
FUNCTION getstr
  @10,20 GET p_z  PICTURE "@s10"
  @11,20 GET p_y  PICTURE "999" ;
    VALID REQUIRED p_y>0 ;
    ERROR "must be >0"
  read
RETURN .t.
>end of examples ************************************************

cy@dbase.a-t.com (Cy Shuster) (05/10/91)

In article <1991May4.063752.10314@resmel.bhp.com.au> paulg@resmel.bhp.com.au (Paul Gallagher) writes:
>Niggles (not strictly problems) I have are :
>    (1) <Deleted - modi comm>
>
>    (2) Is BUILD/DBLINK meant for serious applications? (more
>        than just "Hello, world"). I've tried 386 machines
>        with 4Mb+ configured in every which way, but cannot
>        build & link even the most basic application
>        without getting an out-of-memory error.

Right you are. An interesting workaround came up during the beta testing
of dBASE IV/Macintosh: when our user's application wouldn't dBLINK with
600K free on the PC, I suggested he move the .DBOs to the Macintosh and
try it there (the Mac product is primarily RunTime, but we have a Toolkit
that includes dBLINK). Sure enough, with 2 meg of memory, it worked.
Final .DBO size was only 312K. And, it executed perfectly when copied
back to the PC.

--Cy--
cy@dbase.a-t.com