
         1  ķ
                    phd: Title Page          
            Ľ
            This help file is designed to be displayed at 60 characters
            per line.  Please maximize your help window or adjust its
            size until you can see the large "PhDbase III" directly
            below this paragraph.

                
            Ŀ۳ ۳Ŀ۳Ŀ۳Ŀ۳Ŀ۳  ۳۳
             ۳ ۳ ۳ ۳ ۳ ٳ     ۳۳
            ۳۳ ۳ٳ۳۳   ۳۳
            ٳĿ۳ ۳Ŀ۳ĿĿ۳   ۳۳
                 ۳ ۳ ۳  ۳     ۳۳
                 ۳ٳ۳ ۳۳  ۳۳
                     

              PhDbase III Full Text Index/Search Technology for FoxPro

                  Copyright (c) 1994 by Korenthal Associates, Inc.

                                All Rights Reserved

                           Documentation for Version 3.30
            
         2  ķ
                 phd: Table Of Contents      
            Ľ
            The reference numbers in this Table of Contents are topic
            numbers in the PHDHELP.DBF file.  If you are looking at the
            printed documentation, the topic number appears just before
            each section heading.

            These commands will create a PhDbase III documentation file
            suitable for printing:

                use phdhelp
                set memo to 60
                set heading off
                set margin to 3
                list details nocon to printer   (or "to file xxx")

            phd: Title Page........................................  1
            phd: Table Of Contents.................................  2
            phd: Acknowledgments...................................  3
            phd: Late Breaking News................................  4
            phd: How To Get PhDbase III............................  5
            phd: Welcome...........................................  6
            phd: Royalty-Free License..............................  7
            phd: Dealer Information................................  8
            phd: Packing List......................................  9
            phd: Quick Start....................................... 10
            phd: Introduction...................................... 11
            phd: Loading the Library............................... 12
            phd: Passing Parameters................................ 13
            phd: On-line Help System............................... 14
            phd: Indexing a File................................... 15
            phd: Indexing Many Fields.............................. 16
            phd: Testing for an Index...............................17
            phd: Common English Words.............................. 18
            phd: Frequent Words.................................... 19
            phd: Exclusion Lists................................... 20
            phd: Getting Index Expression.......................... 21
            phd: Removing an Index................................. 22
            phd: Detach/Attach Index............................... 23
            phd: Ad-Hoc Queries.................................... 24
            phd: Ad-Hoc Updates.................................... 25
            phd: Hypertext Implementation.......................... 26
            phd: Font Control...................................... 27
            phd: Search Expressions................................ 28
            phd: Search Examples................................... 29
            phd: Searching Common Words............................ 30
            phd: Queries; PhDbase SELECT........................... 31
            phd: SELECT Clause..................................... 32
            phd: FROM Clause....................................... 33
            phd: WHERE Clause...................................... 34
            phd: AND Clause; Mixed Queries......................... 35
            phd: INTO Clauses...................................... 36
            phd: INTO BROWSE....................................... 37
            phd: INTO TABLE........................................ 38
            phd: INTO CURSOR....................................... 39
            phd: INTO FILE......................................... 40
            phd: INTO FIELD........................................ 41
            phd: INTO HITS CURSOR.................................. 42
            phd: INTO HITS ARRAY................................... 43
            phd: INTO NULL......................................... 44
            phd: ORDER BY Clause................................... 45
            phd: The Null Search; GETNEXT.......................... 46
            phd: Hits Cursors...................................... 47
            phd: FOUND Function.................................... 48
            phd: Locating Hits with VERIFY......................... 49
            phd: Advanced Searching................................ 50
            phd: Wildcard Searches................................. 51
            phd: The LIKE Operator................................. 52
            phd: Field-specific Searches........................... 53
            phd: Phrase Searches................................... 54
            phd: Proximity Searches................................ 55
            phd: Augmented Searches................................ 56
            phd: The LIKE Function................................. 57
            phd: Controlling Fuzzy Search.......................... 58
            phd: The FLUSH Function................................ 59
            phd: Manual Index Control.............................. 60
            phd: Indexing External Files........................... 61
            phd: Indexing Related Files............................ 62
            phd: Wildcards and SQLWILD............................. 63
            phd: Ignoring Search Operators......................... 64
            phd: Direct Index Access............................... 65
            phd: Multi-user Considerations......................... 66
            phd: PhDbase-embedded .EXE's........................... 67
            phd: CD-Rom Considerations............................. 68
            phd: Alternate Index Paths............................. 69
            phd: Running With No Library........................... 70
            phd: The Old API; OLDAPI.PRG........................... 71
            phd: Error Trapping.................................... 72
            phd: Fatal Errors...................................... 73
            phd: Ex: Total Hit Count............................... 74
            phd: Ex: Hit Line #'s in Memo.......................... 75
            phd: Ex: Auto Exclusion List........................... 76
            phd: Ex: Words by Frequency............................ 77
            phd: Ex: Permuted Indexes.............................. 78
            phd: Troubleshooting Guide............................. 79
            phd: Index <g>......................................... 80
            
         3  ķ
                  phd: Acknowledgments       
            Ľ

            Pat Adams provided the original inspiration for PhDbase and
            her continued support and encouragement kept the project
            alive.  This is the first version worthy of the vision, Pat.
            It's dedicated to you.

            The last-minute availability of the full PhDbase III
            documentation as an online help file was made possible
            through Scott Finegan's unsolicited and tireless work.
            Thanks, Scott -- we hope you like the result.

            Peter Somers, Fritz Maurhofer, David Gutierrez and Beppino
            Costa translated the PHDBASE.MSG file into French, German,
            Spanish and Italian respectively.  Merci beaucoup, danke
            schoen, muchas gracias and grazie, guys.

            The following people graciously provided their precious time
            and expertise in the preparation of PhDbase III.  We'd like
            to acknowledge their contributions here, with our heartfelt
            thanks:  Peter Somers, Fritz Maurhofer, Jordan Ellington,
            Charles Fleming, Dave Tenenbaum, Andrew Agoos, Steve Arnott,
            Cheryl Lee, Doug Dodge, Rick Cooper, Larry Manire, Michael
            Chean, Kevin Warmath, Scott Finegan, Paul Maskens, Frank
            Picchione, Mike Feltman, Vince Rice, Ed Gay, Jeff Bankston,
            David Gutierrez, Ramon Mancebo, John Salidis, Eldor Gemst,
            Paul Blank, Erhard Gust, Tina Newton, John Hoffman, Larry
            Bear, Roderick McLeish, Steve Drucker, Riley Spoon, Warren
            Master, Tom Deering, Dave Grow, Paul VanHorne, Michael Dyer,
            John Forsberg, Steve Miller, Gary Smith, Chip O'Neal, Steve
            Kouchoukos, Eric Freedus, Ralph Wirthlin, Mark Smith, John
            Harvey, Joe Alper, Horacio Caceres, Sue Cunningham, Steve
            Black, John Thornton, Rick Rolston, Cliff Lipman, Lew
            Horowitz, Terry Lee, Marek Konieczny, Opher Banarie, Tamar
            Granor, Roy Spiegel, Stewart Shelline, Ray Humphrys, Chris
            Cusack, John Romanek, Skip Charles, Julian Casado, David
            Wilson, Larry Bradley, Peter Juergenliemk, Mark Margolis,
            Chuck Milbourne, Calvin Fabre, William Abram, Pete Heine,
            Doug Nicholas, Erich Lemke, Ken Sponaugle, Chris Palmer,
            Dorn Stickle, Russ Hobbs, Joel Campbell, Michael Hall, Frank
            Farese, Clark Snyder, Norm Weil as The Peacemaker, Bill
            Skeels as Jiminy "MU" Cricket, and featuring Steve and Jay
            Taylor as The Boys From Amarillo.  (I apologize for any
            omissions; please bonk me on the head if I left your name
            out. -Jim)
            
         4  ķ
                 phd: Late Breaking News     
            Ľ

            The following sections of this help file/manual are
            completely new for version 3.30:

                phd: Indexing Many Fields
                phd: Font Control
                phd: PhDbase-embedded .EXE's
                phd: CD-Rom Considerations
                phd: Alternate Index Paths
                phd: Ex: Total Hit Count
                phd: Ex: Hit Line #'s in Memo
                   phd: Troubleshooting Guide
                       (replaces phd: Internal Inconsistency)

            The following sections have enough new or changed
            information so they're worth rereading:

                phd: INTO BROWSE
                phd: AND Clause; Mixed Queries
                phd: ORDER BY Clause (the new BY SIMILARITY clause)
                phd: The LIKE Operator
                phd: Hits Cursors  (added SET ORDER TO 0 in example)

            PhDbase III mini-help and error messages now support the
            English, French, German, Spanish and Italian languages.  We
            have added PHDBASE.ITA to the 3.30 distribution package.
            You can add this statement to your CONFIG.FP or CONFIG.FPW
            to set up PhDbase for Italian:

                phdbase language = Italian

            The default display font under Windows has been changed from
            'FOXPRINT',10 to 'FOXFONT',9.  If you wish to use another
            font for PhDbase Browse and Hypertext displays, add this to
            your CONFIG.FPW:

                phdbase font = 'font name', point size

            For example:

                phdbase font = 'Helv', 12

            FoxPro 2.6 users:  If you use the Catalog Manager while
            PhDbase-indexed tables are open, you may get a "PHD.PRG not
            found" error when you exit Catalog Manager.  This is due to
            an error in FoxPro's strategy for restoring the environment.
            The workaround is to place PHD.PRG as described in the topic
            "Running With No Library" in the same subdirectory as your
            open table.

            We are very close to having a Pioneer version of PhDbase III
            for the Mac.  If you are interested in this version, please
            contact Korenthal Associates (preferably in email at
            76004,2605@compuserve.com) for information about current
            availability of the Mac Pioneer version.

            OLD NEWS IS STILL GOOD NEWS:

            Here are a few interesting uses to which PhDbase III has
            been put:  It was used at the Olympics to find news photos
            by caption; the largest law firm in New York City uses it
            every day in a million record conflict of interest system;
            "America's Funniest Home Videos" uses it to find submissions
            by subject; Tower Records incorporates the technology in its
            customer information kiosks; Merisel searches its inventory
            database with PhDbase III; it's an important part of Peter
            Somers' "Rosetta" translation system (FoxPro Advisor cover
            article, March '94); the Alberta Human Rights Commission
            uses it for mandate review; a Swiss news agency searches
            over a quarter-million articles in their message archive,
            all in German; it's used in Washington D.C. to help track
            available commercial space throughout the city; and the
            Supreme Court of the State of New York uses the hypertext
            feature to query their database on Suppression Law.
            
         5  ķ
               phd: How To Get PhDbase III   
            Ľ
            PhDbase III for DOS/Windows costs $299.95.  Shipping and
            handling is $5 in US/Canada or $10 elsewhere.  There is an
            additional $5 charge if you order on a company or
            governmental purchase order.  All payments must be made in
            U.S. funds drawn on a U.S. bank.  We also accept MasterCard,
            Visa and American Express.

            Here's the contact information for Korenthal Associates:

                Korenthal Associates, Inc.
                511 Ave. of the Americas #400
                New York, NY 10011
                USA

                voice: 212-242-1790
                fax:   212-242-2599  (email's better for tech support)
                orders only: 1-800-KA-PROGS (527-7647)

                Email on CompuServe:  [76004,2605]
                Support forum on CompuServe: GO KORENTHAL, Section 3

            If you're on CompuServe, send credit card information by
            email and we'll set you up to download the software
            immediately -- and then of course we'll follow up with a
            disk and printed documentation.

            Questions?  Send email to [76004,2605] or call us at
            212-242-1790.  We also have a fact sheet which we can fax to
            you if you need something pretty to give to your purchasing
            department.
            
         6  ķ
                       phd: Welcome          
            Ľ
            Welcome to the growing family of PhDbase III users!  If you
            have a CompuServe ID, please let us know right away so we
            can add you to our "form email" list.  That way you'll be
            notified of future PhDbase III upgrades as soon as they're
            posted.  Simply send your KA invoice number (or registration
            number if purchased from a dealer) to Korenthal Associates
            at 76004,2605 and we'll take care of the rest.
            
         7  ķ
                phd: Royalty-Free License    
            Ľ
            1. Each copy of PhDbase III is licensed for use by a single
            developer or end-user.  If there are others in your company
            who will be developing PhDbase III software, they must
            purchase separate copies of PhDbase III or your company must
            obtain a PhDbase III site license from Korenthal Associates
            (just as each developer must be licensed to use FoxPro
            itself).

            2. If PhDbase is being used as an ad-hoc query tool in your
            organization, each end-user must be licensed for their own
            copy of the software.  Check with Korenthal Associates for
            liberal site license policies if you anticipate using
            PhDbase in this fashion.

            3. Developers may distribute applications containing PhDbase
            III technology to any number of customers or clients
            completely royalty-free, but only if the application does
            not impact on Korenthal Associates' potential sales of
            PhDbase or related products.

            Such competing products tend to fall in the "general
            database access" category.  They might include a spelling
            checker or thesaurus, a file deduper, a hypertext engine or
            toolkit, a general search program, a PhDbase file server, a
            free-form database system, or any general-purpose program
            which is built around PhDbase.  These are just examples;
            please check with Korenthal Associates if you are unsure
            whether your app falls into this category.

            Note that in almost all instances, custom and vertical
            market apps CAN be distributed with PhDbase III
            royalty-free.

            4. When distributing a PhDbase III application, you may
            distribute only those PhDbase III files necessary to run the
            application.  For DOS applications, this means you may
            distribute only the EXE file, but not the PhDbase III PLB
            file; for Windows applications, you may also include the FLL
            and BMP files.  You may include the appropriate message
            files -- MSG, FRE, GER, SPA, and/or ITA -- for both DOS and
            Windows.

            You may not distribute any of the other files included with
            PhDbase III to other developers or to your customers or
            clients EVEN IF you are providing the source code for your
            application.  (See paragraph 5 below.)

            5. If your clients wish to be able to modify your
            application or recompile it, they must purchase separate
            copies of PhDbase III or obtain a PhDbase III site license
            from Korenthal Associates (just as they would have to
            purchase their own copies of FoxPro itself).

            6. All versions of your application, including free, demo,
            and trial use versions, must display an on-screen credit for
            PhDbase III.  You can either allow PhDbase III itself to
            automatically display its own title screen when it is loaded
            (if TALK is ON), or you may include the credit on your
            application's title screen or on a credit screen that can be
            accessed from the application's main menu.  The credit
            should be worded similarly to this (and it must contain the
            copyright notice):

            This program contains PhDbase III Text Retrieval Technology
                   Copyright 1994 by Korenthal Associates, Inc.

            Note that merely providing the credit in your user guide or
            other documentation is NOT sufficient.  The credit must
            appear on-screen.

            

            See also: phd: Dealer Information

            
            
         8  ķ
                 phd: Dealer Information     
            Ľ
            As stated in the license agreement, your clients or
            customers must own a copy of PhDbase III if they will be
            working with your source code.  You can easily recover the
            purchase price of PhDbase by selling copies to your clients
            as a dealer.  We will be happy to drop ship to your
            clients/customers, but we must receive payment directly from
            you as opposed to your customer.

            Please contact Korenthal Associates at 212-242-1790 or
            [76004,2605] if you wish to become a PhDbase III dealer.
            
         9  ķ
                    phd: Packing List        
            Ľ
            Here are the files which comprise PhDbase III:

            READ.ME         Please read this text file before installing
            PHDBASE.PLB     PhDbase III library for FoxPro 2.5+ DOS
            PHDBASE.FLL     PhDbase III library for FoxPro 2.5+ Windows
            PHDBASE.MSG     PhDbase III message file (English)
            PHDBASE.FRE     PhDbase III message file (French)
            PHDBASE.GER     PhDbase III message file (German)
            PHDBASE.SPA     PhDbase III message file (Spanish)
            PHDBASE.ITA     PhDbase III message file (Italian)
            PHDBASE.BMP     Title screen graphic for FoxPro Windows
            PHDBASE.FXP     Include this file in PhDbase-embedded .EXE's
            OLDAPI.PRG      PhDbase 2.23 API for use with PhDbase III
            PHDHELP.DBF     \ FoxPro DOS-style help file with
            PHDHELP.FPT     / full PhDbase III documentation

            See "phd: Table Of Contents" for information on creating a
            printed manual from the PHDHELP files.

            

            See also: phd: Table Of Contents

            
            
        10  ķ
                    phd: Quick Start         
            Ľ
            Put all your PhDbase III files in a fresh directory,
            C:\PHDBASE for example.  Either copy PHDBASE.MSG (or .FRE,
            etc -- see below) to your FoxPro system directory or add
            this line to your CONFIG.FP and/or CONFIG.FPW file:

                phdbase path = c:\phdbase

            If you're using FoxPro Windows, copy PHDBASE.BMP to the same
            directory where you've copied PHDBASE.MSG.

            You may want to add one of these to CONFIG.FP and/or
            CONFIG.FPW:

                phdbase language = English  (uses default, PHDBASE.MSG)
                phdbase language = French   (uses PHDBASE.FRE file)
                phdbase language = German   (uses PHDBASE.GER file)
                phdbase language = Spanish  (uses PHDBASE.SPA file)
                phdbase language = Italian  (uses PHDBASE.ITA file)

            Now start FoxProX or FoxProW and type this in the command
            window:

                set library to c:\phdbase\phdbase
                           (substitute your PhDbase path)

            If you get a blank box or a box full of unreadable text, it
            means font called 'FoxFont' isn't available on your system.
            Press Enter, exit FoxProW and add this line to CONFIG.FPW
            before trying again:

                phdbase font = 'helv', 10

            Now type this in the command window:

                use c:\foxpro25\foxhelp
                =phd("index")

            (Substitute your own FoxPro system path.  For example, your
            system help file might be c:\foxprow\foxhelp.)

            You've created a PhDbase full text index on FoxPro's 2.25
            million byte help file.  This operation should take between
            two and three minutes.  You only need to create this index
            once, since PhDbase automatically keeps your indexes up to
            date as the data changes.

            If you look at your directory, you'll see that the PhDbase
            index FOXHELP.PHD is less than 200K, one tenth the size of
            the original data!  And if you have a fairly fast computer
            you've already noticed that PhDbase can index files at rates
            of over a million bytes per minute.

            Let's try a few PhDbase searches:

                =phd("<<rushmore>>")
                    finds and displays 31 records for standard help file

                =phd("<<sql>>")
                    finds and displays 27 records for standard help file

                =phd("<<rushmore and sql>>")    <-- a "boolean search"
                    finds and displays  6 records for standard help file

                =phd("<<like exsell>>")         <-- a "fuzzy search"
                    finds and display 15 records for standard help file

            No matter what speed computer you're using, you've noticed
            that all of these searches are virtually instantaneous!

            If you wish, press F1 when any of these searches displays
            for information on using PhDbase's built-in hypertext
            system.

            You can get rid of the help file's PhDbase index by typing:

                    =phd("unindex")

            Okay, at this point you should have a feel for what PhDbase
            III is all about.  Note that the PhDbase library must be
            loaded ("set library to phdbase") before you USE any file
            which has a PhDbase index.  If you forget to load the
            library, you'll get a message saying "PHD.PRG not found"
            when you try to USE your file.  If you wish to keep a file
            but no longer use it with PhDbase, please read the section
            entitled REMOVING A PHDBASE INDEX.

            Happy searching!
            
        11  ķ
                    phd: Introduction        
            Ľ
            You're in for a treat!  PhDbase III is quite simply the
            fastest, most powerful, flexible and easiest to use full
            text search technology that's ever been seen in the database
            world.  We don't make this claim lightly; our design goals
            for PhDbase III specified that we'd create a product which
            would be useful in so many situations that any serious
            FoxPro developer or user just "couldn't live without it."
            In fact, as you explore its capabilities, you'll certainly
            get ideas for many database applications which previously
            couldn't be done or would be much too slow, large or
            difficult to implement without PhDbase.

            Here are a few of PhDbase's extraordinary capabilities:

            (Note:  We occasionally refer to the "competition" in the
            paragraphs below.  We're aware of two other full text search
            products for FoxPro:  Fastext from Database Consultants,
            Inc., and MIX from Xitech, Inc.)

            Programming required:  NONE.  End-users can easily create a
            PhDbase III index or search a database (and display results
            in a Browse window with full hypertext support) with a
            *single FoxPro command*.  Better yet, PhDbase automatically
            maintains its own indexes so unlike our competitors, you
            don't have to call special functions to tell PhDbase when
            your databases have changed.  Of course, all PhDbase
            features are also available to programmers so it's easy to
            build our search technology into your own database
            applications.

            Multi-platform support:  PhDbase works exactly the same in
            FoxPro 2.5 for DOS or Windows.  No relearning or
            reprogramming is required to switch PhDbase platforms.  A
            Macintosh version of PhDbase is currently under development
            and will work the same as the DOS and Windows versions.

            Multi-user support:  You can incorporate PhDbase in a
            multi-user FoxPro application with no additional programming
            or reindexing required.  PhDbase III works with mixed DOS
            and Windows networks, and the Mac version is specially
            designed so PhDbase-indexed tables can be simultaneously
            searched and updated by IBM compatibles and Macs on the same
            network.

            Indexing speed:  PhDbase indexes your text blindingly fast
            -- as much as fifty times faster than the competition!
            Full-text indexing of multi-megabyte files now takes minutes
            instead of hours...  and updating a single record is
            virtually instantaneous, so PhDbase may be used effectively
            in any real-time application.

            Searching speed:  The vast majority of PhDbase text searches
            take less than one second, even those involving complex
            Boolean (and, or, and not, etc.) operators. Searches that
            "choke" the competition are a breeze for PhDbase!

            Size:  PhDbase provides a number of options which affect
            index size.  Depending on which options are chosen, index
            sizes may be as small as 1/20th of the data being indexed.
            Most PhDbase indexes fall in the 1/10th-1/5th data size
            range.  Competitive products (none of which offer any
            indexing options) create indexes between the full data size
            and eight times the data size.

            Index flexibility:  The programmer or end-user has a great
            deal of control over the information which will be placed in
            a PhDbase III index.  Three different types of index
            compression are provided; these are discussed under "Root
            processing" below.  Multiple fields and/or character
            expressions may be indexed at once.  They may be memo or
            character fields, numeric or date fields, character
            expressions, or even special fields which tell PhDbase to
            index based on the contents of external files (like program
            source files or word processor documents).  Field names may
            be specified with wildcards; for instance, "addr*" would
            index fields address1, address2, etc.  Numbers within text
            fields may be considered significant or insignificant, and
            numbers are normalized so a search for "57" would yield
            "57.000."  Common English words may be ignored or retained;
            the same is true for automatically detected "frequent"
            words, the "frequency threshold" being user-settable.
            Neither of our competitors provides for any indexing
            options; one can only index a single memo field, and the
            other can only index a single character
            expression.

            Common and Frequent words:  By default, PhDbase
            automatically ignores common English words, improving both
            index time and size.  In addition, PhDbase recognizes and
            ignores "frequent" words -- those which occur in the
            database more than a user-specifiable number of times.  Of
            course, either of these features may be turned off by the
            user or programmer.

            Excluded words:  PhDbase allows the user to create multiple
            tables of words which are to be excluded from the index.
            This feature may be used in conjunction with common and
            frequent word recognition to fine-tune an index with a
            minimum amount of effort.

            International support:  "Frequent" word processing
            eliminates the need for an exclusion list when indexing
            non-English databases.  In addition, PhDbase correctly
            handles characters with diacritical marks by mapping them to
            their non-diacritical equivalents at both index and search
            time.  PhDbase's error messages and online help system
            provide multilingual support through the "PHDBASE LANGUAGE="
            command in CONFIG.FP or CONFIG.FPW.

            Support files:  While indexing, PhDbase creates only a
            single support file -- the database name with a .PHD
            extension.  Competitive products create as many as six
            support files!

            Integration:  We've expended a great deal of effort to
            tightly integrate PhDbase III with FoxPro, SQL, and Rushmore
            technology. FoxPro integration provides a simple end-user
            interface and simplifies programming by eliminating the need
            for special update calls.  SQL integration makes it possible
            to perform a search-and-display operation in a single
            command, and also adds full-text search capabilities to the
            full range of the powerful SQL SELECT statement. (If you
            don't use SQL, don't worry -- all of PhDbase's features are
            also available using "normal" FoxPro commands.) Rushmore
            integration provides split-second full-text searches even
            across files containing many millions of records.

            Search expressions:  PhDbase III has, by far, the most
            extensive and flexible search syntax of any product of its
            type.  Search terms may be expressed as words containing
            either DOS- or SQL-type wildcards. Terms may be joined
            together using a variety of Boolean operators, such as AND,
            OR, and AND NOT.  Search operators have precedence,
            eliminating the need for grouping in most cases; but where
            necessary, parentheses or commas may be used to group a
            search in any manner desired.  All search operators have
            English equivalents, so searches may use a programming
            syntax such as "red | white &~ blue" or a style more likely
            preferable to end-users, like "red or white and not blue" or
            equivalently, "red or white without blue."  PhDbase even
            provides an "implied and" operator which makes complex
            searches very natural; for example, "red shoes or green
            socks."

            Root processing:  By default, PhDbase strips common English
            suffixes for both indexing and searching.  Other index
            options provide full word indexing (the only type of
            indexing done by our competitors) or "lossy" compression
            (which is a more complex form of suffix stripping).
            PhDbase's root processing makes searching more accurate by
            returning common variations of search terms.  For example,
            search for "program" and you'll also get records which
            contain "programs" and "programming".  If you use the "full"
            index option, you can get the same result by using a
            wildcard, i.e., "program*".

            Augmented searches:  PhDbase III allows searches to be based
            on the results of previous searches.  For example, If you've
            just searched for "red" and gotten 1000 references, you can
            then search for "and shoes" to narrow down your search.  The
            result of the second search would be exactly the same as a
            search for "red and shoes" or more simply, "red shoes."

            Fuzzy searches:  PhDbase III is built on top of PhDbase 2.2,
            which for the past two years has been the definitive
            phonetic and fuzzy search tool for proper names.  PhDbase
            was originally written to address the widely held perception
            that Soundex (a phonetic algorithm included with FoxPro and
            other database languages) is inadequate for real world name
            searches.  Of our two competitors, one offers no
            phonetic/fuzzy search capability and the other offers a
            capability which some experimentation shows to be similar to
            Soundex.

            Proximity searches:  These searches return only those
            records where search terms occur "near" other search terms;
            they allow a search which will succeed on "red shoes" or "my
            shoes are red", but will fail on "the red-headed boy was
            wearing a bright blue pair of shoes." This search is
            expressed in PhDbase by simply finding "red near shoes" (or
            even "red near shoe" for a normal or lossy index).  You can
            also say something like "red within 3 words of shoe" to
            control the accuracy of the result, or you can construct
            more complex proximity searches like "red near white near
            blue" or "red near (white or blue)".  One of our competitors
            offers no proximity searching; the other provides locations
            of search results within records, but a significant amount
            of programming is required to translate this information
            into a true proximity search.

            Field-specific searches:  You can easily restrict a PhDbase
            search to specific fields.  For example, let's say
            =phd("index on name, addr*") has been used to index fields
            NAME, ADDRESS1, ADDRESS2, and ADDRESS3. You could then
            search for "name is Jones" to retrieve John Jones but to
            bypass anyone who lives on Jones Street; the latter group of
            people might be found by searching for "address has Jones."
            Neither of our competitors allow field-specific searches.

            Record locator information:  In addition to field-specific
            and proximity searches, PhDbase provides a function which
            tells you exactly where in each field the search terms may
            be found.  This information can be useful, for instance, to
            highlight the particular word or words which were found in
            the middle of a complex memo field.

            Relevance-ordered searches:  PhDbase makes it easy to obtain
            search results in order of relevance, meaning that records
            which better satisfy the search (they contain more
            occurrences of the search terms) are retrieved before those
            which are less relevant.  Neither of our competitors has
            this feature.

            Built-in hypertext:  PhDbase instantly transforms any file
            with a memo field into a hypertext system.  PhDbase will
            automatically highlight words and phrases which satisfy
            search expressions, will allow the user to move across
            references and records which contain those references, and
            will perform hypertext "links" by searching on selected text
            or text entered by the operator.
            
        12  ķ
                phd: Loading the Library     
            Ľ
            Put the PHDBASE.PLB file (or PHDBASE.FLL if you're using
            FoxPro for Windows) somewhere accessible -- your FoxPro
            directory is a good place.  Then use the following command
            to activate the PhDbase library:

                    set library to phdbase

            You can add a path to the file name, such as:

                    set library to d:\mylibs\phdbase

            If you're using other libraries in conjunction with PhDbase,
            use this form of the command:

                    set library to phdbase additive

            If you want PhDbase loaded whenever you load FoxPro, create
            a CONFIG.FP file (CONFIG.FPW for Windows) with the following
            line (or add the line to your existing configuration file):

                    command = set library to phdbase

            You can also add this line to CONFIG.FP/FPW to specify that
            error messages and help text should appear in a language
            other than English:

                    phdbase language = french    (or german, etc.)

            This would switch the message file from PHDBASE.MSG to
            PHDBASE.FRE (or PHDBASE.GER, etc.).  Note that the message
            file must be locatable in your current directory or in your
            FoxPro path at the time the library is loaded.

            Once you use PhDbase to index a file, PhDbase must be loaded
            before that file is USEd.  If you USE a PhDbase-indexed file
            when the library isn't loaded, you'll get this error
            message:

                    File PHD.PRG does not exist.

            To unload PhDbase, use the following command:

                    set library to
            
        13  ķ
                 phd: Passing Parameters     
            Ľ
            PhDbase accepts all parameters by either value or reference,
            so don't worry if your program includes a SET UDFPARMS TO
            REFERENCE statement.  Note that passing parameters by value
            can result in slightly faster operation for some functions.
            (Regardless of the UDFPARMS setting, you can pass any
            parameter by value by simply enclosing it in parentheses.)
            
        14  ķ
                phd: On-line Help System     
            Ľ
            This file (PHDHELP.DBF) contains the full PhDbase III
            documentation in FoxPro on-line help form.  You can tell
            FoxPro to use PHDHELP.DBF as your help file with the
            following command:

                set help to phdhelp   (add a path if necessary)

            Then use this command to restore FoxPro's normal help file,
            adjusting the path and help file name if necessary.

                set help to c:\foxpro25\foxhelp

            If you wish, you can combine this help file with FoxPro's
            help file by simply adding all the records to the end of
            Fox's file:

                set help to
                use c:\foxpro25\foxhelp
                append from phdhelp
                   set help to c:\foxpro25\foxhelp

            In addition to PHDHELP.DBF, PhDbase III includes a mini-help
            system which helps you get started and reminds you of syntax
            and basic functionality as you learn more about PhDbase.  To
            access the help system, type this in the command window:

                    =phd("help")
                        or
                    =phd("?")

            This will also work (although we may change it to mean
            something else in the future):

                    =phd()

            The main help window will pop up and you'll get instructions
            on navigating through the help system.  When you press
            Escape and later enter the help system again, you'll be at
            the same screen where you left off.  You can press the Home
            key at any time to return to the help system's table of
            contents.

            Note that PhDbase's automatic hypertext system enters the
            mini-help system at the Hypertext screen when you press F1.
            
        15  ķ
                  phd: Indexing a File       
            Ľ
            PhDbase indexes are created like this:

                use myfile
                =phd("index [descriptor] [, descriptor]...")

            PhDbase III will not allow you to create an index unless the
            table is opened with the EXCLUSIVE attribute set.  If you
            are indexing a table on a network, simply add the EXCLUSIVE
            clause to your USE command before creating the PhDbase
            index.

            The descriptor consists of any of these separated by commas:

                field name
                character or memo field name with optional wildcard
                                characters (i.e., "addr*")
                $field name     (see "Indexing External Files" below)
                (character expression) enclosed in parentheses
                alias.fieldname this is treated the same as a character
                                  expression
                common          includes common English words
                numbers         includes numbers (otherwise all numbers
                                  are ignored)
                numbers n       includes numbers truncated to n digits
                keep n          keeps approximately n references before
                                  a word is considered "frequent"
                keep all        keeps all references for each word
                unique          keeps only one reference for each word
                full            indexes full words
                roots           indexes word roots (default)
                lossy           indexes roots with lossy compression
                exclude         use an exclusion list; see below
                blocksize n     change index blocksize;
                                  n ranges from 20 to 64
                large           large index or long words;
                                  same as blocksize 32
                huge            huge index; same as blocksize 64

            If a field name is the same as one of the keywords listed
            above, you can explicitly refer to the field name by
            preceding it with an "@".

            If no descriptor is supplied, or if the descriptor doesn't
            contain any field names or expressions, all memo fields in
            the file will be indexed.

            Examples:

                =phd("index")
                        index all memo fields
                =phd("index *")
                        index all char and memo fields
                =phd("index topic")
                        index field "topic"
                =phd("index left(topic,20)")
                        index the first twenty characters of field
                        "topic"
                =phd("index topic, details")
                        index fields "topic" and "details"
                =phd("index topic, details, common")
                        index "topic" and "details",
                        include common words
                =phd("index topic, details, @common")
                        index fields "topic", "details", and "common"
                =phd("index numbers")
                        index all memo fields, include numbers in index
                =phd("index *_x")
                        index only those fields whose names end in "_x"
                =phd("index keep all")
                        index all memo fields, keep all references
                =phd("index keep all, full")
                        same but don't strip index terms to roots
                =phd("index lossy, keep all")
                        same but use super-root stripping
                =phd("index large")
                        index memo fields, optimize for a large index
                        and allow most words up to 32 characters
                        ("Large" is recommended for foreign indexes.)
                =phd("index huge")
                        index memo fields, optimize for a huge index
                        and allow all words up to 32 characters

            If the system variable TALK is ON, PhDbase will show
            indexing in progress, just as FoxPro does.  Note that
            PhDbase's ODOMETER setting is always 1/10 of FoxPro's. Thus,
            PhDbase will update the "keys generated" count for every 10
            records by default (because Fox's default ODOMETER setting
            is 100). If you wish PhDbase to update the display for every
            record, issue a SET ODOMETER TO 10 (or anything less than
            10) command before using PhDbase's =phd("index") command.

            After indexing is complete, PhDbase will display various
            statistics if TALK is set ON.  In addition, the system
            variable _TALLY will be set to the number of records
            indexed.

            

            See also: phd: Indexing Many Fields, phd: Testing for an
            Index, phd: Indexing External Files, phd: Exclusion Lists,
            phd: Multi-user Considerations

            
            
        16  ķ
                phd: Indexing Many Fields    
            Ľ
            There is no intrinsic limit on the number of fields which
            may be simultaneously indexed with PhDbase.  However, FoxPro
            imposes a 240 character limit on the number of characters
            which may appear in a compound index key.  PhDbase creates a
            key in the compound index (.CDX file) as part of its own
            index generation, and this key must fit within FoxPro's 240
            character limit.

            If you attempt to exceed the limit by indexing too many
            fields, PhDbase will report the following error:

                index expression too long

            Don't despair if you get this error; you have a number of
            workarounds at your disposal.

            First of all, consider whether you really need to index all
            of those fields with PhDbase.  For example, fields which are
            already handled well with FoxPro indexes should continue to
            use those indexes -- and don't forget PhDbase's capability
            to perform mixed PhDbase-FoxPro searches.

            If you're at an early design stage, consider redefining your
            table with fewer fields.  For example, do you really need to
            separate first, middle and last name?  PhDbase's search
            capabilities increase your design freedom in many cases --
            do take advantage of your additional options.

            If you really do need to index more fields than the tag
            length will allow, consider shortening your field names.  If
            you do a DISPLAY STATUS after PhDbase-indexing any file,
            you'll see that the PHD key contains each field name twice
            in most cases.  Shorter field names will generate a smaller
            PHD key and thus will allow more fields to be indexed.

            If all else fails, try the following approach:  In your
            PhDbase index command, surround each character field with
            parentheses.  Do the same for memo fields but append null so
            they're converted to character strings in the index command.
            For example, here's a "normal" PhDbase index command:

                =phd("index on chField1, chField2, memoField, keep all")

            Here's the command you'd use instead:

                =phd("index on (chField1), (chField2), (''+memoField), ;
                      keep all")

            This treatment creates a shorter PHD key because each field
            name is mentioned only once in the key.  However, there's a
            minor downside.  The first index command would allow you to
            search for "widgets" in the memo field like this:

                =phd("<<memoField has widgets>>")

            The "shortened" command requires that you refer to index
            position in field-specific searches.  Thus the search would
            have to be performed like this:

                =phd("<<3 has widgets>>")

            See "phd: Field-specific Searches" for more details.

            

            See also: phd: Field-specific Searches

            
            
        17  ķ
                phd: Testing for an Index    
            Ľ
            The function phd("isIndexed") returns .T. if the current
            file has been indexed by PhDbase and .F. otherwise.  For
            example, this code sequence would index the file if it
            hasn't been indexed already:

                use myfile
                if !phd("isIndexed")
                    =phd("index")
                endif
            
        18  ķ
                phd: Common English Words    
            Ľ
            Common English words will be omitted from the PhDbase III
            index unless you specify "common" in your index expression.
            These are the words which PhDbase considers to be common
            English words:

            a, also, an, and, are, as, at, be, been, before, but, by,
            can, cannot, did, do, does, for, from, had, has, have, he,
            he'*, her, him, his, however, i, i'*, if, in, is, it, it'*,
            its, may, me, not, of, on, one, or, she, she'*, should,
            since, than, that, the, their, them, then, there, they,
            they'*, this, to, too, unless, was, we, we'*, which, while,
            who, who'*, with, you, you'*, your

            An asterisk in this list means any characters; for instance,
            "we'd", "we're" and "we'll" are all considered to be common
            words.  In addition, any word which ends in "n't" is
            considered to be a common word.
            
        19  ķ
                   phd: Frequent Words       
            Ľ
            While indexing a database or updating an index, PhDbase will
            automatically determine when a word has occurred frequently
            and will no longer maintain index references for that word.
            Words treated in this manner are called "frequent words."
            By default, PhDbase will determine that a word is "frequent"
            when it occurs in more than approximately 60 records (i.e.,
            60 "references") in the database.

            This number is controllable via the "keep" index option.
            For example, you can specify "keep 1000" to allow
            approximately 1,000 references before a frequent word is
            detected.  In addition, you can specify "keep all" to turn
            off frequent word detection and thus keep all references for
            each word in the index.
            
        20  ķ
                   phd: Exclusion Lists      
            Ľ
            Automatic common English word suppression and "frequent"
            word recognition are both intended to reduce index size and
            increase speed with minimum effort on the part of the user
            or programmer.  If you wish, you can augment (or replace)
            these features with specific exclusion lists of your own.

            To make an exclusion list, create a table with a single
            character field (up to 32 characters) called WORD.  The
            table may also contain other fields which will be ignored by
            PhDbase.  For example, this command will create an exclusion
            list called EXCLUDE.DBF:

                create table exclude (word c(32))

            Now add the words you wish to exclude to the table, one per
            record. It's okay to enter these words in upper, lower or
            mixed case.  For example, if you are indexing names of
            institutions, you might want to add these words to the
            exclusion list:

                company
                corporation
                corp            <-- note inclusion of abbreviation
                library
                ... etc.

            Then add the "exclude" parameter to your =phd("index")
            command.  If you simply say "exclude", PhDbase will look for
            the file EXCLUDE.DBF. Alternatively, you can add your own
            filename (with or without extension) to name your exclusion
            list.  You can also specify multiple inclusion lists in a
            single =phd("index") command.  Here are some examples:

                =phd("index *, exclude")
                        list is EXCLUDE.DBF
                =phd("index *, exclude mylist")
                        list is MYLIST.DBF
                =phd("index *, exclude c:\data\mylist")
                        okay to specify a path name
                =phd("index *, exclude mylist.xxx")
                        okay to specify an extension, but
                        the table is still in .DBF format
                =phd("index *, exclude general, exclude special")
                        multiple exclusion lists are okay
                =phd("index *, common, keep all, exclude")
                        don't suppress common words or frequent words,
                        index all terms except those in EXCLUDE.DBF

            Note for Fastext 1.1 users:  PhDbase exclusion lists are
            compatible in format to your existing list.  Simply refer to
            your list like this:

                =phd("index ..., exclude EXCLIST")

            It is important to note that a PhDbase exclusion list is
            only scanned at index time.  When the index is created, the
            words in the exclusion list are stored in the index in a
            compressed form.  From that point on, the excluded words are
            treated the same as "frequent" words, regardless of whether
            "keep all" was specified.  (This implies that you must
            reindex your file in order for any changes in your exclusion
            lists to take effect.)

            

            See also: phd: Ex: Auto Exclusion List

            
            
        21  ķ
              phd: Getting Index Expression  
            Ľ
            You can retrieve the current PhDbase index expression at any
            time. Simply USE (or SELECT) your PhDbase-indexed table and
            use this function:

                s = phd("key")

            S will be set to the characters you put after the "index"
            keyword when your file was originally indexed by PhDbase.
            
        22  ķ
                 phd: Removing an Index      
            Ľ
            If you no longer wish to use PhDbase with a particular file,
            you can get rid of the PhDbase index like this:

                use myfile
                =phd("unindex")

            You may only issue the =phd("unindex") command when the
            table is opened for EXCLUSIVE use.

            You can also remove an index when PhDbase itself isn't
            loaded.  First delete the file's PHD tag which was created
            by the =phd("index") command.  Then remove the associated
            .PHD file.  For example:

                use myfile
                        (ignore the "PHD.PRG not found" error message)
                delete tag phd
                erase myfile.phd

            

            See also: phd: Detach/Attach Index, phd: Multi-user
            Considerations

            
            
        23  ķ
                phd: Detach/Attach Index     
            Ľ
            You can temporarily detach a PhDbase index and then reattach
            it to your table at a later time.  This feature can be
            useful during FoxPro REINDEXes or other maintenance
            operations.

            To detach a PhDbase index, simply USE or SELECT your table
            and issue:

                delete tag phd

            Then, to reattach the PhDbase index at a later time, USE or
            SELECT the table and issue:

                =phd("attach")

            You may only issue the =phd("attach") command when the table
            is opened for EXCLUSIVE use.

            

            See also: phd: Removing an Index, phd: Multi-user
            Considerations

            
            
        24  ķ
                   phd: Ad-Hoc Queries       
            Ľ
            PhDbase III search commands can become quite complicated
            since an extended SQL SELECT syntax is supported.  However,
            all of the clauses (including SELECT itself!) may be
            defaulted, except for the PhDbase search expression.  This
            type of search is suitable for ad-hoc queries in the command
            window.  It yields results in a Browse window with PhDbase's
            hypertext system activated if a memo field was indexed.

            To perform this most basic PhDbase search, make sure that a
            PhDbase-indexed file is open in your current work area and
            type:

                =phd("<<search_expression>>")

            For example:

                use myfile
                =phd("<<mouse>>")
                =phd("<<mouse and driver>>")

            

            See also phd: Queries; PhDbase SELECT

            
            
        25  ķ
                   phd: Ad-Hoc Updates       
            Ľ
            PhDbase III is designed to "get out of your way" as much as
            possible. In general, you can change and add to your tables
            as usual and PhDbase indexes will automatically be kept up
            to date.  However, there are certain limitations on
            PhDbase's ability to know how records have changed.  These
            limitations are discussed here.

            PhDbase does not know when an external file has changed.  If
            you are doing this type of indexing please be aware that you
            must reindex your FoxPro table or use the IxDel and IxAdd
            functions to keep your PhDbase index up to date.  See
            "Indexing External Files" for more information.

            If you edit a PhDbase-indexed memo field "by hand" (within a
            Browse or a Modify Memo), PhDbase is not always able to
            eliminate all the old index entries for that record.  This
            limitation is due to a bug in FoxPro.  The result might be
            an occasional "false hit" -- meaning that PhDbase might
            think that a memo field contains a word that you've
            eliminated in your editing.

            This limitation only applies to words which have been
            eliminated. PhDbase will correctly index new words which
            have been added to memo fields.  Also, it only applies to
            memos which have been edited by hand.  The problem won't
            occur in programs which issue the Replace command (or use an
            equivalent technique like Scatter/Gather) for memo fields.
            Note that programmers can prevent this problem from ever
            occurring by using the IxDel and IxAdd commands as follows:

                goto nnn        && position on the record to be edited
                =phd("IxDel")   && delete all PhDbase entries
                    && now do whatever's needed to modify the record;
                    && for example you might issue a Modify Memo command
                =phd("IxAdd")   && add the new PhDbase index entries

            

            See also: phd: Indexing External Files, phd: Manual Index
            Control

            
            
        26  ķ
              phd: Hypertext Implementation  
            Ľ
            PhDbase can automatically convert any table with a memo
            field into a hypertext system.  Hypertext is loosely defined
            as "living text" -- text which can be viewed not only
            linearly, but in sections which strike the user's interest
            as the text is being viewed.

            When you index a table on a memo field and perform an ad-hoc
            query on that table, PhDbase displays a Browse of found
            records along with a window which says "Hypertext active; F1
            for help."  At that point you can do everything you could do
            in a normal Browse; but if you position the cursor on a
            record and press Ctrl-Enter or the right mouse button, you
            will enter hypertext mode.

            In hypertext mode the Browse still stays on the screen, but
            an additional window opens containing the first
            PhDbase-indexed memo field in the table.  The title of the
            window will be the first character field in the table longer
            than five characters; if none exist, the title will say
            "PhDbase III Hypertext."

            At this point you can press Enter or the right mouse button
            and the first word or phrase which satisfied your query will
            be highlighted. Press Enter or the right mouse button again
            and the next word or phrase will be highlighted.
            Highlighting moves from reference to reference across the
            Browse in this manner, always stopping at the beginning and
            end of each record so it's easy to get your bearings.

            You can also press backspace to move backward by reference.
            Tab and shift-Tab move forward and backward by records in
            the Browse, F1 offers help on using PhDbase hypertext, and
            Escape leaves hypertext mode and puts you back in the
            original Browse.

            If you press Ctrl-Enter while in hypertext mode, PhDbase
            will offer to perform a hypertext link.  A window will open
            with the suggested link, which contains any text you've
            highlighted before pressing Ctrl-Enter.  You can edit the
            link of you wish, and then press Enter (or press Escape to
            cancel the link).  Note that the link may be any valid
            PhDbase search expression.  PhDbase will attempt to perform
            the link.  If successful, the memo field and Browse will be
            replaced by the linked Browse.  If unsuccessful, PhDbase
            will beep once for "no records found" and three times for
            "invalid search expression."

            For example, let's say you've searched the FoxPro help file
            like this:

                use c:\foxpro25\foxhelp
                =phd("<<mouse>>")

            Now say you position the Browse on "INKEY()" and press the
            right mouse button.  A window opens with title "Hypertext:
            INKEY()" and you see the article about INKEY.  The first few
            lines of the article say:

                Returns a number corresponding to the first key
                pressed or mouse click in the typeahead buffer.
                Return value - Numeric

            You say "typeahead buffer? whazzat?" and double click the
            left mouse button, selecting the word "typeahead."  Then you
            press Ctrl-Enter, at which point PhDbase offers "typeahead"
            as a hypertext link.  You confirm by pressing Enter, and
            voila! a new Browse immediately opens with all seven
            articles which mention the typeahead buffer. Hypertext is
            still active at this point, so you can browse and link
            around the help file (or any other PhDbase-indexed file) to
            your heart's content.

            

            See also: phd: Font Control

            
            
        27  ķ
                    phd: Font Control        
            Ľ
            In FoxPro for Windows, you can control PhDbase's Browse
            display font by adding the FONT clause to your Browse
            options.  For example:

                =phd(" <<mouse>> into browse font 'Ariel', 16 ")

            This changes the display font for the Browse only; the
            hypertext window is unaffected.

            In addition, you can globally control the display font for
            the Browse and/or hypertext display.  Put these lines
            (substituting any font and size you wish) in your CONFIG.FPW
            file to change the default display fonts:

                phdbase font = 'Ariel', 16
                phdbase hfont = 'Times New Roman', 14

            You can change the fonts from within your program using
            these statements:

                =phd("font 'Ariel', 16")
                =phd("hfont 'Times New Roman', 14")

            The "font" statement (in CONFIG.FPW or your program) changes
            the display font for the Browse *and* for hypertext; the
            "hfont" statement changes the font for hypertext only.
            Therefore, it's important that you issue the "hfont"
            statement last for independent hypertext font control.
            
        28  ķ
                 phd: Search Expressions     
            Ľ
            The simplest search expression is a single word (or "search
            term," as in:

                =phd("<<Rushmore>>")

            You may enter search terms in upper, lower, or mixed case;
            all are equivalent for searching purposes.

            You can combine terms with either English or symbolic
            operators.  For example, these are equivalent:

                =phd("<<rushmore and sql>>")
                =phd("<<rushmore & sql>>")

            This is also equivalent because a space acts as an implied
            "and" operator:

                =phd("<<rushmore sql>>")

            Here is a table of symbolic operators and their English
            equivalents:

                Symbolic        English
                  ;               (OR -- see below)
                  ,               (varies -- see below)
                  |, ||           OR
                  !, &!           NOT, AND NOT, BUT NOT, WITHOUT
                  &, &&           AND, WITH, (space)
                  =               IS, HAS, HAVE, HAVING
                  ~               LIKE
                  @               NEAR, WITHIN nnn [WORD[S] OF]
                  >, '', "", []   THEN, '...', "...", [...]
                  ( )             (grouping)

            The table is organized by precedence, from lowest to
            highest.  This means that if multiple operators occur in an
            expression, the operator which appears later in the table
            will be considered first, unless the precedence is
            overridden by parentheses.  For example:

                =phd("<<one and two or three and four>>")

            Since "and" has a higher precedence than "or", this is
            equivalent to:

                =phd("<< (one and two) or (three and four) >>")

            The semicolon and comma operators may also be used to change
            expression evaluation order.  Semicolon always means "or",
            but it has a lower precedence than a comma.  Comma usually
            means "and", but a sequence of commas may mean "or" if an
            "or" *explicitly* follows the last comma in the sequence.
            For example, each of the following pairs are equivalent:

                =phd("<<one; two; three>>")
                =phd("<<one or two or three>>")

                =phd("<<one, two, three>>")
                =phd("<<one and two and three>>")

                =phd("<<one, two, or three>>")
                =phd("<<one or two or three>>")

                =phd("<<one, two, and not three>>")
                =phd("<<one and two and not three>>")

                =phd("<< one, two; three, four >>")
                =phd("<< (one and two) or (three and four) >>")
            
        29  ķ
                  phd: Search Examples       
            Ľ
            Here are some examples of search expressions, with comments
            added where the example isn't obvious.  You'll find more
            detailed information about some of these expressions later
            in this document.

                =phd("<<red>>")
                =phd("<<red and white>>")
                =phd("<<red and white and blue>>")
                =phd("<<red or white>>")
                =phd("<<red or white or blue>>")
                =phd("<< red and (white or blue) >>")
                =phd("<< ( red or (white and blue) ) and yellow >>")
                =phd("<<red white blue>>")
                        same as "red and white and blue"
                =phd("<<red*>>")
                        any word which starts with "red",
                        such as "redress"
                =phd("<<red?>>")
                        any word which has "red" and one char,
                        such as "redo"
                =phd("<<*red*>>")
                        any word in which "red" appears,
                        such as "sacred"
                =phd("<<red and not white>>")
                =phd("<<red without white>>")
                =phd("<<red but not white>>")
                        all three of these are the same
                =phd("<<red then white>>")
                        "white" must be the next word after "red"
                =phd("<< 'red white' >>")
                =phd('<< "red white" >>')
                =phd("<< [red white] >>")
                        all three of these are the same
                        as "red then white"
                =phd("<< 'red white blue' >>")
                        same as "red then (white then blue)"
                =phd("<<red near white>>")
                        "red" must occur within 8 words of "white"
                =phd("<<red near 3 white>>")
                        "red" must occur within 3 words of "white"
                =phd("<<red within 3 white>>")
                =phd("<<red within 3 words of white>>")
                        both of these are the same
                        as "red near 3 white"
                =phd("<<red near white near blue>>")
                        all three must occur within
                        8 words of each other
                =phd("<<topic has red>>")
                        "red" must occur in the TOPIC field
                =phd("<<topic is red>>")
                        same as above
                =phd("<< topic has (red or white) >>")
                =phd("<<topic or class has red>>")
                        "red" can occur in either field
                =phd("<<like rushmoor>>")
                        the 5 closest-sounding words in the database
                =phd("<<like 1 rushmoor>>")
                        the single closest-sounding word
                =phd("<<like 10 rushmoor>>")
                        the 10 closest-sounding words
                =phd("<< like (rushmoor or seql) >>")
                        same as "like rushmore or like sql"
            
        30  ķ
               phd: Searching Common Words   
            Ľ
            You might get the following error message when you search:

                You looked for frequent or common words.
                Be more specific or change index options.

            This error happens when you tell PhDbase to search on common
            English words, "frequent" words, or excluded words.  It is
            possible to search on these words, but only when they're
            qualified by words which have been indexed by PhDbase.  For
            example, suppose you indexed the FoxPro help file without
            using the "keep all" option.  The word "display" appears in
            over 400 records in this file, so you'd get the error
            message if you said:

                =phd("<<display>>")

            However, this search is perfectly valid and will yield 26
            records:

                =phd("<<display driver>>")

            Note that you'll get a "PhDbase scanning" countdown window
            when you issue this command.  This scan (also called a
            "post-scan") occurs when PhDbase can only partially resolve
            your search from its index (in this case, "driver" is
            resolved from the index) and PhDbase must look at some of
            the actual records in order to complete the search.

            PhDbase post-scans can affect performance in multi-user
            situations.  See "phd: Multi-user Considerations" for more
            information.

            

            See also: phd: Multi-user Considerations

            
            
        31  ķ
              phd: Queries; PhDbase SELECT   
            Ľ
            Here is the general syntax of a PhDbase SQL SELECT
            statement:

                =phd(" SELECT fields FROM source
                           WHERE phdbase_search_expression
                             AND foxpro_search_expression
                           INTO destination
                           ORDER BY order_expression ")

            All parts (including SELECT) are optional and may appear in
            any order.  The WHERE keyword is also optional, and PhDbase
            recognizes the presence of a PhDbase search expression to
            mean that a SELECT statement is being issued.  Thus, the
            simplest SELECT statement consists only of a PhDbase search
            expression, as shown above.

            Although the syntax is shown as =phd(...), the phd function
            actually returns a value of .T. if the query was satisfied
            and .F. otherwise. This means that you can program the
            SELECT statement like this:

                if phd("select ...")
                    ...records were found...
                else
                    ...no records were found...
                endif

            In addition, the SELECT statement sets the system variable
            _TALLY to the actual number of records which satisfied the
            query.

            The following sections describe the various clauses of the
            PhDbase SELECT statement.

            

            See also: phd: SELECT Clause, phd: FROM Clause, phd: WHERE
            Clause, phd: AND Clause, phd: INTO Clauses, phd: ORDER BY
            Clause

            
            
        32  ķ
                   phd: SELECT Clause        
            Ľ
            Equivalent keywords: SELECT, FIELDS

            The simplest clause is SELECT *, which selects all fields.
            This is the default if no SELECT clause is present.  For
            example, these two statements are equivalent:

                =phd("select * where <<whatever>>")
                =phd("<<whatever>>")

            All PhDbase keywords may be abbreviated to four letters or
            more, so this statement is also equivalent:

                =phd("sele * wher <<whatever>>")

            A SELECT clause may specify a field list separated by
            commas, as in:

                =phd("sele name, city where <<smith>>")

            The special field name RECNO() refers to the record number
            of a "hit" record (a record that satisfies your search).
            For example, this statement would display a Browse window of
            record numbers and customer names:

                =phd("sele recno(), name where <<smith>>")

            The special field name RELE (or RELEVANCE) refers to the
            "hit count" of a record, i.e. the number of times a search
            expression component appears in the record.  RELE may only
            be used in conjunction with an ORDER BY RELEVANCE clause, as
            described below.  Here is an example of a search which
            displays a Browse in most- to least-relevant order, with
            relevance hit counts included in the display:

                =phd("sele rele, topic where <<mouse>> by rele")

            When the SELECT statement destination is a Browse (the
            default), you may also use calculated fields and FoxPro
            browse field options.  For example, these SELECT statements
            are valid:

                =phd("sele topic:10 :h='Hello' where <<mouse>>")

                =phd("sele name=trim(first)+' '+last where <<smith>>")
            
        33  ķ
                    phd: FROM Clause         
            Ľ
            Equivalent keywords: FROM, IN

            The FROM clause tells PhDbase which table or alias to
            search.  You may specify a table name with an optional path
            like this:

                =phd("sele * from myFile where ...")

                =phd("sele * from c:\bizstuff\customer where ...")

            You may specify an alias of a currently open work area:

                =phd("sele * from a where ...")

            In addition, you may specify a character expression enclosed
            in angle brackets.  The expression must evaluate to the name
            of the source table or alias.  For example:

                var = "myFile"
                =phd("sele * from <var> where ...")

                =phd("sele * from <'c:\bizstuff\' + var> where ...")

            If no FROM clause is present, PhDbase searches the table in
            the currently selected work area.  If there is no table in
            the current work area, PhDbase will offer a file selection
            dialog before proceeding with the search.
            
        34  ķ
                    phd: WHERE Clause        
            Ľ
            The WHERE clause specifies the PhDbase search expression.
            This is the only clause necessary for PhDbase to determine
            that a SELECT statement is being issued.  Here is an example
            of a basic WHERE clause:

                =phd("where <<mouse>>")

            The keyword WHERE may be omitted as long as the PhDbase
            search expression is identifiable in context.  For example,
            this is an equivalent statement:

                =phd("<<mouse>>")

            See "Search Expressions" and "Search Examples" for
            information about what may be specified between the angle
            brackets.

            If your search expression is in a memory variable, specify
            the variable name in single angle brackets.  For example:

                =phd("sele * from table where <var> ...")

            You can also place an arbitrary character expression between
            the single angle brackets.  The expression will be
            evaluated, and its value will be used as the PhDbase search
            expression.  For example:

                =phd("sele * from table where <'like (' +var+ ')'> ...")

            

            See also: phd: Search Expressions, phd: Search Examples

            
            
        35  ķ
             phd: AND Clause; Mixed Queries  
            Ľ
            You can mix PhDbase and normal FoxPro searches by including
            an AND clause after the WHERE clause.  To do this, the WHERE
            clause search expression must be enclosed in single or
            double angle brackets.  Here are two examples of mixed
            PhDbase and FoxPro searches:

                =phd("... WHERE <searchVar> AND zipcode = 10011 ...")

                =phd("... << bright (red or blue) >> ;
                    AND ( inv_code = '123' or inv_code = '456' ) ...")

            Note that a mixed PhDbase and FoxPro search can be virtually
            instantaneous if the AND clause is Rushmore-optimizable.

            Application note:  Don't use PhDbase indexes for those
            fields which FoxPro already handles well.  Instead, keep
            your Fox indexes and use a PhDbase mixed search to get at
            your data.  For example, suppose you've constructed a
            PhDbase search expression in phd_expr and a FoxPro search
            expression in fox_expr.  This statement will perform the
            mixed search:

                =phd("<phd_expr> and &fox_expr)

            Note that "*" returns all records in a PhDbase search and
            ".T." returns all records in a FoxPro search.  For example,
            if phd_expr was equal to "*" in the statement above, PhDbase
            would (in effect) only be performing a FoxPro search.
            
        36  ķ
                    phd: INTO Clauses        
            Ľ
            Equivalent keywords: INTO, TO

            Valid destinations:
                BROWSE [ browse options (i.e. LAST) ] [ NOHYPERTEXT ]
                [ TABLE | DBF ] name (including path if necessary)
                CURSOR name
                FILE name [TYPE DELIM, SPF, or any valid FoxPro type]
                FIELD logical or numeric field name
                HITS CURSOR name
                HITS ARRAY name
                NULL  (returns .T. if search succeeds, sets _TALLY)

            The INTO clause determines where PhDbase will place the
            results of your query.  Specific query destinations are
            described in the following group of topics.

            

            See also: phd: INTO BROWSE, phd: INTO TABLE, phd: INTO
            CURSOR, phd: INTO FILE, phd: INTO FIELD, phd: INTO HITS
            CURSOR, phd: INTO HITS ARRAY, phd: INTO NULL

            
            
        37  ķ
                    phd: INTO BROWSE         
            Ľ
            INTO BROWSE is assumed if there is no INTO clause; a browse
            window will open with the query results.  If a memo field
            was indexed by PhDbase, the Browse window will be opened
            with an on-screen message informing you that hypertext is
            active unless you add the NOHYPERTEXT option; see the
            "Hypertext Implementation" topic for details.

            You can specify FoxPro Browse options by explicitly saying
            INTO BROWSE and adding the options afterwards.  Two options
            you might want to add are NOEDIT (to prevent users from
            modifying the original table) and LAST (to preserve browse
            window size and position).

            Versions of PhDbase prior to 3.30 automatically presented a
            BROWSE NOWAIT when searches were performed within an
            application.  Now the PhDbase Browse "holds" just like
            FoxPro's Browse -- but you can add a NOWAIT parameter to
            make it behave as it did before.

            PhDbase's "Browse Wait" is incompatible with FoxPro's SET
            SYSMENU OFF.  In a program, if you have Sysmenu OFF and you
            don't use the NOWAIT option, PhDbase will temporarily turn
            Sysmenu ON until the Browse is taken down.

            

            See also: phd: Hypertext Implementation, phd: Font Control

            
            
        38  ķ
                     phd: INTO TABLE         
            Ľ
            "INTO TABLE name" copies hit records into a new table.  You
            may specify the fields to copy in a SELECT (or equivalently,
            FIELDS) clause, but you may not use calculated fields.  You
            may use the special field names RECNO() and RELE, as
            described above.  If you include an ORDER BY RELEVANCE
            clause, you must include a RELE field or specify SELECT *
            (in which case the RELE field will be added before the first
            field of your table).

            You may specify a character or variable expression in single
            angle brackets; the expression evaluates to the name of the
            destination table.  For example:

                =phd("... INTO TABLE <var> ...")

            When the query finishes, the created table will be open and
            selected in a new work area.

            If you have an extraordinarily large number of fields in
            your table, you may see the following error message when you
            use the INTO TABLE or INTO CURSOR clause:

                FoxPro reported:  Compiled line too long

            PhDbase cannot detect this error in advance.  It simply
            means that all of your fields cannot be processed by PhDbase
            at once.  Either add a "select field1, field2, ..." clause
            to your command or direct your query to a hits cursor (see
            below) and access your table through the hits cursor.
            
        39  ķ
                    phd: INTO CURSOR         
            Ľ
            "INTO CURSOR name" copies hit records into a SQL cursor.
            The same rules apply to cursors as described above for INTO
            TABLE.  When the query finishes, the cursor will be selected
            in a new work area.
            
        40  ķ
                     phd: INTO FILE          
            Ľ
            "INTO FILE name" writes query results to a new file.  If no
            extension is given, the created file will be given the .TXT
            extension.  You can specify the file name as an expression
            in single angle brackets, as in INTO TABLE or INTO CURSOR.

            You may specify fields to write in a SELECT (or FIELDS)
            clause, but you may not use calculated fields.  Also, all
            memo fields will be ignored; INTO FILE cannot write any memo
            fields from your table.

            The default file type will be SDF, or System Data Format.
            This is an ASCII file with fixed-length fields for each
            field in the table.  You may also add a TYPE parameter with
            this syntax:

                INTO FILE name TYPE [  FOXPLUS | DIF | MOD | SDF | SYLK
                                     | WK1 | WKS | WR1 | WRK | XLS
                                     | DELIMITED [ WITH   <delimiter>
                                                     | BLANK | TAB ] ]

            Note that these type specifiers are the same as those used
            in the FoxPro COPY TO command; consult your FoxPro
            documentation for details.
            
        41  ķ
                     phd: INTO FIELD         
            Ľ
            You may save the results of a query back in your original
            table. Here's how it's done:  First, create a logical or
            numeric field in your table to hold query results.  Now
            create a FoxPro index on the field.  For example, suppose
            you've created a logical field called FOUND.  You'd say:

                index on found tag found

            or if you created a numeric field called COUNT, you might
            say:

                index on count tag count

            Now the clause "INTO FIELD FOUND" would set each value of
            FOUND to .T. if the record satisfied the query or .F.
            otherwise.

            In the case of a numeric field ("INTO FIELD COUNT"), the
            field is set to 0 if the record didn't satisfy the query.
            If it did, the numeric field is set to the relevance count
            for that record.  Numeric fields always require PhDbase
            post-scans (as do all relevance-related operations), and
            therefore operate more slowly than logical fields.

            It is very important that you create indexes for fields used
            in the INTO FIELD clause.  Otherwise, the PhDbase III query
            will still work, but it will operate very slowly.

            Note that you can create more than one logical or numeric
            field to simultaneously hold the results of multiple
            queries.
            
        42  ķ
                  phd: INTO HITS CURSOR      
            Ľ
            This clause creates a cursor where each record has a single
            numeric field called HIT which is wide enough to hold the
            widest record number in your table.  The field contains the
            record number of a record which satisfied the search.  If
            you add the "ORDER BY RELEVANCE" clause, an additional field
            called RELE appears in the cursor, consisting of the
            relevance count of the hit record.

            Example:

                =phd("<<mouse>> into hits cursor myCursor")

            When the query finishes, the hits cursor will be open and
            selected in a new work area.

            

            See also: phd: Hits Cursors

            
            
        43  ķ
                  phd: INTO HITS ARRAY       
            Ľ
            You can tell PhDbase to create an array of record numbers
            which satisfied the query.  It's done like this:

                =phd("... INTO HITS ARRAY arrayName ...")

            The "hits array" will be dimensioned to the number of hits x
            1.  This dimensioning allows you to access each hit by a
            single subscript; for example, hits(5) would be the record
            number of the fifth hit.  In addition, you can create
            cursors or tables of hits using straightforward FoxPro
            command.  For example, these two sequences are equivalent
            assuming there's at least one hit:

                =phd("<<mouse>> into hits array myHits")
                create cursor hitsCurs (hit N(9,0))
                insert into hitsCurs from array myHits

                =phd("<<mouse>> into hits cursor hitsCurs")

            The hits array will not be created at all if there are no
            hits.  Note that all PhDbase queries return .T. if there is
            at least one hit, so you can use the value of the phd
            function to determine if the array has been created.  You
            can also use _TALLY to determine the size of the hits array;
            and _TALLY = 0 means the array has not been created.
            
        44  ķ
                     phd: INTO NULL          
            Ľ
            This clause performs a search and discards the results.  As
            do all PhDbase searches, the phd function returns .T. if at
            least one record satisfied the search; and _TALLY is set to
            the number of records which satisfied.

            The INTO NULL clause may be used to simply check for the
            existence of a search expression, or it may be used in
            conjunction with GETNEXT and GONEXT as described below.

            

            See also: phd: The Null Search; GETNEXT

            
            
        45  ķ
                  phd: ORDER BY Clause       
            Ľ
            Equivalent keywords: ORDER, BY, ORDER BY

            You may order your search results by any valid FoxPro index
            expression using the ORDER BY (or more simply, just BY)
            clause.  For example, this query displays a Browse in last
            name order, assuming the last name is in a field called
            LAST:

                =phd("sele * from customer where <<new york>> by last")

            To specify first within last name order, you'd use:

                =phd("... by last + first")

            Note that this is a slight departure from pure SQL syntax;
            you must specify a valid FoxPro index expression in the
            ORDER BY clause.

            You may add the DESCENDING keyword to specify reverse order:

                =phd("... by last + first desc")

            You can also sort your results based on RELEVANCE (density
            of hits in a record) or SIMILARITY (closeness of fuzzy
            match).

            Use ORDER BY RELEVANCE to sort results in descending order
            based on number of occurrences of the search expression.
            For example, here is a search of the FoxPro help file which
            displays a Browse of articles containing the word "mouse."
            Articles which are most likely to be of interest are
            displayed first:

                =phd("sele * from c:\foxpro25\foxhelp ;
                                        where <<mouse>> by rele")

            If you use ORDER BY RELEVANCE with INTO TABLE or CURSOR, you
            must select all fields (SELE * or let the select clause
            default), or you must add the special field name RELE to
            your SELECT clause.  If you select all fields, PhDbase will
            automatically add the special RELE field (which contains the
            relevance count) before the first field of your table or
            cursor.

            Use ORDER BY SIMILARITY along with the LIKE search operator
            to sort results in descending order based on closeness of
            match.  For example, this search will display all SMITHs
            before any SMYTHEs:

                =phd("<<like smith>> by similarity")

            You can use BY SIMILARITY with an arbitrarily complex search
            expression.  Here's another example:

                searchExpr = "(name has like smith) and ;
                              (company has like (computer stuff))
                =phd("sele name, company, simi from myTable ;
                      where <searchExpr> by simi into cursor temp")

            Note that BY SIMILARITY follows the same rules as BY
            RELEVANCE, except the special field name is called SIMI
            instead of RELE.  The SIMI field will contain a "closeness
            of match" score from 0-100, where 100 is a perfect match.
            
        46  ķ
              phd: The Null Search; GETNEXT  
            Ľ
            All PhDbase queries return .T. if at least one record was
            found, and .F.  otherwise.  In addition, the system variable
            _TALLY is set to the number of records actually found.  For
            example:

                s = a search expression entered by the user
                if phd("from myfile where <s> into null")
                    ? _TALLY, "records were found"
                else
                    ? "Not found"
                endif

            After performing this type of query (or in fact any type of
            query), you can determine the found record numbers using the
            GETNEXT function.  For example:

                n = phd("getNext")

            This will set n to the record number of the first "hit."
            Successive evaluations of GETNEXT will return successive
            hits until the last hit has been returned, at which point
            the function will return 0.

            It's possible to access PhDbase's internal "hit list" more
            than once for a given search.  Issue this command to cause
            the first hit to be returned on a subsequent GETNEXT call:

                =phd("getStart")

            A related function called GONEXT returns the next hit
            number, but also performs a GOTO to the actual found record.
            Be sure you have your original file selected and then issue:

                n = phd("goNext")

            You can restart a GONEXT sequence similarly to a GETNEXT
            sequence:

                =phd("goStart")

            Note that GETSTART and GOSTART are equivalent; they are
            actually synonyms for the same internal function.

            Here's a sample use of GONEXT to display a memo field in
            each hit record:

                use c:\foxpro25\foxhelp         <-- assume it's indexed
                =phd("<<rushmore>> into null")  <-- perform a query
                do while phd("goNext") != 0     <-- go to next hit
                    modify memo details noedit  <-- display "details"
                enddo                           <-- loop for all hits
            
        47  ķ
                    phd: Hits Cursors        
            Ľ
            Hits cursors can be efficient tools in PhDbase-based program
            design. While harder to manipulate than normal cursors or
            tables, they're created very quickly and give the programmer
            lots of flexibility.

            For example, here's a code sequence which creates a hits
            cursor, then relates that cursor back to the original file
            and displays a browse window of the records from the file
            which satisfied the search.  Note that the original file
            must have no ORDER set or the related browse won't work
            properly:

                s = a search expression entered by the user
                if phd("from myfile where <s> into hits cursor hits")
                    set order to 0 in myfile
                    set relation to hit into myfile
                    go top
                    browse fields myfile.field1, myfile.field2, ...
                    use         && this closes and deletes the cursor
                    select myfile
                else
                    ? "No records found."
                endif

            This example closely mimics PhDbase's operation when the
            INTO BROWSE (or default) clause is issued.  It can be used
            as the basis of a very speedy custom-tailored user
            interface.

            You can browse the result set in any order you wish by
            creating a temporary FoxPro index on the cursor.  For
            example, placing this statement right after the "set
            relation" would browse the result set in field2 order:

                index on upper(myfile.field2) tag field2

            (Thanks to "the boys in Amarillo" for verifying this
            technique.)

            

            See also: phd: INTO HITS CURSOR

            
            
        48  ķ
                   phd: FOUND Function       
            Ľ
            The function phd("FOUND") returns .T. if the current record
            was found in the last PhDbase query, and .F. otherwise.
            Note that this form of the function assumes that the queried
            table is selected; an alternate form, phd("FOUND", record
            number), returns .T. if the specified record number was
            found regardless of which table is currently selected.

            In rare cases, you might want to perform PhDbase queries
            inside "normal" FoxPro SQL SELECT statements.  It's done in
            two steps, like this:

                =phd("from myfile where <<whatever>> into null")
                select * from myfile where phd("found")

            Note that this type of search is much slower than a PhDbase
            SQL SELECT statement because FoxPro positions on each record
            in your table before evaluating the PhDbase FOUND function.

            Here's another use for the FOUND function, suggested by Rick
            Cooper. First, Rick isolated a set of records with some
            non-PhDbase condition; let's call those records "<tagged>".
            Then he processed just those records which satisfied PhDbase
            conditions (call those "whatever") using the following code
            sequence:

                =phd("<<whatever>> into null")
                scan for <tagged> and phd("found")
                   ...process the found record...
                endscan
            
        49  ķ
             phd: Locating Hits with VERIFY  
            Ľ
            After a successful find, you can position on any record and
            use the VERIFY function to determine how many words satisfy
            any part of the search, and even where they occur in the
            record.  For example:

                x = phd("verify")
                  this returns the total number of words which satisfy

                x = phd("verify details")
                  same but restricted to the field called DETAILS

                x = phd("verify details into refs")
                  same as previous example but creates a reference array

            The last form of VERIFY creates a two-dimensional array
            called REFS (or whatever name you use in the second
            argument).  The array looks like this:

                REFS(1,1) = position in field of first reference
                REFS(1,2) = length of first reference
                REFS(2,1) = position of 2nd ref
                REFS(2,2) = length of 2nd ref
                ... for as many references as exist ("x" in our example)

            This array may be used to highlight specific references in
            the returned records.

            

            See also: phd: Ex: Hit Count in Record, phd: Ex: Hit Line
            #'s in Memo

            

            
        50  ķ
                 phd: Advanced Searching     
            Ľ
            The following topics discuss some advanced features of
            PhDbase III search expressions.
            
        51  ķ
                 phd: Wildcard Searches      
            Ľ
            Search terms may contain any number of wildcards in any
            combination. You may use DOS wildcards ("*" for zero or more
            characters and "?" for one single character) or SQL
            wildcards ("%" and "_"; see the SQLWILD function below).
            For example, this statement finds terms which start with the
            letters "compu", and would therefore find "compute",
            "computers", and "compulsion" if those words appeared in
            your file:

                =phd("<< compu* >>")

            Wildcards may appear anywhere in a search term, hence the
            following would find both "flivver" and "flubber":

                =phd("<< fl*er >>")

            Note that search terms which start with a wildcard can
            result in significantly slower searches.  Note also that
            search term endings are truncated when you use "root" (the
            default) or "lossy" indexing. In root indexing, for example,
            a search for "rushmore" is actually looking for "rushmor"
            and thus searching for "ru*e" would fail but "ru*r" would
            succeed.  If this presents a problem in your application,
            use the "full" index parameter to index complete words.

            For fun, here's a search which finds words like "facetious"
            in which all vowels occur in order:

                =phd("<< *a*e*i*o*u* >>")

            

            See also: phd: Wildcards and SQLWILD

            
            
        52  ķ
                 phd: The LIKE Operator      
            Ľ
            You can use the LIKE operator to find words which are
            similar to but not exactly like your search terms.  For
            example:

                =phd("<< like rushmoor >>")

            PhDbase first creates an internal list of words in the
            database which are similar to "rushmoor" (see "The LIKE
            Function" for details). Then a search is made for records
            which contain the ten closest matches on the list.

            You can control the precision of the LIKE operator like
            this:

                =phd("<< like 20 rushmoor >>")

            This will search for records which contain up to twenty
            close matches.

            Often you're only interested in the single closest match to
            a search term.  This search will do the trick:

                =phd("<< like 1 rushmoor >>")

            This search is probably not what the user intended:

                =phd("<< like sistem and menyou >>")

            Because the LIKE operator has a high precedence, this search
            is equivalent to:

                =phd("<< (like sistem) and menyou >>")

            and thus will return no records.  Here are two correct ways
            to formulate this search:

                =phd("<< like sistem and like menyou >>")
                =phd("<< like (sistem and menu) >>")

            Either one of these searches would return records which
            contain the words "system" and "menu".

            Tip:  You can take an arbitrary search expression (call it
            "expr") and transform it to a fuzzy search like this:

                =phd("<< like (" + expr + ") >>")

            You can retrieve fuzzy search results in order of closeness
            of match using the ORDER BY SIMILARITY clause.  See "phd:
            ORDER BY" clause for details.

            See "phd: Controlling Fuzzy Search" for information about
            getting the most out of PhDbase's fuzzy search capabilities.

            

            See also: phd: ORDER BY Clause, phd: The LIKE Function, phd:
            Controlling Fuzzy Search

            
            
        53  ķ
              phd: Field-specific Searches   
            Ľ
            If you indexed on multiple fields in your table, you can
            search for information which appears in a specific field or
            group of fields. This is done using the "is" (or "has")
            operator.  For example, here's a search which looks for the
            word "rushmore", but only if it appears in the TOPIC field.

                =phd("<< topic has rushmore >>")

            You can refer to multiple fields by using the form "field1
            or field2 or... fieldN has ...".  You can even use DOS (but
            not SQL) wildcards in field expressions; for example, "addr*
            has main" might be used to find anyone who lives on Main
            Street, but not "Joe Main" if he appears in a name field.

            If you index a calculated field (or an aliased field -- see
            "Indexing Related Files"), you must use an index position
            instead of a field name to refer to the calculated field.
            For example, suppose you've indexed like this:

                =phd("index on field1, field2, left(field5,10), field3")

            The calculated field is the third item in the index list, so
            you'd do a field-specific search on the calculated field
            like this:

                =phd("<< 3 has ...whatever... >>")

            Note that for large files, field-specifiers can slow down
            PhDbase searches considerably.  This is because field
            identifiers are not held in the index; PhDbase first
            performs the search without considering fields and then
            narrows down its result set by scanning all the records in
            the set.  We are considering adding fields as an index
            option in a future upgrade.

            

            See also: phd: Indexing Related Files

            
            
        54  ķ
                  phd: Phrase Searches       
            Ľ
            You can search for specific phrases in your database.  To
            search for a phrase, enclose it in single or double quotes
            or in square brackets. Let's first look at an example which
            is NOT a phrase search:

                =phd("<< New York Public Library >>")

            This search is equivalent to:

                =phd("<< new and york and public and library >>")

            and therefore would find this memo field:

                "This library is as noisy as a New York subway,
                 and it doesn't even have a public washroom!"

            In contrast, look at this phrase search:

                =phd("<< 'New York Public Library' >>")
            -or =phd("<< [New York Public Library] >>")

            This is equivalent to:

                =phd("<< new then york then public then library >>")

            and would thus produce the results we'd expect.
            
        55  ķ
                 phd: Proximity Searches     
            Ľ
            A phrase search is a form of proximity (or "nearness"
            search)...  but PhDbase gives you much more flexibility in
            proximity searching.  The "near" (or "within") operator
            specifies that you want to find words which are only within
            a certain number of words of each other.  For example:

                =phd("<< sql near rushmore >>")

            This search would find occurrences of the terms SQL and
            Rushmore, but only if they occur within 8 words of each
            other.  The following examples are all equivalent to the one
            above:

                =phd("<< rushmore near sql >>")
                =phd("<< sql near 8 rushmore >>")
                =phd("<< sql within 8 rushmore >>")
                =phd("<< sql within 8 words of rushmore >>")

            To control the precision of the search, simply supply your
            own proximity value, as in:

                =phd("<< sql near 3 rushmore >>")

            You can search for multiple words in proximity like this:

                =phd("<< sql near rushmore near select >>")
            
        56  ķ
                 phd: Augmented Searches     
            Ľ
            PhDbase keeps track of the last search you've performed, and
            allows you to refine or expand your search results by
            starting a search with the "and", "or", or "and not"
            operator.  For example:

                =phd("<< and blue >>")
                        all records in the previous search which
                        also contain the word "blue"

                =phd("<< and blue or gray >>")
                        all records in the previous search which
                        also contain either "blue" or "gray"

                =phd("<< or blue >>")
                        all records in the previous search plus
                        those records which contain the word "blue"

                =phd("<< and not blue >>")
                        all records in the previous search minus
                        those records which contain the word "blue"

            

            See also: phd: The FLUSH Function

            
            
        57  ķ
                 phd: The LIKE Function      
            Ľ
            We've already described the use of the LIKE operator to
            perform phonetic and fuzzy searches.  Using the LIKE
            function, you can also determine the number of unique words
            in the table which are "close" to a particular word, and you
            can get a list of those words in order of closeness.  For
            example:

                ? phd("like corenthal")

            This would display the number of unique indexed words (up to
            64) which are similar to the word "corenthal."  To get the
            words themselves, you'd use an alternate form of the
            function:

                n = phd("like corenthal into myArray")

            This will set n to the number of close words, and the array
            myArray will be created to hold those words.  MyArray(1)
            will contain the closest word, myArray(2) the next closest,
            and so on.  For our example, the array might look like this:

                ? n
                        3
                ? myArray(1)
                        korenthal
                ? myArray(2)
                        cornthal
                ? myArray(3)
                        korenthall

            You could then use myArray to perform separate PhDbase
            searches such as phd("<myArray(j)>") to view the search
            results in order of closeness to the original search term.

            Note that PhDbase's root compression can affect the results
            returned by LIKE.  The "words" returned are actually PhDbase
            index entries which may have the last few letters truncated.
            You can always get back to the original word by using the
            FIND and VERIFY functions; but if necessary, you can use the
            "full" parameter when indexing to completely avoid this
            truncation.

            See "Controlling Fuzzy Search" for information about getting
            the most out of PhDbase's fuzzy search capabilities.

            

            See also: phd: The LIKE Operator; phd: Controlling Fuzzy
            Search

            
            
        58  ķ
              phd: Controlling Fuzzy Search  
            Ľ
            You can control PhDbase's fuzzy search in a variety of ways.
            This control changes the results returned by both the LIKE
            search operator and the phd("LIKE...") function.

            As part of its fuzzy search logic, PhDbase generates a
            "score" from 0-100 when comparing two words.  A score of 100
            means they're a perfect match and a score of 0 means they
            don't match at all.  You can use the SCORE function to
            retrieve PhDbase's score, like this:

                ?phd("score mouse mouse")
                        100
                ?phd("score moose mouse")
                        86
                ?phd("score amuse mouse")
                        50
                ?phd("score bullwinkle moose")
                        0

            For both the LIKE operator and function, PhDbase ignores
            words which fall below a certain threshold.  By default,
            this threshold is set to 55.  You can set the threshold to a
            different value like this:

                =phd("threshold 65")

            This would result in "tighter" matches; in library parlance
            this is called increasing "precision" at the expense of
            "recall."

            This statement will set the threshold back to the default
            value. It's preferable to use this form rather than
            "threshold 55":

                =phd("threshold default")

            PhDbase uses a fuzzy search algorithm with "proximity" and
            "spot checking" components.  "Proximity" refers to the
            number of words in the index surrounding the word you're
            looking for in alphabetic order.  PhDbase always scans this
            number of words for close matches. The default proximity
            scan is 100 words in either direction.  You can change
            PhDbase's proximity scan like this:

                =phd("proximity 500")

            The above statement will cause PhDbase to inspect 1000 words
            during its proximity scan.

            In unusual situations, you can tell PhDbase to scan the
            entire index for hard-to-find words like this:

                =phd("proximity all")

            We tried "proximity all" on the FoxPro help file and
            =phd("like korenthal" found the word "rentalcost."

            This statement will set the proximity scan back to its
            default value:

                =phd("proximity default")

            PhDbase's spot checking heuristics allow words to be found
            which are phonetically similar to the target word, even
            though those words are in very different alphabetic
            positions; for example, "phonetics" and "foneticks."  In
            addition, PhDbase can find many common typographical errors
            such as "typo" vs. "ytpo."  PhDbase's "spot check"
            inspection scans 20 words around each heuristic by default.
            You can change the value like this:

                =phd("spotcheck 50")

            or you can set it back to the default like this:

                =phd("spotcheck default")

            Note that PhDbase's spot checking is completely eliminated
            when "proximity all" is specified.

            You can retrieve all of PhDbase's fuzzy search parameters
            without changing them like this:

                ?phd("threshold")
                ?phd("proximity")
                ?phd("spotcheck")
            
        59  ķ
                 phd: The FLUSH Function     
            Ľ
            The following statement will make sure that the current
            PhDbase index is completely up to date:

                =phd("flush")

            You might want to use the PhDbase FLUSH function as a
            replacement for the FoxPro FLUSH statement in your code,
            since =phd("flush") flushes buffers for both PhDbase and
            FoxPro.  Note that it doesn't do any harm to call
            =phd("flush") when no PhDbase index is active.

            Here's another time =phd("flush") can come in handy:  If the
            search expression passed to a query is exactly the same as
            it was in the last query, PhDbase won't actually perform
            another search; it'll just reuse the results of the prior
            search.  This is done for three reasons: speed, SQL
            compatibility, and to facilitate augmented search
            processing.  If you want to force a new search to be
            performed no matter what was typed before, use =phd("flush")
            just before doing the new search.  Note, though, that
            =phd("flush") won't allow the next search to be an augmented
            search.

            If you're creating a multi-user application, please see
            "phd: Multi-user Considerations" for some other situations
            in which =phd("flush") can be useful.

            

            See also: phd: Multi-user Considerations

            
            
        60  ķ
                phd: Manual Index Control    
            Ľ
            Just the same as a normal FoxPro index, a PhDbase index will
            not automatically be updated when records are DELETEd from
            or RECALLed to a file; rather, the index (FoxPro or PhDbase)
            will remain unchanged and access to deleted records will be
            controlled by the FoxPro SET DELETED flag.  If you wish, you
            can exercise greater control over the PhDbase index by using
            the IXDEL function to delete records and the IXADD function
            to recall them.

            To flag a record as deleted and delete references to that
            record in the PhDbase index, GOTO that record and issue
            these commands:

                =phd("ixDel")
                delete

            To recall the record and its PhDbase index entries, GOTO
            that record and issue these commands:

                recall
                =phd("ixAdd")

            To delete the PhDbase references for a record without
            deleting the record itself (thus making a record "invisible"
            to PhDbase searches), simply GOTO the record and:

                =phd("ixDel")

            Suppose you've deleted a bunch of records in a BROWSE, and
            you now want to remove the PhDbase references to all those
            records.  Here's a sneaky way to do it in a single command:

                count for deleted() and phd("ixDel")
            
        61  ķ
              phd: Indexing External Files   
            Ľ
            PhDbase may be used to find information in an arbitrary
            group of files.  The files are assumed to be ASCII, but many
            word processor files are "close enough" to ASCII so that
            they can be handled by PhDbase.

            To index these "external files," first create a character
            field in a FoxPro database which is large enough to hold the
            file names you'll be indexing.  We call this field the "file
            pointer."  Put one filename to be indexed in each file
            pointer, and then create a PhDbase index with a dollar sign
            preceding the pointer field name.

            For example, this sequence creates a cross-reference index
            of all your FoxPro .PRG files.  It first puts the file names
            in an array called PROGS and then creates PROGS.DBF with
            file pointer FILENAME. Then PROGS.DBF is filled with the
            file names and PhDbase is told to index on the file pointer.

                =adir(progs, "*.prg")
                create table progs (filename c(12))
                insert into progs from array progs
                =phd("index on $filename")

            After doing this, you can (for example) find the names of
            all your programs which refer to the variable name "bleep"
            like this:

                =phd("sele * from progs where <<bleep>>")

            Unlike other field types, PhDbase cannot maintain indexes on
            external files automatically because there's no way for
            PhDbase to know that an external file has changed.  However,
            PhDbase will properly add new external files to its index as
            new file pointers are filled in.  Of course, you can make
            sure an index is up to date by recreating it (it's okay to
            =phd("index") an already-indexed file), but there's a way to
            make sure the index is always up to date if you know when an
            external file is about to change.  You'd do it like this:

                GOTO the pointer for this external file
                =phd("ixDel")   && remove old index entries
                ... change the external file ...
                =phd("ixAdd")   && add new index entries
            
        62  ķ
               phd: Indexing Related Files   
            Ľ
            Thanks to Michael Chean for initiating the discussion on
            CompuServe which led to the creation of this technique.

            Let's say you have a CUSTOMER table with a unique
            8-character CODE and a 30-character NAME.  For each customer
            code, there are any number of records in an ORDER table.
            Each ORDER record has a matching customer CODE and a
            40-character PRODUCT field.  Consider this sequence:

                use customer
                index on code tag code
                select 0
                use order
                set relation to code into customer
                =phd("index on product, customer.name")

            This is perfectly legal -- ignore FoxPro's "aliased field"
            warning.  PhDbase will create and automatically maintain a
            combined product and name index, as long as the relation is
            active whenever you change the order file -- and best of
            all, PhDbase will be perfectly happy with a one-to-many
            relationship between customer and order!

            Using this approach, you could find all orders from customer
            name "Chean" like this:

                =phd("sele * from order where <<chean>>")

            Another example:  To find every instance of customer name
            "Microsoft" ordering product name "PhDbase," you could say:

                =phd("sele * from order where <<microsoft phdbase>>")

            and you could get a very nice combined Browse like this:

                =phd("sele code, customer.name, product from order ;
                                      where <<microsoft and phdbase>>")

            Indexed aliased fields are considered by PhDbase to be
            calculated fields.  Therefore, you can't do this:

                =phd("<< customer.name is microsoft >>")

            but, noting that customer.name is the second item indexed,
            this will work just fine:

                =phd("<< 2 is microsoft >>")

            See "Field-specific Searches" for information about using
            numbers as field specifiers.

            

            See also phd: Field-specific Searches

            
            
        63  ķ
               phd: Wildcards and SQLWILD    
            Ľ
            You can use enhanced DOS wildcards in any field name -- even
            in the INDEX statement -- or in any search term.  An
            asterisk ("*") may be used anywhere (and even multiple
            times) in a term to indicate an arbitrary sequence of zero
            or more characters.  A question mark ("?") may be used
            anywhere to indicate an arbitrary single character.

            In addition, you can use the SQL wildcards percent ("%") to
            mean any sequence of characters and underscore ("_") to mean
            any single character.  These may be used only in search
            terms (not in field names), and only if you've activated SQL
            wildcard processing.  To activate SQL wildcards, issue this
            command:

                =phd("sqlWild on")

            To deactivate SQL wildcards, issue this command:

                =phd("sqlWild off")

            Note that activating SQL wildcards has no effect on DOS
            wildcards; DOS wildcards are always active whether SQL
            wildcards are active or not.

            The SQLWILD function returns the previous state of SQL
            wildcard processing (before the new parameter takes effect).
            In addition, you can call the function with no parameters to
            obtain the current state without making a change.
            
        64  ķ
             phd: Ignoring Search Operators  
            Ľ
            If you are writing a program which accepts an arbitrary
            search expression from the user, sometimes it's useful to
            tell PhDbase to ignore search operators like AND and OR.
            Use this command:

                =phd("operators off")

            To turn search operators back on, use this:

                =phd("operators on")

            The OPERATORS function returns the previous state of search
            operator processing (before the new parameter takes effect).
            In addition, you can call the function with no parameters to
            obtain the current state without making a change.
            
        65  ķ
                phd: Direct Index Access     
            Ľ
            It is possible to make a list of all the words in your
            database by directly accessing the PhDbase index.  First USE
            the PhDbase-indexed file, and then issue the command:

                =phd("ixStart")

            Alternatively, you can start from the middle of the index
            like this:

                =phd("ixStart starting_characters")

            For example, =phd("ixStart cat") will access the index
            starting from "cat" or the first index term which
            alphabetically follows.

            After using IXSTART, you retrieve index terms like this:

                =phd("ixNext")

            This expression returns the next index term in alphabetical
            order. You know that you've reached the end of the index
            when phd("ixNext") returns the null string.

            Note that under normal or lossy root compression, index
            terms are not equivalent to true words in your database.  If
            you wish to create a true word list, you must index your
            file using the "full" option in your =phd("index") command.

            You can determine the number of records which contain a
            particular word in the index.  First retrieve the word with
            IXNEXT and then do this:

                n = phd("ixFreq")

            The IXFREQ function will return the number of references
            (records) with this word, or it will return 0 if the word is
            a frequent or excluded word.  IXFREQ returns -1 if it is not
            immediately preceded by a valid call to IXNEXT or if the
            last call to IXNEXT returned the null string.
            
        66  ķ
             phd: Multi-user Considerations  
            Ľ
            PhDbase III is designed to work transparently on any network
            which supports FoxPro.  Under most circumstances the
            programmer or end-user need not be concerned with any
            network-related activity that PhDbase is performing behind
            the scenes.  However, if you are creating a PhDbase-based
            application to be run on a network you may find the
            following information helpful.

            Windows note:  The current version of PhDbase is multi-user,
            but it is not reentrant.  This means that PHDBASE.FLL may
            not be used in multiple instances of FoxProW on the same
            machine (but the same .FLL may be used on different
            machines).  If you need to run multiple instances of FoxProW
            with PhDbase, simply create a copy of PHDBASE.FLL under a
            different name and load the "different" library under the
            second instance of FoxProW.

            PhDbase uses the current sharing attributes of each table to
            determine how its associated index (the .PHD file) should be
            dealt with.  If the table is opened with the EXCLUSIVE
            attribute, PhDbase will treat its index as if it were opened
            EXCLUSIVE as well -- in other words, PhDbase will act the
            same as if it were operating in single-user mode with
            respect to that particular table.

            The PhDbase INDEX and ATTACH commands require the table to
            be opened EXCLUSIVE (as does the FoxPro INDEX command).

            If a PhDbase-indexed table is opened with the SHARED
            attribute, PhDbase will take control of the .PHD file only
            when absolutely necessary, thus allowing other users to
            perform PhDbase searches and index updates as quickly as
            possible.  The critical times worth noting when the .PHD
            file is unavailable to other users are:

                1. The first part of a search, before the "constructing
            results" phase.  Most PhDbase searches are virtually
            instantaneous, even for very large tables.  Searches that
            take longer often display "PhDbase scanning" in a countdown
            window on the screen.  If network performance suffers from
            too many of these "post-scans," you can anticipate the
            post-scan and take appropriate action (warn the user,
            schedule the search for later, etc.).  Common requests which
            will trigger a post-scan are: the ORDER BY RELEVANCE or BY
            SIMILARITY clause, proximity and field-specific searches, or
            boolean searches which involve "normal" words in conjunction
            with common or frequent words.

                2. PhDbase index update.  This happens "behind the
            scenes" when a PhDbase-indexed file is changed.  The update
            operation is very fast -- not noticeable to the user in most
            situations.  In some odd cases, PhDbase can be fooled into
            thinking that an update or an append is in process when it
            has in fact been completed.  If you suspect this is
            happening in your application (i.e., other users are locked
            out longer than necessary), simply add this command right
            after your FoxPro commands which change or add to the table:

                =phd("flush")

            If an application needs access to the PhDbase index but it's
            in use by another user, the following message will appear on
            the screen:

                      +-----------------------------+
                      | PhDbase waiting for access. |
                      | Press ESCAPE to cancel.     |
                      +-----------------------------+

            The message will disappear and the application will continue
            when access to the PhDbase index is achieved.  If access
            cannot be gotten after one minute (see below) or if ESCAPE
            is pressed, PhDbase will "give up" and the program will
            continue as if there were no associated PhDbase index for
            this table.

            You can control the time PhDbase will wait for access with
            the PhDbase REPROCESS command.  The command looks like this:

                   =phd("REPRocess nnn")

            Where nnn is the number of seconds (up to 1000) to wait for
            access to the .PHD file before "giving up."  You can set the
            time back to its default of 60 seconds like this:

                   =phd("REPRocess DEFAult")

            You can also find out the current wait time by calling the
            REPRocess function with no arguments:

                   waitTime = phd("REPR")

            In summary, you can probably run your PhDbase-based
            application in multi-user mode with no programming changes.
            If you run into any trouble, here are the two things worth
            doing first:

                1. Add =phd("flush") commands immediately after opening
            your PhDbase-indexed table(s), and also after any FoxPro
            commands which change or append information in these tables.

                2. Consider accessing the PhDbase-indexed table(s) in
            EXCLUSIVE mode and controlling multiple access to these
            tables yourself.
            
        67  ķ
              phd: PhDbase-embedded .EXE's   
            Ľ
            Using the FoxPro Distribution Kit, you may create compact or
            standalone .EXE's with embedded PhDbase technology.  Please
            be sure to read the section "phd: Royalty-Free License"
            before distributing any PhDbase-embedded application.  In
            particular, note that 1. you must load the library with TALK
            set ON, or you must give on-screen credit to your use of the
            PhDbase library, and 2. if you provide source to your
            clients or customers, they must own their own copy of
            PhDbase in order to legally recompile your application.

            If you create a DOS .EXE, you must include PHDBASE.PLB in
            your executable; you may not distribute the library
            directly.  However, you must *not* include PHDBASE.MSG (or
            its non-English variants) in your project or the message
            file won't be found on library load.

            For Windows .EXE's, you may distribute PHDBASE.FLL,
            PHDBASE.MSG (or variants) and PHDBASE.BMP.  However, this
            does not give your users permission to make use of PhDbase
            outside of your application.

            *** IMPORTANT:  If you create a standalone .EXE (in DOS or
            Windows), be sure to include the file PHDBASE.FXP in your
            project.  Don't call this program, just make it part of your
            .EXE; it's only there to force FoxPro to include all
            necessary features in the .EXE for successful use of the
            PhDbase library.

            

            See also: phd: Royalty-Free License

            
            
        68  ķ
               phd: CD-Rom Considerations    
            Ľ
            It's simple to use PhDbase in CD-Rom based applications.  If
            you've created a PhDbase index for a table, all you have to
            do is copy the .PHD file to CD-Rom along with your table
            (and its associates FoxPro index files) and open the table
            like this:

                use myTable noupdate

            Then you may access your table from CD-Rom and perform
            PhDbase searches on it just as if it were on a read/write
            device.

            You may instead choose to leave your data on CD-Rom but to
            copy its indexes (with or without the PhDbase index) onto
            hard disk before searching the file.  See "phd: Alternate
            Index Paths" for further information.

            

            See also: phd: Alternate Index Paths

            
            
        69  ķ
               phd: Alternate Index Paths    
            Ľ
            PhDbase III provides four functions to be used in unusual
            circumstances only.  These functions globally change the
            path or filename which PhDbase uses to locate its indexes
            and the FoxPro compound index which contains the PHD tag.
            These functions are:

                =phd("phdLoc xxx")
                =phd("cdxLoc xxx")

                =phd("phdFile xxx")
                =phd("cdxFile xxx")

            The first two functions assert that all PhDbase index files
            (phdLoc) or compound indexes with PHD tags (cdxLoc) will be
            found in xxx, the specified directory.  The directory must
            be fully qualified and must end with either a backslash or a
            colon.

            The next two functions assert that filename xxx is the only
            PhDbase index file (phdFile) or compound index with PHD tag
            (cdxFile).  The filenames will be given default extensions
            of .PHD or .CDX if no extension is supplied in the phdFile
            or cdxFile command.  If a phdFile or cdxFile command is in
            effect, it supercedes the effect of a corresponding phdLoc
            or cdxLoc command.

            To cancel the effect of any of these commands, issue the
            command again with no argument.  For example:

                =phd("phdLoc")

            Here's an example of how you might use these commands.
            Suppose there's a table which is already on CD-Rom and it
            already contains a structural index (.CDX file).  You can't
            PhDbase-index this file normally because if you do, PhDbase
            will attempt to create a .PHD file on the CD-Rom, and will
            also attempt to add a PHD tag to the .CDX residing on
            CD-Rom.  Here's a sequence which will solve the problem:

                use g:romTable
                =phd("phdLoc c:\myStuff\")
                =phd("cdxLoc c:\myStuff\")
                =phd("index ...")

            Now let's say you quit and reenter FoxPro.  You'd use the
            table like this:

                =phd("phdLoc c:\myStuff\")
                =phd("cdxLoc c:\myStuff\")
                use g:romtable index c:\myStuff\romTable

            Note that we issued the phdLoc and cdxLoc commands before
            using the file.  We also opened the file with the
            c:\myStuff\romTable index specified so PhDbase would know
            where to find its PHD tag.

            Suppose that in the example above you wished to create a
            special compound index for the PHD tag called ROMTABLE.PHX.
            You could do it by issuing this command instead of the
            cdxLoc command:

                =phd("cdxFile c:\myStuff\romTable.phx")
            
        70  ķ
              phd: Running With No Library   
            Ľ
            If you try to access a PhDbase-indexed file without loading
            the PhDbase library, FoxPro will report the following error
            message:

                File 'PHD.PRG' does not exist.

            It is possible to access PhDbase-indexed files without
            loading the library.  You might want to do this in
            multi-user situations where some machines don't have enough
            memory to run PhDbase.  Or you might want to distribute
            PhDbase-ready files to your clients but only have them run
            the library if they've bought an optional component of your
            system.

            To run without the library, create the following file:

                * PHD.PRG
                para p01, p02, p03, p04, p05, p06, p07, p08, p09, p10, ;
                     p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, ;
                     p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, ;
                     p31, p32, p33, p34, p35, p36, p37, p38, p39, p40
                return .t.

            This "dummy function" will allow PhDbase-indexed files to be
            opened and accessed normally with no error message from Fox.
            Note that you can provide the dummy PHD function in your
            code -- it doesn't have to come from a separate .PRG file.
            The important caveat here is that without the library
            loaded, the PhDbase index will get "out of sync" as
            PhDbase-indexed fields in your file change.  It is assumed
            that programmers who use this technique know what they're
            doing and either guard against PhDbase fields changing or
            reindex the file (with the library loaded) in a subsequent
            maintenance run.
            
        71  ķ
              phd: The Old API; OLDAPI.PRG   
            Ľ
            The PhDbase 2.23 Applications Programming Interface (the
            "Old API") is included within PhDbase III.  In order to make
            the function calls conform exactly to PhDbase 2.23 calls and
            still retain the "single function" philosopy of PhDbase III,
            we've provided a file called OLDAPI.PRG which translates the
            old calls into PhDbase III equivalents.

            To use OLDAPI.PRG, either SET PROC TO OLDAPI or include the
            functions directly in your source program.

            We present a minimal description of the Old API here.  All
            functions are presented in terms of their OLDAPI.PRG
            interfaces.



            PHDINIT
            -------
            =phdInit("xxxx") sets various initialization options.  Each
            x has the value "y" for yes or "n" for no.  In order, the
            options are:
                . y to return only unique words (default = n)
                . y to prune results below internal threshold
                  (default = y)
                . y to include common English words in phdWord
                  (default = n)
                . y to strip possessives in phdWord (default = y)

            PHDBASE
            -------
            PhDbase(<expC>) returns a character string consisting of
            PhDbase's phonetic transformation of the original string.
            This value is typically used to construct an old-style
            PhDbase phonetic index, as in:

                index on phdbase(last) tag phonetic

            PHDFIND
            -------
            =phdFind(<expC>) clears any pending results list and stores
            a target string for PhDbase to use in its fuzzy search
            comparisons.

            PHDTEST
            -------
            =phdTest(<expC>) compares the current phdFind string with
            the supplied string and accumulates search results in an
            internal list.

            PHDFUZZY
            --------
            =phdFuzzy(<expC>) works like phdTest, except the phdFind
            string is compared against the whole argument and the best
            match within the argument is used to decide how good a match
            the argument is.

            PHDNEXT
            -------
            After a phdFind and a sequence of phdTests or phdFuzzies,
            phdNext() returns the best matched argument that was passed
            in a phdTest or phdFuzzy.  Subsequent calls to phdNext()
            return the next best match, etc., until a null string is
            returned.

            The arguments are passed back exactly as they were supplied
            to phdTest or phdFuzzy.  Both phdTest and phdFuzzy ignore
            all characters before the first slash, so this "header
            information" may contain data which will be returned by
            phdNext() and used to relate back to the original file.

            PHDTOP
            ------
            =phdTop() resets the internal results list so that the next
            call to phdNext() will return the first (best) match.

            PHDTSCOR
            --------
            phdTscor(<expC>) compares the argument to the phdFind string
            (as in phdTest) and returns a character string score from
            "00" (best match) to "99" (worst match).

            PHDFSCOR
            --------
            phdFscor(<expC>) fuzzily compares the argument to the
            phdFind string (as in phdFuzzy) and returns a character
            string score from "00" (best match) to "99" (worst match).

            PHDVERSION
            ----------
            phdVersion() returns the PhDbase version and copyright
            information as a character string.

            PHDTHRESH
            ---------
            phdThresh() returns the pruning threshold computed during
            the last call to phdFind.  PhDbase considers phdTscors and
            phdFscors at or below this threshold to be "good matches."

            PHDNAME
            -------
            Any application which used old-style name normalization is
            much better suited to PhDbase III's full text indexes.
            Therefore, we have not included the phdName function in the
            PhDbase III old API.

            PHDWORD
            -------
            This word splitting function may be of use in PhDbase III
            applications.  PhdWord(<expC>,<expN>) returns the N'th word
            in the supplied character string, or the null string if
            there are less than N words in the character argument.  If N
            is 0, phdWord returns the next word in sequence; it's the
            user's responsibility to make sure the character argument
            remains exactly the same through a series of
            phdWord(<expC>,0) calls.

            PHDWORDPOS
            ----------

            After a successful call to phdWord, phdWordPos() returns the
            position of the word returned.  The first position in the
            string is 1, and phdWordPos will return 0 if phdWord
            returned the null string.

            EXAMPLES
            --------

            Here is an example of an old API "quick search":

                set order to phonetic   && the phonetic key name
                target = ...            && what we're looking for
                phdKey = trim(phdbase(target))
                seek phdKey             && look for matches in index
                if !found()             && if there are none
                    ? "no matches"
                else                    && if at least one match
                    =phdFind(trim(target))  && inform PhDbase of target
                    && send all matches through the compare function
                    scan while phdbase(lastName) = phdKey
                        =phdTest(trim(lastName))  && compare this match
                    endscan                       && to previous matches
                    match = phdNext()       && get most likely match
                    do while !empty(match)  && for each match
                        ? " " + match       && display match on screen
                        match = phdNext()   && next most likely match
                    enddo
                endif

            Here is a function which compares two character strings and
            returns a normalized score from 0 (worst match) to 100 (best
            match), with 50 being the minimum "acceptable" score. (Note
            that the scoring here refers only to the old API -- the
            PhDbase III phd("score") function uses an entirely different
            approach to fuzzy scoring.)

            func score
                para source, target
                priv thresh, raw, cooked
                =phdFind(target)                && set the target
                thresh = val(phdThresh())       && get the threshold
                raw = val(phdTscor(source))     && get & cook raw score
                cooked = iif( raw < thresh ,                     ;
                                100 - int(raw * 50 / thresh) ,   ;
                                50 - int((raw - thresh) * 50 /   ;
                                              (100 - thresh))  )
                return cooked
            *end score

            Here's a function which counts the words in its argument.
            By default, common English words are ignored in the count.
            Issue the statement =phdInit("nyy") to include common
            English words.

            func nWords
                para s
                priv j
                j = 1
                do while !empty(phdWord(s, j))
                    j = j + 1
                enddo
                return j - 1
            *end nWords
            
        72  ķ
                   phd: Error Trapping       
            Ľ
            PhDbase deals with most errors in the same manner as FoxPro:
            An error window appears on-screen and the command or program
            is aborted when you press a key.  You can analyze and deal
            with PhDbase errors using the FoxPro ON ERROR statement,
            along with FoxPro ERROR() and MESSAGE() functions and the
            PhDbase ERROR function:

                phd("error")

            In your error trapping routine, you must first detect that a
            PhDbase error has occurred.  All PhDbase errors are reported
            as FoxPro "User Errors," and thus ERROR() will return 1098.
            In addition, phd("error") will return the PhDbase error code
            (or 0 for no error), and MESSAGE() will return the PhDbase
            error message.  Note that =phd("error") resets the internal
            error number to 0 so that a subsequent non-PhDbase User
            Error may be correctly analyzed.

            These are the possible PhDbase User Errors:

            =phd("error")  MESSAGE()
                0       blank -- not a PhDbase error
                1       Invalid FIND expression
                2       (reserved)
                3       FIND buffer overflow
                4       FIND stack overflow
                5       Unmatched quotes in FIND
                6       FIND: Invalid or unindexed field name
                7       FIND: No words in character string
                8       Invalid LIKE parameter; must be 1-100
                9       FIND: Can't nest field restriction ops
               10       Parameter type must be CHAR
               11       Parameter type must be INTEGER
               12       Parameter must be ON (YES) or OFF (NO)
               13       Table has no PhDbase index
               14       No table in use
               15       Syntax error
               16       Can't index an empty file
               17       Keep 1-32000 (or keep all) only
               18       No more than 5 excludes
               19       Index expression too long
               20       Bad index field type
               21       No memo fields to index
               22       No char or memo fields match
               23       Field not in table
               24       Exclude file does not exist
               25       Exclude file must have WORD field
               26       No active search
               27       Field not indexed
               28       Invalid FIND clause
               29       You looked for frequent or common words.
                        Be more specific or change index options.
               30       (Find failed while executing a FoxPro command.
                        The FoxPro error message is shown.)
               31       Find clause too long
               32       ORDER BY error; RELEVANCE or <expr> but not both
               33       Calculated field not allowed with INTO clause
               34       BY RELE into TABLE or CURSOR requires RELE Field
               35       Nothing to search for (missing WHERE clause)
               36       FIND macro must be <character expression>
               37       Incompatible PhDbase index version
               38       Intermediate search results overflowed buffers
               39       Unbalanced literal WHERE clause (">>" not found)
               40       Block size must be between 20 and 64
               41       Old API error: arg must be char variable name
               42       FoxPro search expression must be of type LOGICAL
               43       Access to .PHD file denied
               44       Access to .CDX file denied
               45       Can't open .PHD file
               46       Can't open .CDX file
               47       Exclusive open of file is required

            

            See also: phd: Fatal Errors

            
            
        73  ķ
                    phd: Fatal Errors        
            Ľ
            If PhDbase detects an internal inconsistency or other
            unrecoverable error, it will present a "Fatal error" or
            "Fatal I/O error" window with numeric error codes, sometimes
            accompanied by a line of explanatory text at the bottom of
            the screen.  When you press a key or a mouse button, PhDbase
            will immediately shut down FoxPro.  It is important that
            FoxPro be shut down in this instance in order to minimize
            the risk of potential data loss.

            If you get such a fatal error, please note the error code(s)
            and on-screen information and report the error to Korenthal
            Associates. We will make every attempt possible to analyze
            the problem and fix it if it is due to PhDbase III program
            failure.

            

            See also: phd: Error Trapping

            
            
        74  ķ
                phd: Ex: Total Hit Count     
            Ľ
            EXAMPLE: GETTING THE TOTAL NUMBER OF HITS

            (Thanks to Bill Skeels for inspiring this example.)

            After a PhDbase search, the system variable _TALLY will
            contain the total number of records which satisfy the
            search.  But suppose to want to determine the total number
            of "hits" across records?  For example, if you're searching
            for a single word, the total hit count would be the number
            of times the word appears in PhDbase-indexed fields in your
            table.

            The VERIFY function gives you hit counts within a record.
            The FOUND function tells you if a record was found in the
            previous search.  Here's a sneaky way to get a total hit
            count:

                =phd("<<...do your search...>> INTO NULL")
                calc sum(phd("verify")) for phd("found") to hitCount

            Note that Rushmore won't kick in here so this approach,
            while easy to code, isn't great for large files.  Here's a
            much faster method of performing the same calculation:

                =phd("<<...do your search...>> INTO NULL")
                hitCount = 0
                do while phd("goNext") != 0
                    hitCount = hitCount + phd("verify")
                enddo

            You don't have to do these searches INTO NULL, by the way.
            Any search destination will do as long as you reselect your
            original table before issuing the GONEXT command.
            
        75  ķ
              phd: Ex: Hit Line #'s in Memo  
            Ľ
            EXAMPLE: DETERMINING THE LINE NUMBERS FOR HITS IN A MEMO

            (Thanks to Bill Skeels for inspiring this example.)

            Here's the full form of the PhDbase VERIFY function:

                =phd(" VERIFY [fieldName [ [IN]TO [ARRAY] arrayName ] ]
            ")

            For example, say you're positioned on one of the "hit"
            records (the GONEXT function is handy for this -- or you can
            use a hits cursor and do the GOTO's yourself).  Assuming
            your indexed field is called "document," you might issue
            this command:

                =phd("verify document into vArray")

            vArray will be dimensioned to n,2 where n is the total
            number of hit occurrences in that record.  vArray(j,1) will
            be the starting location of the hit and vArray(j,2) will be
            the length of the hit.  For example, say you had a document
            consisting of:

                "Send bill to Bill Skeels."
                 1234567890123456789012345  <-- positions in memo field

            Say you did this:

                =phd("<<bill skeels>> into cursor temp")

            Now, positioned on the document above, you did this:

                =phd("verify document into vArray")

            After the verify command, vArray would look like this:

                vArray(1,1) = 6      position of "bill"
                vArray(1,2) = 4      length of "bill"
                vArray(2,1) = 14     position of "Bill"
                vArray(2,2) = 4      length of "Bill"
                vArray(3,1) = 19     position of "Skeels"
                vArray(3,2) = 6      length of "Skeels"

            Note that <<bill skeels>> is the same as <<bill AND
            skeels>>.  If you searched on <<'bill skeels'>> it would be
            a phrase search -- the same as <<bill THEN skeels>> -- and
            then the VERIFY command wouldn't return the first element of
            the vArray example above.

            Okay, so now you know how to get the position of hits within
            a field.  If the field is a multi-line memo field, you can
            use FoxPro functions (MLINE, etc.) to figure out the line
            numbers in which the hits occur, regardless of the current
            MEMOWIDTH setting.  See FoxPro's on-line help for SET
            MEMOWIDTH (and the accompanying SEE ALSO's) for details.

            Inside joke alert:  The value of vArray(2,2) above is 4 and
            not 6'10" as you might otherwise expect.  <g&r, d not nec.>
            
        76  ķ
               phd: Ex: Auto Exclusion List  
            Ľ
            EXAMPLE: CREATING AN AUTOMATIC EXCLUSION LIST

            Let's say you've indexed a table like this:

                use myTable
                =phd("index on field1, field2, ..., full")

            Now run this code:

                create table exclude (word c(32))
                select myTable
                =phd("ixStart")             && beginning of index
                s = phd("ixNext")           && get first index entry
                do while !empty(s)          && scan entire index
                    if phd("ixFreq") = 0    && if entry is frequent word
                        insert into exclude value (s)
                    endif                   && add to exclude list
                    s = phd("ixNext")       && get next index entry
                enddo

            Now you have a table called "exclude" in the correct format
            for a PhDbase exclusion list.  The table contains all the
            words which PhDbase considers to be "frequent" by default.
            If you had used the parameter "keep 500" in the original
            index command, then the words in the exclusion list would
            only be those which occurred more than approximately 500
            times in the file (note that the number 500 is a gross
            estimate, as explained in the section on indexing above).

            Once you have your "base" exclusion list, you can edit it
            any way you wish (add or delete words) and then apply it to
            your original file like this:

                use myTable
                =phd("index on field1, field2, ..., exclude, keep all")

            Note that even though we've added the "keep all" parameter,
            the words in the exclusion list will still be excluded from
            the index.
            
        77  ķ
              phd: Ex: Words by Frequency    
            Ľ
            EXAMPLE: CREATING A WORD LIST BY FREQUENCY OF OCCURRENCE

            Here's a code segment which creates a cursor ordered by
            descending order of word frequency.  Note that the frequency
            count refers to the number of records in which the word
            appears.

                create cursor myFreq (word c(32), freq n(6))
                select myTable
                =phd("ixStart")             && beginning of index
                s = phd("ixNext")           && get first index entry
                do while !empty(s)          && scan entire index
                    n = phd("ixFreq")       && get frequency of entry
                    if n > 0                && if not frequent/excluded
                        insert into myFreq values (s, n)
                    endif                   && add to frequency table
                    s = phd("ixNext")       && get next index entry
                enddo
                select myFreq               && select frequency table
                index on freq descending    && create temporary index
            
        78  ķ
                phd: Ex: Permuted Indexes    
            Ľ
            EXAMPLE: PERMUTED INDEXES, KWIC AND KWOC INDEXES

            PhDbase III can be used to create printed indexes in a
            variety of forms.  Let's say you have a table called BOOKS
            which contains book titles.  Now you want to create a
            printed index of titles.  Each title should appear in the
            index once in its original form, and again for each
            important word in the title.  For example, say a particular
            title is "The Rise and Fall of the Roman Empire."  A
            permuted index might have these entries:

                The Rise and Fall of the Roman Empire
                Rise and Fall of the Roman Empire, The
                Fall of the Roman Empire, The Rise and
                Roman Empire, The Rise and Fall of The
                Empire, The Rise and Fall of the Roman

            A Keyword In Context (KWIC) index might have these entries:

                The Rise and Fall of the Roman Empire
                                            (sorted under "The")
                The RISE and Fall of the Roman Empire
                                            (sorted under "Rise")
                The Rise and FALL of the Roman Empire
                                            (sorted under "Fall")
                The Rise and Fall of the ROMAN Empire
                                            (sorted under "Roman")
                The Rise and Fall of the Roman EMPIRE
                                            (sorted under "Empire")

            A Keyword Out of Context (KWOC) index might have these
            entries:

                The Rise and Fall of the Roman Empire
                RISE, The ... and Fall of the Roman Empire
                FALL, The Rise and ... of the Roman Empire
                ROMAN, The Rise and Fall of the ... Empire
                EMPIRE, The Rise and Fall of the Roman ...

            We're going to show an example of the creation of a KWOC
            index here. You can easily adapt this code to create the
            other index types.

            Index your table like this:

                use books
                =phd("index on title, full")

            Now create a file called KWOC.PRG with this code (or
            incorporate the code in your program):

            *
            * IsIxWord(word) returns .T. if word is in the PhDbase III
            * index and is not a frequent or excluded word (in other
            * words, if the word is a normal, searchable word).  The
            * function assumes that the PhDbase index has been created
            * with the "full" parameter.
            *
            func isIxWord
                para word
                =phd("ixStart &word")
                return phd("ixNext") == lower(word) ;
                       and phd("ixFreq") > 0
            *end func isIxWord

            *
            * MakeKwoc(phrase, aName) creates KWOC index entries for
            * phrase and puts them in a new array called aName.  The
            * original phrase is always the first element of the array.
            * The function returns the number of elements in the array,
            * and assumes the indexed table is selected upon entry.
            * MakeKwoc(phrase) defaults to public array KWOC.
            *
            #define MAXWORDS 20
            func makeKwoc
                para phrase, aName
                priv w, j
                if para() < 2           && default array to public KWOC
                    public kwoc
                    aName = "kwoc"
                endif
                dime &aName(MAXWORDS)       && dimension array
                phrase = alltrim(phrase)    && remove surrounding blanks
                &aName(1) = phrase          && phrase is first entry
                w = phd("phdWord phrase 1") && get first uncommon word
                for j=2 to MAXWORDS         && for up to MAXWORDS words
                    * skip first word or frequent/excluded word
                    do while phd("phdWordPos") = 1 or ;
                           ( phd("phdWordPos") > 1 and not isIxWord(w) )
                        w = phd("phdWord phrase")  && w is now next word
                    enddo
                    if phd("phdWordPos") = 0
                        exit         && break after last searchable word
                    endif            && else create j'th KWOC entry
                    &aName(j) = upper(w) + ", " + ;
                        stuff(phrase, phd("phdWordPos")-1, len(w)+1, "")
                    w = phd("phdWord phrase")   && skip to next word
                next
                dime &aName(j-1)            && adjust array dimension
                return j-1                  && # of KWOC index entries
            *end func kwoc

            To use the code, SET PROC TO KWOC unless the functions are
            already in your program.  Now for each record in your table,
            first execute this function:

                n = makeKwoc(TITLE)

            N will be the number of KWOC index entries for this book.
            To display the KWOC entries:

                for j=1 to n
                    ? kwoc(j)
                endfor

            Of course, all you'd have to do to create your printed index
            is collect these entries (along with other information
            needed for your index) in a new table and sort or index the
            new table.

            (Note that the makeKwoc function uses the PHDWORD function,
            which is technically part of the "old API".  We've used the
            "new" form of the function so you don't have to SET PROG TO
            OLDAPI; if you read the explanation of PHDWORD below it
            should be clear how this function is used in makeKwoc.)
            
        79  ķ
               phd: Troubleshooting Guide    
            Ľ
            Q. I get a "PhDbase message file not found" error when the
            library is loaded.

            A. PhDbase looks for the file PHDBASE.MSG (or PHDBASE.xxx if
            you have a "phdbase language=xxx" statement in your
            CONFIG.FP[W] file).  This file must be in your FoxPro
            default directory, your FoxPro path or in your FoxPro system
            directory.  If necessary, place this statement in your
            CONFIG.FP[W] file to tell PhDbase where to find the message
            file (substitute your own path):

                phdbase path=c:\mystuff\phdbase\

            If you've created a PhDbase-embedded .EXE, you may include
            the PhDbase library but do not include the PHDBASE.MSG file.

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

            Q. There's an open file hanging out called <mytable>.PHD
            which never gets closed.

            A. This is normal if your table is opened with EXCLUSIVE
            access.  Versions of PhDbase prior to 3.30 attempted to
            automatically close the PhDbase index file (the .PHD file)
            whenever possible.  This strategy turned out to cause
            conflicts with FoxPro, leading to the "internal
            inconsistency" error mentioned below.  If you wish to
            explicitly close the .PHD file, you can do it with this
            command:

                =phd("flush")

            If your table is open in shared mode, you should never see a
            "dangling" .PHD file.  If for some reason a .PHD file stays
            open in your app, try issuing =phd("flush") commands after
            commands which change the table; and also please inform
            Korenthal Associates of the circumstances under which the
            .PHD file is remaining open.

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

            Q. Users are getting locked out with the message "PhDbase
            waiting for access."

            A. PhDbase must gain exclusive control of the .PHD file for
            short periods of time.  Under certain circumstances, PhDbase
            cannot recognize that control may be released and thus other
            users are locked out.  You can almost always make this
            problem go away by inserting the following command in
            strategic places:

                =phd("flush")

            Place the flush command 1. After USEing any file which has a
            PhDbase index.  2. After any commands which change
            PhDbase-related information -- for example, directly after
            an APPEND BLANK/REPLACE sequence.

            ** Note:  The addition of =phd("flush") commands should be
            unnecessary due to internal changes in multi-user access
            strategy introduced in version 3.30.

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

            Q. I'm getting the error message "Feature not found" when I
            run my PhDbase-embedded .EXE.

            A. You must include the PHDBASE.FXP in your project when you
            create a standalone .EXE.  Don't call this program -- just
            make it part of your project before compiling the .EXE.

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

            Q. The PhDbase index is not getting automatically updated
            properly.

            A. Are you indexing external files, or are you directly
            modifying memo fields via a Browse or a Modify Memo command?
            See the section "phd: Ad-Hoc Updates" for information on how
            to deal with these situations.

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

            Q. I get an "Internal Inconsistency" error when running a
            PhDbase application.

            A. FoxPro's handling of the INKEY function sometimes causes
            an "Internal Inconsistency" error to occur when a large
            library is in memory.  This error shows up most often when
            the FoxPro INKEY function is used in an error handling
            routine.

            If you get the Internal Inconsistency error and are using
            INKEY, use the replacement function which PhDbase III
            provides:

                If you use:        INKEY()
                Use this instead:  phd("inkey")

                   If you use:        INKEY(0)
                Use this instead:  phd("inkey 0")

                If you use:        INKEY(2.5)
                Use this instead:  phd("inkey 2.5")

                If you use:        INKEY(0, "M")
                Use this instead:  phd("inkey 0, M")

                If you use:        INKEY(18, "MH")
                Use this instead:  phd("inkey 18, MH")

            We have found that the substitution of phd("inkey") for
            INKEY in your code will be an effective safeguard against
            the FoxPro Internal Inconsistency error.

            ** Note:  An internal workaround to this problem was
            introduced in version 3.30.  We will be "grandfathering" the
            =phd("inkey") function in a future release unless the
            workaround isn't 100% effective.  Please inform Korenthal
            Associates if you are still getting this error under 3.30
            and if it is bypassed by using =phd("inkey") instead of the
            FoxPro INKEY function.

            ** Note:  The workaround introduced in 3.30 should also be
            effective if you've experienced internal inconsistencies
            when using Fox's GETFILE, PUTFILE or GETEXPR functions.
            Please inform Korenthal Associates is this turns out not to
            be true.

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

            

            See also: phd: Ad-Hoc Updates

            

            
        80  ķ
                     phd: Index <g>          
            Ľ

                set library to phdbase
                use phdhelp
                =phd("index keep all, numbers")
                =phd("<<...whatever...>>")

