Dec 122017
 
Very large and complete Clipper library of routines.
File GRUMP131.ZIP from The Programmer’s Corner in
Category Dbase Source Code
Very large and complete Clipper library of routines.
File Name File Size Zip Size Zip Type
DEMO.PRG 6714 2785 deflated
GRUMP.LIB 82432 27397 deflated
HELP.DBF 233 93 deflated
HELP.DBT 1729 847 deflated
HELP.NTX 2048 580 deflated
MAKEDEMO.BAT 73 53 deflated
ORDER 1928 322 deflated
PHONE.DBF 1463 598 deflated
PHONE.NTX 2048 271 deflated
QUESTION.DOC 1801 610 deflated
README.1ST 780 360 deflated
README.DOC 53270 16357 deflated

Download File GRUMP131.ZIP Here

Contents of the README.DOC file




GRUMPFISH LIBRARY VERSION 1.31
Creative Tools for the Clipper Programmer
Copyright 1988 by Greg Lief
CompuServe ID 72460,1760
Serial No. 0001






Greetings, Clipper programmer! The Grumpfish Library contains a number
of high quality, extremely useful pop-up applications and functions
that you can integrate into your Clipper programs with an absolute
minimum of effort.

The pop-up applications include a full-featured calculator, phone
number/address database, calendar, user-defined context-specific help
screens, Mastermind game, and puzzle. The functions include automatic
generation of vertical and horizontal bounce-bar menus, user-defined
queries (filters), exploding, shrinking, pop-up and drop-down
boxes, a global replacement capability that simulates the
flexibility of the dBASE dot prompt, and plenty of other useful
things. Also included is a musical library of various themes that
you can stick into your program to amuse yourself and/or annoy the
end user.

In general, to use a Grumpfish application or function, you merely use
the command to call the function in your source code, then link your
application with GRUMP.LIB. Only the required code will be included
from the library file, thus eliminating unnecessary overhead.

*** IMPORTANT: The Grumpfish Library is written entirely in Clipper
using the Summer '87 version. If you are using an earlier version of
Clipper, some of the Grumpfish functions may not link properly because
they utilize some of the new Clipper functions. However, if you are a
registered Clipper owner and have not yet updated to Summer '87, what
are you waiting for? The speed advantages alone are worth it!


COPYRIGHT NOTICE

The Grumpfish Library is protected by U.S. Copyright law. It is
NOT public domain software! It may not be dissembled or resold
(either modified or unmodified) without the express written
permission of the author. However, because of its shareware status
you are allowed to use it for a limited period (for example, two
weeks) and make copies to give to other people.


SHAREWARE/REGISTRATION

1. BENEFITS

The Grumpfish Library for Clipper programmers is a "Shareware" product.
You are encouraged to freely distribute copies of the entire Grumpfish
Library package, which consists of either:

(1) the archive file (GRUMP.ARC or GRUMP???.ARC), or

(2) the library file (GRUMP.LIB), documentation file (README.DOC),
and order form (ORDER) together.

Please do not distribute the library (.LIB) file without the
documentation. The two files need each other!

If you find the Grumpfish Library useful in your Clipper programming
endeavors, you are both morally obligated and highly encouraged to
register your copy. No mention will be made of the countless
hours that went into programming and debugging this library, other
than to say that you should be glad that you weren't the one doing
it. There are two levels of registration, Landlubber and Captain,
which entitle you to the following great benefits:

LANDLUBBER ($30)

1. The most current version of the Grumpfish Library delivered to
your home by the United States Postal Service, with your
personal registration number on this screen.

2. Run-time royalty-free license. In other words, you will be free to
integrate any or all functions of the Grumpfish Library into your
own Clipper applications without having to pay any royalty or fee
for doing so. You may also distribute or market any such
applications royalty-free.

3. Notification of future versions of the Grumpfish Library. I expect
to be releasing new versions at least every several months, which
will both add new features and update existing ones.

4. A $5 commission each time someone registers from one of your copies.

CAPTAIN ($60)

All Landlubber's benefits listed above, plus

5. The source code for all functions and applications in the Grumpfish
Library, written entirely in Clipper (Summer '87). The code is
well-documented, and is invaluable as a learning tool for beginning
and intermediate programmers. More advanced programmers will be
able to customize the applications and functions as desired.

6. An increased commission of $10 whenever someone registers from
one of your copies.

Bear in mind, dear programmer, that this does NOT entitle you to
re-sell Grumpfish functions in any other form! This would
constitute a serious violation of the U.S. copyright on this
program.

Special user group registrations or site licenses are available.
Please write if you are interested.

2. HOW TO REGISTER

a. At the DOS prompt, type "COPY ORDER PRN" to print the registration
form.

b. Mail the completed form (or a reasonable facsimile) with your
check for $30 or $60:

Greg Lief
P. O. Box 17761
Salem, Oregon 97305

3. SUPPORT

I currently cannot offer telephone support. It is not feasible
because I would not be able to answer the phone in person most of
the time. (Most people detest talking to machines, unless of
course they are swearing at them, which we programmers know all
about!) However, I will be happy to answer all correspondence
sent to me via either U.S. Mail or CompuServe (ID 72460,1760).
You DO NOT have to be a registered owner to contact me; if you
have a particular problem or have stumbled across some magnetic
critter that I might have missed, I want to hear from you. Many
of my registered owners contacted me about certain specifics before
registering, and then registered after I responded to their needs.
In other words, I am flexible, I care about the people who are
using my software, and there is a real live person on the other
end of this product who won't leave you in the dark if you have
problems.


USER GROUPS/SHAREWARE DISTRIBUTORS

PC User Groups are welcome to add the Grumpfish Library to their
libraries under the following conditions:

1) it must be completely unmodified;

2) a diskette/copying fee of $5 or less is charged; and

3) this documentation file MUST be included.

I would appreciate notification that you have added Grumpfish
Library to your library.

If you have received the Grumpfish Library through either a user
group or a shareware distributor, please remember that the
diskette fee you paid DOES NOT constitute licensing the software,
and you are still obligated to register if you decide to use
Grumpfish Library features in your Clipper programming endeavors.


STARTING OUT

For convenience's sake, copy GRUMP.LIB to the same subdirectory where
CLIPPER.LIB and EXTEND.LIB are located.


USING THE GRUMPFISH LIBRARY

To use any of the Grumpfish applications or functions, you must first
link in the Grumpfish library (GRUMP.LIB). In addition, you will need
to link in Clipper's Extend library (EXTEND.LIB), because nearly
all of the Grumpfish Library functions call functions in this
library.

The following are examples of what you would enter at the DOS prompt
for the three most commonly used linkers ( represents the
name of your main .obj file):

For PLINK86 linker: PLINK86 FI LIB GRUMP,EXTEND,CLIPPER

For the DOS linker: LINK ,,,GRUMP + EXTEND + CLIPPER

For Borland's TLINK: TLINK ,,,GRUMP EXTEND CLIPPER

Note that if your libraries are not located in the same subdirectory
where linking is being performed, you will have to add the drive
and/or path to prevent the linker from choking!


POP-UP APPLICATIONS

1. CALCULATOR

a. Description and Usage:

This is a useful calculator that includes all the basic operators:
addition (+), subtraction (-), multiplication (*), and division (/).
But it also has some other goodies, including exponentation (^), a
paste function and a full-featured memory. Plus, whenever you press an
operator ('+', '-', '*', '/', or '^'), the previous number is shown
above the display window. This is handy for when you are processing a
list of numbers and forget where you were.

Active Keys:

'+' -- addition '-' -- subtraction

'*' -- multiplication '/' -- division

'^' -- exponentation 'C' -- clear current number

'E' -- clear entry (does not clear previously entered number in
pending operation)

'=' or Enter -- process operation Esc -- exit Calculator

b. Memory Functions:

To access memory functions, press "M", then one of the flashing
function keys. The function keys are:

'R' -- recall number stored in memory

'C' -- clear memory (reset to zero)

'+' -- add current number to number stored in memory

'-' -- subtract add current number from number stored in memory

'*' -- multiply number stored in memory by current number

'/' -- divide number stored in memory by current memory

The maximum value that can be stored in the calculator is
99,999,999,999.9999.

The paste function enables you to paste the current calculator value
into a pending READ by pressing a designated hot key (Ctrl-P is
suggested). PASTE CAVEAT: erratic results may occur if the number
of decimal places in the number to be pasted is larger than the
number of decimals in the memory variable or field. For example,
suppose that you have just used the calculator to derive the result
75.2877. You wish to paste this number into a memory variable
mTOTAL, which you are GETting with a picture template of '###.##'.
The probability is strong that this number will be stored
on-screen as 75.29 (although internally it will remain 75.2877).

c. Using the Calculator in your Clipper application:

There are two ways that you can make use of the calculator. The first
method is to use the SET KEY command to establish a "hot-key" so that
the user can pop up the calculator anywhere within the program. The
following lines added at the top of your program configures the F6 key
to serve as the hot key for the pop-up calculator and Ctrl-P as the hot
key for the paste function:

EXTERNAL popcalc && define external symbol for linker
PUBLIC paste_no && holds current calculator value for pasting
calckey = -5 && hot key will be function key F6
SET KEY calckey TO popcalc
SET KEY 16 to paste && Ctrl-P (optional)

If you want to use different keys as hot keys, please refer to your
Clipper manual for a list of INKEY() values.

The second method is to call the calculator directly. The following is
a sample menu including the calculator as a menu option:

PUBLIC paste_no
SET KEY 16 TO paste
|
|
|
@ 05,05 PROMPT "Data Entry"
@ 06,05 PROMPT "Reports"
@ 07,05 PROMPT "Calculator"
@ 08,05 PROMPT "Exit to Operating System"
MENU TO selection

DO CASE
CASE selection = 1
DO dataentry
CASE selection = 2
DO reports
CASE selection = 3
DO popcalc
CASE selection = 4
QUIT
ENDCASE

Although the second method may appeal to some of you, I highly
recommend using SET KEY so as to permit the user access to the
calculator from anywhere within the program.


2. PHONE DIRECTORY

a. Description:

This application allows the user to maintain a phone database with
names, addresses, and phone numbers of business and personal contacts.
It utilizes two files, PHONE.DBF and PHONE.NTX. You do not need to
create these files; the application automatically generates them if it
cannot find them in the specified subdirectory.

The user interface is a browse-style window. The user can view, add,
edit, and delete records from the phone database. You can instruct the
application to search a specific subdirectory for the database file by
initializing a memory variable named 'phonedir' with the value of the
desired directory (example: "C:\PHONE"). If 'phonedir' is not defined
in your program, the current directory will be used.

Active Keys:

A -- add a record to the database

E -- edit highlighted record

D -- delete highlighted record

Arrow keys -- scroll through the database

Esc -- exit the phone directory

F2 -- view/edit address information for the highlighted record

Pressing F2 allows the user to view and/or edit address information for
the highlighted person. A box containing that information will appear
in the middle of the screen. The user can enter information in these
fields as desired. They can then press Ctrl-W to save their edits, or
Esc to exit without saving. Either way, they will be returned to the
browse window.

b. Using the Phone Directory in your Clipper applications:

As with the calculator, there are two methods to choose from. The
first is to use SET KEY to establish a hot-key so that the user can pop
up the phone directory anywhere within the program. The following
lines added at the top of your program configures the F7 key to serve
as the hot key, and instructs the program to look for the phone
database in the subdirectory "C:\PHONE":

EXTERNAL popphone && define external symbol for linker
phonekey = -6 && hot key will be function key F7
phonedir = 'C:\PHONE' && search directory for phone.dbf
SET KEY phonekey TO popphone

If you want to use a different hot key for the phone directory, please
refer to your Clipper manual for a list of INKEY() values.

The second method is to call the phone directory directly. Refer to
the Calculator discussion for a sample menu. Once again, I highly
recommend using the SET KEY method.


3. CALENDAR

a. Description and Usage:

This is a pop-up calendar that displays the current month and the first
two weeks of the next month. The current day will blink. Press any
key to exit the calendar.

b. Using the Calendar in your Clipper applications:

As with the other applications, there are two ways to utilize the
calendar. The first is to use SET KEY to establish a hot-key so that
the user can pop up the calendar anywhere within the program. The
following lines added at the top of your program configures the F8 key
to serve as the hot key for the calendar:

EXTERNAL popdate && define external symbol for linker
datekey = -7 && hot key will be function key F8
SET KEY datekey TO popdate

If you want to use a different hot key for the calendar, please refer
to your Clipper manual for a list of INKEY() values.

The second method is to call the calendar directly. Refer to the
Calculator discussion for a sample menu. However, I recommend using
SET KEY.


4. STOPWATCH

a. Description and Usage:

Here is a pop-up stop watch that logs minutes, seconds, and hundredths
of seconds. You never know when you might need one. Operation is
simple: press the space bar to start and stop. Press Esc to quit.

b. Using the Stopwatch in your Clipper applications:

As with the other applications, there are two ways to utilize the
stopwatch. The first (and best) is to use SET KEY to establish a hot-
key so that the user can pop up the stopwatch anywhere within the
program. The following lines added at the top of your program
configures the F5 key to serve as the hot key for the stopwatch:

EXTERNAL popstop && define external symbol for linker
stopkey = -7 && hot key will be function key F5
SET KEY stopkey TO popstop

If you want to use a different hot key for the stopwatch, please refer
to your Clipper manual for a list of INKEY() values.

The second method is to call the stopwatch directly. See the
Calculator section above for a sample menu. Once again, however, I
recommend using SET KEY.


5. MASTERMIND*****

a. Description and Usage:

Mastermind is a diversion when the user's brain needs a good workout!
It is based on the logic board game by Pressman Corporation.

The computer selects four colored pegs and arranges them in a specific
sequence. The player's objective is to determine both the color and
position of the four pegs by making educated guesses and analyzing the
clues that the computer dispenses after each guess. These clues are:
one black marker for every peg that matches in both color and location;
and one white marker for every peg that is correct in color but not
location. An average game will take from eight to ten guesses. To
choose a color, the user moves the highlight bar to the desired color
and presses Enter. The user must choose colors from left to right. If
the user wants to quit in the middle of a game, they may do so by
pressing Esc instead of selecting a color. The program keeps track of
the guesses & clues on the right side of the screen so that the player
can refer back to them.

b. Using Mastermind in your Clipper applications:

As with the other applications, there are two ways to utilize
Mastermind. The first is to use SET KEY to establish a hot-key so that
the user can pop up Mastermind from anywhere within the program. The
following lines added at the top of your program configures the F9 key
to serve as the hot key for Mastermind:

EXTERNAL popmm && define external symbol for linker
mmkey = -8 && hot key will be function key F9
SET KEY mmkey TO popmm

If you want to use a different hot key for Mastermind, please refer to
your Clipper manual for a list of INKEY() values.

The second method is to call Mastermind directly. Refer to the
Calculator discussion for a sample menu. However, SET KEY is highly
recommended.


6. PUZZLE

a. Description and Usage:

Puzzle is the four by four square puzzle you had when you were a kid.
Fifteen of the squares are filled with the numbers 1-15, and it is up
to the player to arrange these in order like so:


1 2 3 4

5 6 7 8

9 10 11 12

13 14 15


To move, the player types in the number of the piece they wish to move.
The program will not allow them to cheat. Good luck - this can be
exasperatingly difficult!

b. Using the Puzzle in your Clipper applications:

As with the other applications, there are two ways to utilize the
puzzle. The first is to use SET KEY to establish a hot-key so that
the user can pop it up from anywhere within the program. The
following lines added at the top of your program configures the F10 key
to serve as the hot key for the puzzle:

EXTERNAL poppuz && define external symbol for linker
puzkey = -9 && hot key will be F10
SET KEY puzkey TO poppuz

If you want to use a different hot key for the puzzle, please refer to
your Clipper manual for a list of INKEY() values.

The second method is to call the puzzle directly. Refer to the
Calculator discussion for a sample menu. However, SET KEY is highly
recommended.


7. HELP SCREENS

Context-specific pop-up help screens add enormous user-friendliness to
any program. With the Grumpfish Library, it is a breeze to create your
own. Simply add the following line of code at the top of your program:

EXTERNAL help && declare symbol for linker

Next, recompile and link your program, because the actual creation of
the help screens takes place interactively from within your program.
Then run the program.

You may create a help screen for any wait state. Wait state commands
include ACCEPT, INPUT, MENU TO, MEMOEDIT(), READ, and WAIT. When you
are at a wait state where you wish to have a help screen, press F1. If
this is the first time you have called the HELP function, the program
will take a few seconds to initialize the HELP database. Three files
will be created: HELP.dbf, HELP.dbt, and HELP.ntx. These files should
not be deleted! If you do delete them, any previously-created help
screens will have to be recreated.

Assuming that you have not already created a help screen for this
particular wait state, you will get a help screen with the message:

No help text defined...
Press F2 to create, any other key to return

Press F2 to create the help screen text, then type it in exactly as you
wish it to appear. Once you are satisfied with the text, press Ctrl-W
to save it. The next time you (or another user) presses F1 at this
point in the program, they will be treated to your help screen!

Suppose that you have created a help screen and decide later that you
wish to edit its text. There is a hidden function that will allow you
to do so. Press F1 to pop up the help screen, then press Alt-E (for
Edit). You are then free to edit it as you see fit. Press Ctrl-W to
save your edits. This function is hidden because of the probability
that most of your programs will be used by others, and we wouldn't want
to give them too much freedom, now would we?


8. USING MULTIPLE POP-UP APPLICATIONS

If you would like to integrate more than one of these pop-up
applications into your program, use the following code at the top of
your program:

EXTERNAL help,popcalc,popphone,popdate,popmm,poppuz,popstop
stopkey = -4 && F5 = hot key for stopwatch
calckey = -5 && F6 = hot key for calculator
phonekey = -6 && F7 = hot key for phone directory
phonedir = 'C:\PHONE' && search directory for phone.dbf
datekey = -7 && F8 = hot key for calendar
mmkey = -8 && F9 = hot key for Mastermind
puzkey = -9 && F10= hot key for puzzle
SET KEY calckey TO popcalc
SET KEY phonekey TO popphone
SET KEY datekey TO popdate
SET KEY mmkey TO popmm
SET KEY puzkey TO poppuz


FUNCTIONS

1. YES_NO()

This function displays a box with your message in it, and pauses
program execution until the user presses either 'Y' or 'N'. It returns
a logical value: true if the user pressed 'Y', or false if the user
pressed 'N'. The syntax is:

YES_NO([,])

where and are the messages you wish to have
displayed. is optional.

Sample use of YES_NO:

kill_it = YES_NO('WARNING: Record will be deleted','Shall I continue')
IF kill_it
DELETE
SKIP -1
ENDIF

Note that the function automatically adds "? (Y/N)" to your last
message. For example, in the sample above, the following would be
displayed:

WARNING: Record will be deleted
Shall I continue? (Y/N)


2. ERR_MSG()

This function displays a box with your error message in it, along with
several choice beeps, and pauses program execution until the user
presses any key. It does not return a value. The syntax is:

ERR_MSG()

where is the message you wish to display (not too
insulting, please!).

Sample use of ERR_MSG:

SEEK mVAR
IF .not. found()
ERR_MSG('That record was not found')
ENDIF


3. CENTER()

You will probably make frequent use of this function. It centers
character strings, either on the screen or the printer, at the row you
specify. Syntax is:

CENTER(,,[])

where is the character string or expression to be centered,
is a numeric expression representing the row on which to
center the string, and
is an optional numeric expression representing the
length of a row (default length is 80 for screen displays, but
you may use values of up to 255 when printing wide reports).

Thanks to Jeanne Nerwinski of Durham, NC for the parameter.

Sample usage of CENTER:

CENTER(0,'Change Order Data Input Screen')
CENTER(1,'WACKY WIDGETS MONTHLY PROFIT ANALYSIS',132)


4. WAITON() and WAITOFF()

This function is useful to keep the user of your application apprised
of time-consuming operations, such as printing a report, instead of
letting them stare at a blank screen and wonder what (if anything) is
going on.

First, call WAITON(), which displays a box with your message in it.
The syntax is:

WAITON([])

where is the message you wish to display. Note that if you
do not pass a message, WAITON() will assume that you are about to print
a report and will display the message "Now printing... please wait".

When the operation is complete, use WAITOFF() to refresh the screen.
The syntax is:

WAITOFF()

This will restore the screen to its original state.

Sample usage of WAITON and WAITOFF:

USE Sales
WAITON('Rebuilding index files... please wait')
INDEX ON lname TO Customer
INDEX ON date TO Saledate
INDEX ON inv_code TO Item
WAITOFF()


5. EXBOX()

Exploding boxes add enormous pizzaz to your color applications. The
syntax is as follows:

EXBOX(,,,,,,[])

is an integer numeric representing the top row of the box.

is an integer numeric representing the leftmost column of the box.

is an integer numeric representing the bottom row of the box.

is an integer numeric representing the rightmost box column.

is an integer numeric between 1 and 5, and represents the
type of box desired. The choices are:

Box Type Box String Used

1
2
3
4
5
6 (no border)


The box string forms the box in the same fashion as with Clipper's
"@...BOX" command. The box is drawn using this string starting from
the left hand corner and proceeding clockwise. If you need more
information on this, please refer to your Clipper manual.

is an integer numeric between 1 and 100, and is used to delay
the 'explosion'. The larger the delay, the longer the box drawing
operation will take. I recommend using values between 1 and 10, but
you should experiment with this.

is an optional character string to use as the fill
character. If the length of the character string passed is greater
than one, only the leftmost character will be used. If this
parameter is not specified, the fill character will be chr(32).

Sample usage:

EXBOX(11,28,13,51,2,5)
@ 12,30 SAY 'Enter your ID:'
@ 12,46 GET mID PICTURE 'XXXX'
READ

When using a monochrome monitor, an exploding box will not have any
noticeable effect.


6. SHRBOX()

What good are exploding boxes without shrinking boxes? Now you can
shrink that box you just exploded onto the screen back into
nothingness. Here's the syntax:

SHRBOX(,,,,,[])

The first five parameters are identical to their namesakes in
EXBOX().

is an optional character string parameter specifying the
color you wish to use to blank out the previous box. If not
passed, the current color setting will be used.

What SHRBOX() does is blank out the area marked by the speified
coordinates from the outside in, exactly opposite the method used
by EXBOX().

Sample usage:

(with the color parameter)

SET COLOR TO +w/b
EXBOX(11,17,13,62,2,5)
@ 12,19 SAY 'This box will self-destruct in two seconds'
INKEY(2)
SHRBOX(11,17,13,62,2,'w/n')

(without the color parameter)

SET COLOR TO +w/b
EXBOX(11,17,13,62,2,5)
@ 12,19 SAY 'This box will self-destruct in two seconds'
INKEY(2)
SET COLOR TO w/n
SHRBOX(11,17,13,62,2)

As with the exploding box, a shrinking box will have no noticeable
effect with monochrome monitors.


7. POPBOX()/DROPBOX()

Surely you don't want to restrict yourself to exploding and
shrinking boxes. Toss in a pop-up or drop-down box here and there
to keep the users on their toes. Syntax:

POPBOX / DROPBOX(,,,,)

The first five parameters are identical to their namesakes in
EXBOX() and SHRBOX().

The pop-up box will be drawn from the bottom up, whereas the drop-
down box will be drawn from the top down.

Sample usage:

POPBOX(5,5,23,55)
@ 14,8 SAY 'This box rose like a phoenix from the ashes!'
DROPBOX(1,60,11,79)
@ 5,63 SAY 'This box fell'
@ 6,63 SAY 'like pennies'
@ 7,63 SAY 'from heaven!'

(feel free to substitute cliches of your own choosing)

Unlike the exploding and shrinking boxes, pop-up and drop-down
boxes will be effective on monochrome monitors.


8. SETFILT()

This function allows you to simulate SQL (structured query language)
by establishing a query condition (or filter) for selectively printing
or displaying records. The syntax is hardly complex:

SETFILT()

SETFILT() returns a logical value. The return value is true (.T.) if
there are records found in the current database matching your query
condition, false (.F.) if there are not.

SETFILT() will display all of the field names of the current database
file. First, you move the highlight bar to the desired field and
presses Enter to add it to the query condition. You then select the

desired operator (equal to, less than, greater than, less than or equal
to, greater than or equal to, not equal to), and then the desired value
for that field. [For subsequent additions to the query condition, you
will be asked to select a logical (Boolean) operator (AND/OR)]. Bear in
mind that AND has precedence over OR when evaluating the query
expression. For example:

DATE=CTOD('05/01/81') .and. COST=50.00 .or. ITEM='widget'

will display all records with either (1) a date of 05/01/81 and a cost
of 50.00, or (2) item 'widget'. If you need more clarificationon
logical (Boolean) operators, please refer to your Clipper manual for
enlightenment.

As you add items to the query condition, it will be updated on the
screen so you can keep track of where you are.

When you are finished establishing your query condition, press Esc to
return to the calling program.

Sample Usage:

USE Sales
IF setfilt()
DISPLAY ALL
SET FILTER TO
ENDIF
RETURN


9. BATCHREP()

BATCHREP() allows the user to do global replaces within your program,
in a similar fashion to the REPLACE command at the dBASE dot prompt.
This function is invaluable for data-intensive applications.

The syntax consists of the following line:

BATCHREP()

There is no return value.

BATCHREP() will display all of the field names of the current database
file. First, you select the field yoiu wish to replace by moving the
highlight bar to that field and pressing Enter. You will then be
prompted to enter the new value for that field. Use dBASE III syntax;
if you want to see examples, press Alt-H. If the replacement field is
character type, you will not be permitted to replace it with a value
longer than the field's length. If the replacement field is logical
type, you must replace it with either .T. (True) or .F. (False),
logically enough.

After entering the new value, you then select the field or fields to
define the replacement scope. (If you want to unconditionally replace
all records, hit Esc to begin the replacement.) If you do select a
field, you first select an operator (equal to, greater than, less than,
etc.), and then enter a value for that field. As you add to the
replacement scope, it will be updated near the bottom of the screen.
You can use as many fields as you wish; for each subsequent field,
you will be asked to select a logical (Boolean) operator (AND/OR)].
See SETFILT() above for an example of logical operators.

When you are finished establishing the replacement scope, press Esc to
begin the replacement. If the field being REPLACEd is a key field in
any open index, you will be prompted to that effect. In this instance,
the replacement will take slightly longer, because the index fields
will have to be rebuilt after the replacement. When the replacement is
finished, the number of records replaced will appear in the center of
the screen for reference.

Sample Usage:

USE Sales
batchrep()


10. MEMEDIT()

This permits easy editing of memo fields. The syntax is:

MEMEDIT(,[,,,][,])

is a character string representing the name of the memo field
to be edited.

Optional parameters , , , are all numeric expressions
representing the box coordinates (top, left, bottom, right,
respectively). Default box coordinates are 5,10,19,69.

Optional parameter is a character string to be centered at the
top of your box.

The active keys during MEMEDIT are exactly the same as those in the
Clipper function MEMOEDIT(). Please refer to your manual for more
specifics.

Sample Usage:

USE Letters
MEMEDIT('text',10,20,15,59,'<< Edit Letter >>')
RETURN


11. MENUH()

This function allows you to easily paint a horizontal Lotus-style
light-bar menu on the screen. The syntax is:

MENUH(,,,[,,)

is a numeric expression representing the row at which to display
the light-bar menu.

is a numeric expression representing the starting column for the
light-bar menu.

is a numeric representing the desired spacing between menu
entries.

is a character string containing all of the prompts for the
menu. These prompts must be separated by dollar signs.

Optional parameter is a character string containing any
desired messages corresponding to the prompts. Like the prompts, the
messages must be separated by dollar signs. NOTE: You must SET MESSAGE
in your program before calling MENUH(), or your messages will not be
displayed!

Optional parameter is a character string used to set the menu
color. If this parameter is not passed, white on black will be used
for the unselected options and inverse will be used for the light bar.

MENUH() returns a numeric value representing the selected menu option.
For example, if the user pressed 'D' in the sample below the return
value would be 1.

Sample usage:

sel=MENUH(23,5,4,'Data Entry$Reports$Previous Menu$','','+w/b,+w/n')
DO CASE
CASE sel = 1
DO data
CASE sel = 2
DO reports
OTHERWISE
RETURN
ENDCASE


12. MENUV()

This function will paint a vertical bounce-bar menu on the screen.
First, you must define an array containing the desired menu options
(and corresponding messages, if desired). If you wish to have
messages, you must separate the menu option from the message with a
dollar sign. Also, be sure to SET MESSAGE before calling MENUV().

The syntax for this function is:

MENUV([,,<box type>,<box color>,<title color>])<br /><br /><br /> <array> is a character string representing the name of the array that<br /> contains the menu options.<br /><br /> Optional parameter <title> is a character string representing the menu<br /> title.<br /><br /> Optional parameter <box type> is an integer between 1 and 12<br /> corresponding to the type of box you wish to use. Box types 1-4 are<br /> listed below:<br /><br /> Box Type Box String Used<br /><br /> 1 <br /> 2 <br /> 3 <br /> 4 <br /> 5 <br /><br /> Boxes 6-10 and 11-15 are identical to boxes 1-5, except that 6-10 will<br /> have an additional drop shadow (simulating a three-dimensional effect)<br /> and 11-15 will have two drop shadows for super-duper 3-D.<br /><br /> Optional parameter <box color> is a character string containing the<br /> color to use for the box. The default color is white on black for<br /> unselected options and inverse (black on white) for the bounce bar.<br /><br /> Optional parameter <title color> is a character string containing the<br /> color to use for the menu title. The default is white on black.<br /><br /> MENUV() returns a numeric value representing the selected menu option.<br /> For example, if the user pressed 'Q' in the sample below the return<br /> value would be 4.<br /><br /> Sample usage:<br /><br /> DECLARE mainmenu[4]<br /> mainmenu[1]='Maintain Data$Add and edit information'<br /> mainmenu[2]='Output Reports$Share your information'<br /> mainmenu[3]='Utilities$Select printer, reindex files'<br /> mainmenu[4]='Quit$Exit to DOS'<br /> sel=MENUV(mainmenu,'Main Menu',11,'+w/rb,+w/n','+w/b')<br /> DO CASE<br /> CASE sel = 1<br /> DO maintdata<br /> CASE sel = 2<br /> DO reports<br /> CASE sel = 3<br /> DO utility<br /> OTHERWISE<br /> RETURN<br /> ENDCASE<br /><br /><br />13. NET_USE()<br /><br /> This function and the two that follow are primarily for multi-user<br /> applications. If you have any questions about the basics of <br /> networking, I suggest that you refer to either the Clipper manual <br /> or the Spring 1987 issue of "Nantucket News", which provides an <br /> excellent tutorial.<br /> <br /> NET_USE() will open a specified database in either exclusive or <br /> shared mode, along with up to eight corresponding index files. <br /> The syntax is:<br /><br /> NET_USE(<filename>,<excl_use> [,<index1>,<index2>,...<index8>]<br /> <br /> <filename> is a character string representing the name of the<br /> database file to be opened.<br /> <br /> <excl_use> is a logical expression representing the desired mode:<br /> True (.T.) for exclusive, False (.F.) for shared.<br /> <br /> Optional parameters <index1>...<index8> are character strings<br /> representing the names of the index files to be opened.<br /> <br /> NET_USE() returns a logical value: True (.T.) if the file was<br /> opened successfully, or False (.F.) if it was not.<br /> <br /> If NET_USE() is unable to open the file, the user will be asked if<br /> they wish to wait for it to become available. If not, the return<br /> value will be False. If they do decide to wait, they will be<br /> entertained by an intriguing screen display. They may abort the<br /> wait at any time by pressing Esc (which will then cause the<br /> function to return False).<br /> <br /> This function also provides aural feedback to the user, so that if<br /> they want to wait for the file, they do not necessarily have to<br /> remain glued to the screen. When the file becomes available, the<br /> Charge theme will be played, which is sure to get a Pavlovian<br /> response from your users!<br /> <br /> You will note the absence of explicit selection of work areas.<br /> NET_USE() takes advantage of the Clipper "SELECT 0" command to<br /> automatically select the next available work area.<br /> <br /> WARNING: You must SET EXCLUSIVE OFF prior to calling this<br /> function. If you do not, NET_USE() will attempt to open all files<br /> exclusively, which will give you a terrible headache.<br /> <br /> Sample Usage:<br /> <br /> IF ! NET_USE('customer',.f.,'cust1','cust2')<br /> RETURN<br /> ENDIF<br /> ** code to maintain customer file<br /> |<br /> |<br /> IF ! NET_USE('customer',.t.,'cust1')<br /> RETURN<br /> ENDIF<br /> ** code to print customer reports<br /> <br /> <br />14. REC_LOCK()/FILELOCK()<br /><br /> These two functions are crucial in any multi-user system. <br /> Obviously enough, REC_LOCK() is used to lock records, while<br /> FILELOCK() locks files. The syntax is simple:<br /> <br /> REC_LOCK() / FILELOCK()<br /> <br /> There are no parameters.<br /> <br /> Both functions return logical values: True (.T.) if the lock was<br /> successful, or False (.F.) if unsuccessful.<br /> <br /> If the locks are initially unsuccessful, the user will be given<br /> the option to wait for availability in the same fashion as with<br /> NET_USE(). Likewise, a dazzling screen will keep them amused<br /> while they wait, and the Charge theme will be played when the lock<br /> is finally successful.<br /> <br /> Sample Usage:<br /> <br /> IF REC_LOCK()<br /> REPLACE name WITH mname, address WITH maddress<br /> ENDIF<br /><br /> IF FILELOCK()<br /> DO reports<br /> ENDIF<br /> <br /><br />15. ADD_REC()<br /><br /> This function is for APPENDing BLANK records to a database in a<br /> multi-user system. The syntax is:<br /> <br /> ADD_REC([<wait time>])<br /> <br /> <wait time> is an optional numeric expression representing the<br /> number of seconds to wait for the APPEND BLANK to be successful.<br /> If this parameter is not passed, the function will loop until<br /> either the APPEND BLANK is successful or the user presses Esc.<br /><br /> ADD_REC() returns a logical value: True (.T.) if the APPEND BLANK<br /> is successful, or False (.F.) if it did not succeed within the<br /> specified time. Please note that it is highly unlikely that this<br /> function will ever return False, except in the rare event that two<br /> users have attempted to APPEND BLANK to the same database at<br /> precisely the same time.<br /> <br /> <br />16. PRINTOK()<br /><br /> How many times have you or your users had problems with printers<br /> not being ready? Use this function and you might never have to<br /> deal with "Printer Not Ready.... Retry (Y/N)?" again. Syntax:<br /><br /> PRINTOK()<br /><br /> It returns a logical value. If the printer is ready, it will<br /> return True (.T.) and SET the DEVICE TO PRINT. If the printer is<br /> not ready, it will return False (.F.).<br /><br /> Sample usage:<br /><br /> IF PRINTOK()<br /> DO report<br /> SET DEVICE TO SCREEN<br /> ENDIF<br /><br /><br />17. DATEST()<br /><br /> If you want to print an empty date field or expression in a report<br /> without printing the slashes (' / / '), use DATEST() instead of<br /> DTOC() like so:<br /><br /> DATEST(<date>)<br /><br /> where <date> is the date field or expression you wish to print.<br /><br /><br />18. ISSTATE()<br /><br /> This function is useful in applications where the user must input a<br /> two-character state abbreviation. ISSTATE() checks to ensure that a<br /> valid abbreviation has been entered. The syntax is:<br /><br /> ISSTATE(<memvar>)<br /><br /> where <memvar> is a character expression to be tested.<br /><br /> ISSTATE() returns a logical value: True (.T.) if the expression is a<br /> valid state abbreviation, or False (.F.) if it is not.<br /><br /> Sample Usage:<br /><br /> mSTATE = space(2)<br /> @ 10,10 get mSTATE valid isstate(mSTATE)<br /><br /><br />19. SPREAD()<br /><br /> This function lets you display a character string on the screen<br /> from the middle out. If this does not make sense, try it for<br /> yourself. It is simple, yet slick. The syntax is as follows:<br /><br /> SPREAD(<string>,<row>[,<delay>,<column>])<br /><br /> <string> is the character string to display.<br /><br /> <row> is the row at which to display it.<br /><br /> Optional parameter <delay> is a numeric integer to delay the<br /> effect. The default delay setting is 8. Experiment with this<br /> until you find one that you like.<br /><br /> Optional parameter <column> is a numeric integer specifying the<br /> column at which to spread the string out from (the default is 40).<br /><br /> Sample usage:<br /><br /> SPREAD("This effect will get the user's attention!",12)<br /> SPREAD("This line will be drawn very slowly",14,50)<br /><br /><br />20. TTY()<br /><br /> This function displays a character string across the screen in a<br /> continuously scrolling "teletype" manner until the user presses <br /> any key. The syntax is as follows:<br /> <br /> TTY(<row>, <message>, <delay>)<br /><br /> <row> is a numeric expression representing the row at which to<br /> display the message.<br /> <br /> <message> is the character string to be displayed.<br /> <br /> <delay> is a numeric expression representing the delay factor to<br /> be introduced into the scrolling process. Values between 10 and <br /> 100 are recommended, although you should experiment to determine <br /> what works best on your particular computer.<br /> <br /> There is no return value. The message will scroll across the<br /> screen until the user presses a key.<br /> <br /> Sample Usage:<br /> <br /> TTY(12, 'Press any key to return to the Main Menu', 75)<br /> <br /> <br />21. PASS_CHK()<br /><br /> This is a generic routine to be used whenever the user must enter a<br /> password to continue. The syntax is as follows:<br /><br /> PASS_CHK(<password>, [<row>])<br /><br /> where <password> is a character expression and <row> is an optional<br /> parameter indicating the row number at which you want the "Enter<br /> password..." message to appear.<br /><br /> PASS_CHK() compares the user's entry against the password you<br /> passed to it. The function is case-insensitive.<br /><br /> PASS_CHK() returns a logical value: True (.T.) if the user<br /> enters the correct password, or False (.F.) if they do not.<br /><br /> Sample Usage:<br /><br /> IF pass_chk(chr(77)+chr(79)+chr(79)+chr(76)+chr(65)) && MOOLA<br /> DO payroll<br /> ENDIF<br /><br /><br />22. RAND()<br /><br /> Here is a random number generator so that you can work on that pop-up<br /> poker game you've been dreaming of! It is driven by the system clock,<br /> so there is no need for you to initialize a 'seed'. Syntax is:<br /><br /> RAND(<range>)<br /><br /> where <range> is an integer numeric expression.<br /><br /> RAND() will return a random integer between zero and <range>-1.<br /><br /> Sample Usage: Output:<br /><br /> ? RAND(100) 75<br /> ? RAND(50) 22<br /> ? RAND(10) 7<br /><br /><br />23. TIMEWORD()<br /><br /> This function may seem trivial, but believe it or not, you might<br /> find use for it someday. It simply returns a word describing the<br /> time of day (based on the system clock). Syntax:<br /><br /> TIMEWORD()<br /><br /> There are no parameters.<br /><br /> The return value is a character string which relates to the time as<br /> follows:<br /><br /> 12:00 am - 11:59 am "Morning"<br /> 12:00 pm - 5:59 pm "Afternoon"<br /> 6:00 pm - 11:59 pm "Evening"<br /><br /> I use this in several of my multi-user systems in the following<br /> manner: first, an environmental variable with the user's name is<br /> defined in the network login script. Then I grab the user's name<br /> with the Clipper function GETE() and use TIMEWORD() to give them a<br /> personal and time-specific greeting when they enter my program. Not<br /> exactly a cure for cancer, but it is a nice touch.<br /><br /> Sample Usage:<br /><br /> @ 12,20 say 'Good '+TIMEWORD()+', '+user_name<br /><br /><br />24. GL_VER()<br /><br /> This function simply returns the version number of the Grumpfish<br /> Library that you are using.<br /><br /> Sample Usage:<br /> <br /> ? GL_VER()<br /> <br /><br />THE SINGING P.C.<br /><br /> A number of musical themes are available to you if you dare to use<br /> them. They are listed below, followed by the code syntax to call them.<br /><br /> 1. "Beat It" by Michael Jackson (intro) - DO BEATIT<br /><br /> 2. "Born to Run" by Bruce Springsteen (one verse) - DO BORN2RUN<br /><br /> 3. "Charge!" as heard at finer sporting events everywhere - DO CHARGE<br /><br /> 4. "Mexican Hat Dance", popular at many hockey rinks - DO HATDANCE<br /><br /> 5. "Theme from Final Jeopardy" - DO JEOPARDY<br /><br /> 6. "The Girl from Ipanema" - DO IPANEMA<br /> <br /> If you have any musical requests, please let me know!<br /><br /><br />FUTURE IMPROVEMENTS<br /><br />Word Processing/Notepad, Memo Editor, Label Printer, Printer Set-up String<br />Manager, Function Key Manager, Database File Manager, more UDFs --- and any<br />ideas that you might have and want to send me!<br /><br /> Greg Lief<br /> P. O. Box 17761<br /> Salem, Oregon 97305<br /><br />TRADEMARK ACKNOWLEDGEMENTS<br /><br />CLIPPER is a registered trademark of Nantucket Corporation.<br /><br />PLINK86 is a registered trademark of Phoenix Technologies.<br /><br />DOS is a registered trademark of Microsoft Corporation.<br /><br />TLINK (Turbo Link) is a registered trademark of Borland International.<br /><br />MASTERMIND is a registered trademark of Pressman Corporation.<br /><br />LOTUS is a registered trademark of Lotus Development Corporation.<br /><br /><br /><br />REVISION HISTORY<br /><br /> 1.0 - July 1988 (initial release)<br /><br /> 1.1 - August 1988 - corrected discrepancy between documentation and<br /> source code regarding hot key implementation for pop-ups. Added<br /> SETFILT(), BATCHREP(), ISSTATE(), RAND(), and <length> parameter for<br /> CENTER().<br /><br /> 1.2 - September 1988 - Added POPSTOP, paste function for POPCALC,<br /> and PASS_CHK(). Added solid border box option to EXBOX(). Updated<br /> most functions to properly set colors dependent upon type of<br /> monitor (color vs. monochrome). Corrected MEMED() so that menu<br /> title is centered properly between left and right columns.<br /><br /> 1.25 - October 1988 - Added SHRBOX(), SPREAD(), TIMEWORD(),<br /> PRINTOK(), and fill character option for EXBOX(). Cleaned up<br /> documentation and added demo program with supporting databases to<br /> distribution disk. <br /><br /> 1.3 - November 1988 - Added multi-user functions (NET_USE, ADD_REC,<br /> FILELOCK, REC_LOCK). Added POPBOX(), DROPBOX(), and GL_VER().<br /> Added IPANEMA to the Singing P.C.'s repertoire, and made it<br /> possible to escape from any of the songs as they play.<br /><br /> 1.31 - November 1988 - Fixed persistent bug in POPCALC involving<br /> use and pasting of non-integer numbers, and added TTY().</div></div><br><br><div style="border-style: groove;border-width: 3px;padding: 20px;" class="description_body"><div style="" class="description_title"><h2>Contents of the README.1ST file</h2><br></div><div class="description_content"> <br /> <br /> GRUMPFISH LIBRARY VERSION 1.31 <br /> Creative Tools for the Clipper Programmer <br /> Copyright 1988 by Greg Lief <br /> CompuServe ID 72460,1760 <br /> Serial No. 0001 <br /> <br /> <br /> <br /> <br /><br /><br /> Greetings, Clipper programmer! The Grumpfish Library contains a number<br /> of high quality, extremely useful pop-up applications and functions<br /> that you can integrate into your Clipper programs with an absolute<br /> minimum of effort.<br /><br /> The pop-up applications include a full-featured calculator, phone<br /> number/address database, calendar, user-defined context-specific help<br /> screens, Mastermind game, and puzzle. The functions include automatic<br /> generation of vertical and horizontal bounce-bar menus, user-defined<br /> queries (filters), exploding, shrinking, pop-up and drop-down<br /> boxes, a global replacement capability that simulates the<br /> flexibility of the dBASE dot prompt, and plenty of other useful<br /> things. Also included is a musical library of various themes that<br /> you can stick into your program to amuse yourself and/or annoy the<br /> end user.<br /><br /> In general, to use a Grumpfish application or function, you merely use<br /> the command to call the function in your source code, then link your<br /> application with GRUMP.LIB. Only the required code will be included<br /> from the library file, thus eliminating unnecessary overhead.<br /><br /> *** IMPORTANT: The Grumpfish Library is written entirely in Clipper<br /> using the Summer '87 version. If you are using an earlier version of<br /> Clipper, some of the Grumpfish functions may not link properly because<br /> they utilize some of the new Clipper functions. However, if you are a<br /> registered Clipper owner and have not yet updated to Summer '87, what<br /> are you waiting for? The speed advantages alone are worth it!<br /><br /> <br />COPYRIGHT NOTICE<br /><br /> The Grumpfish Library is protected by U.S. Copyright law. It is<br /> NOT public domain software! It may not be dissembled or resold<br /> (either modified or unmodified) without the express written<br /> permission of the author. However, because of its shareware status<br /> you are allowed to use it for a limited period (for example, two<br /> weeks) and make copies to give to other people.<br /><br /><br />SHAREWARE/REGISTRATION<br /><br />1. BENEFITS<br /><br /> The Grumpfish Library for Clipper programmers is a "Shareware" product.<br /> You are encouraged to freely distribute copies of the entire Grumpfish<br /> Library package, which consists of either:<br /><br /> (1) the archive file (GRUMP.ARC or GRUMP???.ARC), or<br /><br /> (2) the library file (GRUMP.LIB), documentation file (README.DOC),<br /> and order form (ORDER) together.<br /><br /> Please do not distribute the library (.LIB) file without the<br /> documentation. The two files need each other!<br /><br /> If you find the Grumpfish Library useful in your Clipper programming<br /> endeavors, you are both morally obligated and highly encouraged to<br /> register your copy. No mention will be made of the countless<br /> hours that went into programming and debugging this library, other<br /> than to say that you should be glad that you weren't the one doing<br /> it. There are two levels of registration, Landlubber and Captain,<br /> which entitle you to the following great benefits:<br /><br /> LANDLUBBER ($30)<br /><br /> 1. The most current version of the Grumpfish Library delivered to<br /> your home by the United States Postal Service, with your<br /> personal registration number on this screen.<br /><br /> 2. Run-time royalty-free license. In other words, you will be free to<br /> integrate any or all functions of the Grumpfish Library into your<br /> own Clipper applications without having to pay any royalty or fee<br /> for doing so. You may also distribute or market any such<br /> applications royalty-free.<br /><br /> 3. Notification of future versions of the Grumpfish Library. I expect<br /> to be releasing new versions at least every several months, which<br /> will both add new features and update existing ones.<br /><br /> 4. A $5 commission each time someone registers from one of your copies.<br /><br /> CAPTAIN ($60)<br /><br /> All Landlubber's benefits listed above, plus<br /><br /> 5. The source code for all functions and applications in the Grumpfish<br /> Library, written entirely in Clipper (Summer '87). The code is<br /> well-documented, and is invaluable as a learning tool for beginning<br /> and intermediate programmers. More advanced programmers will be<br /> able to customize the applications and functions as desired.<br /><br /> 6. An increased commission of $10 whenever someone registers from<br /> one of your copies.<br /><br /> Bear in mind, dear programmer, that this does NOT entitle you to<br /> re-sell Grumpfish functions in any other form! This would<br /> constitute a serious violation of the U.S. copyright on this<br /> program.<br /><br /> Special user group registrations or site licenses are available.<br /> Please write if you are interested.<br /><br />2. HOW TO REGISTER<br /><br /> a. At the DOS prompt, type "COPY ORDER PRN" to print the registration<br /> form.<br /><br /> b. Mail the completed form (or a reasonable facsimile) with your<br /> check for $30 or $60:<br /><br /> Greg Lief<br /> P. O. Box 17761<br /> Salem, Oregon 97305<br /><br />3. SUPPORT<br /><br /> I currently cannot offer telephone support. It is not feasible<br /> because I would not be able to answer the phone in person most of<br /> the time. (Most people detest talking to machines, unless of<br /> course they are swearing at them, which we programmers know all<br /> about!) However, I will be happy to answer all correspondence<br /> sent to me via either U.S. Mail or CompuServe (ID 72460,1760).<br /> You DO NOT have to be a registered owner to contact me; if you<br /> have a particular problem or have stumbled across some magnetic<br /> critter that I might have missed, I want to hear from you. Many <br /> of my registered owners contacted me about certain specifics before<br /> registering, and then registered after I responded to their needs.<br /> In other words, I am flexible, I care about the people who are<br /> using my software, and there is a real live person on the other<br /> end of this product who won't leave you in the dark if you have<br /> problems.<br /> <br /><br />USER GROUPS/SHAREWARE DISTRIBUTORS<br /><br /> PC User Groups are welcome to add the Grumpfish Library to their<br /> libraries under the following conditions:<br /><br /> 1) it must be completely unmodified;<br /><br /> 2) a diskette/copying fee of $5 or less is charged; and<br /><br /> 3) this documentation file MUST be included.<br /><br /> I would appreciate notification that you have added Grumpfish<br /> Library to your library.<br /><br /> If you have received the Grumpfish Library through either a user<br /> group or a shareware distributor, please remember that the<br /> diskette fee you paid DOES NOT constitute licensing the software,<br /> and you are still obligated to register if you decide to use<br /> Grumpfish Library features in your Clipper programming endeavors.<br /><br /><br />STARTING OUT<br /><br /> For convenience's sake, copy GRUMP.LIB to the same subdirectory where<br /> CLIPPER.LIB and EXTEND.LIB are located.<br /><br /><br />USING THE GRUMPFISH LIBRARY<br /><br /> To use any of the Grumpfish applications or functions, you must first<br /> link in the Grumpfish library (GRUMP.LIB). In addition, you will need<br /> to link in Clipper's Extend library (EXTEND.LIB), because nearly<br /> all of the Grumpfish Library functions call functions in this<br /> library.<br /><br /> The following are examples of what you would enter at the DOS prompt<br /> for the three most commonly used linkers (<yourfile> represents the<br /> name of your main .obj file):<br /><br /> For PLINK86 linker: PLINK86 FI <yourfile> LIB GRUMP,EXTEND,CLIPPER<br /><br /> For the DOS linker: LINK <yourfile>,,,GRUMP + EXTEND + CLIPPER<br /><br /> For Borland's TLINK: TLINK <yourfile>,,,GRUMP EXTEND CLIPPER<br /><br /> Note that if your libraries are not located in the same subdirectory<br /> where linking is being performed, you will have to add the drive<br /> and/or path to prevent the linker from choking!<br /><br /><br />POP-UP APPLICATIONS<br /><br />1. CALCULATOR<br /><br />a. Description and Usage:<br /><br /> This is a useful calculator that includes all the basic operators:<br /> addition (+), subtraction (-), multiplication (*), and division (/).<br /> But it also has some other goodies, including exponentation (^), a<br /> paste function and a full-featured memory. Plus, whenever you press an<br /> operator ('+', '-', '*', '/', or '^'), the previous number is shown<br /> above the display window. This is handy for when you are processing a<br /> list of numbers and forget where you were.<br /><br /> Active Keys:<br /><br /> '+' -- addition '-' -- subtraction<br /><br /> '*' -- multiplication '/' -- division<br /><br /> '^' -- exponentation 'C' -- clear current number<br /><br /> 'E' -- clear entry (does not clear previously entered number in<br /> pending operation)<br /><br /> '=' or Enter -- process operation Esc -- exit Calculator<br /><br />b. Memory Functions:<br /><br /> To access memory functions, press "M", then one of the flashing<br /> function keys. The function keys are:<br /><br /> 'R' -- recall number stored in memory<br /><br /> 'C' -- clear memory (reset to zero)<br /><br /> '+' -- add current number to number stored in memory<br /><br /> '-' -- subtract add current number from number stored in memory<br /><br /> '*' -- multiply number stored in memory by current number<br /><br /> '/' -- divide number stored in memory by current memory<br /><br /> The maximum value that can be stored in the calculator is<br /> 99,999,999,999.9999.<br /><br /> The paste function enables you to paste the current calculator value<br /> into a pending READ by pressing a designated hot key (Ctrl-P is<br /> suggested). PASTE CAVEAT: erratic results may occur if the number<br /> of decimal places in the number to be pasted is larger than the <br /> number of decimals in the memory variable or field. For example,<br /> suppose that you have just used the calculator to derive the result<br /> 75.2877. You wish to paste this number into a memory variable<br /> mTOTAL, which you are GETting with a picture template of '###.##'.<br /> The probability is strong that this number will be stored<br /> on-screen as 75.29 (although internally it will remain 75.2877).<br /><br />c. Using the Calculator in your Clipper application:<br /><br /> There are two ways that you can make use of the calculator. The first<br /> method is to use the SET KEY command to establish a "hot-key" so that<br /> the user can pop up the calculator anywhere within the program. The<br /> following lines added at the top of your program configures the F6 key<br /> to serve as the hot key for the pop-up calculator and Ctrl-P as the hot<br /> key for the paste function:<br /><br /> EXTERNAL popcalc && define external symbol for linker<br /> PUBLIC paste_no && holds current calculator value for pasting<br /> calckey = -5 && hot key will be function key F6<br /> SET KEY calckey TO popcalc<br /> SET KEY 16 to paste && Ctrl-P (optional)<br /><br /> If you want to use different keys as hot keys, please refer to your<br /> Clipper manual for a list of INKEY() values.<br /><br /> The second method is to call the calculator directly. The following is<br /> a sample menu including the calculator as a menu option:<br /><br /> PUBLIC paste_no<br /> SET KEY 16 TO paste<br /> |<br /> |<br /> |<br /> @ 05,05 PROMPT "Data Entry"<br /> @ 06,05 PROMPT "Reports"<br /> @ 07,05 PROMPT "Calculator"<br /> @ 08,05 PROMPT "Exit to Operating System"<br /> MENU TO selection<br /><br /> DO CASE<br /> CASE selection = 1<br /> DO dataentry<br /> CASE selection = 2<br /> DO reports<br /> CASE selection = 3<br /> DO popcalc<br /> CASE selection = 4<br /> QUIT<br /> ENDCASE<br /><br /> Although the second method may appeal to some of you, I highly<br /> recommend using SET KEY so as to permit the user access to the<br /> calculator from anywhere within the program.<br /><br /><br />2. PHONE DIRECTORY<br /><br />a. Description:<br /><br /> This application allows the user to maintain a phone database with<br /> names, addresses, and phone numbers of business and personal contacts.<br /> It utilizes two files, PHONE.DBF and PHONE.NTX. You do not need to<br /> create these files; the application automatically generates them if it<br /> cannot find them in the specified subdirectory.<br /><br /> The user interface is a browse-style window. The user can view, add,<br /> edit, and delete records from the phone database. You can instruct the<br /> application to search a specific subdirectory for the database file by<br /> initializing a memory variable named 'phonedir' with the value of the<br /> desired directory (example: "C:\PHONE"). If 'phonedir' is not defined<br /> in your program, the current directory will be used.<br /><br /> Active Keys:<br /><br /> A -- add a record to the database<br /><br /> E -- edit highlighted record<br /><br /> D -- delete highlighted record<br /><br /> Arrow keys -- scroll through the database<br /><br /> Esc -- exit the phone directory<br /><br /> F2 -- view/edit address information for the highlighted record<br /><br /> Pressing F2 allows the user to view and/or edit address information for<br /> the highlighted person. A box containing that information will appear<br /> in the middle of the screen. The user can enter information in these<br /> fields as desired. They can then press Ctrl-W to save their edits, or<br /> Esc to exit without saving. Either way, they will be returned to the<br /> browse window.<br /><br />b. Using the Phone Directory in your Clipper applications:<br /><br /> As with the calculator, there are two methods to choose from. The<br /> first is to use SET KEY to establish a hot-key so that the user can pop<br /> up the phone directory anywhere within the program. The following<br /> lines added at the top of your program configures the F7 key to serve<br /> as the hot key, and instructs the program to look for the phone<br /> database in the subdirectory "C:\PHONE":<br /><br /> EXTERNAL popphone && define external symbol for linker<br /> phonekey = -6 && hot key will be function key F7<br /> phonedir = 'C:\PHONE' && search directory for phone.dbf<br /> SET KEY phonekey TO popphone<br /><br /> If you want to use a different hot key for the phone directory, please<br /> refer to your Clipper manual for a list of INKEY() values.<br /><br /> The second method is to call the phone directory directly. Refer to<br /> the Calculator discussion for a sample menu. Once again, I highly<br /> recommend using the SET KEY method.<br /><br /><br />3. CALENDAR<br /><br />a. Description and Usage:<br /><br /> This is a pop-up calendar that displays the current month and the first<br /> two weeks of the next month. The current day will blink. Press any<br /> key to exit the calendar.<br /><br />b. Using the Calendar in your Clipper applications:<br /><br /> As with the other applications, there are two ways to utilize the<br /> calendar. The first is to use SET KEY to establish a hot-key so that<br /> the user can pop up the calendar anywhere within the program. The<br /> following lines added at the top of your program configures the F8 key<br /> to serve as the hot key for the calendar:<br /><br /> EXTERNAL popdate && define external symbol for linker<br /> datekey = -7 && hot key will be function key F8<br /> SET KEY datekey TO popdate<br /><br /> If you want to use a different hot key for the calendar, please refer<br /> to your Clipper manual for a list of INKEY() values.<br /><br /> The second method is to call the calendar directly. Refer to the<br /> Calculator discussion for a sample menu. However, I recommend using<br /> SET KEY.<br /><br /><br />4. STOPWATCH<br /><br />a. Description and Usage:<br /><br /> Here is a pop-up stop watch that logs minutes, seconds, and hundredths<br /> of seconds. You never know when you might need one. Operation is<br /> simple: press the space bar to start and stop. Press Esc to quit.<br /><br />b. Using the Stopwatch in your Clipper applications:<br /><br /> As with the other applications, there are two ways to utilize the<br /> stopwatch. The first (and best) is to use SET KEY to establish a hot-<br /> key so that the user can pop up the stopwatch anywhere within the<br /> program. The following lines added at the top of your program<br /> configures the F5 key to serve as the hot key for the stopwatch:<br /><br /> EXTERNAL popstop && define external symbol for linker<br /> stopkey = -7 && hot key will be function key F5<br /> SET KEY stopkey TO popstop<br /><br /> If you want to use a different hot key for the stopwatch, please refer<br /> to your Clipper manual for a list of INKEY() values.<br /><br /> The second method is to call the stopwatch directly. See the<br /> Calculator section above for a sample menu. Once again, however, I<br /> recommend using SET KEY.<br /><br /><br />5. MASTERMIND*****<br /><br />a. Description and Usage:<br /><br /> Mastermind is a diversion when the user's brain needs a good workout!<br /> It is based on the logic board game by Pressman Corporation.<br /><br /> The computer selects four colored pegs and arranges them in a specific<br /> sequence. The player's objective is to determine both the color and<br /> position of the four pegs by making educated guesses and analyzing the<br /> clues that the computer dispenses after each guess. These clues are:<br /> one black marker for every peg that matches in both color and location;<br /> and one white marker for every peg that is correct in color but not<br /> location. An average game will take from eight to ten guesses. To<br /> choose a color, the user moves the highlight bar to the desired color<br /> and presses Enter. The user must choose colors from left to right. If<br /> the user wants to quit in the middle of a game, they may do so by<br /> pressing Esc instead of selecting a color. The program keeps track of<br /> the guesses & clues on the right side of the screen so that the player<br /> can refer back to them.<br /><br />b. Using Mastermind in your Clipper applications:<br /><br /> As with the other applications, there are two ways to utilize<br /> Mastermind. The first is to use SET KEY to establish a hot-key so that<br /> the user can pop up Mastermind from anywhere within the program. The<br /> following lines added at the top of your program configures the F9 key<br /> to serve as the hot key for Mastermind:<br /><br /> EXTERNAL popmm && define external symbol for linker<br /> mmkey = -8 && hot key will be function key F9<br /> SET KEY mmkey TO popmm<br /><br /> If you want to use a different hot key for Mastermind, please refer to<br /> your Clipper manual for a list of INKEY() values.<br /><br /> The second method is to call Mastermind directly. Refer to the<br /> Calculator discussion for a sample menu. However, SET KEY is highly<br /> recommended.<br /><br /><br />6. PUZZLE<br /><br />a. Description and Usage:<br /><br /> Puzzle is the four by four square puzzle you had when you were a kid.<br /> Fifteen of the squares are filled with the numbers 1-15, and it is up<br /> to the player to arrange these in order like so:<br /><br /> <br /> 1 2 3 4 <br /> <br /> 5 6 7 8 <br /> <br /> 9 10 11 12 <br /> <br /> 13 14 15 <br /> <br /><br /> To move, the player types in the number of the piece they wish to move.<br /> The program will not allow them to cheat. Good luck - this can be<br /> exasperatingly difficult!<br /><br />b. Using the Puzzle in your Clipper applications:<br /><br /> As with the other applications, there are two ways to utilize the<br /> puzzle. The first is to use SET KEY to establish a hot-key so that<br /> the user can pop it up from anywhere within the program. The<br /> following lines added at the top of your program configures the F10 key<br /> to serve as the hot key for the puzzle:<br /><br /> EXTERNAL poppuz && define external symbol for linker<br /> puzkey = -9 && hot key will be F10<br /> SET KEY puzkey TO poppuz<br /><br /> If you want to use a different hot key for the puzzle, please refer to<br /> your Clipper manual for a list of INKEY() values.<br /><br /> The second method is to call the puzzle directly. Refer to the<br /> Calculator discussion for a sample menu. However, SET KEY is highly<br /> recommended.<br /><br /><br />7. HELP SCREENS<br /><br /> Context-specific pop-up help screens add enormous user-friendliness to<br /> any program. With the Grumpfish Library, it is a breeze to create your<br /> own. Simply add the following line of code at the top of your program:<br /><br /> EXTERNAL help && declare symbol for linker<br /><br /> Next, recompile and link your program, because the actual creation of<br /> the help screens takes place interactively from within your program.<br /> Then run the program.<br /><br /> You may create a help screen for any wait state. Wait state commands<br /> include ACCEPT, INPUT, MENU TO, MEMOEDIT(), READ, and WAIT. When you<br /> are at a wait state where you wish to have a help screen, press F1. If<br /> this is the first time you have called the HELP function, the program<br /> will take a few seconds to initialize the HELP database. Three files<br /> will be created: HELP.dbf, HELP.dbt, and HELP.ntx. These files should<br /> not be deleted! If you do delete them, any previously-created help<br /> screens will have to be recreated.<br /><br /> Assuming that you have not already created a help screen for this<br /> particular wait state, you will get a help screen with the message:<br /><br /> No help text defined...<br /> Press F2 to create, any other key to return<br /><br /> Press F2 to create the help screen text, then type it in exactly as you<br /> wish it to appear. Once you are satisfied with the text, press Ctrl-W<br /> to save it. The next time you (or another user) presses F1 at this<br /> point in the program, they will be treated to your help screen!<br /><br /> Suppose that you have created a help screen and decide later that you<br /> wish to edit its text. There is a hidden function that will allow you<br /> to do so. Press F1 to pop up the help screen, then press Alt-E (for<br /> Edit). You are then free to edit it as you see fit. Press Ctrl-W to<br /> save your edits. This function is hidden because of the probability<br /> that most of your programs will be used by others, and we wouldn't want<br /> to give them too much freedom, now would we?<br /><br /><br />8. USING MULTIPLE POP-UP APPLICATIONS<br /><br /> If you would like to integrate more than one of these pop-up<br /> applications into your program, use the following code at the top of<br /> your program:<br /><br /> EXTERNAL help,popcalc,popphone,popdate,popmm,poppuz,popstop<br /> stopkey = -4 && F5 = hot key for stopwatch<br /> calckey = -5 && F6 = hot key for calculator<br /> phonekey = -6 && F7 = hot key for phone directory<br /> phonedir = 'C:\PHONE' && search directory for phone.dbf<br /> datekey = -7 && F8 = hot key for calendar<br /> mmkey = -8 && F9 = hot key for Mastermind<br /> puzkey = -9 && F10= hot key for puzzle<br /> SET KEY calckey TO popcalc<br /> SET KEY phonekey TO popphone<br /> SET KEY datekey TO popdate<br /> SET KEY mmkey TO popmm<br /> SET KEY puzkey TO poppuz<br /><br /><br />FUNCTIONS<br /><br />1. YES_NO()<br /><br /> This function displays a box with your message in it, and pauses<br /> program execution until the user presses either 'Y' or 'N'. It returns<br /> a logical value: true if the user pressed 'Y', or false if the user<br /> pressed 'N'. The syntax is:<br /><br /> YES_NO(<message 1>[,<message 2>])<br /><br /> where <message 1> and <message 2> are the messages you wish to have<br /> displayed. <Message 2> is optional.<br /><br /> Sample use of YES_NO:<br /><br /> kill_it = YES_NO('WARNING: Record will be deleted','Shall I continue')<br /> IF kill_it<br /> DELETE<br /> SKIP -1<br /> ENDIF<br /><br /> Note that the function automatically adds "? (Y/N)" to your last<br /> message. For example, in the sample above, the following would be<br /> displayed:<br /><br /> WARNING: Record will be deleted<br /> Shall I continue? (Y/N)<br /><br /><br />2. ERR_MSG()<br /><br /> This function displays a box with your error message in it, along with<br /> several choice beeps, and pauses program execution until the user<br /> presses any key. It does not return a value. The syntax is:<br /><br /> ERR_MSG(<message>)<br /><br /> where <message 1> is the message you wish to display (not too<br /> insulting, please!).<br /><br /> Sample use of ERR_MSG:<br /><br /> SEEK mVAR<br /> IF .not. found()<br /> ERR_MSG('That record was not found')<br /> ENDIF<br /><br /><br />3. CENTER()<br /><br /> You will probably make frequent use of this function. It centers<br /> character strings, either on the screen or the printer, at the row you<br /> specify. Syntax is:<br /><br /> CENTER(<row>,<string>,[<length>])<br /><br /> where <string> is the character string or expression to be centered,<br /> <row> is a numeric expression representing the row on which to<br /> center the string, and<br /> <length> is an optional numeric expression representing the<br /> length of a row (default length is 80 for screen displays, but<br /> you may use values of up to 255 when printing wide reports).<br /><br /> Thanks to Jeanne Nerwinski of Durham, NC for the <length> parameter.<br /><br /> Sample usage of CENTER:<br /><br /> CENTER(0,'Change Order Data Input Screen')<br /> CENTER(1,'WACKY WIDGETS MONTHLY PROFIT ANALYSIS',132)<br /><br /><br />4. WAITON() and WAITOFF()<br /><br /> This function is useful to keep the user of your application apprised<br /> of time-consuming operations, such as printing a report, instead of<br /> letting them stare at a blank screen and wonder what (if anything) is<br /> going on.<br /><br /> First, call WAITON(), which displays a box with your message in it.<br /> The syntax is:<br /><br /> WAITON([<message>])<br /><br /> where <message> is the message you wish to display. Note that if you<br /> do not pass a message, WAITON() will assume that you are about to print<br /> a report and will display the message "Now printing... please wait".<br /><br /> When the operation is complete, use WAITOFF() to refresh the screen.<br /> The syntax is:<br /><br /> WAITOFF()<br /><br /> This will restore the screen to its original state.<br /><br /> Sample usage of WAITON and WAITOFF:<br /><br /> USE Sales<br /> WAITON('Rebuilding index files... please wait')<br /> INDEX ON lname TO Customer<br /> INDEX ON date TO Saledate<br /> INDEX ON inv_code TO Item<br /> WAITOFF()<br /><br /><br />5. EXBOX()<br /><br /> Exploding boxes add enormous pizzaz to your color applications. The<br /> syntax is as follows:<br /><br /> EXBOX(<top>,<left>,<bottom>,<right>,<box type>,<delay>,[<fill>])<br /><br /> <top> is an integer numeric representing the top row of the box.<br /><br /> <left> is an integer numeric representing the leftmost column of the box.<br /><br /> <bottom> is an integer numeric representing the bottom row of the box.<br /><br /> <right> is an integer numeric representing the rightmost box column.<br /><br /> <box type> is an integer numeric between 1 and 5, and represents the<br /> type of box desired. The choices are:<br /><br /> Box Type Box String Used<br /><br /> 1 <br /> 2 <br /> 3 <br /> 4 <br /> 5 <br /> 6 (no border)<br /><br /><br /> The box string forms the box in the same fashion as with Clipper's<br /> "@...BOX" command. The box is drawn using this string starting from<br /> the left hand corner and proceeding clockwise. If you need more<br /> information on this, please refer to your Clipper manual.<br /><br /> <delay> is an integer numeric between 1 and 100, and is used to delay<br /> the 'explosion'. The larger the delay, the longer the box drawing<br /> operation will take. I recommend using values between 1 and 10, but<br /> you should experiment with this.<br /><br /> <fill> is an optional character string to use as the fill<br /> character. If the length of the character string passed is greater<br /> than one, only the leftmost character will be used. If this<br /> parameter is not specified, the fill character will be chr(32).<br /><br /> Sample usage:<br /><br /> EXBOX(11,28,13,51,2,5)<br /> @ 12,30 SAY 'Enter your ID:'<br /> @ 12,46 GET mID PICTURE 'XXXX'<br /> READ<br /><br /> When using a monochrome monitor, an exploding box will not have any<br /> noticeable effect.<br /><br /><br />6. SHRBOX()<br /><br /> What good are exploding boxes without shrinking boxes? Now you can<br /> shrink that box you just exploded onto the screen back into<br /> nothingness. Here's the syntax:<br /><br /> SHRBOX(<top>,<left>,<bottom>,<right>,<delay>,[<color>])<br /><br /> The first five parameters are identical to their namesakes in<br /> EXBOX().<br /><br /> <color> is an optional character string parameter specifying the<br /> color you wish to use to blank out the previous box. If not<br /> passed, the current color setting will be used.<br /><br /> What SHRBOX() does is blank out the area marked by the speified<br /> coordinates from the outside in, exactly opposite the method used<br /> by EXBOX().<br /><br /> Sample usage:<br /><br /> (with the color parameter)<br /><br /> SET COLOR TO +w/b<br /> EXBOX(11,17,13,62,2,5)<br /> @ 12,19 SAY 'This box will self-destruct in two seconds'<br /> INKEY(2)<br /> SHRBOX(11,17,13,62,2,'w/n')<br /><br /> (without the color parameter)<br /><br /> SET COLOR TO +w/b<br /> EXBOX(11,17,13,62,2,5)<br /> @ 12,19 SAY 'This box will self-destruct in two seconds'<br /> INKEY(2)<br /> SET COLOR TO w/n<br /> SHRBOX(11,17,13,62,2)<br /><br /> As with the exploding box, a shrinking box will have no noticeable<br /> effect with monochrome monitors.<br /><br /><br />7. POPBOX()/DROPBOX()<br /><br /> Surely you don't want to restrict yourself to exploding and<br /> shrinking boxes. Toss in a pop-up or drop-down box here and there<br /> to keep the users on their toes. Syntax:<br /> <br /> POPBOX / DROPBOX(<top>,<left>,<bottom>,<right>,<delay>)<br /><br /> The first five parameters are identical to their namesakes in<br /> EXBOX() and SHRBOX().<br /><br /> The pop-up box will be drawn from the bottom up, whereas the drop-<br /> down box will be drawn from the top down.<br /><br /> Sample usage:<br /><br /> POPBOX(5,5,23,55)<br /> @ 14,8 SAY 'This box rose like a phoenix from the ashes!'<br /> DROPBOX(1,60,11,79)<br /> @ 5,63 SAY 'This box fell'<br /> @ 6,63 SAY 'like pennies'<br /> @ 7,63 SAY 'from heaven!'<br /><br /> (feel free to substitute cliches of your own choosing)<br /><br /> Unlike the exploding and shrinking boxes, pop-up and drop-down<br /> boxes will be effective on monochrome monitors.<br /> <br /><br />8. SETFILT()<br /><br /> This function allows you to simulate SQL (structured query language)<br /> by establishing a query condition (or filter) for selectively printing<br /> or displaying records. The syntax is hardly complex:<br /><br /> SETFILT()<br /><br /> SETFILT() returns a logical value. The return value is true (.T.) if<br /> there are records found in the current database matching your query<br /> condition, false (.F.) if there are not.<br /><br /> SETFILT() will display all of the field names of the current database<br /> file. First, you move the highlight bar to the desired field and<br /> presses Enter to add it to the query condition. You then select the<br /><br /> desired operator (equal to, less than, greater than, less than or equal<br /> to, greater than or equal to, not equal to), and then the desired value<br /> for that field. [For subsequent additions to the query condition, you<br /> will be asked to select a logical (Boolean) operator (AND/OR)]. Bear in<br /> mind that AND has precedence over OR when evaluating the query<br /> expression. For example:<br /><br /> DATE=CTOD('05/01/81') .and. COST=50.00 .or. ITEM='widget'<br /><br /> will display all records with either (1) a date of 05/01/81 and a cost<br /> of 50.00, or (2) item 'widget'. If you need more clarificationon<br /> logical (Boolean) operators, please refer to your Clipper manual for<br /> enlightenment.<br /><br /> As you add items to the query condition, it will be updated on the<br /> screen so you can keep track of where you are.<br /><br /> When you are finished establishing your query condition, press Esc to<br /> return to the calling program.<br /><br /> Sample Usage:<br /><br /> USE Sales<br /> IF setfilt()<br /> DISPLAY ALL<br /> SET FILTER TO<br /> ENDIF<br /> RETURN<br /><br /><br />9. BATCHREP()<br /><br /> BATCHREP() allows the user to do global replaces within your program,<br /> in a similar fashion to the REPLACE command at the dBASE dot prompt.<br /> This function is invaluable for data-intensive applications.<br /><br /> The syntax consists of the following line:<br /><br /> BATCHREP()<br /><br /> There is no return value.<br /><br /> BATCHREP() will display all of the field names of the current database<br /> file. First, you select the field yoiu wish to replace by moving the<br /> highlight bar to that field and pressing Enter. You will then be<br /> prompted to enter the new value for that field. Use dBASE III syntax;<br /> if you want to see examples, press Alt-H. If the replacement field is<br /> character type, you will not be permitted to replace it with a value<br /> longer than the field's length. If the replacement field is logical<br /> type, you must replace it with either .T. (True) or .F. (False),<br /> logically enough.<br /><br /> After entering the new value, you then select the field or fields to<br /> define the replacement scope. (If you want to unconditionally replace<br /> all records, hit Esc to begin the replacement.) If you do select a<br /> field, you first select an operator (equal to, greater than, less than,<br /> etc.), and then enter a value for that field. As you add to the<br /> replacement scope, it will be updated near the bottom of the screen.<br /> You can use as many fields as you wish; for each subsequent field,<br /> you will be asked to select a logical (Boolean) operator (AND/OR)].<br /> See SETFILT() above for an example of logical operators.<br /><br /> When you are finished establishing the replacement scope, press Esc to<br /> begin the replacement. If the field being REPLACEd is a key field in<br /> any open index, you will be prompted to that effect. In this instance,<br /> the replacement will take slightly longer, because the index fields<br /> will have to be rebuilt after the replacement. When the replacement is<br /> finished, the number of records replaced will appear in the center of<br /> the screen for reference.<br /><br /> Sample Usage:<br /><br /> USE Sales<br /> batchrep()<br /><br /><br />10. MEMEDIT()<br /><br /> This permits easy editing of memo fields. The syntax is:<br /><br /> MEMEDIT(<mfield>,[<t>,<l>,<b>,<r>][,<msg>])<br /><br /> <mfield> is a character string representing the name of the memo field<br /> to be edited.<br /><br /> Optional parameters <t>, <l>, <b>, <r> are all numeric expressions<br /> representing the box coordinates (top, left, bottom, right,<br /> respectively). Default box coordinates are 5,10,19,69.<br /><br /> Optional parameter <msg> is a character string to be centered at the<br /> top of your box.<br /><br /> The active keys during MEMEDIT are exactly the same as those in the<br /> Clipper function MEMOEDIT(). Please refer to your manual for more<br /> specifics.<br /><br /> Sample Usage:<br /><br /> USE Letters<br /> MEMEDIT('text',10,20,15,59,'<< Edit Letter >>')<br /> RETURN<br /><br /><br />11. MENUH()<br /><br /> This function allows you to easily paint a horizontal Lotus-style<br /> light-bar menu on the screen. The syntax is:<br /><br /> MENUH(<row>,<col>,<spc>,<prompts>[,<messages>,<color>)<br /><br /> <row> is a numeric expression representing the row at which to display<br /> the light-bar menu.<br /><br /> <col> is a numeric expression representing the starting column for the<br /> light-bar menu.<br /><br /> <spc> is a numeric representing the desired spacing between menu<br /> entries.<br /><br /> <prompts> is a character string containing all of the prompts for the<br /> menu. These prompts must be separated by dollar signs.<br /><br /> Optional parameter <messages> is a character string containing any<br /> desired messages corresponding to the prompts. Like the prompts, the<br /> messages must be separated by dollar signs. NOTE: You must SET MESSAGE<br /> in your program before calling MENUH(), or your messages will not be<br /> displayed!<br /><br /> Optional parameter <color> is a character string used to set the menu<br /> color. If this parameter is not passed, white on black will be used<br /> for the unselected options and inverse will be used for the light bar.<br /><br /> MENUH() returns a numeric value representing the selected menu option.<br /> For example, if the user pressed 'D' in the sample below the return<br /> value would be 1.<br /><br /> Sample usage:<br /><br /> sel=MENUH(23,5,4,'Data Entry$Reports$Previous Menu$','','+w/b,+w/n')<br /> DO CASE<br /> CASE sel = 1<br /> DO data<br /> CASE sel = 2<br /> DO reports<br /> OTHERWISE<br /> RETURN<br /> ENDCASE<br /><br /><br />12. MENUV()<br /><br /> This function will paint a vertical bounce-bar menu on the screen.<br /> First, you must define an array containing the desired menu options<br /> (and corresponding messages, if desired). If you wish to have<br /> messages, you must separate the menu option from the message with a<br /> dollar sign. Also, be sure to SET MESSAGE before calling MENUV().<br /><br /> The syntax for this function is:<br /><br /> MENUV(<array>[,<title>,<box type>,<box color>,<title color>])<br /><br /><br /> <array> is a character string representing the name of the array that<br /> contains the menu options.<br /><br /> Optional parameter <title> is a character string representing the menu<br /> title.<br /><br /> Optional parameter <box type> is an integer between 1 and 12<br /> corresponding to the type of box you wish to use. Box types 1-4 are<br /> listed below:<br /><br /> Box Type Box String Used<br /><br /> 1 <br /> 2 <br /> 3 <br /> 4 <br /> 5 <br /><br /> Boxes 6-10 and 11-15 are identical to boxes 1-5, except that 6-10 will<br /> have an additional drop shadow (simulating a three-dimensional effect)<br /> and 11-15 will have two drop shadows for super-duper 3-D.<br /><br /> Optional parameter <box color> is a character string containing the<br /> color to use for the box. The default color is white on black for<br /> unselected options and inverse (black on white) for the bounce bar.<br /><br /> Optional parameter <title color> is a character string containing the<br /> color to use for the menu title. The default is white on black.<br /><br /> MENUV() returns a numeric value representing the selected menu option.<br /> For example, if the user pressed 'Q' in the sample below the return<br /> value would be 4.<br /><br /> Sample usage:<br /><br /> DECLARE mainmenu[4]<br /> mainmenu[1]='Maintain Data$Add and edit information'<br /> mainmenu[2]='Output Reports$Share your information'<br /> mainmenu[3]='Utilities$Select printer, reindex files'<br /> mainmenu[4]='Quit$Exit to DOS'<br /> sel=MENUV(mainmenu,'Main Menu',11,'+w/rb,+w/n','+w/b')<br /> DO CASE<br /> CASE sel = 1<br /> DO maintdata<br /> CASE sel = 2<br /> DO reports<br /> CASE sel = 3<br /> DO utility<br /> OTHERWISE<br /> RETURN<br /> ENDCASE<br /><br /><br />13. NET_USE()<br /><br /> This function and the two that follow are primarily for multi-user<br /> applications. If you have any questions about the basics of <br /> networking, I suggest that you refer to either the Clipper manual <br /> or the Spring 1987 issue of "Nantucket News", which provides an <br /> excellent tutorial.<br /> <br /> NET_USE() will open a specified database in either exclusive or <br /> shared mode, along with up to eight corresponding index files. <br /> The syntax is:<br /><br /> NET_USE(<filename>,<excl_use> [,<index1>,<index2>,...<index8>]<br /> <br /> <filename> is a character string representing the name of the<br /> database file to be opened.<br /> <br /> <excl_use> is a logical expression representing the desired mode:<br /> True (.T.) for exclusive, False (.F.) for shared.<br /> <br /> Optional parameters <index1>...<index8> are character strings<br /> representing the names of the index files to be opened.<br /> <br /> NET_USE() returns a logical value: True (.T.) if the file was<br /> opened successfully, or False (.F.) if it was not.<br /> <br /> If NET_USE() is unable to open the file, the user will be asked if<br /> they wish to wait for it to become available. If not, the return<br /> value will be False. If they do decide to wait, they will be<br /> entertained by an intriguing screen display. They may abort the<br /> wait at any time by pressing Esc (which will then cause the<br /> function to return False).<br /> <br /> This function also provides aural feedback to the user, so that if<br /> they want to wait for the file, they do not necessarily have to<br /> remain glued to the screen. When the file becomes available, the<br /> Charge theme will be played, which is sure to get a Pavlovian<br /> response from your users!<br /> <br /> You will note the absence of explicit selection of work areas.<br /> NET_USE() takes advantage of the Clipper "SELECT 0" command to<br /> automatically select the next available work area.<br /> <br /> WARNING: You must SET EXCLUSIVE OFF prior to calling this<br /> function. If you do not, NET_USE() will attempt to open all files<br /> exclusively, which will give you a terrible headache.<br /> <br /> Sample Usage:<br /> <br /> IF ! NET_USE('customer',.f.,'cust1','cust2')<br /> RETURN<br /> ENDIF<br /> ** code to maintain customer file<br /> |<br /> |<br /> IF ! NET_USE('customer',.t.,'cust1')<br /> RETURN<br /> ENDIF<br /> ** code to print customer reports<br /> <br /> <br />14. REC_LOCK()/FILELOCK()<br /><br /> These two functions are crucial in any multi-user system. <br /> Obviously enough, REC_LOCK() is used to lock records, while<br /> FILELOCK() locks files. The syntax is simple:<br /> <br /> REC_LOCK() / FILELOCK()<br /> <br /> There are no parameters.<br /> <br /> Both functions return logical values: True (.T.) if the lock was<br /> successful, or False (.F.) if unsuccessful.<br /> <br /> If the locks are initially unsuccessful, the user will be given<br /> the option to wait for availability in the same fashion as with<br /> NET_USE(). Likewise, a dazzling screen will keep them amused<br /> while they wait, and the Charge theme will be played when the lock<br /> is finally successful.<br /> <br /> Sample Usage:<br /> <br /> IF REC_LOCK()<br /> REPLACE name WITH mname, address WITH maddress<br /> ENDIF<br /><br /> IF FILELOCK()<br /> DO reports<br /> ENDIF<br /> <br /><br />15. ADD_REC()<br /><br /> This function is for APPENDing BLANK records to a database in a<br /> multi-user system. The syntax is:<br /> <br /> ADD_REC([<wait time>])<br /> <br /> <wait time> is an optional numeric expression representing the<br /> number of seconds to wait for the APPEND BLANK to be successful.<br /> If this parameter is not passed, the function will loop until<br /> either the APPEND BLANK is successful or the user presses Esc.<br /><br /> ADD_REC() returns a logical value: True (.T.) if the APPEND BLANK<br /> is successful, or False (.F.) if it did not succeed within the<br /> specified time. Please note that it is highly unlikely that this<br /> function will ever return False, except in the rare event that two<br /> users have attempted to APPEND BLANK to the same database at<br /> precisely the same time.<br /> <br /> <br />16. PRINTOK()<br /><br /> How many times have you or your users had problems with printers<br /> not being ready? Use this function and you might never have to<br /> deal with "Printer Not Ready.... Retry (Y/N)?" again. Syntax:<br /><br /> PRINTOK()<br /><br /> It returns a logical value. If the printer is ready, it will<br /> return True (.T.) and SET the DEVICE TO PRINT. If the printer is<br /> not ready, it will return False (.F.).<br /><br /> Sample usage:<br /><br /> IF PRINTOK()<br /> DO report<br /> SET DEVICE TO SCREEN<br /> ENDIF<br /><br /><br />17. DATEST()<br /><br /> If you want to print an empty date field or expression in a report<br /> without printing the slashes (' / / '), use DATEST() instead of<br /> DTOC() like so:<br /><br /> DATEST(<date>)<br /><br /> where <date> is the date field or expression you wish to print.<br /><br /><br />18. ISSTATE()<br /><br /> This function is useful in applications where the user must input a<br /> two-character state abbreviation. ISSTATE() checks to ensure that a<br /> valid abbreviation has been entered. The syntax is:<br /><br /> ISSTATE(<memvar>)<br /><br /> where <memvar> is a character expression to be tested.<br /><br /> ISSTATE() returns a logical value: True (.T.) if the expression is a<br /> valid state abbreviation, or False (.F.) if it is not.<br /><br /> Sample Usage:<br /><br /> mSTATE = space(2)<br /> @ 10,10 get mSTATE valid isstate(mSTATE)<br /><br /><br />19. SPREAD()<br /><br /> This function lets you display a character string on the screen<br /> from the middle out. If this does not make sense, try it for<br /> yourself. It is simple, yet slick. The syntax is as follows:<br /><br /> SPREAD(<string>,<row>[,<delay>,<column>])<br /><br /> <string> is the character string to display.<br /><br /> <row> is the row at which to display it.<br /><br /> Optional parameter <delay> is a numeric integer to delay the<br /> effect. The default delay setting is 8. Experiment with this<br /> until you find one that you like.<br /><br /> Optional parameter <column> is a numeric integer specifying the<br /> column at which to spread the string out from (the default is 40).<br /><br /> Sample usage:<br /><br /> SPREAD("This effect will get the user's attention!",12)<br /> SPREAD("This line will be drawn very slowly",14,50)<br /><br /><br />20. TTY()<br /><br /> This function displays a character string across the screen in a<br /> continuously scrolling "teletype" manner until the user presses <br /> any key. The syntax is as follows:<br /> <br /> TTY(<row>, <message>, <delay>)<br /><br /> <row> is a numeric expression representing the row at which to<br /> display the message.<br /> <br /> <message> is the character string to be displayed.<br /> <br /> <delay> is a numeric expression representing the delay factor to<br /> be introduced into the scrolling process. Values between 10 and <br /> 100 are recommended, although you should experiment to determine <br /> what works best on your particular computer.<br /> <br /> There is no return value. The message will scroll across the<br /> screen until the user presses a key.<br /> <br /> Sample Usage:<br /> <br /> TTY(12, 'Press any key to return to the Main Menu', 75)<br /> <br /> <br />21. PASS_CHK()<br /><br /> This is a generic routine to be used whenever the user must enter a<br /> password to continue. The syntax is as follows:<br /><br /> PASS_CHK(<password>, [<row>])<br /><br /> where <password> is a character expression and <row> is an optional<br /> parameter indicating the row number at which you want the "Enter<br /> password..." message to appear.<br /><br /> PASS_CHK() compares the user's entry against the password you<br /> passed to it. The function is case-insensitive.<br /><br /> PASS_CHK() returns a logical value: True (.T.) if the user<br /> enters the correct password, or False (.F.) if they do not.<br /><br /> Sample Usage:<br /><br /> IF pass_chk(chr(77)+chr(79)+chr(79)+chr(76)+chr(65)) && MOOLA<br /> DO payroll<br /> ENDIF<br /><br /><br />22. RAND()<br /><br /> Here is a random number generator so that you can work on that pop-up<br /> poker game you've been dreaming of! It is driven by the system clock,<br /> so there is no need for you to initialize a 'seed'. Syntax is:<br /><br /> RAND(<range>)<br /><br /> where <range> is an integer numeric expression.<br /><br /> RAND() will return a random integer between zero and <range>-1.<br /><br /> Sample Usage: Output:<br /><br /> ? RAND(100) 75<br /> ? RAND(50) 22<br /> ? RAND(10) 7<br /><br /><br />23. TIMEWORD()<br /><br /> This function may seem trivial, but believe it or not, you might<br /> find use for it someday. It simply returns a word describing the<br /> time of day (based on the system clock). Syntax:<br /><br /> TIMEWORD()<br /><br /> There are no parameters.<br /><br /> The return value is a character string which relates to the time as<br /> follows:<br /><br /> 12:00 am - 11:59 am "Morning"<br /> 12:00 pm - 5:59 pm "Afternoon"<br /> 6:00 pm - 11:59 pm "Evening"<br /><br /> I use this in several of my multi-user systems in the following<br /> manner: first, an environmental variable with the user's name is<br /> defined in the network login script. Then I grab the user's name<br /> with the Clipper function GETE() and use TIMEWORD() to give them a<br /> personal and time-specific greeting when they enter my program. Not<br /> exactly a cure for cancer, but it is a nice touch.<br /><br /> Sample Usage:<br /><br /> @ 12,20 say 'Good '+TIMEWORD()+', '+user_name<br /><br /><br />24. GL_VER()<br /><br /> This function simply returns the version number of the Grumpfish<br /> Library that you are using.<br /><br /> Sample Usage:<br /> <br /> ? GL_VER()<br /> <br /><br />THE SINGING P.C.<br /><br /> A number of musical themes are available to you if you dare to use<br /> them. They are listed below, followed by the code syntax to call them.<br /><br /> 1. "Beat It" by Michael Jackson (intro) - DO BEATIT<br /><br /> 2. "Born to Run" by Bruce Springsteen (one verse) - DO BORN2RUN<br /><br /> 3. "Charge!" as heard at finer sporting events everywhere - DO CHARGE<br /><br /> 4. "Mexican Hat Dance", popular at many hockey rinks - DO HATDANCE<br /><br /> 5. "Theme from Final Jeopardy" - DO JEOPARDY<br /><br /> 6. "The Girl from Ipanema" - DO IPANEMA<br /> <br /> If you have any musical requests, please let me know!<br /><br /><br />FUTURE IMPROVEMENTS<br /><br />Word Processing/Notepad, Memo Editor, Label Printer, Printer Set-up String<br />Manager, Function Key Manager, Database File Manager, more UDFs --- and any<br />ideas that you might have and want to send me!<br /><br /> Greg Lief<br /> P. O. Box 17761<br /> Salem, Oregon 97305<br /><br />TRADEMARK ACKNOWLEDGEMENTS<br /><br />CLIPPER is a registered trademark of Nantucket Corporation.<br /><br />PLINK86 is a registered trademark of Phoenix Technologies.<br /><br />DOS is a registered trademark of Microsoft Corporation.<br /><br />TLINK (Turbo Link) is a registered trademark of Borland International.<br /><br />MASTERMIND is a registered trademark of Pressman Corporation.<br /><br />LOTUS is a registered trademark of Lotus Development Corporation.<br /><br /><br /><br />REVISION HISTORY<br /><br /> 1.0 - July 1988 (initial release)<br /><br /> 1.1 - August 1988 - corrected discrepancy between documentation and<br /> source code regarding hot key implementation for pop-ups. Added<br /> SETFILT(), BATCHREP(), ISSTATE(), RAND(), and <length> parameter for<br /> CENTER().<br /><br /> 1.2 - September 1988 - Added POPSTOP, paste function for POPCALC,<br /> and PASS_CHK(). Added solid border box option to EXBOX(). Updated<br /> most functions to properly set colors dependent upon type of<br /> monitor (color vs. monochrome). Corrected MEMED() so that menu<br /> title is centered properly between left and right columns.<br /><br /> 1.25 - October 1988 - Added SHRBOX(), SPREAD(), TIMEWORD(),<br /> PRINTOK(), and fill character option for EXBOX(). Cleaned up<br /> documentation and added demo program with supporting databases to<br /> distribution disk. <br /><br /> 1.3 - November 1988 - Added multi-user functions (NET_USE, ADD_REC,<br /> FILELOCK, REC_LOCK). Added POPBOX(), DROPBOX(), and GL_VER().<br /> Added IPANEMA to the Singing P.C.'s repertoire, and made it<br /> possible to escape from any of the songs as they play.<br /><br /> 1.31 - November 1988 - Fixed persistent bug in POPCALC involving<br /> use and pasting of non-integer numbers, and added TTY().This diskette includes the following files:<br /><br /> demo.prg - program demonstrating some Grumpfish Library capabilities<br /> grump.lib - Grumpfish Library Version 1.31<br /> help.dbf - sample help database for use with demo<br /> help.dbt - sample help memofield file for use with demo<br /> help.ntx - sample help index file for use with demo<br /> makedemo.bat - batch file to create demo program<br /> order - registration form<br /> phone.dbf - sample phone database for use with demo<br /> phone.ntx - sample phone index file for use with demo<br /> question.doc - user questionnaire: please fill it out and return to me <br /> readme.1st- the file you are reading<br /> readme.doc- main documentation for Grumpfish Library<br /><br />Feel free to distribute copies of GRUMP131.ARC. Have fun!<br /><br /></div></div><br><br> <div id='jp-relatedposts' class='jp-relatedposts' > <h3 class="jp-relatedposts-headline"><em>Related</em></h3> </div> </div><!--/entry --> </div><!-- .entry-container --> <footer class="post-footer postdata fix"> </footer><!-- .post-footer --> <div class='postdata line'> <span class='line-date'><span class='icon'> </span>December 12, 2017</span> <span class="comments"><span class="icon"> </span><a href="#respond">Add comments</a></span> </div> <section id="comments"> <div id="respond" class="comment-respond"> <h3 id="reply-title" class="comment-reply-title">Leave a Reply <small><a rel="nofollow" id="cancel-comment-reply-link" href="/list/DBASE/GRUMP131.ZIP/INFO/#respond" style="display:none;">Cancel reply</a></small> </h3> <form id="commentform" class="comment-form"> <iframe title="Comment Form" src="https://jetpack.wordpress.com/jetpack-comment/?blogid=30175801&postid=8780&comment_registration=0&require_name_email=1&stc_enabled=1&stb_enabled=1&show_avatars=1&avatar_default=mystery&greeting=Leave+a+Reply&greeting_reply=Leave+a+Reply+to+%25s&color_scheme=light&lang=en_US&jetpack_version=6.8&show_cookie_consent=10&has_cookie_consent=0&sig=3aefe2e16b0da650d687dac9a4ce6803a6f8eed3#parent=https%3A%2F%2Fwww.pcorner.com%2Flist%2FDBASE%2FGRUMP131.ZIP%2FINFO%2F" style="width:100%; height: 430px; border:0;" name="jetpack_remote_comment" class="jetpack_remote_comment" id="jetpack_remote_comment" sandbox="allow-same-origin allow-top-navigation allow-scripts allow-forms allow-popups"></iframe> <!--[if !IE]><!--> <script> document.addEventListener('DOMContentLoaded', function () { var commentForms = document.getElementsByClassName('jetpack_remote_comment'); for (var i = 0; i < commentForms.length; i++) { commentForms[i].allowTransparency = false; commentForms[i].scrolling = 'no'; } }); </script> <!--<![endif]--> </form> </div> <input type="hidden" name="comment_parent" id="comment_parent" value="" /> </section> <!-- #comments --> </article><!--/post --> <nav class='post-nav fix'> <table> <tr> <td class='previous'><a href="https://www.pcorner.com/list/DPGRAPH/OCR22.ZIP/INFO/" rel="prev"><span class="icon"> </span> DPGRAPH – OCR22.ZIP</a></td> <td class='next'><a href="https://www.pcorner.com/list/DPGRAPH/NPFONT2.ZIP/INFO/" rel="next"><span class="icon"> </span> DPGRAPH – NPFONT2.ZIP</a></td> </tr> </table> </nav> </div><!-- content --> </div><!-- main col --> <div id='sidebar-shell-1' class='sidebar-shell sidebar-shell-right'> <div class="dbx-group right boxed warea" id="sidebar"> <!--widget start --><aside id="paypal_donations-2" class="dbx-box suf-widget widget_paypal_donations"><div class="dbx-content"><h3 class="dbx-handle plain">Donate</h3><p>Please help defray the cost of running this free service.</p> <!-- Begin PayPal Donations by https://www.tipsandtricks-hq.com/paypal-donations-widgets-plugin --> <form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <div class="paypal-donations"> <input type="hidden" name="cmd" value="_donations" /> <input type="hidden" name="bn" value="TipsandTricks_SP" /> <input type="hidden" name="business" value="gjsmith66@pcorner.com" /> <input type="hidden" name="rm" value="0" /> <input type="hidden" name="currency_code" value="USD" /> <input type="image" style="cursor: pointer;" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" name="submit" alt="PayPal - The safer, easier way to pay online." /> <img alt="" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" /> </div> </form> <!-- End PayPal Donations --></div></aside><!--widget end --><!--widget start --><aside id="text-7" class="dbx-box suf-widget widget_text"><div class="dbx-content"> <div class="textwidget"><script type="text/javascript"> amzn_assoc_placement = "adunit0"; amzn_assoc_enable_interest_ads = "true"; amzn_assoc_tracking_id = "zca-20"; amzn_assoc_ad_mode = "auto"; amzn_assoc_ad_type = "smart"; amzn_assoc_marketplace = "amazon"; amzn_assoc_region = "US"; amzn_assoc_linkid = "ea8faac85a6c9ee94ab5174bccaeb487"; amzn_assoc_emphasize_categories = "13900871"; amzn_assoc_fallback_mode = {"type":"search","value":"DOS Windows"}; amzn_assoc_default_category = "All"; </script> <script src="//z-na.amazon-adsystem.com/widgets/onejs?MarketPlace=US"></script> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <ins class="adsbygoogle" style="display:inline-block;width:160px;height:600px" data-ad-client="ca-pub-8001169946558833" data-ad-slot="3404908173"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div> </div></aside><!--widget end --></div><!--/sidebar --> </div> </div><!-- /container --> </div><!--/wrapper --> <footer> <div id='page-footer'> <div class='col-control'> <div id="cred"> <table> <tr> <td class="cred-left">© 2018 <a href='http://www.pcorner.com'>The Programmer's Corner</a> by Personalized Computer Systems </td> <td class="cred-center"><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-8001169946558833" data-ad-slot="6568049104"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </td> <td class="cred-right"></td> </tr> </table> </div> </div> </div> </footer> <!-- 95 queries, 11MB in 0.300 seconds. --> <!-- location footer --> <script type='text/javascript'> //<![CDATA[ jQuery(document).ready(function($) { $('html').MagicLiquidizerTable({ whichelement: 'table', breakpoint: '780', headerSelector: 'thead td, thead th, tr th', bodyRowSelector: 'tbody tr, tr', table: '1' }) }) //]]> </script> <!-- tracker added by Ultimate Google Analytics plugin v1.6.0: http://www.oratransplant.nl/uga --> <script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); </script> <script type="text/javascript"> var pageTracker = _gat._getTracker("UA-10500370-7"); pageTracker._initData(); pageTracker._trackPageview(); </script> <div style="display:none"> </div> <script type='text/javascript' src='https://www.pcorner.com/wp-includes/js/comment-reply.min.js?ver=4.9.9'></script> <script type='text/javascript' src='https://www.pcorner.com/wp-includes/js/jquery/ui/core.min.js?ver=1.11.4'></script> <script type='text/javascript' src='https://www.pcorner.com/wp-includes/js/jquery/ui/datepicker.min.js?ver=1.11.4'></script> <script type='text/javascript'> jQuery(document).ready(function(jQuery){jQuery.datepicker.setDefaults({"closeText":"Close","currentText":"Today","monthNames":["January","February","March","April","May","June","July","August","September","October","November","December"],"monthNamesShort":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"nextText":"Next","prevText":"Previous","dayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"dayNamesShort":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"dayNamesMin":["S","M","T","W","T","F","S"],"dateFormat":"MM d, yy","firstDay":1,"isRTL":false});}); </script> <script type='text/javascript' src='https://www.pcorner.com/wp-includes/js/jquery/ui/widget.min.js?ver=1.11.4'></script> <script type='text/javascript' src='https://www.pcorner.com/wp-includes/js/jquery/ui/progressbar.min.js?ver=1.11.4'></script> <script type='text/javascript' src='https://s0.wp.com/wp-content/js/devicepx-jetpack.js?ver=201851'></script> <script type='text/javascript' src='https://www.pcorner.com/wp-includes/js/jquery/ui/mouse.min.js?ver=1.11.4'></script> <script type='text/javascript' src='https://www.pcorner.com/wp-includes/js/jquery/ui/sortable.min.js?ver=1.11.4'></script> <script type='text/javascript' src='https://secure.gravatar.com/js/gprofiles.js?ver=2018Decaa'></script> <script type='text/javascript'> /* <![CDATA[ */ var WPGroHo = {"my_hash":""}; /* ]]> */ </script> <script type='text/javascript' src='https://www.pcorner.com/wp-content/plugins/jetpack/modules/wpgroho.js?ver=4.9.9'></script> <script type='text/javascript' src='https://www.pcorner.com/wp-content/plugins/jetpack/_inc/build/likes/queuehandler.min.js?ver=6.8'></script> <script type='text/javascript' src='https://www.pcorner.com/wp-includes/js/wp-embed.min.js?ver=4.9.9'></script> <script async="async" type='text/javascript' src='https://www.pcorner.com/wp-content/plugins/akismet/_inc/form.js?ver=4.1'></script> <!--[if IE]> <script type="text/javascript"> if ( 0 === window.location.hash.indexOf( '#comment-' ) ) { // window.location.reload() doesn't respect the Hash in IE window.location.hash = window.location.hash; } </script> <![endif]--> <script type="text/javascript"> (function () { var comm_par_el = document.getElementById( 'comment_parent' ), comm_par = ( comm_par_el && comm_par_el.value ) ? comm_par_el.value : '', frame = document.getElementById( 'jetpack_remote_comment' ), tellFrameNewParent; tellFrameNewParent = function () { if ( comm_par ) { frame.src = "https://jetpack.wordpress.com/jetpack-comment/?blogid=30175801&postid=8780&comment_registration=0&require_name_email=1&stc_enabled=1&stb_enabled=1&show_avatars=1&avatar_default=mystery&greeting=Leave+a+Reply&greeting_reply=Leave+a+Reply+to+%25s&color_scheme=light&lang=en_US&jetpack_version=6.8&show_cookie_consent=10&has_cookie_consent=0&sig=3aefe2e16b0da650d687dac9a4ce6803a6f8eed3#parent=https%3A%2F%2Fwww.pcorner.com%2Flist%2FDBASE%2FGRUMP131.ZIP%2FINFO%2F" + '&replytocom=' + parseInt( comm_par, 10 ).toString(); } else { frame.src = "https://jetpack.wordpress.com/jetpack-comment/?blogid=30175801&postid=8780&comment_registration=0&require_name_email=1&stc_enabled=1&stb_enabled=1&show_avatars=1&avatar_default=mystery&greeting=Leave+a+Reply&greeting_reply=Leave+a+Reply+to+%25s&color_scheme=light&lang=en_US&jetpack_version=6.8&show_cookie_consent=10&has_cookie_consent=0&sig=3aefe2e16b0da650d687dac9a4ce6803a6f8eed3#parent=https%3A%2F%2Fwww.pcorner.com%2Flist%2FDBASE%2FGRUMP131.ZIP%2FINFO%2F"; } }; if ( 'undefined' !== typeof addComment ) { addComment._Jetpack_moveForm = addComment.moveForm; addComment.moveForm = function ( commId, parentId, respondId, postId ) { var returnValue = addComment._Jetpack_moveForm( commId, parentId, respondId, postId ), cancelClick, cancel; if ( false === returnValue ) { cancel = document.getElementById( 'cancel-comment-reply-link' ); cancelClick = cancel.onclick; cancel.onclick = function () { var cancelReturn = cancelClick.call( this ); if ( false !== cancelReturn ) { return cancelReturn; } if ( ! comm_par ) { return cancelReturn; } comm_par = 0; tellFrameNewParent(); return cancelReturn; }; } if ( comm_par == parentId ) { return returnValue; } comm_par = parentId; tellFrameNewParent(); return returnValue; }; } // Do the post message bit after the dom has loaded. document.addEventListener( 'DOMContentLoaded', function () { var iframe_url = "https:\/\/jetpack.wordpress.com"; if ( window.postMessage ) { if ( document.addEventListener ) { window.addEventListener( 'message', function ( event ) { var origin = event.origin.replace( /^http:\/\//i, 'https://' ); if ( iframe_url.replace( /^http:\/\//i, 'https://' ) !== origin ) { return; } jQuery( frame ).height( event.data ); }); } else if ( document.attachEvent ) { window.attachEvent( 'message', function ( event ) { var origin = event.origin.replace( /^http:\/\//i, 'https://' ); if ( iframe_url.replace( /^http:\/\//i, 'https://' ) !== origin ) { return; } jQuery( frame ).height( event.data ); }); } } }) })(); </script> <script type='text/javascript' src='https://stats.wp.com/e-201851.js' async='async' defer='defer'></script> <script type='text/javascript'> _stq = window._stq || []; _stq.push([ 'view', {v:'ext',j:'1:6.8',blog:'30175801',post:'8780',tz:'0',srv:'www.pcorner.com'} ]); _stq.push([ 'clickTrackerInit', '30175801', '8780' ]); </script> </body> </html>